diff --git a/.github/workflows/delete-workflow-runs.yml b/.github/workflows/delete-workflow-runs.yml
new file mode 100644
index 000000000..accc54494
--- /dev/null
+++ b/.github/workflows/delete-workflow-runs.yml
@@ -0,0 +1,16 @@
+---
+name: Delete old workflow runs
+on:
+ workflow_dispatch:
+
+jobs:
+ del_runs:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Delete workflow runs
+ uses: Mattraks/delete-workflow-runs@v2
+ with:
+ token: ${{ github.token }}
+ repository: ${{ github.repository }}
+ retain_days: 15
+ keep_minimum_runs: 6
diff --git a/app/build.gradle b/app/build.gradle
index bab71e916..8d201fcf8 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,61 +1,57 @@
plugins {
- id 'com.android.application'
- id 'org.jetbrains.kotlin.android'
+ id 'com.android.application'
+ id 'org.jetbrains.kotlin.android'
}
android {
- namespace 'com.pranav.java.ide'
- compileSdk 32
+ namespace 'com.pranav.java.ide'
+ compileSdk 32
- defaultConfig {
- applicationId 'com.pranav.java.ide'
- minSdk 26
- targetSdk 32
- versionCode 3
- versionName '0.0.3'
- }
+ defaultConfig {
+ applicationId 'com.pranav.java.ide'
+ minSdk 26
+ targetSdk 32
+ versionCode 3
+ versionName '0.0.3'
+ }
- buildTypes {
- release {
- proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
- }
-
- debug {
- multiDexEnabled true
- }
- }
-
- compileOptions {
- sourceCompatibility JavaVersion.VERSION_11
- targetCompatibility JavaVersion.VERSION_11
- }
-
- kotlinOptions {
- jvmTarget = '1.8'
- }
-
- packagingOptions {
- resources.excludes.add("plugin.xml")
- resources.excludes.add(".options")
- resources.excludes.add("about.xml")
- resources.excludes.add("plugin.properties")
- resources.excludes.add(".api_description")
- resources.excludes.add("about_files/*")
- resources.excludes.add("META-INF/*")
- }
+ buildTypes {
+ release {
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+
+ debug {
+ multiDexEnabled true
+ }
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
+ packagingOptions {
+ resources.excludes.add("plugin.xml")
+ resources.excludes.add(".options")
+ resources.excludes.add("about.xml")
+ resources.excludes.add("plugin.properties")
+ resources.excludes.add(".api_description")
+ resources.excludes.add("about_files/*")
+ resources.excludes.add("META-INF/*")
+ }
}
dependencies {
- implementation fileTree(dir: 'libs', include: ['*.jar'])
- implementation 'com.google.guava:guava:31.1-android'
- implementation 'org.benf:cfr:0.152'
- implementation 'org.smali:dexlib2:2.5.2'
- implementation 'io.github.Rosemoe.sora-editor:editor:0.10.11'
- implementation 'io.github.Rosemoe.sora-editor:language-java:0.10.11'
- implementation 'androidx.appcompat:appcompat:1.6.0-alpha01'
- implementation 'com.google.android.material:material:1.6.0-beta01'
- implementation project(path: ':lib-android')
- testImplementation 'junit:junit:4.13.2'
- androidTestImplementation 'androidx.test.ext:junit:1.1.4-alpha05'
- androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.0-alpha05'
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
+ implementation 'com.google.guava:guava:31.1-android'
+ implementation 'org.benf:cfr:0.152'
+ implementation 'org.smali:dexlib2:2.5.2'
+ implementation 'io.github.Rosemoe.sora-editor:editor:0.10.11'
+ implementation 'io.github.Rosemoe.sora-editor:language-java:0.10.11'
+ implementation 'androidx.appcompat:appcompat:1.6.0-alpha01'
+ implementation 'com.google.android.material:material:1.6.0-beta01'
+ implementation project(path: ':lib-android')
+ testImplementation 'junit:junit:4.13.2'
+ androidTestImplementation 'androidx.test.ext:junit:1.1.4-alpha05'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.0-alpha05'
}
diff --git a/app/src/androidTest/java/com/pranav/java/ide/ExampleInstrumentedTest.kt b/app/src/androidTest/java/com/pranav/java/ide/ExampleInstrumentedTest.kt
index 11ac87bb9..2475037ee 100644
--- a/app/src/androidTest/java/com/pranav/java/ide/ExampleInstrumentedTest.kt
+++ b/app/src/androidTest/java/com/pranav/java/ide/ExampleInstrumentedTest.kt
@@ -14,11 +14,11 @@ import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
// Check the package name of project.
- @Test
- // Check if app context is accessible.
- fun useAppContext() {
- // Context of the app under test.
- val appContext = InstrumentationRegistry.getInstrumentation().targetContext
- assertEquals("com.pranav.java.ide", appContext.packageName)
- }
+ @Test
+ // Check if app context is accessible.
+ fun useAppContext() {
+ // Context of the app under test.
+ val appContext = InstrumentationRegistry.getInstrumentation().targetContext
+ assertEquals("com.pranav.java.ide", appContext.packageName)
+ }
}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 75eb16db1..bb476bb5e 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,19 +1,19 @@
+ xmlns:tools="http://schemas.android.com/tools">
-
-
+
@@ -27,5 +27,6 @@
-
+
+
diff --git a/app/src/main/java/com/pranav/java/ide/ApplicationLoader.java b/app/src/main/java/com/pranav/java/ide/ApplicationLoader.java
deleted file mode 100644
index 09ef06cff..000000000
--- a/app/src/main/java/com/pranav/java/ide/ApplicationLoader.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package com.pranav.java.ide;
-
-import android.app.AlarmManager;
-import android.app.Application;
-import android.app.PendingIntent;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Process;
-import android.util.Log;
-import com.pranav.lib_android.util.FileUtil;
-
-public final class ApplicationLoader extends Application {
-
- private static Context mContext;
-
- @Override
- public void onCreate() {
- mContext = getApplicationContext();
- FileUtil.initializeContext(mContext);
- Thread.UncaughtExceptionHandler uncaughtExceptionHandler =
- Thread.getDefaultUncaughtExceptionHandler();
-
- Thread.setDefaultUncaughtExceptionHandler(
- (thread, throwable) -> {
- Intent intent = new Intent(getApplicationContext(), DebugActivity.class);
- intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
- intent.putExtra("error", Log.getStackTraceString(throwable));
- PendingIntent pendingIntent =
- PendingIntent.getActivity(
- getApplicationContext(), 11111, intent, PendingIntent.FLAG_ONE_SHOT);
-
- AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
- am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 0, pendingIntent);
-
- Process.killProcess(Process.myPid());
- System.exit(1);
-
- uncaughtExceptionHandler.uncaughtException(thread, throwable);
- });
- super.onCreate();
- }
-
- public static Context getContext() {
- return mContext;
- }
-}
diff --git a/app/src/main/java/com/pranav/java/ide/ApplicationLoader.kt b/app/src/main/java/com/pranav/java/ide/ApplicationLoader.kt
new file mode 100644
index 000000000..900d5c1b6
--- /dev/null
+++ b/app/src/main/java/com/pranav/java/ide/ApplicationLoader.kt
@@ -0,0 +1,42 @@
+package com.pranav.java.ide
+
+import android.app.AlarmManager
+import android.app.Application
+import android.app.PendingIntent
+import android.content.Context
+import android.content.Intent
+import android.os.Process
+import android.util.Log
+import com.pranav.lib_android.util.FileUtil
+
+class ApplicationLoader : Application() {
+
+ private lateinit var mContext: Context
+
+ override fun onCreate() {
+ super.onCreate()
+ mContext = getApplicationContext()
+ FileUtil.initializeContext(mContext)
+ val uncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler()
+
+ Thread.setDefaultUncaughtExceptionHandler {
+ thread, throwable ->
+ val intent = Intent(mContext, DebugActivity::class.java)
+ intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
+ intent.putExtra("error", Log.getStackTraceString(throwable))
+ val pendingIntent =
+ PendingIntent.getActivity(
+ mContext, 11111, intent, PendingIntent.FLAG_ONE_SHOT)
+
+ val am = getSystemService(Context.ALARM_SERVICE) as AlarmManager
+ am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 0, pendingIntent)
+
+ Process.killProcess(Process.myPid())
+ System.exit(0)
+
+ uncaughtExceptionHandler?.uncaughtException(thread, throwable)
+ }
+ }
+
+ fun getContext(): Context = mContext
+}
diff --git a/app/src/main/java/com/pranav/java/ide/DebugActivity.java b/app/src/main/java/com/pranav/java/ide/DebugActivity.java
deleted file mode 100644
index b33b7d203..000000000
--- a/app/src/main/java/com/pranav/java/ide/DebugActivity.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.pranav.java.ide;
-
-import android.content.Intent;
-import android.os.Bundle;
-import androidx.appcompat.app.AlertDialog;
-import androidx.appcompat.app.AppCompatActivity;
-
-public final class DebugActivity extends AppCompatActivity {
-
- @Override
- protected void onCreate(final Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- Intent intent = getIntent();
- String errorMessage = intent.getStringExtra("error");
-
- new AlertDialog.Builder(this)
- .setTitle("An error occurred")
- .setMessage(errorMessage)
- .setPositiveButton("Quit", (dialog, which) -> finish())
- .create()
- .show();
- }
-}
diff --git a/app/src/main/java/com/pranav/java/ide/DebugActivity.kt b/app/src/main/java/com/pranav/java/ide/DebugActivity.kt
new file mode 100644
index 000000000..bcc1811eb
--- /dev/null
+++ b/app/src/main/java/com/pranav/java/ide/DebugActivity.kt
@@ -0,0 +1,23 @@
+package com.pranav.java.ide
+
+import android.content.Intent
+import android.os.Bundle
+import androidx.appcompat.app.AlertDialog
+import androidx.appcompat.app.AppCompatActivity
+
+class DebugActivity : AppCompatActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ val intent: Intent? = getIntent()
+ val errorMessage = intent?.getStringExtra("error")!!
+
+ AlertDialog.Builder(this)
+ .setTitle("An error occurred")
+ .setMessage(errorMessage)
+ .setPositiveButton("Quit", {_, _ -> finish()})
+ .create()
+ .show()
+ }
+}
diff --git a/app/src/main/java/com/pranav/java/ide/MainActivity.java b/app/src/main/java/com/pranav/java/ide/MainActivity.java
deleted file mode 100644
index 521ae455f..000000000
--- a/app/src/main/java/com/pranav/java/ide/MainActivity.java
+++ /dev/null
@@ -1,482 +0,0 @@
-package com.pranav.java.ide;
-
-import android.content.ClipData;
-import android.content.ClipboardManager;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.graphics.Typeface;
-import android.os.Bundle;
-import android.util.Log;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.widget.LinearLayout;
-
-import androidx.appcompat.app.AlertDialog;
-import androidx.appcompat.app.AppCompatActivity;
-
-import com.google.android.material.dialog.MaterialAlertDialogBuilder;
-import com.google.android.material.snackbar.Snackbar;
-import com.google.common.io.ByteStreams;
-import com.google.common.io.Files;
-import com.google.common.base.Charsets;
-import com.googlecode.d2j.smali.BaksmaliCmd;
-import com.pranav.lib_android.exception.CompilationFailedException;
-import com.pranav.lib_android.task.JavaBuilder;
-import com.pranav.lib_android.task.java.CompileJavaTask;
-import com.pranav.lib_android.task.java.D8Task;
-import com.pranav.lib_android.task.java.ExecuteJavaTask;
-import com.pranav.lib_android.code.disassembler.ClassFileDisassembler;
-import com.pranav.lib_android.code.formatter.Formatter;
-import com.pranav.lib_android.util.ZipUtil;
-import com.pranav.lib_android.util.FileUtil;
-import com.pranav.lib_android.util.ConcurrentUtilKt;
-
-import io.github.rosemoe.sora.langs.java.JavaLanguage;
-import io.github.rosemoe.sora.widget.CodeEditor;
-import io.github.rosemoe.sora.widget.schemes.SchemeDarcula;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-
-import org.jf.dexlib2.DexFileFactory;
-import org.jf.dexlib2.Opcodes;
-import org.jf.dexlib2.iface.ClassDef;
-import org.jf.dexlib2.iface.DexFile;
-
-public final class MainActivity extends AppCompatActivity {
-
- private CodeEditor editor;
-
- private long d8Time = 0;
- private long ecjTime = 0;
-
- private boolean errorsArePresent = false;
-
- @Override
- protected void onCreate(final Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
-
- setSupportActionBar(findViewById(R.id.toolbar));
- getSupportActionBar().setDisplayHomeAsUpEnabled(false);
- getSupportActionBar().setHomeButtonEnabled(false);
-
- editor = findViewById(R.id.editor);
-
- editor.setTypefaceText(Typeface.MONOSPACE);
- editor.setEditorLanguage(new JavaLanguage());
- editor.setColorScheme(new SchemeDarcula());
- editor.setTextSize(12);
-
- final File file = file(FileUtil.getJavaDir() + "Main.java");
-
- if (file.exists()) {
- try {
- editor.setText(
- Files.asCharSource(file, Charsets.UTF_8)
- .read()
- );
- } catch (Exception e) {
- dialog("Cannot read file", getString(e), true);
- }
- } else {
- editor.setText(
- "package com.example;\n\nimport java.util.*;\n\n" +
- "public class Main {\n\n" +
- "\tpublic static void main(String[] args) {\n" +
- "\t\tSystem.out.print(\"Hello, World!\");\n" + "\t}\n" +
- "}\n"
- );
- }
-
- final JavaBuilder builder = new JavaBuilder(getApplicationContext(),
- getClassLoader());
-
- ConcurrentUtilKt.executeInBackground(() -> {
- if (!file(FileUtil.getClasspathDir() + "android.jar").exists()) {
- ZipUtil.unzipFromAssets(MainActivity.this,
- "android.jar.zip", FileUtil.getClasspathDir());
- }
- File output = file(FileUtil.getClasspathDir() + "/core-lambda-stubs.jar");
- if (!output.exists() &&
- getSharedPreferences("compiler_settings", Context.MODE_PRIVATE)
- .getString("javaVersion", "7.0")
- .equals("8.0")) {
- try {
- Files.write(
- ByteStreams.toByteArray(
- getAssets().open("core-lambda-stubs.jar")
- ),
- output);
- } catch (Exception e) {
- showErr(getString(e));
- }
- }
- });
-
- findViewById(R.id.btn_disassemble).setOnClickListener(v -> disassemble());
- findViewById(R.id.btn_smali2java).setOnClickListener(v -> decompile());
- findViewById(R.id.btn_smali).setOnClickListener(v -> smali());
- findViewById(R.id.btn_run).setOnClickListener(view -> {
- try {
- // Delete previous build files
- FileUtil.deleteFile(FileUtil.getBinDir());
- file(FileUtil.getBinDir()).mkdirs();
- final File mainFile = file(
- FileUtil.getJavaDir() + "Main.java");
- Files.createParentDirs(mainFile);
- // a simple workaround to prevent calls to system.exit
- Files.write(editor.getText().toString()
- .replace("System.exit(",
- "System.err.print(\"Exit code \" + ")
- .getBytes(), mainFile);
- } catch (final IOException e) {
- dialog("Cannot save program", getString(e), true);
- }
-
- // code that runs ecj
- long time = System.currentTimeMillis();
- errorsArePresent = true;
- try {
- CompileJavaTask javaTask = new CompileJavaTask(builder);
- javaTask.doFullTask();
- errorsArePresent = false;
- } catch (CompilationFailedException e) {
- showErr(e.getMessage());
- } catch (Throwable e) {
- showErr(getString(e));
- }
- if (errorsArePresent) {
- return;
- }
-
- ecjTime = System.currentTimeMillis() - time;
- time = System.currentTimeMillis();
-
- // run d8
- try {
- new D8Task().doFullTask();
- } catch (Exception e) {
- errorsArePresent = true;
- showErr(e.toString());
- return;
- }
- d8Time = System.currentTimeMillis() - time;
- // code that loads the final dex
- try {
- final String[] classes = getClassesFromDex();
- if (classes == null) {
- return;
- }
- listDialog("Select a class to execute", classes,
- (dialog, pos) -> {
- ExecuteJavaTask task = new ExecuteJavaTask(
- builder, classes[pos]);
- try {
- task.doFullTask();
- } catch (java.lang.reflect.InvocationTargetException e) {
- dialog("Failed...",
- "Runtime error: " +
- e.getMessage() +
- "\n\n" +
- getString(e),
- true);
- } catch (Exception e) {
- dialog("Failed..",
- "Couldn't execute the dex: "
- + e.toString()
- + "\n\nSystem logs:\n"
- + task.getLogs(),
- true);
- }
- StringBuilder s = new StringBuilder();
- s.append("Success! ECJ took: ");
- s.append(String.valueOf(ecjTime));
- s.append("ms, ");
- s.append("D8");
- s.append(" took: ");
- s.append(String.valueOf(d8Time));
- s.append("ms");
- dialog(s.toString(), task.getLogs(), true);
- });
- } catch (Throwable e) {
- showErr(getString(e));
- }
- });
- }
-
- public void showErr(final String e) {
- Snackbar.make((LinearLayout) findViewById(R.id.container), "An error occurred",
- Snackbar.LENGTH_INDEFINITE)
- .setAction("Show error", (view) -> dialog("Failed...", e, true))
- .show();
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- menu.add(0, 0, 0, "Format");
- menu.add(0, 1, 0, "Settings");
- return super.onCreateOptionsMenu(menu);
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case 0 :
- Formatter formatter = new Formatter(
- editor.getText().toString());
- editor.setText(formatter.format());
- break;
-
- case 1 :
- Intent intent = getIntent();
- intent.setClass(this, SettingActivity.class);
- startActivity(intent);
- default :
- break;
- }
- return super.onOptionsItemSelected(item);
- }
-
- public void smali() {
- try {
- final String[] classes = getClassesFromDex();
- if (classes == null)
- return;
- listDialog("Select a class to extract source", classes,
- (d, pos) -> {
- final String claz = classes[pos];
- final String[] args = new String[] {
- "-f",
- "-o",
- FileUtil.getBinDir()
- .concat("smali/"),
- FileUtil.getBinDir()
- .concat("classes.dex")
- };
- ConcurrentUtilKt.execute(() -> BaksmaliCmd.main(args));
-
- CodeEditor edi = new CodeEditor(MainActivity.this);
- edi.setTypefaceText(Typeface.MONOSPACE);
- edi.setEditorLanguage(new JavaLanguage());
- edi.setColorScheme(new SchemeDarcula());
- edi.setTextSize(13);
-
- File smaliFile = file(FileUtil.getBinDir() + "smali/" + claz.replace(".", "/") + ".smali");
-
- try {
- edi.setText(formatSmali(Files.asCharSource(smaliFile, Charsets.UTF_8).read()));
- } catch (IOException e) {
- dialog("Cannot read file", getString(e), true);
- }
-
- final AlertDialog dialog = new AlertDialog.Builder(
- MainActivity.this).setView(edi).create();
- dialog.setCanceledOnTouchOutside(true);
- dialog.show();
- });
- } catch (Throwable e) {
- dialog("Failed to extract smali source", getString(e),
- true);
- }
- }
-
- public void decompile() {
- final String[] classes = getClassesFromDex();
- if (classes == null)
- return;
- listDialog("Select a class to extract source", classes,
- (dialog, pos) -> {
- final String claz = classes[pos].replace(".", "/");
- String[] args = {
- FileUtil.getBinDir() +
- "classes/" +
- claz + // full class name
- ".class",
- "--extraclasspath",
- FileUtil.getClasspathDir() + "android.jar",
- "--outputdir",
- FileUtil.getBinDir() + "cfr/"
- };
-
- ConcurrentUtilKt.execute(() -> {
- try {
- org.benf.cfr.reader.Main.main(args);
- } catch (Exception e) {
- dialog("Failed to decompile...",
- getString(e), true);
- }
- });
-
- final CodeEditor edi = new CodeEditor(MainActivity.this);
- edi.setTypefaceText(Typeface.MONOSPACE);
- edi.setEditorLanguage(new JavaLanguage());
- edi.setColorScheme(new SchemeDarcula());
- edi.setTextSize(12);
-
- File decompiledFile = file(
- FileUtil.getBinDir() + "cfr/" + claz + ".java");
-
- try {
- edi.setText(Files
- .asCharSource(decompiledFile, Charsets.UTF_8)
- .read());
- } catch (IOException e) {
- dialog("Cannot read file", getString(e),
- true);
- }
-
- final AlertDialog d = new AlertDialog.Builder(
- MainActivity.this).setView(edi).create();
- d.setCanceledOnTouchOutside(true);
- d.show();
- });
- }
-
- public void disassemble() {
- final String[] classes = getClassesFromDex();
- if (classes == null)
- return;
- listDialog("Select a class to disassemble", classes, (dialog, pos) -> {
- final String claz = classes[pos].replace(".", "/");
-
- final CodeEditor edi = new CodeEditor(MainActivity.this);
- edi.setTypefaceText(Typeface.MONOSPACE);
- edi.setEditorLanguage(new JavaLanguage());
- edi.setColorScheme(new SchemeDarcula());
- edi.setTextSize(12);
-
- try {
- final String disassembled = new ClassFileDisassembler(
- FileUtil.getBinDir() + "classes/" + claz + ".class")
- .disassemble();
-
- edi.setText(disassembled);
-
- AlertDialog d = new AlertDialog.Builder(MainActivity.this)
- .setView(edi).create();
- d.setCanceledOnTouchOutside(true);
- d.show();
- } catch (Throwable e) {
- dialog("Failed to disassemble", getString(e),
- true);
- }
- });
- }
-
- private String formatSmali(String in) {
-
- ArrayList lines = new ArrayList<>(
- Arrays.asList(in.split("\n"))
- );
-
- boolean insideMethod = false;
-
- for (int i = 0; i < lines.size(); i++) {
-
- String line = lines.get(i);
-
- if (line.startsWith(".method"))
- insideMethod = true;
-
- if (line.startsWith(".end method"))
- insideMethod = false;
-
- if (insideMethod && !shouldSkip(line))
- lines.set(i, line + "\n");
- }
-
- StringBuilder result = new StringBuilder();
-
- for (int i = 0; i < lines.size(); i++) {
- if (i != 0)
- result.append("\n");
-
- result.append(lines.get(i));
- }
-
- return result.toString();
- }
-
- private boolean shouldSkip(String smaliLine) {
-
- String[] ops = {".line", ":", ".prologue"};
-
- for (String op : ops) {
- if (smaliLine.trim().startsWith(op))
- return true;
- }
- return false;
- }
-
- public void listDialog(String title, String[] items,
- DialogInterface.OnClickListener listener) {
- new MaterialAlertDialogBuilder(MainActivity.this)
- .setTitle(title)
- .setItems(items, listener)
- .create()
- .show();
- }
-
- public void dialog(String title, final String message, boolean copyButton) {
- final MaterialAlertDialogBuilder dialog = new MaterialAlertDialogBuilder(
- MainActivity.this).setTitle(title).setMessage(message)
- .setPositiveButton("GOT IT", null)
- .setNegativeButton("CANCEL", null);
- if (copyButton)
- dialog.setNeutralButton("COPY", (dialogInterface, i) -> {
- ((ClipboardManager) getSystemService(
- getApplicationContext().CLIPBOARD_SERVICE))
- .setPrimaryClip(ClipData
- .newPlainText("clipboard", message));
- });
- dialog.create().show();
- }
-
-// for granting execute permissions to file/folder (currently unused)
- public void grantChmod(File file) {
- File[] files = file.listFiles();
- try {
- for (File f : files) {
- if (f.isDirectory()) {
- grantChmod(f);
- } else {
- f.setExecutable(true, true);
- }
- }
- } catch (Throwable e) {
- e.printStackTrace();
- }
- }
-
- public String[] getClassesFromDex() {
- try {
- final ArrayList classes = new ArrayList<>();
- DexFile dexfile = DexFileFactory.loadDexFile(FileUtil.getBinDir().concat("classes.dex"),
- Opcodes.forApi(26)
- );
- for (ClassDef f : dexfile.getClasses()
- .toArray(new ClassDef[0])
- ) {
- String name = f.getType().replace("/", "."); // convert class name to standard form
- classes.add(name.substring(1, name.length() - 1));
- }
- return classes.toArray(new String[0]);
- } catch (Exception e) {
- dialog("Failed to get available classes in dex...",
- getString(e), true);
- return null;
- }
- }
-
- public File file(final String path) {
- return new File(path);
- }
-
- private String getString(final Throwable e) {
- return Log.getStackTraceString(e);
- }
-}
diff --git a/app/src/main/java/com/pranav/java/ide/MainActivity.kt b/app/src/main/java/com/pranav/java/ide/MainActivity.kt
new file mode 100644
index 000000000..fc2efc11b
--- /dev/null
+++ b/app/src/main/java/com/pranav/java/ide/MainActivity.kt
@@ -0,0 +1,448 @@
+package com.pranav.java.ide
+
+import android.content.ClipData
+import android.content.ClipboardManager
+import android.content.Context
+import android.content.DialogInterface
+import android.content.Intent
+import android.graphics.Typeface
+import android.os.Bundle
+import android.util.Log
+import android.view.Menu
+import android.view.MenuItem
+import android.view.View
+import android.widget.LinearLayout
+
+import androidx.appcompat.app.AlertDialog
+import androidx.appcompat.app.AppCompatActivity
+
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
+import com.google.android.material.snackbar.Snackbar
+import com.google.common.io.ByteStreams
+import com.google.common.io.Files
+import com.google.common.base.Charsets
+import com.googlecode.d2j.smali.BaksmaliCmd
+import com.pranav.lib_android.exception.CompilationFailedException
+import com.pranav.lib_android.task.JavaBuilder
+import com.pranav.lib_android.task.java.CompileJavaTask
+import com.pranav.lib_android.task.java.D8Task
+import com.pranav.lib_android.task.java.ExecuteJavaTask
+import com.pranav.lib_android.code.disassembler.ClassFileDisassembler
+import com.pranav.lib_android.code.formatter.Formatter
+import com.pranav.lib_android.util.ZipUtil
+import com.pranav.lib_android.util.FileUtil
+import com.pranav.lib_android.util.ConcurrentUtil
+
+import io.github.rosemoe.sora.langs.java.JavaLanguage
+import io.github.rosemoe.sora.widget.CodeEditor
+import io.github.rosemoe.sora.widget.schemes.SchemeDarcula
+
+import java.io.File
+import java.io.IOException
+import java.util.ArrayList
+import java.util.Arrays
+
+import org.jf.dexlib2.DexFileFactory
+import org.jf.dexlib2.Opcodes
+import org.jf.dexlib2.iface.ClassDef
+import org.jf.dexlib2.iface.DexFile
+
+class MainActivity: AppCompatActivity() {
+
+ private lateinit var editor: CodeEditor
+
+ private var d8Time: Long = 0
+ private var ecjTime: Long = 0
+
+ private var errorsArePresent = false
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_main)
+
+ setSupportActionBar(findViewById(R.id.toolbar))
+ getSupportActionBar()?.setDisplayHomeAsUpEnabled(false)
+ getSupportActionBar()?.setHomeButtonEnabled(false)
+
+ editor = findViewById(R.id.editor)
+
+ editor.setTypefaceText(Typeface.MONOSPACE)
+ editor.setEditorLanguage(JavaLanguage())
+ editor.setColorScheme(SchemeDarcula())
+ editor.setTextSize(12f)
+
+ val file = File(FileUtil.getJavaDir(), "Main.java")
+
+ if (file.exists()) {
+ try {
+ editor.setText(
+ file.readText()
+ )
+ } catch (e: Exception) {
+ dialog("Cannot read file", getString(e), true)
+ }
+ } else {
+ editor.setText(
+ "package com.example;\n\nimport java.util.*;\n\n" +
+ "public class Main {\n\n" +
+ "\tpublic static void main(String[] args) {\n" +
+ "\t\tSystem.out.print(\"Hello, World!\");\n" + "\t}\n" +
+ "}\n"
+ )
+ }
+
+ val builder = JavaBuilder(getApplicationContext(),
+ getClassLoader())
+
+ ConcurrentUtil.executeInBackground {
+ if (!File(FileUtil.getClasspathDir(), "android.jar").exists()) {
+ ZipUtil.unzipFromAssets(this,
+ "android.jar.zip", FileUtil.getClasspathDir())
+ }
+ val output = File(FileUtil.getClasspathDir(), "core-lambda-stubs.jar")
+ if (!output.exists() &&
+ getSharedPreferences("compiler_settings", Context.MODE_PRIVATE)
+ .getFloat("javaVersion", 7.0f) >= 8.0f) {
+ try {
+ output.writeBytes(getAssets().open("core-lambda-stubs.jar").readBytes())
+ } catch (e: Exception) {
+ showErr(getString(e))
+ }
+ }
+ }
+
+ (findViewById(R.id.btn_disassemble) as View).setOnClickListener { _ -> disassemble()}
+ (findViewById(R.id.btn_smali2java) as View).setOnClickListener { _ -> decompile()}
+ (findViewById(R.id.btn_smali) as View).setOnClickListener { _ -> smali()}
+ (findViewById(R.id.btn_run) as View).setOnClickListener { _ ->
+ try {
+ // Delete previous build files
+ FileUtil.deleteFile(FileUtil.getBinDir())
+ File(FileUtil.getBinDir()).mkdirs()
+ val mainFile = File(
+ FileUtil.getJavaDir() + "Main.java")
+ Files.createParentDirs(mainFile)
+ // a simple workaround to prevent calls to system.exit
+ mainFile.writeText(editor.getText().toString()
+ .replace("System.exit(",
+ "System.err.print(\"Exit code \" + ")
+ )
+ } catch (e: IOException) {
+ dialog("Cannot save program", getString(e), true)
+ }
+
+ // code that runs ecj
+ var time = System.currentTimeMillis()
+ errorsArePresent = true
+ try {
+ val javaTask = CompileJavaTask(builder)
+ javaTask.doFullTask()
+ errorsArePresent = false
+ } catch (e: CompilationFailedException) {
+ showErr(e.message)
+ } catch (e: Throwable) {
+ showErr(getString(e))
+ }
+ if (errorsArePresent) {
+ return@setOnClickListener
+ }
+
+ ecjTime = System.currentTimeMillis() - time
+ time = System.currentTimeMillis()
+
+ // run d8
+ try {
+ D8Task().doFullTask()
+ } catch (e: Throwable) {
+ errorsArePresent = true
+ showErr(e.toString())
+ return@setOnClickListener
+ }
+ d8Time = System.currentTimeMillis() - time
+ // code that loads the final dex
+ try {
+ val classes = getClassesFromDex()
+ if (classes == null) {
+ return@setOnClickListener
+ }
+ listDialog("Select a class to execute", classes,
+ { _, pos ->
+ val task = ExecuteJavaTask(
+ builder, classes[pos])
+ try {
+ task.doFullTask()
+ } catch (e: java.lang.reflect.InvocationTargetException) {
+ dialog("Failed...",
+ "Runtime error: " +
+ e.message +
+ "\n\n" +
+ getString(e),
+ true)
+ } catch (e: Exception) {
+ dialog("Failed..",
+ "Couldn't execute the dex: "
+ + e.toString()
+ + "\n\nSystem logs:\n"
+ + task.getLogs(),
+ true)
+ }
+ val s = StringBuilder()
+ s.append("Success! ECJ took: ")
+ s.append(ecjTime.toString())
+ s.append("ms, ")
+ s.append("D8")
+ s.append(" took: ")
+ s.append(d8Time.toString())
+ s.append("ms")
+ dialog(s.toString(), task.getLogs(), true)
+ })
+ } catch (e: Throwable) {
+ showErr(getString(e))
+ }
+ }
+ }
+
+ fun showErr(e: String?) {
+ Snackbar.make(findViewById(R.id.container) as LinearLayout, "An error occurred",
+ Snackbar.LENGTH_INDEFINITE)
+ .setAction("Show error", { _ -> dialog("Failed...", e, true)})
+ .show()
+ }
+
+ override fun onCreateOptionsMenu(menu: Menu): Boolean {
+ menu.add(0, 0, 0, "Format")
+ menu.add(0, 1, 0, "Settings")
+ return super.onCreateOptionsMenu(menu)
+ }
+
+ override fun onOptionsItemSelected(item: MenuItem): Boolean {
+ when (item.getItemId()) {
+ 0 -> {
+ val formatter = Formatter(
+ editor.getText().toString())
+ ConcurrentUtil.execute {
+ editor.setText(formatter.format())
+ }
+ }
+
+ 1 -> {
+ val intent = getIntent()
+ intent.setClass(this, SettingActivity::class.java)
+ startActivity(intent)
+ }
+ }
+ return super.onOptionsItemSelected(item)
+ }
+
+ fun smali() {
+ try {
+ val classes = getClassesFromDex()
+ if (classes == null)
+ return
+ listDialog("Select a class to extract source", classes,
+ { _, pos ->
+ val claz = classes[pos]
+ val args = listOf(
+ "-f",
+ "-o",
+ FileUtil.getBinDir() + "smali/",
+ FileUtil.getBinDir() + "classes.dex"
+ )
+ ConcurrentUtil.execute {
+ BaksmaliCmd.main(args.toTypedArray())
+ }
+
+ val edi = CodeEditor(this@MainActivity)
+ edi.setTypefaceText(Typeface.MONOSPACE)
+ edi.setEditorLanguage(JavaLanguage())
+ edi.setColorScheme(SchemeDarcula())
+ edi.setTextSize(13f)
+
+ val smaliFile = File(FileUtil.getBinDir() + "smali/" + claz.replace(".", "/") + ".smali")
+
+ try {
+ edi.setText(formatSmali(smaliFile.readText()))
+ } catch (e: IOException) {
+ dialog("Cannot read file", getString(e), true)
+ }
+
+ val dialog = AlertDialog.Builder(
+ this).setView(edi).create()
+ dialog.setCanceledOnTouchOutside(true)
+ dialog.show()
+ })
+ } catch (e: Throwable) {
+ dialog("Failed to extract smali source", getString(e),
+ true)
+ }
+ }
+
+ fun decompile() {
+ val classes = getClassesFromDex()
+ if (classes == null)
+ return
+ listDialog("Select a class to extract source", classes,
+ { _, pos ->
+ val claz = classes[pos].replace(".", "/")
+ val args = listOf(
+ FileUtil.getBinDir() +
+ "classes/" +
+ claz + // full class name
+ ".class",
+ "--extraclasspath",
+ FileUtil.getClasspathDir() + "android.jar",
+ "--outputdir",
+ FileUtil.getBinDir() + "cfr/"
+ )
+
+ ConcurrentUtil.execute {
+ try {
+ } catch (e: Exception) {
+ dialog("Failed to decompile...",
+ getString(e), true)
+ }
+ }
+
+ val edi = CodeEditor(this)
+ edi.setTypefaceText(Typeface.MONOSPACE)
+ edi.setEditorLanguage(JavaLanguage())
+ edi.setColorScheme(SchemeDarcula())
+ edi.setTextSize(12f)
+
+ val decompiledFile = File(
+ FileUtil.getBinDir() + "cfr/" + claz + ".java")
+
+ try {
+ edi.setText(decompiledFile.readText())
+ } catch (e: IOException) {
+ dialog("Cannot read file", getString(e),
+ true)
+ }
+
+ val d = AlertDialog.Builder(
+ this).setView(edi).create()
+ d.setCanceledOnTouchOutside(true)
+ d.show()
+ })
+ }
+
+ fun disassemble() {
+ val classes = getClassesFromDex()
+ if (classes == null)
+ return
+ listDialog("Select a class to disassemble", classes, { _, pos ->
+ val claz = classes[pos].replace(".", "/")
+
+ val edi = CodeEditor(this)
+ edi.setTypefaceText(Typeface.MONOSPACE)
+ edi.setEditorLanguage(JavaLanguage())
+ edi.setColorScheme(SchemeDarcula())
+ edi.setTextSize(12f)
+
+ try {
+ val disassembled = ClassFileDisassembler(
+ FileUtil.getBinDir() + "classes/" + claz + ".class")
+ .disassemble()
+
+ edi.setText(disassembled)
+
+ val d = AlertDialog.Builder(this)
+ .setView(edi).create()
+ d.setCanceledOnTouchOutside(true)
+ d.show()
+ } catch (e: Throwable) {
+ dialog("Failed to disassemble", getString(e),
+ true)
+ }
+ })
+ }
+
+ private fun formatSmali(inp: String): String {
+
+ val lines: List = Arrays.asList(inp.split("\n"))
+
+ var insideMethod = false
+
+ lines.forEach {
+
+ if (it.startsWith(".method"))
+ insideMethod = true
+
+ if (it.startsWith(".end method"))
+ insideMethod = false
+
+ if (insideMethod && !shouldSkip(it))
+ lines.set(lines.indexOf(it), it + "\n")
+ }
+
+ val result = StringBuilder()
+
+ for (line in lines.toTypedArray()) {
+ result.append("\n")
+
+ result.append(line)
+ }
+
+ return result.toString()
+ }
+
+ private fun shouldSkip(smaliLine: String?): Boolean {
+
+ val ops = listOf(".line", ":", ".prologue")
+
+ for (op in ops) {
+ if (smaliLine?.trim().startsWith(op))
+ return true
+ }
+ return false
+ }
+
+ fun listDialog(title: String, items: Array,
+ listener: DialogInterface.OnClickListener) {
+ MaterialAlertDialogBuilder(this)
+ .setTitle(title)
+ .setItems(items, listener)
+ .create()
+ .show()
+ }
+
+ fun dialog(title: String, message: String?, copyButton: Boolean) {
+ val dialog = MaterialAlertDialogBuilder(this)
+ .setTitle(title)
+ .setMessage(message)
+ .setPositiveButton("GOT IT", null)
+ .setNegativeButton("CANCEL", null)
+ if (copyButton)
+ dialog.setNeutralButton("COPY", { _, _ ->
+ (getSystemService(
+ Context.CLIPBOARD_SERVICE) as ClipboardManager)
+ .setPrimaryClip(ClipData
+ .newPlainText("content", message))
+ })
+ dialog.create().show()
+ }
+
+ fun getClassesFromDex(): Array? {
+ try {
+ val classes = ArrayList()
+ val dexfile = DexFileFactory.loadDexFile(FileUtil.getBinDir().plus("classes.dex"),
+ Opcodes.forApi(26)
+ )
+ for (f in dexfile.getClasses()
+ .toTypedArray()
+ ) {
+ val name = f.getType().replace("/", ".") // convert class name to standard form
+ classes.add(name.substring(1, name.length - 1))
+ }
+ return classes.toTypedArray()
+ } catch (e: Exception) {
+ dialog("Failed to get available classes in dex...",
+ getString(e), true)
+ return null
+ }
+ }
+
+ private fun getString(e: Throwable): String {
+ return Log.getStackTraceString(e)
+ }
+}
diff --git a/app/src/main/java/com/pranav/java/ide/SettingActivity.java b/app/src/main/java/com/pranav/java/ide/SettingActivity.java
deleted file mode 100644
index d1feb92ad..000000000
--- a/app/src/main/java/com/pranav/java/ide/SettingActivity.java
+++ /dev/null
@@ -1,155 +0,0 @@
-package com.pranav.java.ide;
-
-import android.content.SharedPreferences;
-import android.os.Bundle;
-
-import androidx.appcompat.app.AppCompatActivity;
-import androidx.appcompat.widget.AppCompatEditText;
-import androidx.appcompat.widget.Toolbar;
-
-import com.google.android.material.radiobutton.MaterialRadioButton;
-
-public final class SettingActivity extends AppCompatActivity {
-
- private MaterialRadioButton java3;
- private MaterialRadioButton java4;
- private MaterialRadioButton java5;
- private MaterialRadioButton java6;
- private MaterialRadioButton java8;
- private MaterialRadioButton java9;
- private MaterialRadioButton java10;
- private MaterialRadioButton java11;
- private MaterialRadioButton java12;
- private MaterialRadioButton java13;
- private MaterialRadioButton java14;
- private MaterialRadioButton java15;
- private MaterialRadioButton java16;
- private MaterialRadioButton java17;
-
- private AppCompatEditText classpath;
-
- private SharedPreferences settings;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_setting);
-
- final Toolbar toolbar = findViewById(R.id.toolbar);
-
- setSupportActionBar(toolbar);
- getSupportActionBar().setDisplayHomeAsUpEnabled(true);
- getSupportActionBar().setHomeButtonEnabled(true);
- toolbar.setNavigationOnClickListener(v -> onBackPressed());
-
- java3 = findViewById(R.id.java3);
- java4 = findViewById(R.id.java4);
- java5 = findViewById(R.id.java5);
- java6 = findViewById(R.id.java6);
- java8 = findViewById(R.id.java8);
- java9 = findViewById(R.id.java9);
- java10 = findViewById(R.id.java10);
- java11 = findViewById(R.id.java11);
- java12 = findViewById(R.id.java12);
- java13 = findViewById(R.id.java13);
- java14 = findViewById(R.id.java14);
- java15 = findViewById(R.id.java15);
- java16 = findViewById(R.id.java16);
- java17 = findViewById(R.id.java17);
-
- final MaterialRadioButton java7 = findViewById(R.id.java7);
- classpath = findViewById(R.id.classpath);
- settings = getSharedPreferences("compiler_settings", MODE_PRIVATE);
-
- switch (settings.getString("javaVersion", "7.0")) {
-
- case "1.3":
- java3.setChecked(true);
- break;
-
- case "1.4":
- java4.setChecked(true);
- break;
-
- case "5.0":
- java5.setChecked(true);
- break;
-
- case "6.0":
- java6.setChecked(true);
- break;
-
- case "8.0":
- java8.setChecked(true);
- break;
-
- case "9.0":
- java9.setChecked(true);
- break;
-
- case "10.0":
- java10.setChecked(true);
- break;
-
- case "11.0":
- java11.setChecked(true);
- break;
-
- case "12.0":
- java12.setChecked(true);
- break;
-
- case "13.0":
- java13.setChecked(true);
- break;
-
- case "14.0":
- java14.setChecked(true);
- break;
-
- case "15.0":
- java15.setChecked(true);
- break;
-
- case "16.0":
- java16.setChecked(true);
- break;
-
- case "17.0":
- java17.setChecked(true);
- break;
-
- case "7.0":
- default:
- java7.setChecked(true);
- break;
- }
-
- classpath.setText(settings.getString("classpath", ""));
- }
-
- @Override
- public void onDestroy() {
- double version = 1.7;
-
- if (java3.isChecked()) version = 1.3;
- else if (java4.isChecked()) version = 1.4;
- else if (java5.isChecked()) version = 5.0;
- else if (java6.isChecked()) version = 6.0;
- else if (java8.isChecked()) version = 8.0;
- else if (java9.isChecked()) version = 9.0;
- else if (java10.isChecked()) version = 10.0;
- else if (java11.isChecked()) version = 11.0;
- else if (java12.isChecked()) version = 12.0;
- else if (java13.isChecked()) version = 13.0;
- else if (java14.isChecked()) version = 14.0;
- else if (java15.isChecked()) version = 15.0;
- else if (java16.isChecked()) version = 16.0;
- else if (java17.isChecked()) version = 17.0;
-
- settings.edit().putString("javaVersion", String.valueOf(version)).apply();
-
- settings.edit().putString("classpath", classpath.getText().toString()).apply();
- super.onDestroy();
- }
-}
diff --git a/app/src/main/java/com/pranav/java/ide/SettingActivity.kt b/app/src/main/java/com/pranav/java/ide/SettingActivity.kt
new file mode 100644
index 000000000..08a50ba7a
--- /dev/null
+++ b/app/src/main/java/com/pranav/java/ide/SettingActivity.kt
@@ -0,0 +1,125 @@
+package com.pranav.java.ide
+
+import android.content.SharedPreferences
+import android.os.Bundle
+
+import androidx.appcompat.app.AppCompatActivity
+import androidx.appcompat.widget.AppCompatEditText
+import androidx.appcompat.widget.Toolbar
+
+import com.google.android.material.radiobutton.MaterialRadioButton
+
+class SettingActivity : AppCompatActivity() {
+
+ lateinit var java3: MaterialRadioButton
+ lateinit var java4: MaterialRadioButton
+ lateinit var java5: MaterialRadioButton
+ lateinit var java6: MaterialRadioButton
+ lateinit var java8: MaterialRadioButton
+ lateinit var java9: MaterialRadioButton
+ lateinit var java10: MaterialRadioButton
+ lateinit var java11: MaterialRadioButton
+ lateinit var java12: MaterialRadioButton
+ lateinit var java13: MaterialRadioButton
+ lateinit var java14: MaterialRadioButton
+ lateinit var java15: MaterialRadioButton
+ lateinit var java16: MaterialRadioButton
+ lateinit var java17: MaterialRadioButton
+
+ lateinit var classpath: AppCompatEditText
+
+ lateinit var settings: SharedPreferences
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_setting)
+
+ val toolbar: Toolbar = findViewById(R.id.toolbar)
+
+ setSupportActionBar(toolbar)
+ getSupportActionBar()?.setDisplayHomeAsUpEnabled(true)
+ getSupportActionBar()?.setHomeButtonEnabled(true)
+ toolbar.setNavigationOnClickListener { _ ->
+ onBackPressed()
+ }
+
+ java3 = findViewById(R.id.java3)
+ java4 = findViewById(R.id.java4)
+ java5 = findViewById(R.id.java5)
+ java6 = findViewById(R.id.java6)
+ java8 = findViewById(R.id.java8)
+ java9 = findViewById(R.id.java9)
+ java10 = findViewById(R.id.java10)
+ java11 = findViewById(R.id.java11)
+ java12 = findViewById(R.id.java12)
+ java13 = findViewById(R.id.java13)
+ java14 = findViewById(R.id.java14)
+ java15 = findViewById(R.id.java15)
+ java16 = findViewById(R.id.java16)
+ java17 = findViewById(R.id.java17)
+
+ classpath = findViewById(R.id.classpath)
+
+ val java7: MaterialRadioButton = findViewById(R.id.java7)
+ settings = getSharedPreferences("compiler_settings", MODE_PRIVATE)
+
+ when (settings.getFloat("javaVersion", 7.0f)) {
+
+ 1.3f -> java3.setChecked(true)
+
+ 1.4f -> java4.setChecked(true)
+
+ 5.0f -> java5.setChecked(true)
+
+ 6.0f -> java6.setChecked(true)
+
+ 8.0f -> java8.setChecked(true)
+
+ 9.0f -> java9.setChecked(true)
+
+ 10.0f -> java10.setChecked(true)
+
+ 11.0f -> java11.setChecked(true)
+
+ 12.0f -> java12.setChecked(true)
+
+ 13.0f -> java13.setChecked(true)
+
+ 14.0f -> java14.setChecked(true)
+
+ 15.0f -> java15.setChecked(true)
+
+ 16.0f -> java16.setChecked(true)
+
+ 17.0f -> java17.setChecked(true)
+
+ else -> java7.setChecked(true)
+ }
+
+ classpath.setText(settings.getString("classpath", ""))
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ var version = 1.7f
+
+ if (java3.isChecked()) version = 1.3f
+ else if (java4.isChecked()) version = 1.4f
+ else if (java5.isChecked()) version = 5.0f
+ else if (java6.isChecked()) version = 6.0f
+ else if (java8.isChecked()) version = 8.0f
+ else if (java9.isChecked()) version = 9.0f
+ else if (java10.isChecked()) version = 10.0f
+ else if (java11.isChecked()) version = 11.0f
+ else if (java12.isChecked()) version = 12.0f
+ else if (java13.isChecked()) version = 13.0f
+ else if (java14.isChecked()) version = 14.0f
+ else if (java15.isChecked()) version = 15.0f
+ else if (java16.isChecked()) version = 16.0f
+ else if (java17.isChecked()) version = 17.0f
+
+ settings.edit().putFloat("javaVersion", version).apply()
+
+ settings.edit().putString("classpath", classpath.getText().toString()).apply()
+ }
+}
diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
index 2b068d114..c6aee64ec 100644
--- a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
+++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
@@ -1,30 +1,30 @@
-
-
-
-
-
-
-
-
-
+ xmlns:aapt="http://schemas.android.com/aapt"
+ android:width="108dp"
+ android:height="108dp"
+ android:viewportWidth="108"
+ android:viewportHeight="108">
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml
index 07d5da9cb..4e12b433a 100644
--- a/app/src/main/res/drawable/ic_launcher_background.xml
+++ b/app/src/main/res/drawable/ic_launcher_background.xml
@@ -1,170 +1,170 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ android:width="108dp"
+ android:height="108dp"
+ android:viewportWidth="108"
+ android:viewportHeight="108">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index fdb31e640..0ba5db7c9 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -4,6 +4,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
+
+
+
diff --git a/app/src/main/res/layout/activity_setting.xml b/app/src/main/res/layout/activity_setting.xml
index 3f0913ec3..63cbabd74 100644
--- a/app/src/main/res/layout/activity_setting.xml
+++ b/app/src/main/res/layout/activity_setting.xml
@@ -5,6 +5,7 @@
android:id="@+id/coordinator"
android:layout_width="match_parent"
android:layout_height="match_parent">
+
+
-
-
+
-
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
index eca70cfe5..65bd9d3e4 100644
--- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -1,5 +1,5 @@
-
-
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
index eca70cfe5..65bd9d3e4 100644
--- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -1,5 +1,5 @@
-
-
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values-night/themes.xml b/app/src/main/res/values-night/themes.xml
index 9565cde1c..f2b854ac7 100644
--- a/app/src/main/res/values-night/themes.xml
+++ b/app/src/main/res/values-night/themes.xml
@@ -1,16 +1,16 @@
-
-
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index f8c6127d3..d95bf93e8 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -1,10 +1,10 @@
- #FFBB86FC
- #FF6200EE
- #FF3700B3
- #FF03DAC5
- #FF018786
- #FF000000
- #FFFFFFFF
+ #FFBB86FC
+ #FF6200EE
+ #FF3700B3
+ #FF03DAC5
+ #FF018786
+ #FF000000
+ #FFFFFFFF
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 28a4581a3..14171904d 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1,14 +1,14 @@
- Java IDE
- Next
- Previous
-
-
- Run
- Smali
- Disassemble
- Smali2Java
-
-
- Java Version
+ Java IDE
+ Next
+ Previous
+
+
+ Run
+ Smali
+ Disassemble
+ Smali2Java
+
+
+ Java Version
\ No newline at end of file
diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml
index ffd4d71a1..539ffd2c6 100644
--- a/app/src/main/res/values/themes.xml
+++ b/app/src/main/res/values/themes.xml
@@ -1,25 +1,25 @@
-
-
+
+
-
+
-
+
-
+
\ No newline at end of file
diff --git a/app/src/test/java/com/pranav/java/ide/ExampleUnitTest.kt b/app/src/test/java/com/pranav/java/ide/ExampleUnitTest.kt
index e7c88ce2d..514509514 100644
--- a/app/src/test/java/com/pranav/java/ide/ExampleUnitTest.kt
+++ b/app/src/test/java/com/pranav/java/ide/ExampleUnitTest.kt
@@ -9,9 +9,9 @@ import org.junit.Test
* See [testing documentation](http://d.android.com/tools/testing).
*/
class ExampleUnitTest {
- @Test
- // Test if assert returns true.
- fun addition_isCorrect() {
- assertEquals(4, 2 + 2)
- }
+ @Test
+ // Test if assert returns true.
+ fun addition_isCorrect() {
+ assertEquals(4, 2 + 2)
+ }
}
diff --git a/build.gradle b/build.gradle
index 09a101b80..c0141e922 100644
--- a/build.gradle
+++ b/build.gradle
@@ -13,4 +13,4 @@ gradle.projectsEvaluated {
tasks.withType(JavaCompile) {
options.compilerArgs << "-Xlint:deprecation"
}
-}
+}
diff --git a/lib-android/build.gradle b/lib-android/build.gradle
index 3987cd0f9..885a7d4cc 100644
--- a/lib-android/build.gradle
+++ b/lib-android/build.gradle
@@ -1,17 +1,17 @@
plugins {
- id 'java-library'
- id 'org.jetbrains.kotlin.jvm'
+ id 'java-library'
+ id 'org.jetbrains.kotlin.jvm'
}
java {
- sourceCompatibility = JavaVersion.VERSION_11
- targetCompatibility = JavaVersion.VERSION_11
+ sourceCompatibility = JavaVersion.VERSION_11
+ targetCompatibility = JavaVersion.VERSION_11
}
dependencies {
- api 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.1'
- // r8 dependency
- implementation 'com.android.tools:r8:3.3.28'
- implementation project(path: ':lib-eclipse')
- compileOnly fileTree(dir: 'classpath', include: ['*.jar'])
+ api 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.1'
+ // r8 dependency
+ implementation 'com.android.tools:r8:3.3.28'
+ implementation project(path: ':lib-eclipse')
+ compileOnly fileTree(dir: 'classpath', include: ['*.jar'])
}
\ No newline at end of file
diff --git a/lib-android/src/main/java/com/pranav/lib_android/code/disassembler/ClassFileDisassembler.java b/lib-android/src/main/java/com/pranav/lib_android/code/disassembler/ClassFileDisassembler.java
deleted file mode 100644
index 3b7545fa8..000000000
--- a/lib-android/src/main/java/com/pranav/lib_android/code/disassembler/ClassFileDisassembler.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.pranav.lib_android.code.disassembler;
-
-import com.google.common.io.Files;
-
-import java.io.File;
-import java.io.IOException;
-
-import org.eclipse.jdt.internal.core.util.Disassembler;
-
-public class ClassFileDisassembler {
-
- final byte[] classFileBytes;
-
- public ClassFileDisassembler(String classFile) throws IOException {
- classFileBytes = Files.asByteSource(new File(classFile)).read();
- }
-
- public String disassemble() throws Throwable {
- return new Disassembler().disassemble(classFileBytes, System.lineSeparator());
- }
-}
diff --git a/lib-android/src/main/java/com/pranav/lib_android/code/disassembler/ClassFileDisassembler.kt b/lib-android/src/main/java/com/pranav/lib_android/code/disassembler/ClassFileDisassembler.kt
new file mode 100644
index 000000000..7682be371
--- /dev/null
+++ b/lib-android/src/main/java/com/pranav/lib_android/code/disassembler/ClassFileDisassembler.kt
@@ -0,0 +1,19 @@
+package com.pranav.lib_android.code.disassembler
+
+import java.io.File
+
+import org.eclipse.jdt.internal.core.util.Disassembler
+
+class ClassFileDisassembler(classFile: String) {
+
+ val classFileBytes: ByteArray
+
+ init {
+ classFileBytes = File(classFile).readBytes()
+ }
+
+ fun disassemble(): String {
+ return Disassembler()
+ .disassemble(classFileBytes, System.lineSeparator())
+ }
+}
diff --git a/lib-android/src/main/java/com/pranav/lib_android/code/formatter/Formatter.java b/lib-android/src/main/java/com/pranav/lib_android/code/formatter/Formatter.java
deleted file mode 100644
index 8d0d7cd30..000000000
--- a/lib-android/src/main/java/com/pranav/lib_android/code/formatter/Formatter.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package com.pranav.lib_android.code.formatter;
-
-import com.pranav.lib_android.util.ConcurrentUtilKt;
-import org.eclipse.jdt.internal.formatter.DefaultCodeFormatterOptions;
-import org.eclipse.jdt.internal.formatter.DefaultCodeFormatter;
-import org.eclipse.text.edits.TextEdit;
-import org.eclipse.jface.text.IDocument;
-import org.eclipse.jface.text.Document;
-
-public class Formatter {
-
- private String source;
-
- public Formatter(String source) {
- this.source = source;
- }
-
- public String format() {
- DefaultCodeFormatterOptions options = DefaultCodeFormatterOptions.getEclipseDefaultSettings();
-
- final DefaultCodeFormatter codeFormatter = new DefaultCodeFormatter(options);
-
- final TextEdit edit = codeFormatter.format(
- DefaultCodeFormatter.K_COMPILATION_UNIT,
- source,
- 0, // starting index
- source.length(), // length
- 0, // initial indentation
- System.lineSeparator() // line separator
- );
-
- final IDocument document = new Document(source);
- ConcurrentUtilKt.execute(() -> {
- try {
- edit.apply(document);
- } catch (Exception e) {
- throw new IllegalStateException(e);
- }
- });
- // return the formatted code
- return document.get();
- }
-}
diff --git a/lib-android/src/main/java/com/pranav/lib_android/code/formatter/Formatter.kt b/lib-android/src/main/java/com/pranav/lib_android/code/formatter/Formatter.kt
new file mode 100644
index 000000000..4526a4aa5
--- /dev/null
+++ b/lib-android/src/main/java/com/pranav/lib_android/code/formatter/Formatter.kt
@@ -0,0 +1,38 @@
+package com.pranav.lib_android.code.formatter
+
+import org.eclipse.jdt.internal.formatter.DefaultCodeFormatterOptions
+import org.eclipse.jdt.internal.formatter.DefaultCodeFormatter
+import org.eclipse.jface.text.Document
+
+class Formatter(javaSource: String) {
+
+ val source: String
+
+ init {
+ source = javaSource
+ }
+
+ fun format(): String {
+ val options = DefaultCodeFormatterOptions.getEclipseDefaultSettings()
+
+ val codeFormatter = DefaultCodeFormatter(options)
+
+ val edit = codeFormatter.format(
+ DefaultCodeFormatter.K_COMPILATION_UNIT,
+ source,
+ 0, // starting index
+ source.length, // length
+ 0, // initial indentation
+ System.lineSeparator() // line separator
+ )
+
+ val document = Document(source)
+ try {
+ edit.apply(document)
+ } catch (e: Exception) {
+ throw IllegalStateException(e)
+ }
+ // return the formatted code
+ return document.get()
+ }
+}
diff --git a/lib-android/src/main/java/com/pranav/lib_android/exception/CompilationFailedException.java b/lib-android/src/main/java/com/pranav/lib_android/exception/CompilationFailedException.java
deleted file mode 100644
index 39786319b..000000000
--- a/lib-android/src/main/java/com/pranav/lib_android/exception/CompilationFailedException.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.pranav.lib_android.exception;
-
-public class CompilationFailedException extends Exception {
-
- public CompilationFailedException(Throwable e) {
- super(e);
- }
-
- public CompilationFailedException(String message) {
- super(message);
- }
-}
diff --git a/lib-android/src/main/java/com/pranav/lib_android/exception/CompilationFailedException.kt b/lib-android/src/main/java/com/pranav/lib_android/exception/CompilationFailedException.kt
new file mode 100644
index 000000000..1f286f24e
--- /dev/null
+++ b/lib-android/src/main/java/com/pranav/lib_android/exception/CompilationFailedException.kt
@@ -0,0 +1,7 @@
+package com.pranav.lib_android.exception
+
+class CompilationFailedException : Throwable {
+ constructor(e: Throwable?): super(e)
+
+ constructor(message: String?): super(message)
+}
diff --git a/lib-android/src/main/java/com/pranav/lib_android/interfaces/Builder.java b/lib-android/src/main/java/com/pranav/lib_android/interfaces/Builder.java
deleted file mode 100644
index 2ee042bd1..000000000
--- a/lib-android/src/main/java/com/pranav/lib_android/interfaces/Builder.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.pranav.lib_android.interfaces;
-
-import android.content.Context;
-
-public abstract class Builder {
-
- public abstract Context getContext();
-
- public abstract ClassLoader getClassloader();
-}
diff --git a/lib-android/src/main/java/com/pranav/lib_android/interfaces/Builder.kt b/lib-android/src/main/java/com/pranav/lib_android/interfaces/Builder.kt
new file mode 100644
index 000000000..ba3c2b102
--- /dev/null
+++ b/lib-android/src/main/java/com/pranav/lib_android/interfaces/Builder.kt
@@ -0,0 +1,10 @@
+package com.pranav.lib_android.interfaces
+
+import android.content.Context
+
+abstract class Builder {
+
+ abstract fun getContext(): Context
+
+ abstract fun getClassloader(): ClassLoader
+}
diff --git a/lib-android/src/main/java/com/pranav/lib_android/interfaces/Task.java b/lib-android/src/main/java/com/pranav/lib_android/interfaces/Task.java
deleted file mode 100644
index f0f5c1aa4..000000000
--- a/lib-android/src/main/java/com/pranav/lib_android/interfaces/Task.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.pranav.lib_android.interfaces;
-
-public abstract class Task {
-
- public abstract String getTaskName();
-
- public abstract void doFullTask() throws Exception;
-}
diff --git a/lib-android/src/main/java/com/pranav/lib_android/interfaces/Task.kt b/lib-android/src/main/java/com/pranav/lib_android/interfaces/Task.kt
new file mode 100644
index 000000000..d32b1a971
--- /dev/null
+++ b/lib-android/src/main/java/com/pranav/lib_android/interfaces/Task.kt
@@ -0,0 +1,8 @@
+package com.pranav.lib_android.interfaces
+
+abstract class Task {
+
+ abstract fun getTaskName(): String
+
+ abstract fun doFullTask()
+}
diff --git a/lib-android/src/main/java/com/pranav/lib_android/task/JavaBuilder.java b/lib-android/src/main/java/com/pranav/lib_android/task/JavaBuilder.java
deleted file mode 100644
index 39d4c69f7..000000000
--- a/lib-android/src/main/java/com/pranav/lib_android/task/JavaBuilder.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.pranav.lib_android.task;
-
-import android.content.Context;
-import com.pranav.lib_android.interfaces.*;
-import com.pranav.lib_android.task.java.*;
-import java.util.ArrayList;
-
-public class JavaBuilder extends Builder {
-
- public final ClassLoader classloader;
-
- public Context mContext;
-
- public JavaBuilder(Context context, ClassLoader loader) {
- mContext = context;
- classloader = loader;
- }
-
- @Override
- public Context getContext() {
- return mContext;
- }
-
- @Override
- public ClassLoader getClassloader() {
- return this.classloader;
- }
-}
diff --git a/lib-android/src/main/java/com/pranav/lib_android/task/JavaBuilder.kt b/lib-android/src/main/java/com/pranav/lib_android/task/JavaBuilder.kt
new file mode 100644
index 000000000..5412a9414
--- /dev/null
+++ b/lib-android/src/main/java/com/pranav/lib_android/task/JavaBuilder.kt
@@ -0,0 +1,18 @@
+package com.pranav.lib_android.task
+
+import android.content.Context
+import com.pranav.lib_android.interfaces.Builder
+
+class JavaBuilder constructor(
+ val mContext: Context,
+ val classLoader: ClassLoader
+ ): Builder() {
+
+ override fun getContext(): Context {
+ return mContext
+ }
+
+ override fun getClassloader(): ClassLoader {
+ return classLoader
+ }
+}
diff --git a/lib-android/src/main/java/com/pranav/lib_android/task/java/CompileJavaTask.java b/lib-android/src/main/java/com/pranav/lib_android/task/java/CompileJavaTask.java
deleted file mode 100644
index cc5a8b5af..000000000
--- a/lib-android/src/main/java/com/pranav/lib_android/task/java/CompileJavaTask.java
+++ /dev/null
@@ -1,84 +0,0 @@
-package com.pranav.lib_android.task.java;
-
-import android.content.Context;
-import android.content.SharedPreferences;
-import com.pranav.lib_android.util.FileUtil;
-import com.pranav.lib_android.util.ConcurrentUtilKt;
-import com.pranav.lib_android.exception.CompilationFailedException;
-import com.pranav.lib_android.interfaces.*;
-import org.eclipse.jdt.internal.compiler.batch.Main;
-import java.io.File;
-import java.io.PrintWriter;
-import java.io.OutputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-
-public class CompileJavaTask extends Task {
-
- private final StringBuilder errs = new StringBuilder();
- private final SharedPreferences prefs;
-
- public CompileJavaTask(Builder builder) {
- prefs = builder.getContext().getSharedPreferences("compiler_settings",
- Context.MODE_PRIVATE);
- }
-
- @Override
- public String getTaskName() {
- return "Compile Java Task";
- }
-
- @Override
- public void doFullTask() throws Exception {
-
- PrintWriter writer = new PrintWriter(new OutputStream() {
- @Override
- public void write(int p1) throws IOException {
- errs.append((char) p1);
- }
- });
-
- final Main main = new Main(writer, writer, false, null, null);
-
- final File output = new File(FileUtil.getBinDir(), "classes");
-
- ConcurrentUtilKt.execute(() -> {
- final ArrayList args = new ArrayList<>();
-
- args.add("-log");
- args.add(FileUtil.getBinDir()
- .concat("debug.xml"));
- args.add("-g");
- args.add("-" + prefs.getString("javaVersion", "7.0"));
- args.add("-d");
- args.add(output.getAbsolutePath());
- args.add("-classpath");
- args.add(FileUtil.getClasspathDir()
- + "android.jar");
- StringBuilder classpath = new StringBuilder();
- if (prefs.getString("javaVersion", "7.0").equals("8.0")) {
- classpath.append(FileUtil.getClasspathDir()
- + "core-lambda-stubs.jar");
- }
- final String clspath = prefs.getString("classpath", "");
- if (!clspath.isEmpty() && classpath.length() > 0) {
- classpath.append(":");
- classpath.append(clspath);
- }
- if (classpath.length() > 0) {
- args.add("-cp");
- args.add(classpath.toString());
- }
- args.add("-proc:none");
- args.add("-sourcepath");
- args.add(" ");
- args.add(FileUtil.getJavaDir());
-
- main.compile(args.toArray(new String[0]));
- });
-
- if (main.globalErrorsCount > 0 | !output.exists()) {
- throw new CompilationFailedException(errs.toString());
- }
- }
-}
diff --git a/lib-android/src/main/java/com/pranav/lib_android/task/java/CompileJavaTask.kt b/lib-android/src/main/java/com/pranav/lib_android/task/java/CompileJavaTask.kt
new file mode 100644
index 000000000..ac9d6daef
--- /dev/null
+++ b/lib-android/src/main/java/com/pranav/lib_android/task/java/CompileJavaTask.kt
@@ -0,0 +1,85 @@
+package com.pranav.lib_android.task.java
+
+import android.content.Context
+import android.content.SharedPreferences
+import com.pranav.lib_android.util.FileUtil
+import com.pranav.lib_android.util.ConcurrentUtil
+import com.pranav.lib_android.exception.CompilationFailedException
+import com.pranav.lib_android.interfaces.*
+import org.eclipse.jdt.internal.compiler.batch.Main
+import java.io.File
+import java.io.PrintWriter
+import java.io.OutputStream
+import java.util.ArrayList
+
+class CompileJavaTask(
+ val builder: Builder
+ ): Task() {
+
+ val errs = StringBuilder()
+ var prefs: SharedPreferences
+
+ init {
+ prefs = builder.getContext().getSharedPreferences("compiler_settings",
+ Context.MODE_PRIVATE)
+ }
+
+ override fun getTaskName(): String {
+ return "Compile Java Task"
+ }
+
+ @Throws(CompilationFailedException::class)
+ override fun doFullTask() {
+ val writer = PrintWriter(
+ object : OutputStream() {
+ override fun write(p1: Int) {
+ errs.append(p1.toChar())
+ }
+ }
+ )
+
+ val main = Main(writer, writer, false, null, null)
+
+ val output = File(FileUtil.getBinDir(), "classes")
+
+ ConcurrentUtil.execute {
+ val version = prefs.getFloat("javaVersion", 7.0f)
+ val args = ArrayList()
+
+ args.add("-log")
+ args.add(FileUtil.getBinDir()
+ .plus("debug.xml"))
+ args.add("-g")
+ args.add("-" + version.toString())
+ args.add("-d")
+ args.add(output.getAbsolutePath())
+ args.add("-classpath")
+ args.add(FileUtil.getClasspathDir()
+ .plus("android.jar"))
+ val classpath = StringBuilder()
+ if (version >= 8.0) {
+ classpath.append(FileUtil.getClasspathDir()
+ + "core-lambda-stubs.jar")
+ }
+ val clspath: String? = prefs.getString("classpath", "")
+ if (clspath!!.length > 0 && classpath.length > 0) {
+ classpath.append(":")
+ classpath.append(clspath)
+ }
+ if (classpath.length > 0) {
+ args.add("-cp")
+ args.add(classpath.toString())
+ }
+ args.add("-proc:none")
+ args.add("-sourcepath")
+ args.add(" ")
+ args.add(FileUtil.getJavaDir())
+
+ main.compile(args.toTypedArray())
+ }
+
+ if (main.globalErrorsCount > 0 || !output.exists()) {
+ throw CompilationFailedException(errs.toString())
+ }
+ }
+}
diff --git a/lib-android/src/main/java/com/pranav/lib_android/task/java/D8Task.java b/lib-android/src/main/java/com/pranav/lib_android/task/java/D8Task.java
deleted file mode 100644
index 8500c2a76..000000000
--- a/lib-android/src/main/java/com/pranav/lib_android/task/java/D8Task.java
+++ /dev/null
@@ -1,66 +0,0 @@
-package com.pranav.lib_android.task.java;
-
-import com.pranav.lib_android.util.FileUtil;
-import com.pranav.lib_android.util.ConcurrentUtilKt;
-import com.pranav.lib_android.interfaces.*;
-import com.android.tools.r8.D8;
-import com.android.tools.r8.D8Command;
-import com.android.tools.r8.OutputMode;
-import java.util.List;
-import java.util.ArrayList;
-import java.io.File;
-import java.io.PrintStream;
-import java.io.OutputStream;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-
-public class D8Task extends Task {
-
- private Exception ex = null;
-
- @Override
- public void doFullTask() throws Exception {
- ConcurrentUtilKt.execute(() -> {
- try {
- D8.run(
- D8Command.builder()
- .setOutput(Paths.get(FileUtil.getBinDir()), OutputMode.DexIndexed)
- .addLibraryFiles(Paths.get(FileUtil.getClasspathDir(), "android.jar"))
- .addProgramFiles(
- getClassFiles(
- new File(FileUtil.getBinDir(), "classes")
- )
- )
- .build()
- );
-
- } catch (Exception e) {
- ex = e;
- }
- });
- if (ex != null) {
- throw ex;
- }
- }
-
- private List getClassFiles(File root) {
- List paths = new ArrayList<>();
-
- File[] files = root.listFiles();
- if (files != null) {
- for (File f : files) {
- if (f.isFile()) {
- paths.add(f.toPath());
- } else {
- paths.addAll(getClassFiles(f));
- }
- }
- }
- return paths;
- }
-
- @Override
- public String getTaskName() {
- return "D8 Task";
- }
-}
diff --git a/lib-android/src/main/java/com/pranav/lib_android/task/java/D8Task.kt b/lib-android/src/main/java/com/pranav/lib_android/task/java/D8Task.kt
new file mode 100644
index 000000000..783597d3e
--- /dev/null
+++ b/lib-android/src/main/java/com/pranav/lib_android/task/java/D8Task.kt
@@ -0,0 +1,51 @@
+package com.pranav.lib_android.task.java
+
+import com.pranav.lib_android.util.FileUtil
+import com.pranav.lib_android.util.ConcurrentUtil
+import com.pranav.lib_android.interfaces.Task
+import com.android.tools.r8.D8
+import com.android.tools.r8.D8Command
+import com.android.tools.r8.OutputMode
+import java.util.ArrayList
+import java.io.File
+import java.nio.file.Path
+import java.nio.file.Paths
+
+class D8Task : Task() {
+
+ @Throws(Throwable::class)
+ override fun doFullTask() {
+ ConcurrentUtil.execute {
+ D8.run(
+ D8Command.builder()
+ .setOutput(Paths.get(FileUtil.getBinDir()), OutputMode.DexIndexed)
+ .addLibraryFiles(Paths.get(FileUtil.getClasspathDir(), "android.jar"))
+ .addProgramFiles(
+ getClassFiles(
+ File(FileUtil.getBinDir(), "classes")
+ )
+ )
+ .build()
+ )
+ }
+ }
+
+ private fun getClassFiles(root: File): List {
+ val paths = ArrayList()
+ val files = root.listFiles()
+ if (files != null) {
+ for (file in files) {
+ if (file.isFile()) {
+ paths.add(file.toPath())
+ } else {
+ paths.addAll(getClassFiles(file))
+ }
+ }
+ }
+ return paths.toList()
+ }
+
+ override fun getTaskName(): String {
+ return "D8 Task"
+ }
+}
diff --git a/lib-android/src/main/java/com/pranav/lib_android/task/java/ExecuteJavaTask.java b/lib-android/src/main/java/com/pranav/lib_android/task/java/ExecuteJavaTask.java
deleted file mode 100644
index 2fdcb3ce5..000000000
--- a/lib-android/src/main/java/com/pranav/lib_android/task/java/ExecuteJavaTask.java
+++ /dev/null
@@ -1,79 +0,0 @@
-package com.pranav.lib_android.task.java;
-
-import com.pranav.lib_android.interfaces.*;
-import com.pranav.lib_android.util.FileUtil;
-import com.pranav.lib_android.util.ConcurrentUtilKt;
-import dalvik.system.PathClassLoader;
-import java.io.PrintStream;
-import java.io.OutputStream;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-
-public class ExecuteJavaTask extends Task {
-
- private final Builder mBuilder;
- private final String clazz;
- private Object result;
- public StringBuilder log = new StringBuilder();
-
- public ExecuteJavaTask(Builder builder, String claz) {
- this.mBuilder = builder;
- this.clazz = claz;
- }
-
- @Override
- public String getTaskName() {
- return "Execute java Task";
- }
-
- @Override
- public void doFullTask() throws Exception {
- final PrintStream defaultOut = System.out;
- final PrintStream defaultErr = System.err;
- final String dexFile = FileUtil.getBinDir() + "classes.dex";
- ConcurrentUtilKt.execute(() -> {
- final OutputStream out = new OutputStream() {
- @Override
- public void write(int b) {
- log.append((char) b);
- }
-
- @Override
- public String toString() {
- return log.toString();
- }
- };
- System.setOut(new PrintStream(out));
- System.setErr(new PrintStream(out));
-
- PathClassLoader loader = new PathClassLoader(dexFile,
- mBuilder.getClassloader());
- try {
-
- Class calledClass = loader.loadClass(clazz);
-
- Method method = calledClass.getDeclaredMethod("main", String[].class);
-
- String[] param = {};
-
- if (Modifier.isStatic(method.getModifiers())) {
- result = method.invoke(null, new Object[] {param});
- } else if (Modifier.isPublic(method.getModifiers())) {
- Object classInstance = calledClass.newInstance();
- result = method.invoke(classInstance, new Object[] {param});
- }
- if (result != null) {
- System.out.println(result.toString());
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- System.setOut(defaultOut);
- System.setErr(defaultErr);
- });
- }
-
- public String getLogs() {
- return log.toString();
- }
-}
\ No newline at end of file
diff --git a/lib-android/src/main/java/com/pranav/lib_android/task/java/ExecuteJavaTask.kt b/lib-android/src/main/java/com/pranav/lib_android/task/java/ExecuteJavaTask.kt
new file mode 100644
index 000000000..4fd92f55c
--- /dev/null
+++ b/lib-android/src/main/java/com/pranav/lib_android/task/java/ExecuteJavaTask.kt
@@ -0,0 +1,77 @@
+package com.pranav.lib_android.task.java
+
+import com.pranav.lib_android.interfaces.*
+import com.pranav.lib_android.util.FileUtil
+import com.pranav.lib_android.util.ConcurrentUtil
+import dalvik.system.PathClassLoader
+import java.io.PrintStream
+import java.io.OutputStream
+import java.lang.reflect.Modifier
+import java.lang.reflect.InvocationTargetException
+
+class ExecuteJavaTask constructor(
+ val mBuilder: Builder,
+ val clazz: String
+ ): Task() {
+
+ var result: Any? = null
+ val log = StringBuilder()
+
+ override fun getTaskName(): String {
+ return "Execute java Task"
+ }
+
+ @Throws(InvocationTargetException::class)
+ override fun doFullTask() {
+ val defaultOut = System.`out`
+ val defaultErr = System.err
+ val dexFile = FileUtil.getBinDir() + "classes.dex"
+ ConcurrentUtil.execute {
+ val out = object: OutputStream() {
+ override fun write(b: Int) {
+ log.append(b.toChar())
+ }
+
+ override fun toString(): String {
+ return log.toString()
+ }
+ }
+ System.setOut(PrintStream(`out`))
+ System.setErr(PrintStream(`out`))
+
+ val loader = PathClassLoader(dexFile, mBuilder.getClassloader())
+ try {
+
+ val calledClass = loader.loadClass(clazz)
+
+ val method = calledClass.getDeclaredMethod("main", Array::class.java)
+
+ var param = arrayOf()
+
+ if (Modifier.isStatic(method.getModifiers())) {
+ val res = method.invoke(null, param as? Any)
+ if (res !is Unit) {
+ result = res
+ }
+ } else if (Modifier.isPublic(method.getModifiers())) {
+ val classInstance = calledClass.newInstance()
+ val res = method.invoke(classInstance, param as? Any)
+ if (res !is Unit) {
+ result = res
+ }
+ }
+ if (result != null) {
+ log.append(result.toString())
+ }
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ System.setOut(defaultOut)
+ System.setErr(defaultErr)
+ }
+ }
+
+ fun getLogs(): String {
+ return log.toString()
+ }
+}
diff --git a/lib-android/src/main/java/com/pranav/lib_android/task/java/JarTask.java b/lib-android/src/main/java/com/pranav/lib_android/task/java/JarTask.java
deleted file mode 100644
index 96b36d3ff..000000000
--- a/lib-android/src/main/java/com/pranav/lib_android/task/java/JarTask.java
+++ /dev/null
@@ -1,95 +0,0 @@
-package com.pranav.lib_android.task.java;
-
-import com.pranav.lib_android.util.FileUtil;
-import com.pranav.lib_android.interfaces.*;
-import java.io.BufferedInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.jar.Attributes;
-import java.util.jar.JarEntry;
-import java.util.jar.JarOutputStream;
-import java.util.jar.Manifest;
-
-public class JarTask extends Task {
-
- @Override
- public void doFullTask() throws Exception {
-
- //input file
- File classesFolder = new File(FileUtil.getBinDir() + "classes");
-
- // Open archive file
- FileOutputStream stream = new FileOutputStream(new File(FileUtil.getBinDir() + "classes.jar"));
-
- Manifest manifest = buildManifest();
-
- //Create the jar file
- JarOutputStream out = new JarOutputStream(stream, manifest);
-
- //Add the files..
- if (classesFolder.listFiles() != null) {
- for (File clazz : classesFolder.listFiles()) {
- add(classesFolder.getPath(), clazz, out);
- }
- }
-
- out.close();
- stream.close();
- }
-
- @Override
- public String getTaskName() {
- return "JarTask";
- }
-
- private Manifest buildManifest() {
- Manifest manifest = new Manifest();
- manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
- return manifest;
- }
-
- private void add(String parentPath, File source, JarOutputStream target) throws IOException {
- String name = source.getPath().substring(parentPath.length() + 1);
-
- BufferedInputStream in = null;
- try {
- if (source.isDirectory()) {
- if (!name.isEmpty()) {
- if (!name.endsWith("/"))
- name += "/";
-
- //Add the Entry
- JarEntry entry = new JarEntry(name);
- entry.setTime(source.lastModified());
- target.putNextEntry(entry);
- target.closeEntry();
- }
-
- for (File nestedFile : source.listFiles()) {
- add(parentPath, nestedFile, target);
- }
- return;
- }
-
- JarEntry entry = new JarEntry(name);
- entry.setTime(source.lastModified());
- target.putNextEntry(entry);
- in = new BufferedInputStream(new FileInputStream(source));
- byte[] buffer = new byte[1024];
- while (true) {
- int count = in.read(buffer);
- if (count == -1)
- break;
- target.write(buffer, 0, count);
- }
- target.closeEntry();
-
- } finally {
- if (in != null) {
- in.close();
- }
- }
- }
-}
diff --git a/lib-android/src/main/java/com/pranav/lib_android/util/BinaryExecutor.java b/lib-android/src/main/java/com/pranav/lib_android/util/BinaryExecutor.java
deleted file mode 100644
index 5ebfb0857..000000000
--- a/lib-android/src/main/java/com/pranav/lib_android/util/BinaryExecutor.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package com.pranav.lib_android.util;
-
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.util.ArrayList;
-import java.util.Scanner;
-
-public class BinaryExecutor {
-
- private final ProcessBuilder mProcess = new ProcessBuilder();
- private final StringWriter mWriter = new StringWriter();
-
- public String execute(ArrayList arrayList) {
- mProcess.command(arrayList);
- try {
- Process process = mProcess.start();
- Scanner scanner = new Scanner(process.getErrorStream());
- while (scanner.hasNextLine()) {
- mWriter.append(scanner.nextLine());
- mWriter.append(System.lineSeparator());
- }
-
- process.waitFor();
- } catch (Exception e) {
- e.printStackTrace(new PrintWriter(mWriter));
- }
- return mWriter.toString();
- }
-
- public String execute(String command) {
- mProcess.command(command);
- try {
- Process process = mProcess.start();
- Scanner scanner = new Scanner(process.getErrorStream());
- while (scanner.hasNextLine()) {
- mWriter.append(scanner.nextLine());
- mWriter.append(System.lineSeparator());
- }
-
- process.waitFor();
- } catch (Exception e) {
- e.printStackTrace(new PrintWriter(mWriter));
- }
- return mWriter.toString();
- }
-
- public String getLogs() {
- return mWriter.toString();
- }
-
- public void clear() {
- mWriter.flush();
- }
-}
diff --git a/lib-android/src/main/java/com/pranav/lib_android/util/BinaryExecutor.kt b/lib-android/src/main/java/com/pranav/lib_android/util/BinaryExecutor.kt
new file mode 100644
index 000000000..ff1feae4e
--- /dev/null
+++ b/lib-android/src/main/java/com/pranav/lib_android/util/BinaryExecutor.kt
@@ -0,0 +1,52 @@
+package com.pranav.lib_android.util
+
+import java.io.PrintWriter
+import java.io.StringWriter
+import java.util.ArrayList
+import java.util.Scanner
+
+class BinaryExecutor {
+
+ var mProcess = ProcessBuilder()
+ var mWriter = StringWriter()
+
+ fun execute(arrayList: ArrayList): String {
+ mProcess.command(arrayList)
+ try {
+ val process = mProcess.start()
+ val scanner = Scanner(process.getErrorStream())
+ while (scanner.hasNextLine()) {
+ mWriter.append(scanner.nextLine())
+ mWriter.append(System.lineSeparator())
+ }
+
+ process.waitFor()
+ } catch (e: Exception) {
+ e.printStackTrace(PrintWriter(mWriter))
+ }
+ return mWriter.toString()
+ }
+
+ fun execute(command: String): String {
+ mProcess.command(command)
+ try {
+ val process = mProcess.start()
+ val scanner = Scanner(process.getErrorStream())
+ while (scanner.hasNextLine()) {
+ mWriter.append(scanner.nextLine())
+ mWriter.append(System.lineSeparator())
+ }
+
+ process.waitFor()
+ } catch (e: Exception) {
+ e.printStackTrace(PrintWriter(mWriter))
+ }
+ return mWriter.toString()
+ }
+
+ fun getLogs(): String = mWriter.toString()
+
+ fun clear() {
+ mWriter.flush()
+ }
+}
diff --git a/lib-android/src/main/java/com/pranav/lib_android/util/ConcurrentUtil.kt b/lib-android/src/main/java/com/pranav/lib_android/util/ConcurrentUtil.kt
index cc2655aac..4899f6764 100644
--- a/lib-android/src/main/java/com/pranav/lib_android/util/ConcurrentUtil.kt
+++ b/lib-android/src/main/java/com/pranav/lib_android/util/ConcurrentUtil.kt
@@ -2,15 +2,21 @@ package com.pranav.lib_android.util
import kotlinx.coroutines.*
-fun execute(runnable: Runnable) = runBlocking {
- val deferred: Deferred = async {
- runnable.run()
- }
- deferred.await()
-}
+class ConcurrentUtil {
+ companion object {
+ @JvmStatic
+ fun execute(runnable: Runnable) = runBlocking {
+ val deferred: Deferred = async {
+ runnable.run()
+ }
+ deferred.await()
+ }
-fun executeInBackground(runnable: Runnable) = runBlocking {
- launch {
- runnable.run()
+ @JvmStatic
+ fun executeInBackground(runnable: Runnable) = runBlocking {
+ launch {
+ runnable.run()
+ }
+ }
}
}
diff --git a/lib-android/src/main/java/com/pranav/lib_android/util/FileUtil.java b/lib-android/src/main/java/com/pranav/lib_android/util/FileUtil.java
deleted file mode 100644
index 01d51bff6..000000000
--- a/lib-android/src/main/java/com/pranav/lib_android/util/FileUtil.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package com.pranav.lib_android.util;
-
-import android.content.Context;
-
-import java.io.File;
-
-public class FileUtil {
-
- private static Context mContext;
-
- public static void initializeContext(Context context) {
- mContext = context;
- }
- public static void deleteFile(String path) {
- File file = new File(path);
-
- if (!file.exists())
- return;
-
- if (file.isFile()) {
- file.delete();
- return;
- }
-
- File[] fileArr = file.listFiles();
-
- if (fileArr != null) {
- for (File subFile : fileArr) {
- if (subFile.isDirectory()) {
- deleteFile(subFile.getAbsolutePath());
- }
-
- if (subFile.isFile()) {
- subFile.delete();
- }
- }
- }
-
- file.delete();
- }
-
- private static String getDataDir() {
- return mContext.getExternalFilesDir(null).getAbsolutePath();
- }
-
- public static String getJavaDir() {
- return getDataDir() + "/java/";
- }
-
- public static String getBinDir() {
- return getDataDir() + "/bin/";
- }
-
- public static String getClasspathDir() {
- return getDataDir() + "/classpath/";
- }
-}
diff --git a/lib-android/src/main/java/com/pranav/lib_android/util/FileUtil.kt b/lib-android/src/main/java/com/pranav/lib_android/util/FileUtil.kt
new file mode 100644
index 000000000..a97a5b4db
--- /dev/null
+++ b/lib-android/src/main/java/com/pranav/lib_android/util/FileUtil.kt
@@ -0,0 +1,42 @@
+package com.pranav.lib_android.util
+
+import android.content.Context
+
+import java.io.File
+
+class FileUtil {
+
+ companion object {
+ lateinit var mContext: Context
+
+ @JvmStatic
+ fun initializeContext(context: Context) {
+ mContext = context
+ }
+
+ @JvmStatic
+ fun deleteFile(path: String) {
+ File(path).deleteRecursively()
+ }
+
+ @JvmStatic
+ fun getDataDir(): String? {
+ return mContext.getExternalFilesDir(null)?.getAbsolutePath()
+ }
+
+ @JvmStatic
+ fun getJavaDir(): String {
+ return getDataDir() + "/java/"
+ }
+
+ @JvmStatic
+ fun getBinDir(): String {
+ return getDataDir() + "/bin/"
+ }
+
+ @JvmStatic
+ fun getClasspathDir(): String {
+ return getDataDir() + "/classpath/"
+ }
+ }
+}
diff --git a/lib-android/src/main/java/com/pranav/lib_android/util/ZipUtil.java b/lib-android/src/main/java/com/pranav/lib_android/util/ZipUtil.java
deleted file mode 100644
index ed5c60b0d..000000000
--- a/lib-android/src/main/java/com/pranav/lib_android/util/ZipUtil.java
+++ /dev/null
@@ -1,83 +0,0 @@
-package com.pranav.lib_android.util;
-
-import android.content.Context;
-import android.util.Log;
-
-import com.google.common.io.ByteStreams;
-import com.google.common.io.Files;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipInputStream;
-
-public class ZipUtil {
- private static final int BUFFER_SIZE = 1024 * 10;
- private static final String TAG = "ZipUtil";
-
- public static void unzipFromAssets(Context context, String zipFile,
- String destination) {
- try {
- InputStream stream = context.getAssets().open(zipFile);
- unzip(stream, destination);
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
-
- private static void unzip(InputStream stream, String destination) {
- dirChecker(destination, "");
- byte[] buffer = new byte[BUFFER_SIZE];
- try {
- ZipInputStream zin = new ZipInputStream(stream);
- ZipEntry ze = null;
-
- while ((ze = zin.getNextEntry()) != null) {
- Log.v(TAG, "Unzipping " + ze.getName());
-
- if (ze.isDirectory()) {
- dirChecker(destination, ze.getName());
- } else {
- File f = new File(destination, ze.getName());
- if (!f.toPath().normalize().startsWith(destination))
- throw new SecurityException("Potentially harmful files detected inside zip");
- if (!f.exists()) {
- boolean success = f.createNewFile();
- if (!success) {
- Log.w(TAG, "Failed to create file " + f.getName());
- continue;
- }
- FileOutputStream fout = new FileOutputStream(f);
- int count;
- while ((count = zin.read(buffer)) != -1) {
- fout.write(buffer, 0, count);
- }
- zin.closeEntry();
- fout.close();
- }
- }
- }
- zin.close();
- } catch (IOException e) {
- Log.e(TAG, "unzip", e);
- }
- }
-
- private static void dirChecker(String destination, String dir) {
- File f = new File(destination, dir);
-
- if (!f.isDirectory() && !f.mkdirs()) {
- Log.w(TAG, "Failed to create folder " + f.getName());
- }
- }
-
-
- public static void copyFileFromAssets(Context context, String inputFile, String fileName) throws IOException {
- final InputStream in = context.getAssets().open(inputFile);
- final String outputPath = context.getFilesDir() + "/" + fileName;
- final File out = new File(outputPath);
- Files.write(ByteStreams.toByteArray(in), out);
- }
-}
diff --git a/lib-android/src/main/java/com/pranav/lib_android/util/ZipUtil.kt b/lib-android/src/main/java/com/pranav/lib_android/util/ZipUtil.kt
new file mode 100644
index 000000000..f8a8ea073
--- /dev/null
+++ b/lib-android/src/main/java/com/pranav/lib_android/util/ZipUtil.kt
@@ -0,0 +1,67 @@
+package com.pranav.lib_android.util
+
+import android.content.Context
+import android.util.Log
+
+import java.io.File
+import java.io.FileOutputStream
+import java.io.IOException
+import java.io.InputStream
+import java.util.zip.ZipEntry
+import java.util.zip.ZipInputStream
+
+class ZipUtil {
+ companion object {
+ private val TAG = "ZipUtil"
+
+ @JvmStatic
+ fun unzipFromAssets(context: Context, zipFile: String, destination: String) {
+ try {
+ val stream = context.getAssets().`open`(zipFile)
+ unzip(stream, destination)
+ } catch (e: IOException) {
+ e.printStackTrace()
+ }
+ }
+
+ private fun unzip(stream: InputStream, destination: String) {
+ dirChecker(destination, "")
+ try {
+ val zin = ZipInputStream(stream)
+ var ze: ZipEntry? = zin.getNextEntry()
+
+ label@ while (ze != null) {
+ if (ze.isDirectory()) {
+ dirChecker(destination, ze.getName())
+ } else {
+ val f = File(destination, ze.getName())
+ if (!f.normalize().startsWith(destination))
+ throw SecurityException("Potentially harmful files detected inside zip")
+ if (!f.exists()) {
+ val success = f.createNewFile()
+ if (!success) continue@label
+ f.appendBytes(zin.readBytes())
+ zin.closeEntry()
+ }
+ }
+ try {
+ ze = zin.getNextEntry()
+ } catch (e: NullPointerException) {
+ ze = null
+ }
+ }
+ zin.close()
+ } catch (e: IOException) {
+ Log.e(TAG, "Unzip", e)
+ }
+ }
+
+ private fun dirChecker(destination: String, dir: String) {
+ val f = File(destination, dir)
+
+ if (!f.isDirectory() && !f.mkdirs()) {
+ Log.w(TAG, "Failed to create folder " + f.getName())
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/lib-eclipse/build.gradle b/lib-eclipse/build.gradle
index 454ff057a..c47dfac3d 100644
--- a/lib-eclipse/build.gradle
+++ b/lib-eclipse/build.gradle
@@ -1,20 +1,20 @@
plugins {
- id 'java-library'
+ id 'java-library'
}
java {
- sourceCompatibility = JavaVersion.VERSION_11
- targetCompatibility = JavaVersion.VERSION_11
+ sourceCompatibility = JavaVersion.VERSION_11
+ targetCompatibility = JavaVersion.VERSION_11
}
dependencies {
- api 'com.google.guava:guava:31.1-android'
+ api 'com.google.guava:guava:31.1-android'
- api 'org.eclipse.platform:org.eclipse.core.resources:3.16.100'
- api 'org.eclipse.platform:org.eclipse.core.runtime:3.24.100'
- api 'org.eclipse.platform:org.eclipse.core.filesystem:1.9.300'
- api 'org.eclipse.platform:org.eclipse.text:3.12.0'
+ api 'org.eclipse.platform:org.eclipse.core.resources:3.16.100'
+ api 'org.eclipse.platform:org.eclipse.core.runtime:3.24.100'
+ api 'org.eclipse.platform:org.eclipse.core.filesystem:1.9.300'
+ api 'org.eclipse.platform:org.eclipse.text:3.12.0'
- implementation 'com.zeoflow:jx:1.2.1' // javax classes
- api fileTree(dir: 'libs', include: ['*.jar'])
+ implementation 'com.zeoflow:jx:1.2.1' // javax classes
+ api fileTree(dir: 'libs', include: ['*.jar'])
}
\ No newline at end of file