/*
* This file is part of AndroidIDE.
*
* AndroidIDE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AndroidIDE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AndroidIDE. If not, see .
*
*/
package com.itsaky.androidide.handlers;
import android.view.View;
import com.itsaky.androidide.R;
import com.itsaky.androidide.managers.PreferenceManager;
import com.itsaky.androidide.project.AndroidProject;
import com.itsaky.androidide.project.IDEModule;
import com.itsaky.androidide.project.IDEProject;
import com.itsaky.androidide.services.builder.BuildListener;
import com.itsaky.androidide.services.builder.IDEService;
import com.itsaky.androidide.tasks.GradleTask;
import com.itsaky.androidide.tasks.gradle.build.ApkGeneratingTask;
import com.itsaky.androidide.utils.Environment;
import java.io.File;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
public class BuildServiceHandler extends IDEHandler implements BuildListener {
private IDEService service;
private boolean shouldInstallApk = false;
public BuildServiceHandler(Provider provider) {
super(provider);
}
public boolean isBuilding() {
return getService().isBuilding();
}
public IDEService getService() {
return service;
}
@Override
public void start() {
Objects.requireNonNull(this.activity());
AndroidProject project = provider.provideAndroidProject();
Objects.requireNonNull(project);
Objects.requireNonNull(project.getProjectPath());
this.service = new IDEService(new File(project.getProjectPath()));
this.service.setListener(this);
}
@Override
public void stop() {
this.service.stopAllDaemons();
this.service.exit();
}
@Override
public void onBuildModified() {
// Does nothing currently
}
@Override
public void onProjectLoaded(IDEProject project, Optional appModule) {
project.iconPath = provider.provideAndroidProject().getIconPath();
activity().setIDEProject(project);
if (appModule.isPresent()) {
IDEModule app = appModule.get();
activity().setStatus(activity().getString(R.string.msg_starting_completion));
final List paths =
app.dependencies.stream()
.filter(this::isClasspathValid)
.collect(Collectors.toList());
provider.provideAndroidProject().setClassPaths(paths);
File androidJar =
new File(
Environment.ANDROID_HOME,
String.format("platforms/%s/android.jar", app.compileSdkVersion));
if (androidJar.exists()) {
Environment.setBootClasspath(androidJar);
provider.provideAndroidProject().addClasspath(androidJar.getAbsolutePath());
activity().updateServices();
} else {
activity().setStatus("android.jar not found!");
}
} else {
activity().setStatus("Cannot get :app module...");
}
}
@Override
public void onStartingGradleDaemon(GradleTask task) {
activity().setStatus(activity().getString(R.string.msg_starting_daemon));
}
@Override
public void onRunTask(GradleTask task, String name) {
if (task != null && task.canOutput()) {
activity().setStatus(service.typeString(task.getTaskID()) + " " + name);
}
}
@Override
public void onBuildSuccessful(GradleTask task, String msg) {
appendOutput(task, msg);
analyzeCurrentFile();
if (task == null || activity() == null) {
return;
}
if (task.canOutput()) {
activity().setStatus(msg);
}
// If this task generates APK, ask user if he/she wants to install them
if (shouldInstallApk && task instanceof ApkGeneratingTask) {
final IDEProject project = activity().provideIDEProject();
final Optional app =
project.getModuleByPath(":app"); // TODO Handle multiple application modules
if (app.isPresent()) {
final String path = app.get().projectDir;
if (path != null) {
final File buildDir = new File(path, "build");
// installApks(((ApkGeneratingTask) task).getApks(buildDir));
}
}
}
activity()
.getApp()
.getPrefManager()
.putBoolean(PreferenceManager.KEY_IS_FIRST_PROJECT_BUILD, false);
activity().getBinding().buildProgressIndicator.setVisibility(View.GONE);
}
@Override
public void onBuildFailed(GradleTask task, String msg) {
appendOutput(task, msg);
analyzeCurrentFile();
if (task == null) {
return;
}
if (task.canOutput()) {
activity().setStatus(msg);
}
activity()
.getApp()
.getPrefManager()
.putBoolean(PreferenceManager.KEY_IS_FIRST_PROJECT_BUILD, false);
activity().getBinding().buildProgressIndicator.setVisibility(View.GONE);
}
@Override
public void saveFiles() {
activity().saveAll(false, false);
}
@Override
public void appendOutput(GradleTask task, CharSequence text) {
if (text == null) {
return;
}
if (task != null && !task.canOutput()) {
return;
}
activity().appendBuildOut(text.toString());
}
@Override
public void prepareBuild() {}
private void analyzeCurrentFile() {
final var editorView = activity().getCurrentEditor();
if (editorView != null) {
final var editor = editorView.getEditor();
if (editor != null) {
editor.analyze();
}
}
}
private boolean isClasspathValid(String path) {
if (path == null || path.trim().length() <= 0 || path.trim().equals("/")) {
return false;
}
File file = new File(path);
return file.isFile()
&& file.getName().endsWith(".jar")
// Release R.jar shouldn't be included in classpath
&& !file.getAbsolutePath().endsWith("/release/R.jar");
}
public void assembleDebug(boolean shouldInstallApk) {
setShouldInstallApk(shouldInstallApk);
getService().assembleDebug();
}
public void setShouldInstallApk(boolean install) {
this.shouldInstallApk = install;
}
}