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

View File

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

View File

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

View File

@ -18,6 +18,10 @@ public class ScriptExecutionIntentService extends IntentService {
protected void onHandleIntent(@Nullable Intent intent) {
if (intent == null)
return;
ScriptIntents.handleIntent(this, intent);
try {
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.Intent;
import android.util.Log;
import android.widget.Toast;
import com.stardust.autojs.execution.ExecutionConfig;
@ -37,6 +38,11 @@ public class BootCompleteReceiver extends BroadcastReceiver {
ExecutionConfig config = new ExecutionConfig();
config.setArgument("intent", intent.clone());
config.executePath(file.getParent());
AutoJs.getInstance().getScriptEngineService().execute(file.toSource(), config);
try {
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.Explorers;
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;

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.script.Scripts;
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.

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){
int i = 0;
for(ExplorerItem item : mChildren){

View File

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

View File

@ -24,6 +24,12 @@ public class ExplorerProjectPage extends ExplorerDirPage {
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.net.Uri;
import android.support.annotation.Nullable;
import android.widget.Toast;
import com.stardust.app.GlobalAppContext;
import com.stardust.autojs.execution.ExecutionConfig;
@ -96,15 +97,27 @@ public class Scripts {
}
public static ScriptExecution run(ScriptFile file) {
return AutoJs.getInstance().getScriptEngineService().execute(file.toSource(), new ExecutionConfig()
.executePath(file.getParent()));
try {
return AutoJs.getInstance().getScriptEngineService().execute(file.toSource(), new ExecutionConfig()
.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) {
return AutoJs.getInstance().getScriptEngineService().execute(source, new ExecutionConfig()
try {
return AutoJs.getInstance().getScriptEngineService().execute(source, new ExecutionConfig()
.executePath(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) {

View File

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

View File

@ -190,7 +190,7 @@ public class EditorMenu {
private void startBuildApkActivity() {
BuildActivity_.intent(mContext)
.extra(BuildActivity.EXTRA_SOURCE_FILE, mEditorView.getFile().getPath())
.extra(BuildActivity.EXTRA_SOURCE, mEditorView.getFile().getPath())
.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();
}
ScriptExecution execution = Scripts.runWithBroadcastSender(mFile);
if(execution == null){
return null;
}
mScriptExecutionId = execution.getId();
setMenuItemStatus(R.id.run, false);
return execution;

View File

@ -9,6 +9,7 @@ import android.util.Log;
import android.view.View;
import android.widget.Toast;
import com.stardust.autojs.execution.ScriptExecution;
import com.stardust.autojs.rhino.debug.DebugCallback;
import com.stardust.autojs.rhino.debug.Debugger;
import com.stardust.autojs.rhino.debug.Dim;
@ -77,7 +78,12 @@ public class DebugToolbarFragment extends ToolbarFragment implements DebugCallba
mCurrentEditorSourceUrl = mInitialEditorSourceUrl = mEditorView.getFile().toString();
mInitialEditorSource = mEditorView.getEditor().getText();
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");
}

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

View File

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

View File

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

View File

@ -4,12 +4,15 @@ import android.annotation.SuppressLint;
import android.os.Bundle;
import android.support.annotation.Nullable;
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.ImageView;
import android.widget.Toast;
import com.stardust.autojs.project.LaunchConfig;
import com.stardust.autojs.project.ProjectConfig;
import com.stardust.pio.PFiles;
import org.androidannotations.annotations.AfterViews;
import org.androidannotations.annotations.Click;
@ -17,13 +20,18 @@ import org.androidannotations.annotations.EActivity;
import org.androidannotations.annotations.ViewById;
import org.autojs.autojs.R;
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.project.ProjectTemplate;
import org.autojs.autojs.ui.BaseActivity;
import org.autojs.autojs.ui.widget.SimpleTextWatcher;
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)
public class ProjectConfigActivity extends BaseActivity {
@ -75,7 +83,7 @@ public class ProjectConfigActivity extends BaseActivity {
mProjectConfig = new ProjectConfig();
} else {
String dir = getIntent().getStringExtra(EXTRA_DIRECTORY);
if(dir == null){
if (dir == null) {
finish();
return;
}
@ -87,10 +95,18 @@ public class ProjectConfigActivity extends BaseActivity {
@AfterViews
void setupViews() {
setToolbarAsBack(mNewProject ? getString(R.string.text_new_project) : mProjectConfig.getName());
mAppName.addTextChangedListener(new SimpleTextWatcher(s ->
mProjectLocation.setText(new File(mParentDirectory, s.toString()).getPath()))
);
if (mNewProject) {
mAppName.addTextChangedListener(new SimpleTextWatcher(s ->
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")
@ -100,26 +116,60 @@ public class ProjectConfigActivity extends BaseActivity {
if (!checkInputs()) {
return;
}
if(mNewProject){
if (mNewProject) {
String location = mProjectLocation.getText().toString();
new ProjectTemplate(mProjectConfig, new File(location))
.newProject()
.subscribe(ignored -> {
Explorers.workspace().notifyItemCreated(new ExplorerDirPage(location, null));
Explorers.workspace().notifyChildrenChanged(new ExplorerDirPage(mParentDirectory, null));
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.setVersionCode(Integer.parseInt(mVersionCode.getText().toString()));
mProjectConfig.setVersionName(mVersionName.getText().toString());
mProjectConfig.setMainScriptFile(mMainFileName.getText().toString());
mProjectConfig.setPackageName(mPackageName.getText().toString());
//mProjectConfig.getLaunchConfig().setHideLogs(true);
}
private boolean checkInputs() {
return true;
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;
// 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"/>
<LinearLayout
android:id="@+id/source_path_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
@ -116,6 +117,7 @@
</android.support.v7.widget.CardView>
<android.support.v7.widget.CardView
android:id="@+id/app_config"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="6dp"

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -175,14 +175,6 @@ public class ScriptEngineService {
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
public void onScriptExecution(ScriptExecutionEvent event) {
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.support.annotation.NonNull;
import android.text.TextUtils;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
@ -32,7 +33,7 @@ public class ProjectConfig {
private String mVersionName;
@SerializedName("versionCode")
private int mVersionCode;
private int mVersionCode = -1;
@SerializedName("packageName")
private String mPackageName;
@ -46,11 +47,40 @@ public class ProjectConfig {
@SerializedName("launchConfig")
private LaunchConfig mLaunchConfig;
@SerializedName("build")
private BuildInfo mBuildInfo = new BuildInfo();
@SerializedName("icon")
private String mIcon;
public static ProjectConfig fromJson(String json) {
if (json == 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);
}
public BuildInfo getBuildInfo() {
return mBuildInfo;
}
public void setBuildInfo(BuildInfo buildInfo) {
mBuildInfo = buildInfo;
}
public String getName() {
return mName;
@ -166,4 +203,15 @@ public class ProjectConfig {
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);
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.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import com.stardust.auojs.inrt.BuildConfig;
import com.stardust.auojs.inrt.LogActivity;
@ -81,15 +82,12 @@ public class AssetsProjectLauncher {
private void prepare() {
String projectConfigPath = PFiles.join(mProjectDir, ProjectConfig.CONFIG_FILE_NAME);
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;
}
PFiles.copyAsset(mActivity, PFiles.join(mAssetsProjectDir, ProjectConfig.CONFIG_FILE_NAME), projectConfigPath);
PFiles.copyAsset(mActivity, PFiles.join(mAssetsProjectDir, mProjectConfig.getMainScriptFile()),
mMainScriptFile.getPath());
for (String asset : mProjectConfig.getAssets()) {
PFiles.copyAsset(mActivity, PFiles.join(mAssetsProjectDir, asset), PFiles.join(mProjectDir, asset));
}
PFiles.deleteRecursively(new File(mAssetsProjectDir));
PFiles.copyAssetDir(mActivity, mAssetsProjectDir, mProjectDir);
}
}