diff --git a/app/src/main/java/com/itsaky/androidide/DownloadActivity.java b/app/src/main/java/com/itsaky/androidide/DownloadActivity.java
index 7ca65411b..d6356bacb 100755
--- a/app/src/main/java/com/itsaky/androidide/DownloadActivity.java
+++ b/app/src/main/java/com/itsaky/androidide/DownloadActivity.java
@@ -1,35 +1,34 @@
-/************************************************************************************
+/*
* 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;
import abhishekti7.unicorn.filepicker.UnicornFilePicker;
+
import android.content.Intent;
import android.content.res.ColorStateList;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
+
import androidx.core.content.ContextCompat;
import androidx.transition.TransitionManager;
+
import com.blankj.utilcode.util.FileIOUtils;
import com.blankj.utilcode.util.SizeUtils;
import com.blankj.utilcode.util.ThreadUtils;
@@ -49,175 +48,173 @@ import com.itsaky.androidide.utils.Environment;
import com.itsaky.androidide.utils.FileUtil;
import com.itsaky.androidide.utils.InputStreamLineReader;
import com.itsaky.toaster.Toaster;
+
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.ArrayList;
public class DownloadActivity extends StudioActivity {
-
- private ActivityDownloadBinding binding;
- private ProgressSheet progressSheet;
- private File choosenDir = null;
-
- @Override
- protected View bindLayout() {
- binding = ActivityDownloadBinding.inflate(getLayoutInflater());
- return binding.getRoot();
- }
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- OnClickListener clickListener = v -> handleClick(v);
- binding.dismiss.setOnClickListener(clickListener);
- binding.choose.setOnClickListener(clickListener);
- binding.install.setOnClickListener(clickListener);
-
- binding.install.setEnabled(false);
- }
-
- private void handleClick(View v) {
- final int id = v.getId();
- if(id == binding.dismiss.getId()) {
- TransitionManager.beginDelayedTransition(binding.getRoot());
- binding.card.setVisibility(View.GONE);
- } else if(id == binding.choose.getId()) {
- try {
- binding.install.setEnabled(false);
- UnicornFilePicker.from(this)
- .addConfigBuilder()
- .addItemDivider(false)
- .selectMultipleFiles(false)
- .setRootDirectory(FileUtil.getExternalStorageDir())
- .showHiddenFiles(true)
- .showOnlyDirectory(true)
- .theme(R.style.AppTheme_FilePicker)
- .build()
- .forResult(abhishekti7.unicorn.filepicker.utils.Constants.REQ_UNICORN_FILE);
- } catch (Throwable th){
- LOG.error(getString (R.string.err_cannot_start_file_picker), th);
- }
- } else if(id == binding.install.getId()) {
- if(choosenDir == null) {
- getApp().toast(R.string.msg_pick_files, Toaster.Type.ERROR);
- return;
- }
-
- if(!choosenDir.exists()) {
- getApp().toast(R.string.msg_file_doesnt_exist, Toaster.Type.ERROR);
- return;
- }
-
- installAll();
- }
- }
-
- private final String DONE = "DONE";
- private void installAll() {
- showProgress();
- getApp().getPrefManager().putBoolean(PreferenceManager.KEY_FRAMEWORK_DOWNLOADED, true);
-
- try {
- final File script = createExtractScript();
- final ProcessStreamsHolder holder = new ProcessStreamsHolder ();
- final IProcessExecutor executor = ProcessExecutorFactory.commonExecutor();
+ private ActivityDownloadBinding binding;
+ private ProgressSheet progressSheet;
+ private File choosenDir = null;
+
+ @Override
+ protected View bindLayout () {
+ binding = ActivityDownloadBinding.inflate (getLayoutInflater ());
+ return binding.getRoot ();
+ }
+
+ @Override
+ protected void onCreate (Bundle savedInstanceState) {
+ super.onCreate (savedInstanceState);
+ final OnClickListener clickListener = this::handleClick;
+ binding.dismiss.setOnClickListener (clickListener);
+ binding.choose.setOnClickListener (clickListener);
+ binding.install.setOnClickListener (clickListener);
+
+ binding.install.setEnabled (false);
+ }
+
+ private void handleClick (View v) {
+ final int id = v.getId ();
+ if (id == binding.dismiss.getId ()) {
+ TransitionManager.beginDelayedTransition (binding.getRoot ());
+ binding.card.setVisibility (View.GONE);
+ } else if (id == binding.choose.getId ()) {
+ try {
+ binding.install.setEnabled (false);
+ UnicornFilePicker.from (this)
+ .addConfigBuilder ()
+ .addItemDivider (false)
+ .selectMultipleFiles (false)
+ .setRootDirectory (FileUtil.getExternalStorageDir ())
+ .showHiddenFiles (true)
+ .showOnlyDirectory (true)
+ .theme (R.style.AppTheme_FilePicker)
+ .build ()
+ .forResult (abhishekti7.unicorn.filepicker.utils.Constants.REQ_UNICORN_FILE);
+ } catch (Throwable th) {
+ LOG.error (getString (R.string.err_cannot_start_file_picker), th);
+ }
+ } else if (id == binding.install.getId ()) {
+ if (choosenDir == null) {
+ getApp ().toast (R.string.msg_pick_files, Toaster.Type.ERROR);
+ return;
+ }
- executor.execAsync(holder,
- code -> onInstallProcessExit (code),
- true,
- Environment.BUSYBOX.getAbsolutePath(), "sh",// We use busybox's sh, because Environment.SHELL is not installed yet...
- script.getAbsolutePath()
+ if (!choosenDir.exists ()) {
+ getApp ().toast (R.string.msg_file_doesnt_exist, Toaster.Type.ERROR);
+ return;
+ }
+
+ installAll ();
+ }
+ }
+
+ private void installAll () {
+ showProgress ();
+ getApp ().getPrefManager ().putBoolean (PreferenceManager.KEY_FRAMEWORK_DOWNLOADED, true);
+
+ try {
+ final File script = createExtractScript ();
+ final ProcessStreamsHolder holder = new ProcessStreamsHolder ();
+ final IProcessExecutor executor = ProcessExecutorFactory.commonExecutor ();
+
+ executor.execAsync (holder,
+ this::onInstallProcessExit,
+ true,
+ Environment.BUSYBOX.getAbsolutePath (), "sh",// We use busybox's sh, because Environment.SHELL is not installed yet...
+ script.getAbsolutePath ()
);
- final InputStreamLineReader reader = new InputStreamLineReader (holder.in, line -> onInstallationOutput (line));
- new Thread (reader).start();
+ final InputStreamLineReader reader = new InputStreamLineReader (holder.in, this::onInstallationOutput);
+ new Thread (reader).start ();
} catch (DownloadActivity.InstallationException e) {
- LOG.error(getString(R.string.err_installation), e);
- onInstallationFailed(e.exitCode);
+ LOG.error (getString (R.string.err_installation), e);
+ onInstallationFailed (e.exitCode);
} catch (IOException e) {
- LOG.error(getString(R.string.err_installation), e);
- onInstallationFailed(5); // Exit code 5 : I/O Error
+ LOG.error (getString (R.string.err_installation), e);
+ onInstallationFailed (5); // Exit code 5 : I/O Error
}
- }
+ }
private void onInstallationOutput (final String line) {
- ThreadUtils.runOnUiThread(() -> {
- getProgressSheet().setSubMessage(line);
- });
+ ThreadUtils.runOnUiThread (() -> getProgressSheet ().setSubMessage (line));
}
private void onInstallProcessExit (final int code) {
- ThreadUtils.runOnUiThread(() -> {
+ ThreadUtils.runOnUiThread (() -> {
if (code == 0) { // 0 = normal execution
- getApp().getPrefManager().putBoolean(PreferenceManager.KEY_FRAMEWORK_INSTALLED, true);
- showRestartNeeded();
- if(getProgressSheet().isShowing()) {
- getProgressSheet().dismiss();
+ getApp ().getPrefManager ().putBoolean (PreferenceManager.KEY_FRAMEWORK_INSTALLED, true);
+ showRestartNeeded ();
+ if (getProgressSheet ().isShowing ()) {
+ getProgressSheet ().dismiss ();
}
} else {
onInstallationFailed (code);
}
});
}
-
- private void onInstallationFailed(int code) {
+
+ private void onInstallationFailed (int code) {
// TODO Can this be improved by adding some animations?
- if(getProgressSheet().isShowing()) {
- getProgressSheet().dismiss();
+ if (getProgressSheet ().isShowing ()) {
+ getProgressSheet ().dismiss ();
}
final MaterialAlertDialogBuilder builder = DialogUtils.newMaterialDialogBuilder (this);
- builder.setTitle(R.string.title_installation_failed);
- builder.setMessage(getString(R.string.msg_installation_failed, code));
- builder.setPositiveButton(android.R.string.ok, (d, w) -> {
- d.dismiss();
- finishAffinity();
+ builder.setTitle (R.string.title_installation_failed);
+ builder.setMessage (getString (R.string.msg_installation_failed, code));
+ builder.setPositiveButton (android.R.string.ok, (d, w) -> {
+ d.dismiss ();
+ finishAffinity ();
});
- builder.setNegativeButton(android.R.string.cancel, null);
- builder.show();
+ builder.setNegativeButton (android.R.string.cancel, null);
+ builder.show ();
}
-
- private File createExtractScript() throws DownloadActivity.InstallationException {
+
+ private File createExtractScript () throws DownloadActivity.InstallationException {
final StringBuilder sb = new StringBuilder ();
- sb.append("cd");
- joiner(sb);
- sb.append("echo 'Installing...'");
- joiner(sb);
+ sb.append ("cd");
+ joiner (sb);
+ sb.append ("echo 'Installing...'");
+ joiner (sb);
- File[] files = choosenDir.listFiles(ARCHIVE_FILTER);
+ File[] files = choosenDir.listFiles (ARCHIVE_FILTER);
if (files == null || files.length <= 0) {
throw new InstallationException (2);
}
for (File f : files) {
- if(f.getName().endsWith(".tar.xz")) {
- if(f.getName().startsWith("androidide-sysroot")) {
- sb.append("cd $SYSROOT/..");
- joiner(sb);
+ if (f.getName ().endsWith (".tar.xz")) {
+ if (f.getName ().startsWith ("androidide-sysroot")) {
+ sb.append ("cd $SYSROOT/..");
+ joiner (sb);
}
- sb.append("$BUSYBOX tar xvJf '" + f.getAbsolutePath() + "'");
- joiner(sb);
- sb.append("cd $HOME");
- joiner(sb);
- } else if(f.getName().endsWith(".zip")) {
- sb.append("$BUSYBOX unzip '" + f.getAbsolutePath() + "'");
- joiner(sb);
+ sb.append ("$BUSYBOX tar xvJf '").append (f.getAbsolutePath ()).append ("'");
+ joiner (sb);
+ sb.append ("cd $HOME");
+ joiner (sb);
+ } else if (f.getName ().endsWith (".zip")) {
+ sb.append ("$BUSYBOX unzip '").append (f.getAbsolutePath ()).append ("'");
+ joiner (sb);
}
}
- sb.append("echo 'Cleaning unsupported flags in binaries...'");
- joiner(sb);
- sb.append("$BUSYBOX find $JAVA_HOME -type f -exec androidide-cleaner {} \\;");
- joiner(sb);
- sb.append("echo " + DONE);
+ sb.append ("echo 'Cleaning unsupported flags in binaries...'");
+ joiner (sb);
+ sb.append ("$BUSYBOX find $JAVA_HOME -type f -exec androidide-cleaner {} \\;");
+ joiner (sb);
+ String DONE = "DONE";
+ sb.append ("echo ").append (DONE);
final File script = new File (Environment.TMP_DIR, "extract_tools.sh");
- if (!FileIOUtils.writeFileFromString(script, sb.toString())) {
+ if (!FileIOUtils.writeFileFromString (script, sb.toString ())) {
throw new InstallationException (2);
}
@@ -225,85 +222,77 @@ public class DownloadActivity extends StudioActivity {
}
private void joiner (StringBuilder sb) {
- sb.append(" && ");
+ sb.append (" && ");
}
-
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- super.onActivityResult(requestCode, resultCode, data);
- if(requestCode == abhishekti7.unicorn.filepicker.utils.Constants.REQ_UNICORN_FILE && resultCode == RESULT_OK) {
- ArrayList files = data.getStringArrayListExtra("filePaths");
- if(files != null) {
- if(files.size() == 1) {
- File choosenDir = new File(files.get(0));
- if(choosenDir.exists() && choosenDir.isDirectory()) {
- this.choosenDir = choosenDir;
- setDone(binding.choose);
- binding.install.setEnabled(true);
- new TaskExecutor().executeAsync(new ListDirectoryCallable(choosenDir), __ -> {
- binding.filesText.setText(getString(R.string.msg_installable_files, __));
- });
- } else {
- getApp().toast(R.string.msg_picked_isnt_dir, Toaster.Type.ERROR);
- choosenDir = null;
- }
- } else {
- getApp().toast(R.string.msg_pick_single_file, Toaster.Type.ERROR);
- }
- }
- }
- }
-
- private void setDone(MaterialButton button) {
- final int dp8 = SizeUtils.dp2px(8);
- final int dp4 = SizeUtils.dp2px(4);
- final int dp24 = SizeUtils.dp2px(24);
- button.setText("");
- button.setIconResource(R.drawable.ic_ok);
- button.setIconTint(ColorStateList.valueOf(ContextCompat.getColor(this, R.color.bg_green)));
- button.setBackgroundColor(android.graphics.Color.TRANSPARENT);
- button.setPaddingRelative(dp8, dp4, dp8, dp4);
- button.setStrokeWidth(0);
- button.setGravity(Gravity.CENTER);
- button.setIconPadding(0);
- button.setInsetTop(0);
- button.setInsetBottom(0);
- button.setPaddingRelative(dp24, dp4, dp24, dp4);
- }
-
- private void showProgress() {
- getProgressSheet().setCancelable(false);
- getProgressSheet().setShowShadow(false);
- getProgressSheet().setSubMessageEnabled(true)
- .setWelcomeTextEnabled(true)
- .show(getSupportFragmentManager(), "progress_sheet");
- }
-
- private void showRestartNeeded() {
- setDone(binding.install);
- final MaterialAlertDialogBuilder builder = DialogUtils.newMaterialDialogBuilder (this);
- builder.setTitle(R.string.title_restart);
- builder.setMessage(R.string.msg_restart);
- builder.setCancelable(false);
- builder.setPositiveButton(android.R.string.ok, (p1, p2) -> finishAffinity());
- builder.create().show();
- }
-
- private ProgressSheet getProgressSheet() {
- return progressSheet == null ? progressSheet = new ProgressSheet().setMessage(getString(R.string.please_wait)) : progressSheet;
- }
-
- private final FileFilter ARCHIVE_FILTER = new FileFilter(){
-
- @Override
- public boolean accept(File p1) {
- return p1.isFile() && (p1.getName().endsWith(".tar.xz") || p1.getName().endsWith(".zip"));
- }
- };
- private class InstallationException extends Exception {
+ @Override
+ protected void onActivityResult (int requestCode, int resultCode, Intent data) {
+ super.onActivityResult (requestCode, resultCode, data);
+ if (requestCode == abhishekti7.unicorn.filepicker.utils.Constants.REQ_UNICORN_FILE && resultCode == RESULT_OK) {
+ ArrayList files = data.getStringArrayListExtra ("filePaths");
+ if (files != null) {
+ if (files.size () == 1) {
+ File choosenDir = new File (files.get (0));
+ if (choosenDir.exists () && choosenDir.isDirectory ()) {
+ this.choosenDir = choosenDir;
+ setDone (binding.choose);
+ binding.install.setEnabled (true);
+ new TaskExecutor ().executeAsync (new ListDirectoryCallable (choosenDir), __ -> binding.filesText.setText (getString (R.string.msg_installable_files, __)));
+ } else {
+ getApp ().toast (R.string.msg_picked_isnt_dir, Toaster.Type.ERROR);
+ }
+ } else {
+ getApp ().toast (R.string.msg_pick_single_file, Toaster.Type.ERROR);
+ }
+ }
+ }
+ }
+
+ private void setDone (MaterialButton button) {
+ final int dp8 = SizeUtils.dp2px (8);
+ final int dp4 = SizeUtils.dp2px (4);
+ final int dp24 = SizeUtils.dp2px (24);
+ button.setText ("");
+ button.setIconResource (R.drawable.ic_ok);
+ button.setIconTint (ColorStateList.valueOf (ContextCompat.getColor (this, R.color.bg_green)));
+ button.setBackgroundColor (android.graphics.Color.TRANSPARENT);
+ button.setPaddingRelative (dp8, dp4, dp8, dp4);
+ button.setStrokeWidth (0);
+ button.setGravity (Gravity.CENTER);
+ button.setIconPadding (0);
+ button.setInsetTop (0);
+ button.setInsetBottom (0);
+ button.setPaddingRelative (dp24, dp4, dp24, dp4);
+ }
+
+ private void showProgress () {
+ getProgressSheet ().setCancelable (false);
+ getProgressSheet ().setShowShadow (false);
+ getProgressSheet ().setSubMessageEnabled (true)
+ .setWelcomeTextEnabled (true)
+ .show (getSupportFragmentManager (), "progress_sheet");
+ }
+
+ private void showRestartNeeded () {
+ setDone (binding.install);
+ final MaterialAlertDialogBuilder builder = DialogUtils.newMaterialDialogBuilder (this);
+ builder.setTitle (R.string.title_restart);
+ builder.setMessage (R.string.msg_restart);
+ builder.setCancelable (false);
+ builder.setPositiveButton (android.R.string.ok, (p1, p2) -> finishAffinity ());
+ builder.create ().show ();
+ }
+
+ private ProgressSheet getProgressSheet () {
+ return progressSheet == null ? progressSheet = new ProgressSheet ().setMessage (getString (R.string.please_wait)) : progressSheet;
+ }
+
+ private final FileFilter ARCHIVE_FILTER = p1 -> p1.isFile () && (p1.getName ().endsWith (".tar.xz") || p1.getName ().endsWith (".zip"));
+
+ private static class InstallationException extends Exception {
private final int exitCode;
- public InstallationException(int exitCode) {
+
+ public InstallationException (int exitCode) {
this.exitCode = exitCode;
}
}
diff --git a/app/src/main/java/com/itsaky/androidide/services/builder/IDEService.java b/app/src/main/java/com/itsaky/androidide/services/builder/IDEService.java
index 0daa45d06..8df2da9f9 100755
--- a/app/src/main/java/com/itsaky/androidide/services/builder/IDEService.java
+++ b/app/src/main/java/com/itsaky/androidide/services/builder/IDEService.java
@@ -353,7 +353,7 @@ public class IDEService {
final ProcessStreamsHolder holder = new ProcessStreamsHolder();
listener.saveFiles();
- Environment.mkdirIfNotExits(Environment.TMP_DIR);
+
currentTask = task;
listener.appendOutput(task, getString(R.string.msg_task_begin, currentTime(), task.getName()));
try {
diff --git a/common/src/main/java/com/itsaky/androidide/utils/BootstrapInstaller.java b/common/src/main/java/com/itsaky/androidide/utils/BootstrapInstaller.java
index 7997d41a6..b995110dd 100644
--- a/common/src/main/java/com/itsaky/androidide/utils/BootstrapInstaller.java
+++ b/common/src/main/java/com/itsaky/androidide/utils/BootstrapInstaller.java
@@ -69,32 +69,32 @@ public class BootstrapInstaller {
LOG.error ("Cannot delete staging directory");
throw new CompletionException (new InstallationException (context.getString (R.string.msg_delete_sysroot_staging)));
}
-
+
if (SYSROOT.exists () && !FileUtils.delete (SYSROOT)) {
LOG.error ("Cannot delete sysroot directory.");
throw new CompletionException (new InstallationException (context.getString (R.string.msg_delete_sysroot)));
}
-
+
if (stagingDir.exists () && !FileUtils.createOrExistsDir (stagingDir)) {
LOG.error ("Cannot create staging directory");
throw new CompletionException (new InstallationException (context.getString (R.string.msg_create_sysroot_staging)));
}
-
+
if (SYSROOT.exists () && !FileUtils.createOrExistsDir (SYSROOT)) {
LOG.error ("Cannot create sysroot directory");
throw new CompletionException (new InstallationException (context.getString (R.string.msg_create_sysroot)));
}
-
+
final var buffer = new byte[8096];
final var symlinks = new ArrayList> (50);
-
+
ZipEntry entry;
while ((entry = zip.getNextEntry ()) != null) {
msg = "Reading zip entry " + entry.getName ();
notify (listener, msg);
LOG.verbose (msg);
if (entry.getName ().equals ("SYMLINKS.txt")) {
-
+
msg = "Reading SYMLINKS.txt...";
notify (listener, msg);
LOG.debug (msg);
@@ -127,39 +127,39 @@ public class BootstrapInstaller {
LOG.error ("Cannot create target file parent directory");
throw new CompletionException (new InstallationException (context.getString (R.string.msg_mkdir_failed, ___.getAbsolutePath ())));
}
-
+
if (!isDirectory) {
try (final var outStream = new FileOutputStream (targetFile)) {
int readBytes;
while ((readBytes = zip.read (buffer)) != -1)
outStream.write (buffer, 0, readBytes);
}
-
+
if (zipEntryName.startsWith ("bin/") || zipEntryName.startsWith ("libexec") ||
zipEntryName.startsWith ("lib/apt/apt-helper") || zipEntryName.startsWith ("lib/apt/methods")) {
- notify (listener, context.getString(R.string.msg_chmod_exec));
+ notify (listener, context.getString (R.string.msg_chmod_exec));
LOG.verbose ("chmod 0700", zipEntryName);
-
+
//noinspection OctalInteger
Os.chmod (targetFile.getAbsolutePath (), 0700);
}
}
}
}
-
- if (symlinks.isEmpty()) {
+
+ if (symlinks.isEmpty ()) {
LOG.error ("No SYMLINKS.txt file encountered...");
throw new CompletionException (new InstallationException ("No SYMLINKS.txt encountered"));
}
-
+
for (Pair symlink : symlinks) {
notify (listener, context.getString (R.string.msg_linking, symlink.second, symlink.first));
- Os.symlink(symlink.first, symlink.second);
+ Os.symlink (symlink.first, symlink.second);
}
LOG.info ("Renaming 'sysroot-staging' directory to 'sysroot'");
-
+
if (!FileUtils.rename (stagingDir, SYSROOT.getName ())) {
LOG.error ("Cannot rename 'sysroot-staging' to 'sysroot'");
throw new CompletionException (new InstallationException ("Failed to rename staging sysroot directory."));
@@ -167,9 +167,9 @@ public class BootstrapInstaller {
notify (listener, context.getString (R.string.msg_extracting_hooks));
ToolsManager.extractLibHooks ();
-
+
LOG.info ("Bootstrap packages installed successfully.");
- } catch (IOException| ErrnoException e) {
+ } catch (IOException | ErrnoException e) {
LOG.error ("Failed to extract bootstrap", e);
throw new RuntimeException (e);
}