feat: new project, project manager

This commit is contained in:
hyb1996
2018-09-18 17:30:57 +08:00
parent 36e9c9481a
commit c8d2a6e7a2
42 changed files with 747 additions and 166 deletions

Binary file not shown.

View File

@@ -8,8 +8,8 @@ android {
applicationId "org.autojs.autojs" applicationId "org.autojs.autojs"
minSdkVersion 17 minSdkVersion 17
targetSdkVersion 23 targetSdkVersion 23
versionCode 416 versionCode 420
versionName "4.0.2 Alpha11" versionName "4.0.3 Alpha"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
multiDexEnabled true multiDexEnabled true
ndk { ndk {

View File

@@ -1,23 +1,23 @@
package org.autojs.autojs.autojs.build; package org.autojs.autojs.autojs.build;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.text.TextUtils; import android.graphics.BitmapFactory;
import com.stardust.app.GlobalAppContext; import com.stardust.app.GlobalAppContext;
import com.stardust.autojs.apkbuilder.ApkBuilder; import com.stardust.autojs.apkbuilder.ApkBuilder;
import com.stardust.autojs.apkbuilder.ManifestEditor; import com.stardust.autojs.apkbuilder.ManifestEditor;
import com.stardust.autojs.apkbuilder.util.StreamUtils; import com.stardust.autojs.apkbuilder.util.StreamUtils;
import com.stardust.autojs.project.BuildInfo;
import com.stardust.autojs.project.ProjectConfig; import com.stardust.autojs.project.ProjectConfig;
import com.stardust.pio.PFiles; import com.stardust.pio.PFiles;
import org.autojs.autojs.App;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
/** /**
@@ -42,10 +42,27 @@ public class AutoJsApkBuilder extends ApkBuilder {
String appName; String appName;
String versionName; String versionName;
int versionCode; int versionCode;
String jsPath; String sourcePath;
String packageName; String packageName;
ArrayList<File> ignoredDirs = new ArrayList<>();
Callable<Bitmap> icon; Callable<Bitmap> icon;
public static AppConfig fromProjectConfig(String projectDir, ProjectConfig projectConfig) {
return new AppConfig()
.setAppName(projectConfig.getName())
.ignoreDir(new File(projectDir, projectConfig.getBuildDir()))
.setVersionCode(projectConfig.getVersionCode())
.setVersionName(projectConfig.getVersionName())
.setIcon(projectConfig.getIcon())
.setSourcePath(projectDir);
}
public AppConfig ignoreDir(File dir) {
ignoredDirs.add(dir);
return this;
}
public AppConfig setAppName(String appName) { public AppConfig setAppName(String appName) {
this.appName = appName; this.appName = appName;
return this; return this;
@@ -61,8 +78,8 @@ public class AutoJsApkBuilder extends ApkBuilder {
return this; return this;
} }
public AppConfig setJsPath(String jsPath) { public AppConfig setSourcePath(String sourcePath) {
this.jsPath = jsPath; this.sourcePath = sourcePath;
return this; return this;
} }
@@ -76,6 +93,31 @@ public class AutoJsApkBuilder extends ApkBuilder {
this.icon = icon; this.icon = icon;
return this; return this;
} }
public AppConfig setIcon(String iconPath) {
this.icon = () -> BitmapFactory.decodeFile(iconPath);
return this;
}
public String getAppName() {
return appName;
}
public String getVersionName() {
return versionName;
}
public int getVersionCode() {
return versionCode;
}
public String getSourcePath() {
return sourcePath;
}
public String getPackageName() {
return packageName;
}
} }
private ProgressCallback mProgressCallback; private ProgressCallback mProgressCallback;
@@ -86,6 +128,7 @@ public class AutoJsApkBuilder extends ApkBuilder {
public AutoJsApkBuilder(InputStream apkInputStream, File outApkFile, String workspacePath) { public AutoJsApkBuilder(InputStream apkInputStream, File outApkFile, String workspacePath) {
super(apkInputStream, outApkFile, workspacePath); super(apkInputStream, outApkFile, workspacePath);
mWorkspacePath = workspacePath; mWorkspacePath = workspacePath;
PFiles.ensureDir(outApkFile.getPath());
} }
public AutoJsApkBuilder(File inFile, File outFile, String workspacePath) throws FileNotFoundException { public AutoJsApkBuilder(File inFile, File outFile, String workspacePath) throws FileNotFoundException {
@@ -124,10 +167,12 @@ public class AutoJsApkBuilder extends ApkBuilder {
StreamUtils.write(new FileInputStream(child), StreamUtils.write(new FileInputStream(child),
new FileOutputStream(new File(toDir, child.getName()))); new FileOutputStream(new File(toDir, child.getName())));
} else { } else {
if (!mAppConfig.ignoredDirs.contains(child)) {
copyDir(PFiles.join(relativePath, child.getName() + "/"), child.getPath()); copyDir(PFiles.join(relativePath, child.getName() + "/"), child.getPath());
} }
} }
} }
}
@Override @Override
public ApkBuilder replaceFile(String relativePath, String newFilePath) throws IOException { public ApkBuilder replaceFile(String relativePath, String newFilePath) throws IOException {
@@ -144,26 +189,19 @@ public class AutoJsApkBuilder extends ApkBuilder {
.setPackageName(config.packageName); .setPackageName(config.packageName);
setArscPackageName(config.packageName); setArscPackageName(config.packageName);
updateProjectConfig(config); updateProjectConfig(config);
setScriptFile(config.jsPath); setScriptFile(config.sourcePath);
return this; return this;
} }
private void updateProjectConfig(AppConfig config) { private void updateProjectConfig(AppConfig config) {
if (!PFiles.isDir(config.jsPath)) { if (!PFiles.isDir(config.sourcePath)) {
return; return;
} }
ProjectConfig projectConfig = ProjectConfig.fromProjectDir(config.jsPath); ProjectConfig projectConfig = ProjectConfig.fromProjectDir(config.sourcePath);
if (projectConfig == null) long buildNumber = projectConfig.getBuildInfo().getBuildNumber();
projectConfig = new ProjectConfig(); projectConfig.setBuildInfo(BuildInfo.generate(buildNumber + 1));
projectConfig.setName(config.appName) //updateProjectConfigAssets(projectConfig, config.sourcePath, config.sourcePath);
.setPackageName(config.packageName) PFiles.write(ProjectConfig.configFileOfDir(config.sourcePath), projectConfig.toJson());
.setVersionCode(config.versionCode)
.setVersionName(config.versionName);
if (TextUtils.isEmpty(projectConfig.getMainScriptFile())) {
projectConfig.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) { private void updateProjectConfigAssets(ProjectConfig config, String projectDir, String dir) {
@@ -189,8 +227,11 @@ public class AutoJsApkBuilder extends ApkBuilder {
mManifestEditor.commit(); mManifestEditor.commit();
if (mAppConfig.icon != null) { if (mAppConfig.icon != null) {
try { try {
mAppConfig.icon.call().compress(Bitmap.CompressFormat.PNG, 100, Bitmap bitmap = mAppConfig.icon.call();
if (bitmap != null) {
bitmap.compress(Bitmap.CompressFormat.PNG, 100,
new FileOutputStream(new File(mWorkspacePath, "res/mipmap/ic_launcher.png"))); new FileOutputStream(new File(mWorkspacePath, "res/mipmap/ic_launcher.png")));
}
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
@@ -203,6 +244,7 @@ public class AutoJsApkBuilder extends ApkBuilder {
if (mProgressCallback != null) { if (mProgressCallback != null) {
GlobalAppContext.post(() -> mProgressCallback.onSign(AutoJsApkBuilder.this)); GlobalAppContext.post(() -> mProgressCallback.onSign(AutoJsApkBuilder.this));
} }
return (AutoJsApkBuilder) super.sign(); return (AutoJsApkBuilder) super.sign();
} }

View File

@@ -18,6 +18,10 @@ public class ScriptExecutionIntentService extends IntentService {
protected void onHandleIntent(@Nullable Intent intent) { protected void onHandleIntent(@Nullable Intent intent) {
if (intent == null) if (intent == null)
return; return;
try {
ScriptIntents.handleIntent(this, intent); ScriptIntents.handleIntent(this, intent);
}catch (Exception e){
e.printStackTrace();
}
} }
} }

View File

@@ -5,6 +5,7 @@ import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.util.Log; import android.util.Log;
import android.widget.Toast;
import com.stardust.autojs.execution.ExecutionConfig; import com.stardust.autojs.execution.ExecutionConfig;
@@ -37,6 +38,11 @@ public class BootCompleteReceiver extends BroadcastReceiver {
ExecutionConfig config = new ExecutionConfig(); ExecutionConfig config = new ExecutionConfig();
config.setArgument("intent", intent.clone()); config.setArgument("intent", intent.clone());
config.executePath(file.getParent()); config.executePath(file.getParent());
try {
AutoJs.getInstance().getScriptEngineService().execute(file.toSource(), config); AutoJs.getInstance().getScriptEngineService().execute(file.toSource(), config);
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(context, e.getMessage(), Toast.LENGTH_LONG).show();
}
} }
} }

View File

@@ -19,7 +19,7 @@ import org.autojs.autojs.external.ScriptIntents;
import org.autojs.autojs.model.explorer.ExplorerDirPage; import org.autojs.autojs.model.explorer.ExplorerDirPage;
import org.autojs.autojs.model.explorer.Explorers; import org.autojs.autojs.model.explorer.Explorers;
import org.autojs.autojs.ui.BaseActivity; import org.autojs.autojs.ui.BaseActivity;
import org.autojs.autojs.ui.main.scripts.ExplorerView; import org.autojs.autojs.ui.explorer.ExplorerView;
import static org.autojs.autojs.ui.edit.EditorView.EXTRA_CONTENT; import static org.autojs.autojs.ui.edit.EditorView.EXTRA_CONTENT;

View File

@@ -16,7 +16,7 @@ import org.autojs.autojs.model.explorer.ExplorerDirPage;
import org.autojs.autojs.model.explorer.ExplorerFileProvider; import org.autojs.autojs.model.explorer.ExplorerFileProvider;
import org.autojs.autojs.model.script.Scripts; import org.autojs.autojs.model.script.Scripts;
import org.autojs.autojs.ui.BaseActivity; import org.autojs.autojs.ui.BaseActivity;
import org.autojs.autojs.ui.main.scripts.ExplorerView; import org.autojs.autojs.ui.explorer.ExplorerView;
/** /**
* Created by Stardust on 2017/7/11. * Created by Stardust on 2017/7/11.

View File

@@ -42,6 +42,11 @@ public class ExplorerDirPage extends ExplorerFileItem implements ExplorerPage {
} }
} }
@Override
public ExplorerFileItem rename(String newName) {
return new ExplorerDirPage(getFile().renameAndReturnNewFile(newName), getParent());
}
protected int indexOf(ExplorerItem child){ protected int indexOf(ExplorerItem child){
int i = 0; int i = 0;
for(ExplorerItem item : mChildren){ for(ExplorerItem item : mChildren){

View File

@@ -5,10 +5,17 @@ import com.stardust.pio.PFile;
import org.autojs.autojs.model.script.ScriptFile; import org.autojs.autojs.model.script.ScriptFile;
import java.io.File; import java.io.File;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
public class ExplorerFileItem implements ExplorerItem { public class ExplorerFileItem implements ExplorerItem {
private final PFile mFile; private static final Set<String> sEditableFileExts = new HashSet<>(Arrays.asList(
"js", "java", "xml", "json", "txt", "log", "ts"
));
private PFile mFile;
private final ExplorerPage mParent; private final ExplorerPage mParent;
public ExplorerFileItem(PFile file, ExplorerPage parent) { public ExplorerFileItem(PFile file, ExplorerPage parent) {
@@ -60,9 +67,13 @@ public class ExplorerFileItem implements ExplorerItem {
return mFile.canWrite(); return mFile.canWrite();
} }
public ExplorerFileItem rename(String newName) {
return new ExplorerFileItem(mFile.renameAndReturnNewFile(newName), getParent());
}
@Override @Override
public String getType() { public String getType() {
if(mFile.isDirectory()){ if (mFile.isDirectory()) {
return "/"; return "/";
} }
return mFile.getExtension(); return mFile.getExtension();
@@ -80,8 +91,7 @@ public class ExplorerFileItem implements ExplorerItem {
@Override @Override
public boolean isEditable() { public boolean isEditable() {
String type = getType(); return sEditableFileExts.contains(getType());
return !type.equals(TYPE_AUTO_FILE) && !type.equals(TYPE_APK);
} }
@Override @Override

View File

@@ -24,6 +24,12 @@ public class ExplorerProjectPage extends ExplorerDirPage {
mProjectConfig = projectConfig; mProjectConfig = projectConfig;
} }
public ProjectConfig getProjectConfig() {
return mProjectConfig;
}
@Override
public ExplorerFileItem rename(String newName) {
return new ExplorerProjectPage(getFile().renameAndReturnNewFile(newName), getParent(), mProjectConfig);
}
} }

View File

@@ -3,6 +3,7 @@ package org.autojs.autojs.model.script;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.widget.Toast;
import com.stardust.app.GlobalAppContext; import com.stardust.app.GlobalAppContext;
import com.stardust.autojs.execution.ExecutionConfig; import com.stardust.autojs.execution.ExecutionConfig;
@@ -96,15 +97,27 @@ public class Scripts {
} }
public static ScriptExecution run(ScriptFile file) { public static ScriptExecution run(ScriptFile file) {
try {
return AutoJs.getInstance().getScriptEngineService().execute(file.toSource(), new ExecutionConfig() return AutoJs.getInstance().getScriptEngineService().execute(file.toSource(), new ExecutionConfig()
.executePath(file.getParent())); .executePath(file.getParent()));
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(GlobalAppContext.get(), e.getMessage(), Toast.LENGTH_LONG).show();
return null;
}
} }
public static ScriptExecution run(ScriptSource source) { public static ScriptExecution run(ScriptSource source) {
try {
return AutoJs.getInstance().getScriptEngineService().execute(source, new ExecutionConfig() return AutoJs.getInstance().getScriptEngineService().execute(source, new ExecutionConfig()
.executePath(Pref.getScriptDirPath()) .executePath(Pref.getScriptDirPath())
.requirePath(Pref.getScriptDirPath())); .requirePath(Pref.getScriptDirPath()));
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(GlobalAppContext.get(), e.getMessage(), Toast.LENGTH_LONG).show();
return null;
}
} }
public static ScriptExecution runWithBroadcastSender(File file) { public static ScriptExecution runWithBroadcastSender(File file) {

View File

@@ -8,8 +8,10 @@ import android.os.Looper;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar; import android.support.design.widget.Snackbar;
import android.text.Editable;
import android.text.InputType; import android.text.InputType;
import android.view.View; import android.view.View;
import android.widget.CompoundButton;
import android.widget.EditText; import android.widget.EditText;
import android.widget.Toast; import android.widget.Toast;
@@ -123,9 +125,46 @@ public class ScriptOperations {
mExplorer.notifyItemCreated(new ExplorerFileItem(scriptFile, mExplorerPage)); mExplorer.notifyItemCreated(new ExplorerFileItem(scriptFile, mExplorerPage));
} }
public void newScriptFile() { public void newFile() {
showFileNameInputDialog("", "js") DialogUtils.showDialog(new ThemeColorMaterialDialogBuilder(mContext).title(R.string.text_name)
.subscribe(input -> createScriptFile(getCurrentDirectoryPath() + input + ".js", null, true)); .inputType(InputType.TYPE_CLASS_TEXT)
.alwaysCallInputCallback()
.input(getString(R.string.text_please_input_name), "", false, (dialog, input) ->
validateInput(dialog, dialog.isPromptCheckBoxChecked() ? ".js" : null))
.checkBoxPromptRes(R.string.text_js_file, true, (buttonView, isChecked) -> {
})
.onPositive((dialog, which) -> {
boolean createJs = dialog.isPromptCheckBoxChecked();
assert dialog.getInputEditText() != null;
if (createJs) {
createScriptFile(getCurrentDirectoryPath() + dialog.getInputEditText().getText() + ".js", null, true);
} else {
createScriptFile(getCurrentDirectoryPath() + dialog.getInputEditText().getText(), null, false);
}
})
.build());
}
private void validateInput(MaterialDialog dialog, String extension) {
EditText editText = dialog.getInputEditText();
if (editText == null)
return;
Editable input = editText.getText();
int errorResId = 0;
if (input == null || input.length() == 0) {
dialog.getActionButton(DialogAction.POSITIVE).setEnabled(false);
return;
}
if (new File(getCurrentDirectory(), extension == null ? input.toString() : input.toString() + extension).exists()) {
errorResId = R.string.text_file_exists;
}
if (errorResId == 0) {
editText.setError(null);
dialog.getActionButton(DialogAction.POSITIVE).setEnabled(true);
} else {
editText.setError(getString(errorResId));
dialog.getActionButton(DialogAction.POSITIVE).setEnabled(false);
}
} }
public Observable<String> importFile(final String pathFrom) { public Observable<String> importFile(final String pathFrom) {
@@ -223,23 +262,22 @@ public class ScriptOperations {
} }
} }
public Observable<Boolean> rename(final ScriptFile file) { public Observable<Boolean> rename(final ExplorerFileItem item) {
final ScriptFile oldFile = new ScriptFile(file.getPath()); final ScriptFile oldFile = new ScriptFile(item.getPath());
String originalName = file.getSimplifiedName(); String originalName = item.getName();
return showNameInputDialog(originalName, new InputCallback(file.isDirectory() ? null : PFiles.getExtension(file.getName()), return showNameInputDialog(originalName, new InputCallback(oldFile.isDirectory() ? null : PFiles.getExtension(item.getName()),
originalName)) originalName))
.map(newName -> { .map(newName -> {
PFile newFile = file.renameAndReturnNewFile(newName); ExplorerFileItem newItem = item.rename(newName);
if (newFile != null) { if (newItem != null) {
notifyFileChanged(mCurrentDirectory, oldFile, newFile); notifyFileChanged(mCurrentDirectory, item, newItem);
} }
return newFile != null; return newItem != null;
}); });
} }
private void notifyFileChanged(ScriptFile directory, ScriptFile oldFile, PFile newFile) { private void notifyFileChanged(ScriptFile directory, ExplorerFileItem oldItem, ExplorerFileItem newItem) {
mExplorer.notifyItemChanged(new ExplorerFileItem(oldFile, mExplorerPage), mExplorer.notifyItemChanged(oldItem, newItem);
new ExplorerFileItem(newFile, mExplorerPage));
} }
public void createShortcut(ScriptFile file) { public void createShortcut(ScriptFile file) {
@@ -353,22 +391,12 @@ public class ScriptOperations {
EditText editText = dialog.getInputEditText(); EditText editText = dialog.getInputEditText();
if (editText == null) if (editText == null)
return; return;
int errorResId = 0; if (mExcluded != null && input.equals(mExcluded)) {
if (input == null || input.length() == 0) {
errorResId = R.string.text_name_should_not_be_empty;
} else if (!input.equals(mExcluded)) {
if (new File(getCurrentDirectory(), mExtension == null ? input.toString() : input.toString() + mExtension).exists()) {
errorResId = R.string.text_file_exists;
}
}
if (errorResId == 0) {
editText.setError(null); editText.setError(null);
dialog.getActionButton(DialogAction.POSITIVE).setEnabled(true); dialog.getActionButton(DialogAction.POSITIVE).setEnabled(true);
} else { return;
editText.setError(getString(errorResId));
dialog.getActionButton(DialogAction.POSITIVE).setEnabled(false);
} }
validateInput(dialog, mExtension);
} }
} }

View File

@@ -190,7 +190,7 @@ public class EditorMenu {
private void startBuildApkActivity() { private void startBuildApkActivity() {
BuildActivity_.intent(mContext) BuildActivity_.intent(mContext)
.extra(BuildActivity.EXTRA_SOURCE_FILE, mEditorView.getFile().getPath()) .extra(BuildActivity.EXTRA_SOURCE, mEditorView.getFile().getPath())
.start(); .start();
} }

View File

@@ -392,6 +392,9 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC
Snackbar.make(this, R.string.text_start_running, Snackbar.LENGTH_SHORT).show(); Snackbar.make(this, R.string.text_start_running, Snackbar.LENGTH_SHORT).show();
} }
ScriptExecution execution = Scripts.runWithBroadcastSender(mFile); ScriptExecution execution = Scripts.runWithBroadcastSender(mFile);
if(execution == null){
return null;
}
mScriptExecutionId = execution.getId(); mScriptExecutionId = execution.getId();
setMenuItemStatus(R.id.run, false); setMenuItemStatus(R.id.run, false);
return execution; return execution;

View File

@@ -9,6 +9,7 @@ import android.util.Log;
import android.view.View; import android.view.View;
import android.widget.Toast; import android.widget.Toast;
import com.stardust.autojs.execution.ScriptExecution;
import com.stardust.autojs.rhino.debug.DebugCallback; import com.stardust.autojs.rhino.debug.DebugCallback;
import com.stardust.autojs.rhino.debug.Debugger; import com.stardust.autojs.rhino.debug.Debugger;
import com.stardust.autojs.rhino.debug.Dim; import com.stardust.autojs.rhino.debug.Dim;
@@ -77,7 +78,12 @@ public class DebugToolbarFragment extends ToolbarFragment implements DebugCallba
mCurrentEditorSourceUrl = mInitialEditorSourceUrl = mEditorView.getFile().toString(); mCurrentEditorSourceUrl = mInitialEditorSourceUrl = mEditorView.getFile().toString();
mInitialEditorSource = mEditorView.getEditor().getText(); mInitialEditorSource = mEditorView.getEditor().getText();
setupEditor(); setupEditor();
mDebugger.attach(mEditorView.run(false)); ScriptExecution execution = mEditorView.run(false);
if (execution != null) {
mDebugger.attach(execution);
} else {
mEditorView.exitDebugging();
}
Log.d(LOG_TAG, "onViewCreated"); Log.d(LOG_TAG, "onViewCreated");
} }

View File

@@ -0,0 +1,127 @@
package org.autojs.autojs.ui.explorer;
import android.content.Context;
import android.support.annotation.Nullable;
import android.support.v7.widget.CardView;
import android.util.AttributeSet;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.stardust.autojs.project.ProjectConfig;
import com.stardust.autojs.project.ProjectLauncher;
import com.stardust.pio.PFile;
import org.androidannotations.annotations.Click;
import org.autojs.autojs.R;
import org.autojs.autojs.autojs.AutoJs;
import org.autojs.autojs.model.explorer.ExplorerChangeEvent;
import org.autojs.autojs.model.explorer.ExplorerItem;
import org.autojs.autojs.model.explorer.Explorers;
import org.autojs.autojs.ui.project.BuildActivity;
import org.autojs.autojs.ui.project.BuildActivity_;
import org.autojs.autojs.ui.project.ProjectConfigActivity;
import org.autojs.autojs.ui.project.ProjectConfigActivity_;
import org.greenrobot.eventbus.Subscribe;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class ExplorerProjectToolbar extends CardView {
private ProjectConfig mProjectConfig;
private PFile mDirectory;
@BindView(R.id.project_name)
TextView mProjectName;
public ExplorerProjectToolbar(Context context) {
super(context);
init();
}
public ExplorerProjectToolbar(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public ExplorerProjectToolbar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
inflate(getContext(), R.layout.explorer_project_toolbar, this);
ButterKnife.bind(this);
setOnClickListener(view -> edit());
}
public void setProject(PFile dir, ProjectConfig config) {
mDirectory = dir;
mProjectConfig = config;
mProjectName.setText(config.getName());
}
public void refresh() {
if (mDirectory != null) {
setProject(mDirectory, ProjectConfig.fromProjectDir(mDirectory.getPath()));
}
}
@OnClick(R.id.run)
void run() {
try {
new ProjectLauncher(mDirectory.getPath())
.launch(AutoJs.getInstance().getScriptEngineService());
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(getContext(), e.getMessage(), Toast.LENGTH_LONG).show();
}
}
@OnClick(R.id.build)
void build() {
BuildActivity_.intent(getContext())
.extra(BuildActivity.EXTRA_SOURCE, mDirectory.getPath())
.start();
}
@OnClick(R.id.sync)
void sync() {
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
Explorers.workspace().registerChangeListener(this);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
Explorers.workspace().unregisterChangeListener(this);
}
@Subscribe
public void onExplorerChange(ExplorerChangeEvent event) {
if (mDirectory == null) {
return;
}
ExplorerItem item = event.getItem();
if ((event.getAction() == ExplorerChangeEvent.ALL)
|| (item != null && mDirectory.getPath().equals(item.getPath()))) {
refresh();
}
}
void edit() {
ProjectConfigActivity_.intent(getContext())
.extra(ProjectConfigActivity.EXTRA_DIRECTORY, mDirectory.getPath())
.start();
}
}

View File

@@ -1,4 +1,4 @@
package org.autojs.autojs.ui.main.scripts; package org.autojs.autojs.ui.explorer;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
@@ -6,6 +6,7 @@ import android.graphics.drawable.GradientDrawable;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v4.widget.SwipeRefreshLayout; import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@@ -22,8 +23,10 @@ import com.stardust.pio.PFiles;
import org.autojs.autojs.R; import org.autojs.autojs.R;
import org.autojs.autojs.model.explorer.Explorer; import org.autojs.autojs.model.explorer.Explorer;
import org.autojs.autojs.model.explorer.ExplorerChangeEvent; import org.autojs.autojs.model.explorer.ExplorerChangeEvent;
import org.autojs.autojs.model.explorer.ExplorerFileItem;
import org.autojs.autojs.model.explorer.ExplorerItem; import org.autojs.autojs.model.explorer.ExplorerItem;
import org.autojs.autojs.model.explorer.ExplorerPage; import org.autojs.autojs.model.explorer.ExplorerPage;
import org.autojs.autojs.model.explorer.ExplorerProjectPage;
import org.autojs.autojs.model.explorer.ExplorerSamplePage; import org.autojs.autojs.model.explorer.ExplorerSamplePage;
import org.autojs.autojs.model.script.ScriptFile; import org.autojs.autojs.model.script.ScriptFile;
import org.autojs.autojs.model.script.Scripts; import org.autojs.autojs.model.script.Scripts;
@@ -31,7 +34,6 @@ import org.autojs.autojs.ui.project.BuildActivity;
import org.autojs.autojs.ui.project.BuildActivity_; import org.autojs.autojs.ui.project.BuildActivity_;
import org.autojs.autojs.ui.common.ScriptLoopDialog; import org.autojs.autojs.ui.common.ScriptLoopDialog;
import org.autojs.autojs.ui.common.ScriptOperations; import org.autojs.autojs.ui.common.ScriptOperations;
import org.autojs.autojs.ui.explorer.ExplorerViewHelper;
import org.autojs.autojs.ui.viewmodel.ExplorerItemList; import org.autojs.autojs.ui.viewmodel.ExplorerItemList;
import org.autojs.autojs.ui.widget.BindableViewHolder; import org.autojs.autojs.ui.widget.BindableViewHolder;
import org.autojs.autojs.theme.widget.ThemeColorSwipeRefreshLayout; import org.autojs.autojs.theme.widget.ThemeColorSwipeRefreshLayout;
@@ -73,6 +75,7 @@ public class ExplorerView extends ThemeColorSwipeRefreshLayout implements SwipeR
private ExplorerItemList mExplorerItemList = new ExplorerItemList(); private ExplorerItemList mExplorerItemList = new ExplorerItemList();
private RecyclerView mExplorerItemListView; private RecyclerView mExplorerItemListView;
private ExplorerProjectToolbar mProjectToolbar;
private ExplorerAdapter mExplorerAdapter = new ExplorerAdapter(); private ExplorerAdapter mExplorerAdapter = new ExplorerAdapter();
protected OnItemClickListener mOnItemClickListener; protected OnItemClickListener mOnItemClickListener;
private Function<ExplorerItem, Boolean> mFilter; private Function<ExplorerItem, Boolean> mFilter;
@@ -100,14 +103,24 @@ public class ExplorerView extends ThemeColorSwipeRefreshLayout implements SwipeR
public void setRootPage(ExplorerPage page) { public void setRootPage(ExplorerPage page) {
mPageStateHistory.clear(); mPageStateHistory.clear();
mCurrentPageState = new ExplorerPageState(page); setCurrentPageState(new ExplorerPageState(page));
loadItemList(); loadItemList();
} }
private void setCurrentPageState(ExplorerPageState currentPageState) {
mCurrentPageState = currentPageState;
if (mCurrentPageState.page instanceof ExplorerProjectPage) {
mProjectToolbar.setVisibility(VISIBLE);
mProjectToolbar.setProject(currentPageState.page.toScriptFile(), ((ExplorerProjectPage) currentPageState.page).getProjectConfig());
} else {
mProjectToolbar.setVisibility(GONE);
}
}
public void enterChildPage(ExplorerPage childItemGroup) { public void enterChildPage(ExplorerPage childItemGroup) {
mCurrentPageState.position = ((LinearLayoutManager) mExplorerItemListView.getLayoutManager()).findFirstVisibleItemPosition();
mPageStateHistory.push(mCurrentPageState); mPageStateHistory.push(mCurrentPageState);
mCurrentPageState = new ExplorerPageState(childItemGroup); setCurrentPageState(new ExplorerPageState(childItemGroup));
loadItemList(); loadItemList();
} }
@@ -136,7 +149,7 @@ public class ExplorerView extends ThemeColorSwipeRefreshLayout implements SwipeR
mExplorer.unregisterChangeListener(this); mExplorer.unregisterChangeListener(this);
mExplorer = explorer; mExplorer = explorer;
mPageStateHistory.clear(); mPageStateHistory.clear();
mCurrentPageState = new ExplorerPageState(rootPage); setCurrentPageState(new ExplorerPageState(rootPage));
mExplorer.registerChangeListener(this); mExplorer.registerChangeListener(this);
enterChildPage(currentPage); enterChildPage(currentPage);
} }
@@ -150,7 +163,7 @@ public class ExplorerView extends ThemeColorSwipeRefreshLayout implements SwipeR
} }
public void goBack() { public void goBack() {
mCurrentPageState = mPageStateHistory.pop(); setCurrentPageState(mPageStateHistory.pop());
loadItemList(); loadItemList();
} }
@@ -169,8 +182,9 @@ public class ExplorerView extends ThemeColorSwipeRefreshLayout implements SwipeR
private void init() { private void init() {
setOnRefreshListener(this); setOnRefreshListener(this);
mExplorerItemListView = new RecyclerView(getContext()); inflate(getContext(), R.layout.explorer_view, this);
addView(mExplorerItemListView); mExplorerItemListView = findViewById(R.id.explorer_item_list);
mProjectToolbar = findViewById(R.id.project_toolbar);
initExplorerItemListView(); initExplorerItemListView();
} }
@@ -215,6 +229,9 @@ public class ExplorerView extends ThemeColorSwipeRefreshLayout implements SwipeR
mExplorerItemList = list; mExplorerItemList = list;
mExplorerAdapter.notifyDataSetChanged(); mExplorerAdapter.notifyDataSetChanged();
setRefreshing(false); setRefreshing(false);
post(() ->
mExplorerItemListView.scrollToPosition(mCurrentPageState.position)
);
}); });
} }
@@ -229,6 +246,7 @@ public class ExplorerView extends ThemeColorSwipeRefreshLayout implements SwipeR
@Override @Override
public void onRefresh() { public void onRefresh() {
mExplorer.notifyChildrenChanged(mCurrentPageState.page); mExplorer.notifyChildrenChanged(mCurrentPageState.page);
mProjectToolbar.refresh();
} }
@@ -241,7 +259,7 @@ public class ExplorerView extends ThemeColorSwipeRefreshLayout implements SwipeR
switch (item.getItemId()) { switch (item.getItemId()) {
case R.id.rename: case R.id.rename:
new ScriptOperations(getContext(), this, getCurrentPage()) new ScriptOperations(getContext(), this, getCurrentPage())
.rename(mSelectedItem.toScriptFile()) .rename((ExplorerFileItem) mSelectedItem)
.subscribe(); .subscribe();
break; break;
case R.id.delete: case R.id.delete:
@@ -272,7 +290,7 @@ public class ExplorerView extends ThemeColorSwipeRefreshLayout implements SwipeR
break; break;
case R.id.action_build_apk: case R.id.action_build_apk:
BuildActivity_.intent(getContext()) BuildActivity_.intent(getContext())
.extra(BuildActivity.EXTRA_SOURCE_FILE, mSelectedItem.getPath()) .extra(BuildActivity.EXTRA_SOURCE, mSelectedItem.getPath())
.start(); .start();
notifyOperated(); notifyOperated();
break; break;
@@ -612,6 +630,8 @@ public class ExplorerView extends ThemeColorSwipeRefreshLayout implements SwipeR
boolean filesCollapsed; boolean filesCollapsed;
int position;
ExplorerPageState() { ExplorerPageState() {
} }

View File

@@ -19,7 +19,7 @@ import org.autojs.autojs.model.explorer.ExplorerItem;
import org.autojs.autojs.model.explorer.ExplorerPage; import org.autojs.autojs.model.explorer.ExplorerPage;
import org.autojs.autojs.model.script.ScriptFile; import org.autojs.autojs.model.script.ScriptFile;
import org.autojs.autojs.ui.explorer.ExplorerViewHelper; import org.autojs.autojs.ui.explorer.ExplorerViewHelper;
import org.autojs.autojs.ui.main.scripts.ExplorerView; import org.autojs.autojs.ui.explorer.ExplorerView;
import org.autojs.autojs.ui.widget.BindableViewHolder; import org.autojs.autojs.ui.widget.BindableViewHolder;
import org.autojs.autojs.ui.widget.CheckBoxCompat; import org.autojs.autojs.ui.widget.CheckBoxCompat;

View File

@@ -30,7 +30,7 @@ import org.autojs.autojs.ui.common.NotAskAgainDialog;
import org.autojs.autojs.ui.floating.layoutinspector.LayoutBoundsFloatyWindow; import org.autojs.autojs.ui.floating.layoutinspector.LayoutBoundsFloatyWindow;
import org.autojs.autojs.ui.floating.layoutinspector.LayoutHierarchyFloatyWindow; import org.autojs.autojs.ui.floating.layoutinspector.LayoutHierarchyFloatyWindow;
import org.autojs.autojs.ui.main.MainActivity_; import org.autojs.autojs.ui.main.MainActivity_;
import org.autojs.autojs.ui.main.scripts.ExplorerView; import org.autojs.autojs.ui.explorer.ExplorerView;
import org.autojs.autojs.theme.dialog.ThemeColorMaterialDialogBuilder; import org.autojs.autojs.theme.dialog.ThemeColorMaterialDialogBuilder;
import com.stardust.util.ClipboardUtil; import com.stardust.util.ClipboardUtil;
import com.stardust.util.Func1; import com.stardust.util.Func1;

View File

@@ -8,12 +8,11 @@ import android.support.design.widget.FloatingActionButton;
import org.autojs.autojs.R; import org.autojs.autojs.R;
import org.autojs.autojs.ui.main.QueryEvent; import org.autojs.autojs.ui.main.QueryEvent;
import org.autojs.autojs.ui.main.ViewPagerFragment; import org.autojs.autojs.ui.main.ViewPagerFragment;
import org.autojs.autojs.ui.main.scripts.ExplorerView;
import com.stardust.util.BackPressedHandler; import com.stardust.util.BackPressedHandler;
import org.androidannotations.annotations.AfterViews; import org.androidannotations.annotations.AfterViews;
import org.androidannotations.annotations.EFragment; import org.androidannotations.annotations.EFragment;
import org.androidannotations.annotations.ViewById;
import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.Subscribe;

View File

@@ -7,6 +7,7 @@ import android.support.annotation.Nullable;
import android.support.design.widget.FloatingActionButton; import android.support.design.widget.FloatingActionButton;
import com.stardust.util.BackPressedHandler; import com.stardust.util.BackPressedHandler;
import com.stardust.util.IntentUtil;
import org.androidannotations.annotations.AfterViews; import org.androidannotations.annotations.AfterViews;
import org.androidannotations.annotations.EFragment; import org.androidannotations.annotations.EFragment;
@@ -18,6 +19,7 @@ import org.autojs.autojs.model.explorer.Explorers;
import org.autojs.autojs.model.script.Scripts; import org.autojs.autojs.model.script.Scripts;
import org.autojs.autojs.tool.SimpleObserver; import org.autojs.autojs.tool.SimpleObserver;
import org.autojs.autojs.ui.common.ScriptOperations; import org.autojs.autojs.ui.common.ScriptOperations;
import org.autojs.autojs.ui.explorer.ExplorerView;
import org.autojs.autojs.ui.main.FloatingActionMenu; import org.autojs.autojs.ui.main.FloatingActionMenu;
import org.autojs.autojs.ui.main.QueryEvent; import org.autojs.autojs.ui.main.QueryEvent;
import org.autojs.autojs.ui.main.ViewPagerFragment; import org.autojs.autojs.ui.main.ViewPagerFragment;
@@ -60,6 +62,8 @@ public class MyScriptListFragment extends ViewPagerFragment implements BackPress
mExplorerView.setOnItemClickListener((view, item) -> { mExplorerView.setOnItemClickListener((view, item) -> {
if (item.isEditable()) { if (item.isEditable()) {
Scripts.edit(item.toScriptFile()); Scripts.edit(item.toScriptFile());
} else {
IntentUtil.viewFile(getContext(), item.getPath());
} }
}); });
} }
@@ -174,7 +178,7 @@ public class MyScriptListFragment extends ViewPagerFragment implements BackPress
break; break;
case 1: case 1:
new ScriptOperations(getContext(), mExplorerView, mExplorerView.getCurrentPage()) new ScriptOperations(getContext(), mExplorerView, mExplorerView.getCurrentPage())
.newScriptFile(); .newFile();
break; break;
case 2: case 2:
new ScriptOperations(getContext(), mExplorerView, mExplorerView.getCurrentPage()) new ScriptOperations(getContext(), mExplorerView, mExplorerView.getCurrentPage())

View File

@@ -10,8 +10,10 @@ import android.os.Environment;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.design.widget.TextInputEditText; import android.support.design.widget.TextInputEditText;
import android.support.design.widget.TextInputLayout; import android.support.design.widget.TextInputLayout;
import android.support.v7.widget.CardView;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import android.view.View;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.Toast; import android.widget.Toast;
@@ -50,13 +52,16 @@ import io.reactivex.schedulers.Schedulers;
@EActivity(R.layout.activity_build) @EActivity(R.layout.activity_build)
public class BuildActivity extends BaseActivity implements AutoJsApkBuilder.ProgressCallback { public class BuildActivity extends BaseActivity implements AutoJsApkBuilder.ProgressCallback {
public static final String EXTRA_SOURCE_FILE = BuildActivity.class.getName() + ".extra_source_file"; public static final String EXTRA_SOURCE = BuildActivity.class.getName() + ".extra_source_file";
private static final String LOG_TAG = "BuildActivity"; private static final String LOG_TAG = "BuildActivity";
@ViewById(R.id.source_path) @ViewById(R.id.source_path)
TextInputEditText mSourcePath; TextInputEditText mSourcePath;
@ViewById(R.id.source_path_container)
View mSourcePathContainer;
@ViewById(R.id.output_path) @ViewById(R.id.output_path)
TextInputEditText mOutputPath; TextInputEditText mOutputPath;
@@ -75,7 +80,12 @@ public class BuildActivity extends BaseActivity implements AutoJsApkBuilder.Prog
@ViewById(R.id.icon) @ViewById(R.id.icon)
ImageView mIcon; ImageView mIcon;
@ViewById(R.id.app_config)
CardView mAppConfig;
private ProjectConfig mProjectConfig;
private MaterialDialog mProgressDialog; private MaterialDialog mProgressDialog;
private String mSource;
private boolean mIsDefaultIcon = true; private boolean mIsDefaultIcon = true;
@Override @Override
@@ -86,19 +96,13 @@ public class BuildActivity extends BaseActivity implements AutoJsApkBuilder.Prog
@AfterViews @AfterViews
void setupViews() { void setupViews() {
setToolbarAsBack(getString(R.string.text_build_apk)); setToolbarAsBack(getString(R.string.text_build_apk));
String sourcePath = getIntent().getStringExtra(EXTRA_SOURCE_FILE); mSource = getIntent().getStringExtra(EXTRA_SOURCE);
if (sourcePath != null) { if (mSource != null) {
setupWithSourceFile(new ScriptFile(sourcePath)); setupWithSourceFile(new ScriptFile(mSource));
} }
loadRewardedVideoAd();
checkApkBuilderPlugin(); checkApkBuilderPlugin();
} }
private void loadRewardedVideoAd() {
}
private void checkApkBuilderPlugin() { private void checkApkBuilderPlugin() {
if (!ApkBuilderPluginHelper.isPluginAvailable(this)) { if (!ApkBuilderPluginHelper.isPluginAvailable(this)) {
showPluginDownloadDialog(R.string.no_apk_builder_plugin, true); showPluginDownloadDialog(R.string.no_apk_builder_plugin, true);
@@ -119,7 +123,7 @@ public class BuildActivity extends BaseActivity implements AutoJsApkBuilder.Prog
new ThemeColorMaterialDialogBuilder(this) new ThemeColorMaterialDialogBuilder(this)
.content(msgRes) .content(msgRes)
.positiveText(R.string.ok) .positiveText(R.string.ok)
.negativeText(R.string.text_exit) .negativeText(R.string.cancel)
.onPositive((dialog, which) -> downloadPlugin()) .onPositive((dialog, which) -> downloadPlugin())
.onNegative((dialog, which) -> { .onNegative((dialog, which) -> {
if (finishIfCanceled) finish(); if (finishIfCanceled) finish();
@@ -162,18 +166,18 @@ public class BuildActivity extends BaseActivity implements AutoJsApkBuilder.Prog
} }
private void setSource(File file) { private void setSource(File file) {
if (!file.isDirectory()) {
mSourcePath.setText(file.getPath()); mSourcePath.setText(file.getPath());
if (!file.isDirectory())
return; 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());
} }
mProjectConfig = ProjectConfig.fromProjectDir(file.getPath());
if (mProjectConfig == null) {
return;
}
mOutputPath.setText(new File(mSource, mProjectConfig.getBuildDir()).getPath());
mAppConfig.setVisibility(View.GONE);
mSourcePathContainer.setVisibility(View.GONE);
}
@Click(R.id.select_output) @Click(R.id.select_output)
void selectOutputDirPath() { void selectOutputDirPath() {
@@ -218,7 +222,7 @@ public class BuildActivity extends BaseActivity implements AutoJsApkBuilder.Prog
} }
private boolean checkNotEmpty(TextInputEditText editText) { private boolean checkNotEmpty(TextInputEditText editText) {
if (!TextUtils.isEmpty(editText.getText())) if (!TextUtils.isEmpty(editText.getText()) || !editText.isShown())
return true; return true;
// TODO: 2017/12/8 more beautiful ways? // TODO: 2017/12/8 more beautiful ways?
String hint = ((TextInputLayout) editText.getParent().getParent()).getHint().toString(); String hint = ((TextInputLayout) editText.getParent().getParent()).getHint().toString();
@@ -228,40 +232,48 @@ public class BuildActivity extends BaseActivity implements AutoJsApkBuilder.Prog
@SuppressLint("CheckResult") @SuppressLint("CheckResult")
private void doBuildingApk() { private void doBuildingApk() {
AutoJsApkBuilder.AppConfig appConfig = createAppConfig();
File tmpDir = new File(getCacheDir(), "build/");
File outApk = new File(mOutputPath.getText().toString(),
String.format("%s_v%s.apk", appConfig.getAppName(), appConfig.getVersionName()));
showProgressDialog();
Observable.fromCallable(() -> callApkBuilder(tmpDir, outApk, appConfig))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(apkBuilder -> onBuildSuccessful(outApk),
this::onBuildFailed);
}
private AutoJsApkBuilder.AppConfig createAppConfig() {
if (mProjectConfig != null) {
return AutoJsApkBuilder.AppConfig.fromProjectConfig(mSource, mProjectConfig);
}
String jsPath = mSourcePath.getText().toString(); String jsPath = mSourcePath.getText().toString();
String versionName = mVersionName.getText().toString(); String versionName = mVersionName.getText().toString();
int versionCode = Integer.parseInt(mVersionCode.getText().toString()); int versionCode = Integer.parseInt(mVersionCode.getText().toString());
String appName = mAppName.getText().toString(); String appName = mAppName.getText().toString();
String packageName = mPackageName.getText().toString(); String packageName = mPackageName.getText().toString();
File tmpDir = new File(getCacheDir(), "build/"); return new AutoJsApkBuilder.AppConfig()
File outApk = new File(mOutputPath.getText().toString(),
String.format("%s_v%s.apk", appName, versionName));
showProgressDialog();
Observable.fromCallable(() -> {
InputStream templateApk = ApkBuilderPluginHelper.openTemplateApk(BuildActivity.this);
return new AutoJsApkBuilder(templateApk, outApk, tmpDir.getPath())
.setProgressCallback(BuildActivity.this)
.prepare()
.withConfig(new AutoJsApkBuilder.AppConfig()
.setAppName(appName) .setAppName(appName)
.setJsPath(jsPath) .setSourcePath(jsPath)
.setPackageName(packageName) .setPackageName(packageName)
.setVersionCode(versionCode) .setVersionCode(versionCode)
.setVersionName(versionName) .setVersionName(versionName)
.setIcon(mIsDefaultIcon ? null : (Callable<Bitmap>) () -> .setIcon(mIsDefaultIcon ? null : (Callable<Bitmap>) () ->
BitmapTool.drawableToBitmap(mIcon.getDrawable()) BitmapTool.drawableToBitmap(mIcon.getDrawable())
) );
) }
private AutoJsApkBuilder callApkBuilder(File tmpDir, File outApk, AutoJsApkBuilder.AppConfig appConfig) throws Exception {
InputStream templateApk = ApkBuilderPluginHelper.openTemplateApk(BuildActivity.this);
return new AutoJsApkBuilder(templateApk, outApk, tmpDir.getPath())
.setProgressCallback(BuildActivity.this)
.prepare()
.withConfig(appConfig)
.build() .build()
.sign() .sign()
.cleanWorkspace(); .cleanWorkspace();
} }
)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(apkBuilder -> onBuildSuccessful(outApk),
this::onBuildFailed);
}
private void showProgressDialog() { private void showProgressDialog() {
mProgressDialog = new MaterialDialog.Builder(this) mProgressDialog = new MaterialDialog.Builder(this)

View File

@@ -4,12 +4,15 @@ import android.annotation.SuppressLint;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.design.widget.TextInputEditText; import android.support.design.widget.TextInputEditText;
import android.text.Editable; import android.support.design.widget.TextInputLayout;
import android.text.TextUtils;
import android.view.View;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.Toast;
import com.stardust.autojs.project.LaunchConfig;
import com.stardust.autojs.project.ProjectConfig; import com.stardust.autojs.project.ProjectConfig;
import com.stardust.pio.PFiles;
import org.androidannotations.annotations.AfterViews; import org.androidannotations.annotations.AfterViews;
import org.androidannotations.annotations.Click; import org.androidannotations.annotations.Click;
@@ -17,13 +20,18 @@ import org.androidannotations.annotations.EActivity;
import org.androidannotations.annotations.ViewById; import org.androidannotations.annotations.ViewById;
import org.autojs.autojs.R; import org.autojs.autojs.R;
import org.autojs.autojs.model.explorer.ExplorerDirPage; import org.autojs.autojs.model.explorer.ExplorerDirPage;
import org.autojs.autojs.model.explorer.ExplorerFileItem;
import org.autojs.autojs.model.explorer.ExplorerItem;
import org.autojs.autojs.model.explorer.Explorers; import org.autojs.autojs.model.explorer.Explorers;
import org.autojs.autojs.model.project.ProjectTemplate; import org.autojs.autojs.model.project.ProjectTemplate;
import org.autojs.autojs.ui.BaseActivity; import org.autojs.autojs.ui.BaseActivity;
import org.autojs.autojs.ui.widget.SimpleTextWatcher; import org.autojs.autojs.ui.widget.SimpleTextWatcher;
import java.io.File; import java.io.File;
import java.util.concurrent.Executors;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
@EActivity(R.layout.activity_project_config) @EActivity(R.layout.activity_project_config)
public class ProjectConfigActivity extends BaseActivity { public class ProjectConfigActivity extends BaseActivity {
@@ -75,7 +83,7 @@ public class ProjectConfigActivity extends BaseActivity {
mProjectConfig = new ProjectConfig(); mProjectConfig = new ProjectConfig();
} else { } else {
String dir = getIntent().getStringExtra(EXTRA_DIRECTORY); String dir = getIntent().getStringExtra(EXTRA_DIRECTORY);
if(dir == null){ if (dir == null) {
finish(); finish();
return; return;
} }
@@ -87,10 +95,18 @@ public class ProjectConfigActivity extends BaseActivity {
@AfterViews @AfterViews
void setupViews() { void setupViews() {
setToolbarAsBack(mNewProject ? getString(R.string.text_new_project) : mProjectConfig.getName()); setToolbarAsBack(mNewProject ? getString(R.string.text_new_project) : mProjectConfig.getName());
if (mNewProject) {
mAppName.addTextChangedListener(new SimpleTextWatcher(s -> mAppName.addTextChangedListener(new SimpleTextWatcher(s ->
mProjectLocation.setText(new File(mParentDirectory, s.toString()).getPath())) mProjectLocation.setText(new File(mParentDirectory, s.toString()).getPath()))
); );
} else {
mAppName.setText(mProjectConfig.getName());
mVersionCode.setText(String.valueOf(mProjectConfig.getVersionCode()));
mPackageName.setText(mProjectConfig.getPackageName());
mVersionName.setText(mProjectConfig.getVersionName());
mMainFileName.setText(mProjectConfig.getMainScriptFile());
mProjectLocation.setVisibility(View.GONE);
}
} }
@SuppressLint("CheckResult") @SuppressLint("CheckResult")
@@ -100,26 +116,60 @@ public class ProjectConfigActivity extends BaseActivity {
if (!checkInputs()) { if (!checkInputs()) {
return; return;
} }
if(mNewProject){ if (mNewProject) {
String location = mProjectLocation.getText().toString(); String location = mProjectLocation.getText().toString();
new ProjectTemplate(mProjectConfig, new File(location)) new ProjectTemplate(mProjectConfig, new File(location))
.newProject() .newProject()
.subscribe(ignored -> { .subscribe(ignored -> {
Explorers.workspace().notifyItemCreated(new ExplorerDirPage(location, null)); Explorers.workspace().notifyChildrenChanged(new ExplorerDirPage(mParentDirectory, null));
finish(); finish();
}, e -> {
e.printStackTrace();
Toast.makeText(this, e.getMessage(), Toast.LENGTH_SHORT).show();
});
} else {
Observable.fromCallable(() -> {
PFiles.write(ProjectConfig.configFileOfDir(mDirectory.getPath()),
mProjectConfig.toJson());
return Void.TYPE;
})
.observeOn(Schedulers.io())
.subscribeOn(AndroidSchedulers.mainThread())
.subscribe(ignored -> {
ExplorerFileItem item = new ExplorerFileItem(mDirectory, null);
Explorers.workspace().notifyItemChanged(item, item);
finish();
}, e -> {
e.printStackTrace();
Toast.makeText(this, e.getMessage(), Toast.LENGTH_SHORT).show();
}); });
} }
} }
private void syncProjectConfig(){ private void syncProjectConfig() {
mProjectConfig.setName(mAppName.getText().toString()); mProjectConfig.setName(mAppName.getText().toString());
mProjectConfig.setVersionCode(Integer.parseInt(mVersionCode.getText().toString())); mProjectConfig.setVersionCode(Integer.parseInt(mVersionCode.getText().toString()));
mProjectConfig.setVersionName(mVersionName.getText().toString()); mProjectConfig.setVersionName(mVersionName.getText().toString());
mProjectConfig.setMainScriptFile(mMainFileName.getText().toString()); mProjectConfig.setMainScriptFile(mMainFileName.getText().toString());
mProjectConfig.setPackageName(mPackageName.getText().toString());
//mProjectConfig.getLaunchConfig().setHideLogs(true); //mProjectConfig.getLaunchConfig().setHideLogs(true);
} }
private boolean checkInputs() { private boolean checkInputs() {
boolean inputValid = true;
inputValid &= checkNotEmpty(mAppName);
inputValid &= checkNotEmpty(mVersionCode);
inputValid &= checkNotEmpty(mVersionName);
inputValid &= checkNotEmpty(mPackageName);
return inputValid;
}
private boolean checkNotEmpty(TextInputEditText editText) {
if (!TextUtils.isEmpty(editText.getText()))
return true; return true;
// TODO: 2017/12/8 more beautiful ways?
String hint = ((TextInputLayout) editText.getParent().getParent()).getHint().toString();
editText.setError(hint + getString(R.string.text_should_not_be_empty));
return false;
} }
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@@ -57,6 +57,7 @@
android:textColor="?android:textColorSecondary"/> android:textColor="?android:textColorSecondary"/>
<LinearLayout <LinearLayout
android:id="@+id/source_path_container"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"> android:orientation="horizontal">
@@ -116,6 +117,7 @@
</android.support.v7.widget.CardView> </android.support.v7.widget.CardView>
<android.support.v7.widget.CardView <android.support.v7.widget.CardView
android:id="@+id/app_config"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="6dp" android:layout_marginLeft="6dp"

View File

@@ -24,7 +24,7 @@
</com.stardust.theme.widget.ThemeColorToolbar> </com.stardust.theme.widget.ThemeColorToolbar>
</android.support.design.widget.AppBarLayout> </android.support.design.widget.AppBarLayout>
<org.autojs.autojs.ui.main.scripts.ExplorerView <org.autojs.autojs.ui.explorer.ExplorerView
android:id="@+id/script_list" android:id="@+id/script_list"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"

View File

@@ -49,7 +49,7 @@
android:textSize="16sp"/> android:textSize="16sp"/>
</LinearLayout> </LinearLayout>
<org.autojs.autojs.ui.main.scripts.ExplorerView <org.autojs.autojs.ui.explorer.ExplorerView
android:id="@+id/script_list" android:id="@+id/script_list"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<View xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:background="#d8d8d8"/>

View File

@@ -0,0 +1,59 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="48dp"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingBottom="3dp"
android:paddingLeft="12dp"
android:paddingTop="3dp">
<ImageView
android:layout_width="30dp"
android:layout_height="30dp"
android:src="@drawable/ic_project"/>
<TextView
android:id="@+id/project_name"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginLeft="8dp"
android:layout_weight="1"
android:gravity="center_vertical"
android:singleLine="true"
android:text="Project"
android:textColor="#606366"
android:textSize="18sp"/>
<ImageView
android:id="@+id/run"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginRight="2dp"
android:background="?selectableItemBackgroundBorderless"
android:padding="6dp"
android:src="@drawable/ic_play_arrow_white_48dp"
android:tint="#606366"/>
<ImageView
android:id="@+id/build"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_marginRight="2dp"
android:background="?selectableItemBackgroundBorderless"
android:padding="6dp"
android:src="@drawable/ic_build_black_48dp"
android:tint="#606366"/>
<ImageView
android:id="@+id/sync"
android:layout_width="38dp"
android:layout_height="38dp"
android:layout_marginRight="2dp"
android:background="?selectableItemBackgroundBorderless"
android:padding="6dp"
android:src="@drawable/ic_sync"
android:tint="#606366"/>
</LinearLayout>

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<org.autojs.autojs.ui.explorer.ExplorerProjectToolbar
android:id="@+id/project_toolbar"
android:layout_width="match_parent"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginBottom="6dp"
android:foreground="?selectableItemBackground"
android:layout_marginTop="8dp"
app:cardElevation="0.97dp"
app:cardUseCompatPadding="true"
android:layout_height="wrap_content"/>
<android.support.v7.widget.RecyclerView
android:id="@+id/explorer_item_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>

View File

@@ -4,7 +4,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<org.autojs.autojs.ui.main.scripts.ExplorerView <org.autojs.autojs.ui.explorer.ExplorerView
android:id="@+id/script_file_list" android:id="@+id/script_file_list"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"/> android:layout_height="wrap_content"/>

View File

@@ -8,8 +8,4 @@
android:id="@+id/delete" android:id="@+id/delete"
android:title="@string/text_delete"/> android:title="@string/text_delete"/>
<item
android:id="@+id/action_build_apk"
android:title="@string/text_build_apk"/>
</menu> </menu>

View File

@@ -11,4 +11,5 @@
<color name="prefTextColorPrimary">#282C2F</color> <color name="prefTextColorPrimary">#282C2F</color>
<color name="divider_functions_keyboard">#f0f0f0</color> <color name="divider_functions_keyboard">#f0f0f0</color>
<color name="color_red">#ef5350</color> <color name="color_red">#ef5350</color>
<color name="project_toolbar_color">#777777</color>
</resources> </resources>

View File

@@ -396,4 +396,5 @@
<string name="text_project">项目</string> <string name="text_project">项目</string>
<string name="text_project_location">项目位置</string> <string name="text_project_location">项目位置</string>
<string name="text_new_project">新建项目</string> <string name="text_new_project">新建项目</string>
<string name="text_js_file">js文件</string>
</resources> </resources>

View File

@@ -57,4 +57,5 @@
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar"/> <style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar"/>
</resources> </resources>

View File

@@ -175,14 +175,6 @@ public class ScriptEngineService {
return execute(new ScriptExecutionTask(source, null, config)); return execute(new ScriptExecutionTask(source, null, config));
} }
public ScriptExecution execute(ScriptSource source, ScriptExecutionListener listener) {
return execute(source, listener, ExecutionConfig.getDefault());
}
public ScriptExecution execute(ScriptSource source) {
return execute(source, null, ExecutionConfig.getDefault());
}
@Subscribe @Subscribe
public void onScriptExecution(ScriptExecutionEvent event) { public void onScriptExecution(ScriptExecutionEvent event) {
if (event.getCode() == ScriptExecutionEvent.ON_START) { if (event.getCode() == ScriptExecutionEvent.ON_START) {

View File

@@ -0,0 +1,59 @@
package com.stardust.autojs.project;
import com.google.gson.annotations.SerializedName;
import java.util.zip.CRC32;
public class BuildInfo {
@SerializedName("build_time")
private long mBuildTime;
@SerializedName("build_id")
private String mBuildId;
@SerializedName("build_number")
private long mBuildNumber;
public BuildInfo() {
}
public long getBuildNumber() {
return mBuildNumber;
}
public void setBuildNumber(long buildNumber) {
mBuildNumber = buildNumber;
}
public long getBuildTime() {
return mBuildTime;
}
public void setBuildTime(long buildTime) {
mBuildTime = buildTime;
}
public String getBuildId() {
return mBuildId;
}
public void setBuildId(String buildId) {
mBuildId = buildId;
}
public static BuildInfo generate(long buildNumber) {
BuildInfo info = new BuildInfo();
info.setBuildNumber(buildNumber);
info.setBuildTime(System.currentTimeMillis());
info.setBuildId(generateBuildId(buildNumber, info.getBuildTime()));
return info;
}
private static String generateBuildId(long buildNumber, long buildTime) {
CRC32 crc32 = new CRC32();
crc32.update((buildNumber + "" + buildTime).getBytes());
return String.format("%08X", crc32.getValue()) + "-" + buildNumber;
}
}

View File

@@ -2,6 +2,7 @@ package com.stardust.autojs.project;
import android.content.Context; import android.content.Context;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.text.TextUtils;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
@@ -32,7 +33,7 @@ public class ProjectConfig {
private String mVersionName; private String mVersionName;
@SerializedName("versionCode") @SerializedName("versionCode")
private int mVersionCode; private int mVersionCode = -1;
@SerializedName("packageName") @SerializedName("packageName")
private String mPackageName; private String mPackageName;
@@ -46,11 +47,40 @@ public class ProjectConfig {
@SerializedName("launchConfig") @SerializedName("launchConfig")
private LaunchConfig mLaunchConfig; private LaunchConfig mLaunchConfig;
@SerializedName("build")
private BuildInfo mBuildInfo = new BuildInfo();
@SerializedName("icon")
private String mIcon;
public static ProjectConfig fromJson(String json) { public static ProjectConfig fromJson(String json) {
if (json == null) { if (json == null) {
return null; return null;
} }
return GSON.fromJson(json, ProjectConfig.class); ProjectConfig config = GSON.fromJson(json, ProjectConfig.class);
if(!isValid(config)){
return null;
}
return config;
}
private static boolean isValid(ProjectConfig config) {
if(TextUtils.isEmpty(config.getName())){
return false;
}
if(TextUtils.isEmpty(config.getPackageName())){
return false;
}
if(TextUtils.isEmpty(config.getVersionName())){
return false;
}
if(TextUtils.isEmpty(config.getMainScriptFile())){
return false;
}
if(config.getVersionCode() == -1){
return false;
}
return true;
} }
@@ -81,6 +111,13 @@ public class ProjectConfig {
return PFiles.join(projectDir, CONFIG_FILE_NAME); return PFiles.join(projectDir, CONFIG_FILE_NAME);
} }
public BuildInfo getBuildInfo() {
return mBuildInfo;
}
public void setBuildInfo(BuildInfo buildInfo) {
mBuildInfo = buildInfo;
}
public String getName() { public String getName() {
return mName; return mName;
@@ -166,4 +203,15 @@ public class ProjectConfig {
return GSON.toJson(this); return GSON.toJson(this);
} }
public String getIcon() {
return mIcon;
}
public void setIcon(String icon) {
mIcon = icon;
}
public String getBuildDir() {
return "build";
}
} }

View File

@@ -0,0 +1,27 @@
package com.stardust.autojs.project;
import com.stardust.autojs.ScriptEngineService;
import com.stardust.autojs.execution.ExecutionConfig;
import com.stardust.autojs.script.JavaScriptFileSource;
import java.io.File;
public class ProjectLauncher {
private String mProjectDir;
private File mMainScriptFile;
private ProjectConfig mProjectConfig;
public ProjectLauncher(String projectDir) {
mProjectDir = projectDir;
mProjectConfig = ProjectConfig.fromProjectDir(projectDir);
mMainScriptFile = new File(mProjectDir, mProjectConfig.getMainScriptFile());
}
public void launch(ScriptEngineService service){
service.execute(new JavaScriptFileSource(mMainScriptFile), new ExecutionConfig()
.executePath(mProjectDir)
.requirePath(mProjectDir));
}
}

View File

@@ -0,0 +1,24 @@
package com.stardust.app;
import android.graphics.drawable.Drawable;
import android.support.v4.graphics.drawable.DrawableCompat;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SubMenu;
public class MenuUtils {
public static void setMenuIconColor(Menu menu, int color) {
for (int i = 0; i < menu.size(); i++) {
MenuItem item = menu.getItem(i);
Drawable icon = item.getIcon();
if (icon != null) {
DrawableCompat.setTint(icon, color);
}
SubMenu subMenu = item.getSubMenu();
if (subMenu != null) {
setMenuIconColor(subMenu, color);
}
}
}
}

View File

@@ -92,4 +92,12 @@ public class IntentUtil {
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent); context.startActivity(intent);
} }
public static void viewFile(Context context, String path) {
path = "file://" + path;
String mimeType = MimeTypes.fromFileOr(path, "*/*");
context.startActivity(new Intent(Intent.ACTION_VIEW)
.setDataAndType(Uri.parse(path), mimeType)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
}
} }

View File

@@ -5,6 +5,7 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.text.TextUtils;
import com.stardust.auojs.inrt.BuildConfig; import com.stardust.auojs.inrt.BuildConfig;
import com.stardust.auojs.inrt.LogActivity; import com.stardust.auojs.inrt.LogActivity;
@@ -81,15 +82,12 @@ public class AssetsProjectLauncher {
private void prepare() { private void prepare() {
String projectConfigPath = PFiles.join(mProjectDir, ProjectConfig.CONFIG_FILE_NAME); String projectConfigPath = PFiles.join(mProjectDir, ProjectConfig.CONFIG_FILE_NAME);
ProjectConfig projectConfig = ProjectConfig.fromFile(projectConfigPath); ProjectConfig projectConfig = ProjectConfig.fromFile(projectConfigPath);
if (!BuildConfig.DEBUG && projectConfig != null && projectConfig.getVersionCode() == mProjectConfig.getVersionCode()) { if (!BuildConfig.DEBUG && projectConfig != null &&
TextUtils.equals(projectConfig.getBuildInfo().getBuildId(), mProjectConfig.getBuildInfo().getBuildId())) {
return; return;
} }
PFiles.copyAsset(mActivity, PFiles.join(mAssetsProjectDir, ProjectConfig.CONFIG_FILE_NAME), projectConfigPath); PFiles.deleteRecursively(new File(mAssetsProjectDir));
PFiles.copyAsset(mActivity, PFiles.join(mAssetsProjectDir, mProjectConfig.getMainScriptFile()), PFiles.copyAssetDir(mActivity, mAssetsProjectDir, mProjectDir);
mMainScriptFile.getPath());
for (String asset : mProjectConfig.getAssets()) {
PFiles.copyAsset(mActivity, PFiles.join(mAssetsProjectDir, asset), PFiles.join(mProjectDir, asset));
}
} }
} }