diff --git a/app/build.gradle b/app/build.gradle
index 8c368da5..35dee1c3 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -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'
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
new file mode 100644
index 00000000..567dca3d
--- /dev/null
+++ b/app/src/main/java/com/stardust/scriptdroid/autojs/build/AutoJsApkBuilder.java
@@ -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();
+ }
+}
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 0a18d6d6..69cc5923 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
@@ -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);
}
}
diff --git a/app/src/main/res/layout/activity_build.xml b/app/src/main/res/layout/activity_build.xml
index 78631eb0..95769116 100644
--- a/app/src/main/res/layout/activity_build.xml
+++ b/app/src/main/res/layout/activity_build.xml
@@ -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"/>
@@ -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"/>
@@ -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"/>
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 09001da3..e9f67f5a 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -247,12 +247,21 @@
选择要导入的文件
打包应用
选择
- 打包应用保存路径
+ 打包应用保存位置
配置
应用名称
包名
版本名称
版本号
+ 打包成功
+ 安装
+ 打包失败,错误信息:
+ apk文件已保存到 %s
+ 准备文件
+ 构建中
+ 打包中
+ 清理临时文件
+ 脚本文件路径
diff --git a/autojs/src/main/java/com/stardust/autojs/runtime/api/ui/ConvertLayoutInflater.java b/autojs/src/main/java/com/stardust/autojs/runtime/api/ui/ConvertLayoutInflater.java
index 93e52e96..02b87194 100644
--- a/autojs/src/main/java/com/stardust/autojs/runtime/api/ui/ConvertLayoutInflater.java
+++ b/autojs/src/main/java/com/stardust/autojs/runtime/api/ui/ConvertLayoutInflater.java
@@ -2,6 +2,7 @@ package com.stardust.autojs.runtime.api.ui;
import android.content.Context;
import android.text.InputType;
+import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
@@ -11,10 +12,19 @@ import com.stardust.autojs.runtime.api.ui.widget.JsFrameLayout;
import com.stardust.autojs.runtime.api.ui.xml.XmlConverter;
import com.stardust.util.MapEntries;
+import org.xml.sax.SAXException;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlPullParserFactory;
+
+import java.io.IOException;
+import java.io.StringReader;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
+import javax.xml.parsers.ParserConfigurationException;
+
/**
* Created by Stardust on 2017/5/14.
*/
@@ -33,10 +43,10 @@ public class ConvertLayoutInflater implements JsLayoutInflater {
.entry("password", InputType.TYPE_TEXT_VARIATION_PASSWORD | InputType.TYPE_CLASS_TEXT)
.entry("email", InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS | InputType.TYPE_CLASS_TEXT)
.entry("date", InputType.TYPE_DATETIME_VARIATION_DATE | InputType.TYPE_CLASS_DATETIME)
- .entry("time", InputType.TYPE_DATETIME_VARIATION_TIME| InputType.TYPE_CLASS_DATETIME)
+ .entry("time", InputType.TYPE_DATETIME_VARIATION_TIME | InputType.TYPE_CLASS_DATETIME)
.map();
- @Override
+ @Override
public void apply(View view, String value, ViewGroup parent, Map attrs) {
if (!(view instanceof TextView))
return;
@@ -56,6 +66,7 @@ public class ConvertLayoutInflater implements JsLayoutInflater {
@Override
public View inflate(Context context, String xml) {
+
try {
String androidLayoutXml = XmlConverter.convertToAndroidLayout(xml);
JsFrameLayout root = new JsFrameLayout(context);
diff --git a/gradle.properties b/gradle.properties
index f4c0978f..d85e1728 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -15,6 +15,6 @@
#Mon Jan 23 10:16:46 CST 2017
systemProp.https.proxyPort=1080
systemProp.http.proxyHost=127.0.0.1
-org.gradle.jvmargs=-Xmx4096m -Dfile.encoding=UTF-8
+org.gradle.jvmargs=-Xms8192m -Xmx8192m -Dfile.encoding=UTF-8
systemProp.https.proxyHost=127.0.0.1
systemProp.http.proxyPort=1080
diff --git a/inrt/src/main/AndroidManifest.xml b/inrt/src/main/AndroidManifest.xml
index 8e9e2b04..9d3358ec 100644
--- a/inrt/src/main/AndroidManifest.xml
+++ b/inrt/src/main/AndroidManifest.xml
@@ -1,15 +1,18 @@
+
+ android:theme="@style/AppTheme"
+ tools:replace="android:label">
diff --git a/inrt/src/main/java/com/stardust/auojs/inrt/MainActivity.java b/inrt/src/main/java/com/stardust/auojs/inrt/MainActivity.java
index a023eeee..ef05d41f 100644
--- a/inrt/src/main/java/com/stardust/auojs/inrt/MainActivity.java
+++ b/inrt/src/main/java/com/stardust/auojs/inrt/MainActivity.java
@@ -1,5 +1,7 @@
package com.stardust.auojs.inrt;
+import android.Manifest;
+import android.os.Build;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
@@ -14,6 +16,7 @@ public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ checkPermissions();
try {
InputStream is = getAssets().open("script.js");
byte[] data = new byte[is.available()];
@@ -25,4 +28,10 @@ public class MainActivity extends AppCompatActivity {
e.printStackTrace();
}
}
+
+ private void checkPermissions() {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 11124);
+ }
+ }
}