From c93c27fcaad71690d4ebe4004ae4cc49bd6483a7 Mon Sep 17 00:00:00 2001 From: hyb1996 <946994919@qq.com> Date: Wed, 24 Jan 2018 17:29:25 +0800 Subject: [PATCH] feat: build apk from project(dir) support --- app/release/output.json | 2 +- .../autojs/build/AutoJsApkBuilder.java | 57 +++++++- .../scriptdroid/ui/build/BuildActivity.java | 24 +++- .../ui/main/scripts/ScriptListView.java | 8 ++ app/src/main/res/menu/menu_dir_options.xml | 4 + app/src/main/res/menu/menu_script_options.xml | 4 + app/src/main/res/values/strings.xml | 2 +- .../stardust/autojs/engine/ScriptEngine.java | 2 + .../autojs/project/ProjectConfig.java | 136 ++++++++++++++++++ .../main/java/com/stardust/pio/PFiles.java | 29 ++++ inrt/src/main/AndroidManifest.xml | 2 +- inrt/src/main/assets/project/auto.js.png | Bin 0 -> 9006 bytes inrt/src/main/assets/project/main.js | 32 +++++ inrt/src/main/assets/project/project.json | 10 ++ inrt/src/main/assets/script.js | 2 - .../java/com/stardust/auojs/inrt/App.java | 5 +- .../com/stardust/auojs/inrt/MainActivity.java | 15 +- .../{rt => autojs}/AccessibilityService.java | 2 +- .../AccessibilityServiceTool.java | 2 +- .../auojs/inrt/{rt => autojs}/AutoJs.java | 4 +- .../{rt => autojs}/GlobalKeyObserver.java | 2 +- .../inrt/launch/AssetsProjectLauncher.java | 55 +++++++ 22 files changed, 365 insertions(+), 34 deletions(-) create mode 100644 autojs/src/main/java/com/stardust/autojs/project/ProjectConfig.java create mode 100644 inrt/src/main/assets/project/auto.js.png create mode 100644 inrt/src/main/assets/project/main.js create mode 100644 inrt/src/main/assets/project/project.json delete mode 100644 inrt/src/main/assets/script.js rename inrt/src/main/java/com/stardust/auojs/inrt/{rt => autojs}/AccessibilityService.java (94%) rename inrt/src/main/java/com/stardust/auojs/inrt/{rt => autojs}/AccessibilityServiceTool.java (97%) rename inrt/src/main/java/com/stardust/auojs/inrt/{rt => autojs}/AutoJs.java (94%) rename inrt/src/main/java/com/stardust/auojs/inrt/{rt => autojs}/GlobalKeyObserver.java (98%) create mode 100644 inrt/src/main/java/com/stardust/auojs/inrt/launch/AssetsProjectLauncher.java diff --git a/app/release/output.json b/app/release/output.json index b3b1532c..aaa06e73 100644 --- a/app/release/output.json +++ b/app/release/output.json @@ -1 +1 @@ -[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":240},"path":"release-3.0.0 Alpha40.apk","properties":{"packageId":"com.stardust.scriptdroid","split":"","minSdkVersion":"17"}}] \ No newline at end of file +[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":34},"path":"inrt-release.apk","properties":{"packageId":"com.stardust.auojs.inrt","split":"","minSdkVersion":"17"}}] \ No newline at end of file diff --git a/app/src/main/java/com/stardust/scriptdroid/autojs/build/AutoJsApkBuilder.java b/app/src/main/java/com/stardust/scriptdroid/autojs/build/AutoJsApkBuilder.java index 470bd398..37e82072 100644 --- a/app/src/main/java/com/stardust/scriptdroid/autojs/build/AutoJsApkBuilder.java +++ b/app/src/main/java/com/stardust/scriptdroid/autojs/build/AutoJsApkBuilder.java @@ -1,15 +1,14 @@ package com.stardust.scriptdroid.autojs.build; import android.graphics.Bitmap; -import android.graphics.BitmapFactory; import com.stardust.autojs.apkbuilder.ApkBuilder; import com.stardust.autojs.apkbuilder.ManifestEditor; import com.stardust.autojs.apkbuilder.util.StreamUtils; +import com.stardust.autojs.project.ProjectConfig; +import com.stardust.pio.PFiles; import com.stardust.scriptdroid.App; -import org.androidannotations.annotations.Click; - import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; @@ -105,10 +104,28 @@ public class AutoJsApkBuilder extends ApkBuilder { } public AutoJsApkBuilder setScriptFile(String path) throws IOException { - replaceFile("assets/script.js", path); + if (PFiles.isDir(path)) { + copyDir("assets/project/", path); + } else { + replaceFile("assets/project/main.js", path); + } return this; } + public void copyDir(String relativePath, String path) throws IOException { + File fromDir = new File(path); + File toDir = new File(this.mWorkspacePath, relativePath); + toDir.mkdir(); + for (File child : fromDir.listFiles()) { + if (child.isFile()) { + StreamUtils.write(new FileInputStream(child), + new FileOutputStream(new File(toDir, child.getName()))); + } else { + copyDir(PFiles.join(relativePath, child.getName() + "/"), child.getPath()); + } + } + } + @Override public ApkBuilder replaceFile(String relativePath, String newFilePath) throws IOException { StreamUtils.write(new FileInputStream(newFilePath), new FileOutputStream(new File(this.mWorkspacePath, relativePath))); @@ -123,10 +140,42 @@ public class AutoJsApkBuilder extends ApkBuilder { .setVersionCode(config.versionCode) .setPackageName(config.packageName); setArscPackageName(config.packageName); + updateProjectConfig(config); setScriptFile(config.jsPath); return this; } + private void updateProjectConfig(AppConfig config) { + if (!PFiles.isDir(config.jsPath)) { + return; + } + ProjectConfig projectConfig = ProjectConfig.fromProjectDir(config.jsPath); + if (projectConfig == null) + projectConfig = new ProjectConfig(); + projectConfig.setName(config.appName) + .setPackageName(config.packageName) + .setVersionCode(config.versionCode) + .setVersionName(config.versionName) + .setMainScriptFile("main.js"); + updateProjectConfigAssets(projectConfig, config.jsPath, config.jsPath); + PFiles.write(ProjectConfig.configFileOfDir(config.jsPath), projectConfig.toJson()); + } + + private void updateProjectConfigAssets(ProjectConfig config, String projectDir, String dir) { + File main = new File(projectDir, config.getMainScriptFile()); + for (File file : new File(dir).listFiles()) { + if (file.isDirectory()) { + updateProjectConfigAssets(config, projectDir, file.getPath()); + continue; + } + if (file.equals(main)) { + continue; + } + String relative = new File(projectDir).toURI().relativize(file.toURI()).getPath(); + config.getAssets().add(relative); + } + } + @Override public AutoJsApkBuilder build() throws IOException { if (mProgressCallback != null) { diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/build/BuildActivity.java b/app/src/main/java/com/stardust/scriptdroid/ui/build/BuildActivity.java index 486ef2ae..200d14d1 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/build/BuildActivity.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/build/BuildActivity.java @@ -4,6 +4,7 @@ import android.content.Intent; import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.graphics.BitmapFactory; +import android.os.Environment; import android.support.design.widget.TextInputEditText; import android.support.design.widget.TextInputLayout; import android.text.TextUtils; @@ -13,6 +14,7 @@ import android.widget.ImageView; import android.widget.Toast; import com.afollestad.materialdialogs.MaterialDialog; +import com.stardust.autojs.project.ProjectConfig; import com.stardust.scriptdroid.R; import com.stardust.scriptdroid.autojs.build.AutoJsApkBuilder; import com.stardust.scriptdroid.build.ApkBuilderPluginHelper; @@ -102,7 +104,6 @@ public class BuildActivity extends BaseActivity implements AutoJsApkBuilder.Prog } private void setupWithSourceFile(ScriptFile file) { - mSourcePath.setText(file.getPath()); String dir = file.getParent(); if (dir.startsWith(getFilesDir().getPath())) { dir = StorageFileProvider.DEFAULT_DIRECTORY_PATH; @@ -110,6 +111,7 @@ public class BuildActivity extends BaseActivity implements AutoJsApkBuilder.Prog mOutputPath.setText(dir); mAppName.setText(file.getSimplifiedName()); mPackageName.setText(getString(R.string.format_default_package_name, System.currentTimeMillis())); + setSource(file); } @Override @@ -123,12 +125,25 @@ public class BuildActivity extends BaseActivity implements AutoJsApkBuilder.Prog String initialDir = new File(mSourcePath.getText().toString()).getParent(); new FileChooserDialogBuilder(this) .title(R.string.text_source_file_path) - .dir(initialDir == null ? StorageFileProvider.DEFAULT_DIRECTORY_PATH : initialDir) - .justScriptFile() - .singleChoice(file -> mSourcePath.setText(file.getPath())) + .dir(Environment.getExternalStorageDirectory().getPath(), + initialDir == null ? StorageFileProvider.DEFAULT_DIRECTORY_PATH : initialDir) + .singleChoice(this::setSource) .show(); } + private void setSource(File file) { + mSourcePath.setText(file.getPath()); + if (!file.isDirectory()) + return; + ProjectConfig config = ProjectConfig.fromProjectDir(file.getPath()); + if (config == null) + return; + mAppName.setText(config.getName()); + mPackageName.setText(config.getPackageName()); + mVersionCode.setText(String.valueOf(config.getVersionCode())); + mVersionName.setText(config.getVersionName()); + } + @Click(R.id.select_output) void selectOutputDirPath() { @@ -221,6 +236,7 @@ public class BuildActivity extends BaseActivity implements AutoJsApkBuilder.Prog mProgressDialog = new MaterialDialog.Builder(this) .progress(true, 100) .content(R.string.text_on_progress) + .cancelable(false) .show(); } diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/main/scripts/ScriptListView.java b/app/src/main/java/com/stardust/scriptdroid/ui/main/scripts/ScriptListView.java index 52f61ebb..e3504671 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/main/scripts/ScriptListView.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/main/scripts/ScriptListView.java @@ -22,6 +22,8 @@ import com.stardust.scriptdroid.R; import com.stardust.scriptdroid.model.script.ScriptFile; import com.stardust.scriptdroid.model.script.Scripts; import com.stardust.scriptdroid.storage.file.StorageFileProvider; +import com.stardust.scriptdroid.ui.build.BuildActivity; +import com.stardust.scriptdroid.ui.build.BuildActivity_; import com.stardust.scriptdroid.ui.common.ScriptLoopDialog; import com.stardust.scriptdroid.ui.common.ScriptOperations; import com.stardust.scriptdroid.ui.viewmodel.ScriptList; @@ -246,6 +248,12 @@ public class ScriptListView extends ThemeColorSwipeRefreshLayout implements Swip .timedTask(mSelectedScriptFile); notifyOperated(); break; + case R.id.action_build_apk: + BuildActivity_.intent(getContext()) + .extra(BuildActivity.EXTRA_SOURCE_FILE, mSelectedScriptFile.getPath()) + .start(); + notifyOperated(); + break; case R.id.action_sort_by_date: sort(ScriptList.SORT_TYPE_DATE, mDirSortMenuShowing); break; diff --git a/app/src/main/res/menu/menu_dir_options.xml b/app/src/main/res/menu/menu_dir_options.xml index d54cfe05..3b388a81 100644 --- a/app/src/main/res/menu/menu_dir_options.xml +++ b/app/src/main/res/menu/menu_dir_options.xml @@ -8,4 +8,8 @@ android:id="@+id/delete" android:title="@string/text_delete"/> + + \ No newline at end of file diff --git a/app/src/main/res/menu/menu_script_options.xml b/app/src/main/res/menu/menu_script_options.xml index 196c2ba0..ee89dace 100644 --- a/app/src/main/res/menu/menu_script_options.xml +++ b/app/src/main/res/menu/menu_script_options.xml @@ -33,6 +33,10 @@ + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 5be762a4..41dabb41 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -252,7 +252,7 @@ 构建中 打包中 清理临时文件 - 脚本文件路径 + 脚本文件(夹)路径 搜索 选择图标 添加到安卓7.0 Shortcut diff --git a/autojs/src/main/java/com/stardust/autojs/engine/ScriptEngine.java b/autojs/src/main/java/com/stardust/autojs/engine/ScriptEngine.java index 4245963a..94498fc8 100644 --- a/autojs/src/main/java/com/stardust/autojs/engine/ScriptEngine.java +++ b/autojs/src/main/java/com/stardust/autojs/engine/ScriptEngine.java @@ -65,6 +65,8 @@ public interface ScriptEngine { @Override public synchronized void setTag(String key, Object value) { + if(value == null) + return; mTags.put(key, value); } diff --git a/autojs/src/main/java/com/stardust/autojs/project/ProjectConfig.java b/autojs/src/main/java/com/stardust/autojs/project/ProjectConfig.java new file mode 100644 index 00000000..e7551ccf --- /dev/null +++ b/autojs/src/main/java/com/stardust/autojs/project/ProjectConfig.java @@ -0,0 +1,136 @@ +package com.stardust.autojs.project; + +import android.content.Context; +import android.support.annotation.NonNull; + +import com.google.gson.Gson; +import com.google.gson.annotations.SerializedName; +import com.stardust.pio.PFiles; +import com.stardust.pio.UncheckedIOException; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * Created by Stardust on 2018/1/24. + */ + +public class ProjectConfig { + + public static final String CONFIG_FILE_NAME = "project.json"; + + private static final Gson GSON = new Gson(); + + @SerializedName("name") + private String mName; + + @SerializedName("versionName") + private String mVersionName; + + @SerializedName("versionCode") + private int mVersionCode; + + @SerializedName("packageName") + private String mPackageName; + + @SerializedName("main") + private String mMainScriptFile; + + @SerializedName("assets") + private List mAssets = new ArrayList<>(); + + public static ProjectConfig fromJson(String json) { + if (json == null) { + return null; + } + return GSON.fromJson(json, ProjectConfig.class); + } + + + public static ProjectConfig fromAssets(Context context, String path) { + try { + return fromJson(PFiles.read(context.getAssets().open(path))); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + public static ProjectConfig fromFile(String path) { + try { + return fromJson(PFiles.read(path)); + } catch (UncheckedIOException e) { + e.printStackTrace(); + return null; + } + } + + public static ProjectConfig fromProjectDir(String path) { + return fromFile(configFileOfDir(path)); + } + + + public static String configFileOfDir(String projectDir) { + return PFiles.join(projectDir, CONFIG_FILE_NAME); + } + + public String getName() { + return mName; + } + + public ProjectConfig setName(String name) { + mName = name; + return this; + } + + public String getVersionName() { + return mVersionName; + } + + public ProjectConfig setVersionName(String versionName) { + mVersionName = versionName; + return this; + } + + public int getVersionCode() { + return mVersionCode; + } + + public ProjectConfig setVersionCode(int versionCode) { + mVersionCode = versionCode; + return this; + } + + public String getPackageName() { + return mPackageName; + } + + public ProjectConfig setPackageName(String packageName) { + mPackageName = packageName; + return this; + } + + public String getMainScriptFile() { + return mMainScriptFile; + } + + public ProjectConfig setMainScriptFile(String mainScriptFile) { + mMainScriptFile = mainScriptFile; + return this; + } + + public List getAssets() { + return mAssets; + } + + public void setAssets(List assets) { + mAssets = assets; + } + + public String toJson() { + return GSON.toJson(this); + } + +} diff --git a/common/src/main/java/com/stardust/pio/PFiles.java b/common/src/main/java/com/stardust/pio/PFiles.java index fb899ef9..c29c97a5 100644 --- a/common/src/main/java/com/stardust/pio/PFiles.java +++ b/common/src/main/java/com/stardust/pio/PFiles.java @@ -278,6 +278,34 @@ public class PFiles { } } + + public static boolean copyAssetDir(Context context, String assetsDir, String toDir) { + new File(toDir).mkdirs(); + AssetManager manager = context.getAssets(); + try { + String[] list = manager.list(assetsDir); + if (list == null) + return false; + for (String file : list) { + InputStream stream; + try { + stream = manager.open(join(assetsDir, file)); + } catch (IOException e) { + if (!copyAssetDir(context, join(assetsDir, file), join(toDir, file))) { + return false; + } + continue; + } + copyStream(stream, join(toDir, file)); + } + } catch (IOException e) { + e.printStackTrace(); + return false; + } + return true; + + } + public static String renameWithoutExtensionAndReturnNewPath(String path, String newName) { File file = new File(path); File newFile = new File(file.getParent(), newName + "." + getExtension(file.getName())); @@ -431,4 +459,5 @@ public class PFiles { } return path; } + } diff --git a/inrt/src/main/AndroidManifest.xml b/inrt/src/main/AndroidManifest.xml index 4489258a..f5ef2179 100644 --- a/inrt/src/main/AndroidManifest.xml +++ b/inrt/src/main/AndroidManifest.xml @@ -28,7 +28,7 @@ diff --git a/inrt/src/main/assets/project/auto.js.png b/inrt/src/main/assets/project/auto.js.png new file mode 100644 index 0000000000000000000000000000000000000000..4dcffcd73a3894d1431b8e429b4278fabe4b6ba4 GIT binary patch literal 9006 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 UJGB#Mx&QzG07*qoM6N<$f~gD%_W%F@ literal 0 HcmV?d00001 diff --git a/inrt/src/main/assets/project/main.js b/inrt/src/main/assets/project/main.js new file mode 100644 index 00000000..988f41e7 --- /dev/null +++ b/inrt/src/main/assets/project/main.js @@ -0,0 +1,32 @@ +"ui"; + +ui.layout( + + + + + + + + + + + + + + + + +