add: build apk from js file
This commit is contained in:
@@ -10,8 +10,8 @@ android {
|
||||
applicationId "com.stardust.scriptdroid"
|
||||
minSdkVersion 17
|
||||
targetSdkVersion 23
|
||||
versionCode 210
|
||||
versionName "3.0.0 Alpha11"
|
||||
versionCode 211
|
||||
versionName "3.0.0 Alpha12"
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
multiDexEnabled true
|
||||
ndk {
|
||||
@@ -121,6 +121,8 @@ dependencies {
|
||||
compile 'com.wang.avi:library:2.1.3'
|
||||
compile 'org.apache.commons:commons-lang3:3.5'
|
||||
compile 'com.github.hyb1996:FloatingCircularActionMenu:0.0.2'
|
||||
compile(name: 'apkbuilder-release', ext: 'aar')
|
||||
|
||||
// RxJava
|
||||
compile "io.reactivex.rxjava2:rxjava:2.1.0"
|
||||
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
package com.stardust.scriptdroid.autojs.build;
|
||||
|
||||
import com.stardust.autojs.apkbuilder.ApkBuilder;
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.ui.build.BuildActivity;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/10/24.
|
||||
*/
|
||||
|
||||
public class AutoJsApkBuilder extends ApkBuilder {
|
||||
|
||||
|
||||
public interface ProgressCallback {
|
||||
void onPrepare(AutoJsApkBuilder builder);
|
||||
|
||||
void onBuild(AutoJsApkBuilder builder);
|
||||
|
||||
void onSign(AutoJsApkBuilder builder);
|
||||
|
||||
void onClean(AutoJsApkBuilder builder);
|
||||
|
||||
}
|
||||
|
||||
public static class AppConfig {
|
||||
String appName;
|
||||
String versionName;
|
||||
int versionCode;
|
||||
String jsPath;
|
||||
|
||||
public AppConfig(String appName, String versionName, int versionCode, String jsPath) {
|
||||
this.appName = appName;
|
||||
this.versionName = versionName;
|
||||
this.versionCode = versionCode;
|
||||
this.jsPath = jsPath;
|
||||
}
|
||||
}
|
||||
|
||||
private ProgressCallback mProgressCallback;
|
||||
|
||||
public AutoJsApkBuilder(InputStream apkInputStream, File outApkFile, String workspacePath) {
|
||||
super(apkInputStream, outApkFile, workspacePath);
|
||||
}
|
||||
|
||||
public AutoJsApkBuilder(File inFile, File outFile, String workspacePath) throws FileNotFoundException {
|
||||
super(inFile, outFile, workspacePath);
|
||||
}
|
||||
|
||||
public AutoJsApkBuilder setProgressCallback(ProgressCallback callback) {
|
||||
mProgressCallback = callback;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AutoJsApkBuilder prepare() throws IOException {
|
||||
if (mProgressCallback != null) {
|
||||
App.getApp().getUiHandler().post(() -> mProgressCallback.onPrepare(AutoJsApkBuilder.this));
|
||||
}
|
||||
return (AutoJsApkBuilder) super.prepare();
|
||||
}
|
||||
|
||||
public AutoJsApkBuilder setScriptFile(String path) throws IOException {
|
||||
replaceFile("assets/script.js", path);
|
||||
return this;
|
||||
}
|
||||
|
||||
public AutoJsApkBuilder withConfig(AppConfig config) throws IOException {
|
||||
editManifest().setAppName(config.appName)
|
||||
.setVersionName(config.versionName)
|
||||
.setVersionCode(config.versionCode)
|
||||
.commit();
|
||||
setScriptFile(config.jsPath);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AutoJsApkBuilder build() throws IOException {
|
||||
if (mProgressCallback != null) {
|
||||
App.getApp().getUiHandler().post(() -> mProgressCallback.onBuild(AutoJsApkBuilder.this));
|
||||
}
|
||||
return (AutoJsApkBuilder) super.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AutoJsApkBuilder sign() throws Exception {
|
||||
if (mProgressCallback != null) {
|
||||
App.getApp().getUiHandler().post(() -> mProgressCallback.onSign(AutoJsApkBuilder.this));
|
||||
}
|
||||
return (AutoJsApkBuilder) super.sign();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AutoJsApkBuilder cleanWorkspace() {
|
||||
if (mProgressCallback != null) {
|
||||
App.getApp().getUiHandler().post(() -> mProgressCallback.onClean(AutoJsApkBuilder.this));
|
||||
}
|
||||
return (AutoJsApkBuilder) super.cleanWorkspace();
|
||||
}
|
||||
}
|
||||
@@ -1,24 +1,46 @@
|
||||
package com.stardust.scriptdroid.ui.build;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.util.Log;
|
||||
import android.widget.EditText;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.afollestad.materialdialogs.MaterialDialog;
|
||||
import com.stardust.autojs.apkbuilder.ApkBuilder;
|
||||
import com.stardust.pio.PFiles;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.autojs.build.AutoJsApkBuilder;
|
||||
import com.stardust.scriptdroid.io.StorageFileProvider;
|
||||
import com.stardust.scriptdroid.model.script.ScriptFile;
|
||||
import com.stardust.scriptdroid.ui.BaseActivity;
|
||||
import com.stardust.scriptdroid.ui.filechooser.FileChooserDialogBuilder;
|
||||
import com.stardust.theme.dialog.ThemeColorMaterialDialogBuilder;
|
||||
import com.stardust.util.IntentUtil;
|
||||
|
||||
import org.androidannotations.annotations.AfterViews;
|
||||
import org.androidannotations.annotations.Click;
|
||||
import org.androidannotations.annotations.EActivity;
|
||||
import org.androidannotations.annotations.ViewById;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import butterknife.OnClick;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/10/22.
|
||||
*/
|
||||
@EActivity(R.layout.activity_build)
|
||||
public class BuildActivity extends BaseActivity {
|
||||
public class BuildActivity extends BaseActivity implements AutoJsApkBuilder.ProgressCallback {
|
||||
|
||||
public static final String EXTRA_SOURCE_FILE = BuildActivity.class.getName() + ".extra_source_file";
|
||||
|
||||
private static final String LOG_TAG = "BuildActivity";
|
||||
|
||||
@ViewById(R.id.source_path)
|
||||
EditText mSourcePath;
|
||||
|
||||
@@ -36,6 +58,7 @@ public class BuildActivity extends BaseActivity {
|
||||
|
||||
@ViewById(R.id.version_code)
|
||||
EditText mVersionCode;
|
||||
private MaterialDialog mProgressDialog;
|
||||
|
||||
@AfterViews
|
||||
void setupViews() {
|
||||
@@ -47,11 +70,110 @@ public class BuildActivity extends BaseActivity {
|
||||
|
||||
}
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
private void setupWithSourceFile(ScriptFile file) {
|
||||
mSourcePath.setText(file.getPath());
|
||||
mOutputPath.setText(file.getParent());
|
||||
mAppName.setText(file.getSimplifiedName());
|
||||
mPackageName.setText("org.autojs.example_" + file.getSimplifiedName());
|
||||
}
|
||||
|
||||
@Click(R.id.select_source)
|
||||
void selectSourceFilePath() {
|
||||
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()))
|
||||
.show();
|
||||
}
|
||||
|
||||
|
||||
@Click(R.id.select_output)
|
||||
void selectOutputDirPath() {
|
||||
String initialDir = new File(mOutputPath.getText().toString()).exists() ?
|
||||
mOutputPath.getText().toString() : StorageFileProvider.DEFAULT_DIRECTORY_PATH;
|
||||
new FileChooserDialogBuilder(this)
|
||||
.title(R.string.text_source_file_path)
|
||||
.dir(initialDir)
|
||||
.chooseDir()
|
||||
.singleChoice(dir -> mOutputPath.setText(dir.getPath()))
|
||||
.show();
|
||||
}
|
||||
|
||||
@Click(R.id.fab)
|
||||
void buildApk() {
|
||||
String jsPath = mSourcePath.getText().toString();
|
||||
String versionName = mVersionName.getText().toString();
|
||||
int versionCode = Integer.parseInt(mVersionCode.getText().toString());
|
||||
String appName = mAppName.getText().toString();
|
||||
File tmpDir = new File(getCacheDir(), "build/");
|
||||
File outApk = new File(mOutputPath.getText().toString(),
|
||||
String.format("%s_v%s.apk", appName, versionName));
|
||||
showProgressDialog();
|
||||
Observable.fromCallable(() ->
|
||||
new AutoJsApkBuilder(getAssets().open("template.apk"), outApk, tmpDir.getPath())
|
||||
.setProgressCallback(BuildActivity.this)
|
||||
.prepare()
|
||||
.withConfig(new AutoJsApkBuilder.AppConfig(appName, versionName, versionCode, jsPath))
|
||||
.build()
|
||||
.sign()
|
||||
.cleanWorkspace()
|
||||
)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(apkBuilder -> onBuildSuccessful(outApk),
|
||||
this::onBuildFailed);
|
||||
|
||||
}
|
||||
|
||||
private void showProgressDialog() {
|
||||
mProgressDialog = new MaterialDialog.Builder(this)
|
||||
.progress(true, 100)
|
||||
.content(R.string.text_on_progress)
|
||||
.show();
|
||||
}
|
||||
|
||||
private void onBuildFailed(Throwable error) {
|
||||
mProgressDialog.dismiss();
|
||||
mProgressDialog = null;
|
||||
Toast.makeText(this, getString(R.string.text_build_failed) + error.getMessage(), Toast.LENGTH_SHORT).show();
|
||||
Log.e(LOG_TAG, "Build failed", error);
|
||||
}
|
||||
|
||||
private void onBuildSuccessful(File outApk) {
|
||||
mProgressDialog.dismiss();
|
||||
mProgressDialog = null;
|
||||
new MaterialDialog.Builder(this)
|
||||
.title(R.string.text_build_successfully)
|
||||
.content(getString(R.string.format_build_successfully, outApk.getPath()))
|
||||
.positiveText(R.string.text_install)
|
||||
.negativeText(R.string.cancel)
|
||||
.onPositive((dialog, which) ->
|
||||
IntentUtil.installApk(BuildActivity.this, outApk.getPath())
|
||||
)
|
||||
.show();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPrepare(AutoJsApkBuilder builder) {
|
||||
mProgressDialog.setContent(R.string.apk_builder_prepare);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBuild(AutoJsApkBuilder builder) {
|
||||
mProgressDialog.setContent(R.string.apk_builder_build);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSign(AutoJsApkBuilder builder) {
|
||||
mProgressDialog.setContent(R.string.apk_builder_package);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClean(AutoJsApkBuilder builder) {
|
||||
mProgressDialog.setContent(R.string.apk_builder_clean);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="24dp"
|
||||
android:text="文件"
|
||||
android:text="@string/text_file"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body2"
|
||||
android:textColor="?android:textColorSecondary"/>
|
||||
|
||||
@@ -69,8 +69,7 @@
|
||||
android:id="@+id/source_path"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="脚本文件路径"
|
||||
android:maxLines="1"/>
|
||||
android:hint="@string/text_source_file_path"/>
|
||||
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
|
||||
@@ -99,8 +98,7 @@
|
||||
android:id="@+id/output_path"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/text_output_apk_path"
|
||||
android:maxLines="1"/>
|
||||
android:hint="@string/text_output_apk_path"/>
|
||||
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
|
||||
@@ -185,6 +183,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/text_version_code"
|
||||
android:inputType="number"
|
||||
android:text="1"/>
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
</LinearLayout>
|
||||
|
||||
@@ -247,12 +247,21 @@
|
||||
<string name="text_select_file_to_import">选择要导入的文件</string>
|
||||
<string name="text_build_apk">打包应用</string>
|
||||
<string name="text_select">选择</string>
|
||||
<string name="text_output_apk_path">打包应用保存路径</string>
|
||||
<string name="text_output_apk_path">打包应用保存位置</string>
|
||||
<string name="text_config">配置</string>
|
||||
<string name="text_app_name">应用名称</string>
|
||||
<string name="text_package_name">包名</string>
|
||||
<string name="text_version_name">版本名称</string>
|
||||
<string name="text_version_code">版本号</string>
|
||||
<string name="text_build_successfully">打包成功</string>
|
||||
<string name="text_install">安装</string>
|
||||
<string name="text_build_failed">打包失败,错误信息:</string>
|
||||
<string name="format_build_successfully" formatted="true">apk文件已保存到 %s</string>
|
||||
<string name="apk_builder_prepare">准备文件</string>
|
||||
<string name="apk_builder_build">构建中</string>
|
||||
<string name="apk_builder_package">打包中</string>
|
||||
<string name="apk_builder_clean">清理临时文件</string>
|
||||
<string name="text_source_file_path">脚本文件路径</string>
|
||||
|
||||
|
||||
<string-array name="ad_showing_mode_keys">
|
||||
|
||||
Reference in New Issue
Block a user