diff --git a/app/build.gradle b/app/build.gradle index b4a4821b..4988d0ab 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -8,8 +8,8 @@ android { applicationId "com.stardust.scriptdroid" minSdkVersion 19 targetSdkVersion 23 - versionCode 114 - versionName "2.0.7 Alpha" + versionCode 116 + versionName "2.0.7 Alpha3" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" multiDexEnabled true @@ -17,7 +17,7 @@ android { buildTypes { release { shrinkResources true - minifyEnabled true + minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } @@ -75,6 +75,7 @@ dependencies { compile 'com.yqritc:recyclerview-flexibledivider:1.4.0' compile 'me.zhanghai.android.materialprogressbar:library:1.3.0' compile group:'com.twofortyfouram', name:'android-plugin-client-sdk-for-locale', version:'[4.0.2, 5.0[' + compile 'com.android.volley:volley:1.0.0' compile(name: 'libtermexec-release', ext: 'aar') compile(name: 'emulatorview-release', ext: 'aar') compile(name: 'term-debug', ext: 'aar') diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index d781ed04..97ef9112 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -24,3 +24,61 @@ -dontwarn jackpal.androidterm.** -dontwarn com.iwebpp.nodeandroid.** -dontwarn org.msgpack.core.** + +-keep class org.mozilla.javascript.** { *; } +-keep class com.jecelyin.editor.** { *; } +-keep class com.stardust.automator.** { *; } +-keep class com.stardust.autojs.** { *; } +-keep class org.greenrobot.eventbus.** { *; } +-keep class * extends c +-keepattributes *Annotation* +-keepclassmembers class ** { + @org.greenrobot.eventbus.Subscribe ; +} +-keepclassmembers class ** { + @com.stardust.autojs.runtime.JavascriptInterface ; +} +-keep class org.msgpack.** { *; } + + +-keepclasseswithmembernames class * { + native ; +} + +-keepclassmembers public class * extends android.view.View { + void set*(***); + *** get*(); +} + +-keep class * extends android.support.v4.app.Fragment { + ; +} + +-keepclassmembers class * extends android.app.Activity { + public void *(android.view.View); +} + +-keepclassmembers enum * { + public static **[] values(); + public static ** valueOf(java.lang.String); +} + +-keep class * implements android.os.Parcelable { + public static final android.os.Parcelable$Creator *; +} + +-keepclassmembers class **.R$* { + public static ; +} + +-keepclassmembers class * implements java.io.Serializable { + static final long serialVersionUID; + private static final java.io.ObjectStreamField[] serialPersistentFields; + private void writeObject(java.io.ObjectOutputStream); + private void readObject(java.io.ObjectInputStream); + java.lang.Object writeReplace(); + java.lang.Object readResolve(); +} + +-keepattributes Signature +-keepattributes EnclosingMethod \ No newline at end of file diff --git a/app/src/main/java/com/stardust/scriptdroid/App.java b/app/src/main/java/com/stardust/scriptdroid/App.java index 306910c6..b11a9e50 100644 --- a/app/src/main/java/com/stardust/scriptdroid/App.java +++ b/app/src/main/java/com/stardust/scriptdroid/App.java @@ -13,6 +13,7 @@ import com.stardust.app.VolumeChangeObserver; import com.stardust.scriptdroid.autojs.AutoJs; import com.stardust.scriptdroid.service.AccessibilityWatchDogService; import com.stardust.scriptdroid.tool.CrashHandler; +import com.stardust.scriptdroid.tool.UpdateChecker; import com.stardust.scriptdroid.ui.error.ErrorReportActivity; import com.stardust.theme.ThemeColor; import com.stardust.theme.ThemeColorManager; diff --git a/app/src/main/java/com/stardust/scriptdroid/Pref.java b/app/src/main/java/com/stardust/scriptdroid/Pref.java index 6c0363cd..5cd8f2df 100644 --- a/app/src/main/java/com/stardust/scriptdroid/Pref.java +++ b/app/src/main/java/com/stardust/scriptdroid/Pref.java @@ -16,7 +16,7 @@ public class Pref { private static SharedPreferences.OnSharedPreferenceChangeListener onSharedPreferenceChangeListener = new SharedPreferences.OnSharedPreferenceChangeListener() { @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { - if (key.equals(App.getResString(R.string.key_run_mode))) { + if (key.equals(getString(R.string.key_run_mode))) { AutoJs.getInstance().getCommandHost().setRunMode(getRunModeFromValue(sharedPreferences.getString(key, null))); } } @@ -33,14 +33,10 @@ public class Pref { } } - public static SharedPreferences def() { + private static SharedPreferences def() { return PreferenceManager.getDefaultSharedPreferences(App.getApp()); } - public static boolean isFirstEnableAssistMode() { - return getDisposableBoolean("isFirstEnableAssistMode", true); - } - private static boolean getDisposableBoolean(String key, boolean defaultValue) { boolean b = DISPOSABLE_BOOLEAN.getBoolean(key, defaultValue); if (b == defaultValue) { @@ -65,9 +61,20 @@ public class Pref { return def().getBoolean(getString(R.string.key_use_volume_control_running), false); } + public static String getStartRecordTrigger() { + return def().getString(getString(R.string.key_start_record_trigger), null); + } + + public static String getStopRecordTrigger() { + return def().getString(getString(R.string.key_stop_record_trigger), null); + } + + public static boolean enableAccessibilityServiceByRoot() { + return def().getBoolean(getString(R.string.key_enable_accessibility_service_by_root), false); + } private static String getString(int id) { - return App.getApp().getString(id); + return App.getResString(id); } public static int MaxTextLengthForCodeCompletion() { @@ -85,4 +92,9 @@ public class Pref { static { def().registerOnSharedPreferenceChangeListener(onSharedPreferenceChangeListener); } + + public static boolean isEditActivityFirstUsing() { + return getDisposableBoolean("Still Love Eating 17.4.6", true); + } + } diff --git a/app/src/main/java/com/stardust/scriptdroid/autojs/AutoJs.java b/app/src/main/java/com/stardust/scriptdroid/autojs/AutoJs.java index d2166353..91a31924 100644 --- a/app/src/main/java/com/stardust/scriptdroid/autojs/AutoJs.java +++ b/app/src/main/java/com/stardust/scriptdroid/autojs/AutoJs.java @@ -63,16 +63,6 @@ public class AutoJs implements AccessibilityBridge { .build(); ScriptEngineService.setInstance(mScriptEngineService); addAccessibilityServiceDelegates(); - getGlobalFunctions(); - } - - private void getGlobalFunctions() { - new Thread(new Runnable() { - @Override - public void run() { - mScriptEngineService.getGlobalFunctions(); - } - }).start(); } private void addAccessibilityServiceDelegates() { @@ -114,8 +104,8 @@ public class AutoJs implements AccessibilityBridge { if (AccessibilityServiceUtils.isAccessibilityServiceEnabled(App.getApp(), AccessibilityWatchDogService.class)) { errorMessage = App.getApp().getString(R.string.text_auto_operate_service_enabled_but_not_running); } else { - if (Pref.def().getBoolean(App.getApp().getString(R.string.key_enable_accessibility_service_by_root), false)) { - if (!AccessibilityServiceTool.enableAccessibilityServiceByRootAndWaitFor(AccessibilityWatchDogService.class, 3000)) { + if (Pref.enableAccessibilityServiceByRoot()) { + if (!AccessibilityServiceTool.enableAccessibilityServiceByRootAndWaitFor(2000)) { errorMessage = App.getApp().getString(R.string.text_enable_accessibility_service_by_root_timeout); } } else { diff --git a/app/src/main/java/com/stardust/scriptdroid/external/floating_window/HoverMenuAdapter.java b/app/src/main/java/com/stardust/scriptdroid/external/floating_window/HoverMenuAdapter.java index e8251276..ad32b701 100644 --- a/app/src/main/java/com/stardust/scriptdroid/external/floating_window/HoverMenuAdapter.java +++ b/app/src/main/java/com/stardust/scriptdroid/external/floating_window/HoverMenuAdapter.java @@ -18,7 +18,7 @@ import android.view.View; import com.stardust.scriptdroid.R; import com.stardust.scriptdroid.external.floating_window.content.MainMenuNavigatorContent; import com.stardust.scriptdroid.external.floating_window.content.RecordNavigatorContent; -import com.stardust.scriptdroid.external.floating_window.content.ScritpListNavigatorContent; +import com.stardust.scriptdroid.external.floating_window.content.ScriptListNavigatorContent; import com.stardust.theme.ThemeColorManagerCompat; import java.util.ArrayList; @@ -52,7 +52,7 @@ public class HoverMenuAdapter implements io.mattcarroll.hover.HoverMenuAdapter { mData.put(HoverMenuAdapter.ID_MAIN, new MainMenuNavigatorContent(context)); mData.put(HoverMenuAdapter.ID_RECORD, new RecordNavigatorContent(context)); - mData.put(HoverMenuAdapter.ID_SCRIPT_LIST, new ScritpListNavigatorContent(context)); + mData.put(HoverMenuAdapter.ID_SCRIPT_LIST, new ScriptListNavigatorContent(context)); mTabIds = new ArrayList<>(); for (String tabId : mData.keySet()) { diff --git a/app/src/main/java/com/stardust/scriptdroid/external/floating_window/content/ScriptListNavigatorContent.java b/app/src/main/java/com/stardust/scriptdroid/external/floating_window/content/ScriptListNavigatorContent.java new file mode 100644 index 00000000..9a7fc773 --- /dev/null +++ b/app/src/main/java/com/stardust/scriptdroid/external/floating_window/content/ScriptListNavigatorContent.java @@ -0,0 +1,104 @@ +package com.stardust.scriptdroid.external.floating_window.content; + +import android.content.Context; +import android.support.annotation.NonNull; +import android.view.ContextThemeWrapper; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import com.stardust.autojs.script.FileScriptSource; +import com.stardust.scriptdroid.R; +import com.stardust.scriptdroid.autojs.AutoJs; +import com.stardust.scriptdroid.external.floating_window.HoverMenuService; +import com.stardust.scriptdroid.scripts.ScriptFile; +import com.stardust.scriptdroid.scripts.StorageScriptProvider; +import com.stardust.scriptdroid.ui.edit.EditActivity; +import com.stardust.scriptdroid.ui.main.script_list.ScriptAndFolderListRecyclerView; +import com.stardust.scriptdroid.ui.main.script_list.ScriptListRecyclerView; +import com.stardust.scriptdroid.ui.main.script_list.ScriptListWithProgressBarView; +import com.stardust.util.MessageEvent; +import com.stardust.widget.ViewHolderSupplier; + +import io.mattcarroll.hover.Navigator; +import io.mattcarroll.hover.NavigatorContent; + +/** + * Created by Stardust on 2017/3/12. + */ + +public class ScriptListNavigatorContent implements NavigatorContent { + + private ViewHolderSupplier mViewHolderSupplier = new ViewHolderSupplier() { + @Override + public ScriptAndFolderListRecyclerView.ViewHolder createViewHolder(ViewGroup parent, int viewType) { + switch (viewType) { + case ScriptAndFolderListRecyclerView.VIEW_TYPE_FILE: + return new FileViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.floating_script_list_recycler_view_file, parent, false)); + case ScriptAndFolderListRecyclerView.VIEW_TYPE_DIRECTORY: + return new DirectoryViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.floating_script_list_recycler_view_directory, parent, false)); + + } + return null; + } + }; + private ScriptAndFolderListRecyclerView mFloatingScriptFileListView; + private ScriptListWithProgressBarView mScriptListWithProgressBarView; + + public ScriptListNavigatorContent(Context context) { + mScriptListWithProgressBarView = new ScriptListWithProgressBarView(new ContextThemeWrapper(context, R.style.AppTheme)); + mFloatingScriptFileListView = mScriptListWithProgressBarView.getScriptAndFolderListRecyclerView(); + mFloatingScriptFileListView.setViewHolderSupplier(mViewHolderSupplier); + mFloatingScriptFileListView.setStorageScriptProvider(StorageScriptProvider.getDefault()); + mFloatingScriptFileListView.setOnItemClickListener(new ScriptAndFolderListRecyclerView.OnScriptFileClickListener() { + + @Override + public void onClick(ScriptFile file, int position) { + AutoJs.getInstance().getScriptEngineService().execute(new FileScriptSource(file)); + HoverMenuService.postEvent(new MessageEvent(HoverMenuService.MESSAGE_COLLAPSE_MENU)); + } + + }); + } + + @NonNull + @Override + public View getView() { + return mScriptListWithProgressBarView; + } + + @Override + public void onShown(@NonNull Navigator navigator) { + + } + + @Override + public void onHidden() { + + } + + private class DirectoryViewHolder extends ScriptAndFolderListRecyclerView.ViewHolder { + + DirectoryViewHolder(View itemView) { + super(itemView); + itemView.setOnClickListener(mFloatingScriptFileListView.getOnItemClickListenerProxy()); + itemView.setOnLongClickListener(mFloatingScriptFileListView.getOnItemLongClickListenerProxy()); + } + } + + private class FileViewHolder extends DirectoryViewHolder { + + FileViewHolder(View itemView) { + super(itemView); + itemView.findViewById(R.id.edit).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + int position = mFloatingScriptFileListView.getChildViewHolder((View) v.getParent()).getAdapterPosition(); + ScriptFile file = mFloatingScriptFileListView.getAdapter().getScriptFileAt(position); + EditActivity.editFile(v.getContext(), file); + } + }); + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/stardust/scriptdroid/external/floating_window/content/ScritpListNavigatorContent.java b/app/src/main/java/com/stardust/scriptdroid/external/floating_window/content/ScritpListNavigatorContent.java deleted file mode 100644 index a3110303..00000000 --- a/app/src/main/java/com/stardust/scriptdroid/external/floating_window/content/ScritpListNavigatorContent.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.stardust.scriptdroid.external.floating_window.content; - -import android.content.Context; -import android.support.annotation.NonNull; -import android.view.ContextThemeWrapper; -import android.view.View; - -import com.stardust.scriptdroid.scripts.ScriptFileList; -import com.stardust.scriptdroid.R; -import com.stardust.scriptdroid.external.floating_window.view.FloatingScriptFileListView; - -import io.mattcarroll.hover.Navigator; -import io.mattcarroll.hover.NavigatorContent; - -/** - * Created by Stardust on 2017/3/12. - */ - -public class ScritpListNavigatorContent implements NavigatorContent { - - private FloatingScriptFileListView mFloatingScriptFileListView; - - public ScritpListNavigatorContent(Context context) { - mFloatingScriptFileListView = new FloatingScriptFileListView(new ContextThemeWrapper(context, R.style.AppTheme)); - mFloatingScriptFileListView.setScriptFileList(ScriptFileList.getImpl()); - } - - @NonNull - @Override - public View getView() { - return mFloatingScriptFileListView; - } - - @Override - public void onShown(@NonNull Navigator navigator) { - - } - - @Override - public void onHidden() { - - } -} diff --git a/app/src/main/java/com/stardust/scriptdroid/external/floating_window/view/FloatingScriptFileListView.java b/app/src/main/java/com/stardust/scriptdroid/external/floating_window/view/FloatingScriptFileListView.java index b113ebd3..5dadcd6c 100644 --- a/app/src/main/java/com/stardust/scriptdroid/external/floating_window/view/FloatingScriptFileListView.java +++ b/app/src/main/java/com/stardust/scriptdroid/external/floating_window/view/FloatingScriptFileListView.java @@ -3,7 +3,6 @@ package com.stardust.scriptdroid.external.floating_window.view; import android.content.Context; import android.support.annotation.NonNull; import android.support.v7.widget.DividerItemDecoration; -import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; @@ -173,7 +172,7 @@ public class FloatingScriptFileListView extends RecyclerView { @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - View itemView = LayoutInflater.from(getContext()).inflate(R.layout.floating_script_list_recycler_view_item, parent, false); + View itemView = LayoutInflater.from(getContext()).inflate(R.layout.floating_script_list_recycler_view_file, parent, false); return new ViewHolder(itemView); } @@ -199,7 +198,7 @@ public class FloatingScriptFileListView extends RecyclerView { name = (TextView) itemView.findViewById(R.id.name); path = (TextView) itemView.findViewById(R.id.path); ViewUtil.$(itemView, R.id.edit).setOnClickListener(mOnEditIconClickListener); - ViewUtil.$(itemView, R.id.more).setOnClickListener(mOnMoreIconClickListener); + //ViewUtil.$(itemView, R.id.more).setOnClickListener(mOnMoreIconClickListener); itemView.setOnClickListener(mOnItemClickListener); } } diff --git a/app/src/main/java/com/stardust/scriptdroid/external/tasker/TaskPrefEditActivity.java b/app/src/main/java/com/stardust/scriptdroid/external/tasker/TaskPrefEditActivity.java index 1a0399d8..8ee6b79a 100644 --- a/app/src/main/java/com/stardust/scriptdroid/external/tasker/TaskPrefEditActivity.java +++ b/app/src/main/java/com/stardust/scriptdroid/external/tasker/TaskPrefEditActivity.java @@ -46,7 +46,7 @@ public class TaskPrefEditActivity extends AbstractAppCompatPluginActivity { scriptList.setCurrentDirectory(StorageScriptProvider.DEFAULT_DIRECTORY); scriptList.setOnItemClickListener(new ScriptAndFolderListRecyclerView.OnScriptFileClickListener() { @Override - public void onClick(ScriptFile file) { + public void onClick(ScriptFile file, int position) { mSelectedScriptFilePath = file.getPath(); finish(); } diff --git a/app/src/main/java/com/stardust/scriptdroid/layout_inspector/NodeInfo.java b/app/src/main/java/com/stardust/scriptdroid/layout_inspector/NodeInfo.java index bfdd8962..1a6e574f 100644 --- a/app/src/main/java/com/stardust/scriptdroid/layout_inspector/NodeInfo.java +++ b/app/src/main/java/com/stardust/scriptdroid/layout_inspector/NodeInfo.java @@ -56,7 +56,7 @@ public class NodeInfo { } private String simplifyId(String idResourceName) { - if(idResourceName == null) + if (idResourceName == null) return null; int i = idResourceName.indexOf('/'); return idResourceName.substring(i + 1); @@ -75,13 +75,15 @@ public class NodeInfo { } public static NodeInfo capture(@NonNull AccessibilityNodeInfo root) { + AccessibilityNodeInfoAllocator allocator = new AccessibilityNodeInfoAllocator(); NodeInfo nodeInfo = new NodeInfo(root); for (int i = 0; i < root.getChildCount(); i++) { - AccessibilityNodeInfo child = AccessibilityNodeInfoAllocator.getGlobal().getChild(root, i); + AccessibilityNodeInfo child = allocator.getChild(root, i); if (child != null) { nodeInfo.children.add(capture(child)); } } + allocator.recycleAll(); return nodeInfo; } diff --git a/app/src/main/java/com/stardust/scriptdroid/record/accessibility/AccessibilityActionConverter.java b/app/src/main/java/com/stardust/scriptdroid/record/accessibility/AccessibilityActionConverter.java index 6a428b47..2e7fae3f 100644 --- a/app/src/main/java/com/stardust/scriptdroid/record/accessibility/AccessibilityActionConverter.java +++ b/app/src/main/java/com/stardust/scriptdroid/record/accessibility/AccessibilityActionConverter.java @@ -9,6 +9,7 @@ import android.view.accessibility.AccessibilityNodeInfo; import com.stardust.automator.simple_action.FilterAction; import com.stardust.scriptdroid.layout_inspector.NodeInfo; import com.stardust.util.SparseArrayEntries; +import com.stardust.view.accessibility.AccessibilityNodeInfoAllocator; import com.stardust.view.accessibility.AccessibilityNodeInfoHelper; import org.greenrobot.eventbus.EventBus; @@ -121,11 +122,13 @@ public class AccessibilityActionConverter { AccessibilityNodeInfo source = event.getSource(); if (source == null) return; - List editableList = FilterAction.EditableFilter.findEditable(service.getRootInActiveWindow()); + AccessibilityNodeInfoAllocator allocator = new AccessibilityNodeInfoAllocator(); + List editableList = FilterAction.EditableFilter.findEditable(allocator, service.getRootInActiveWindow()); int i = findInEditableList(editableList, source); recycle(editableList); sb.append("while(!input(").append(i).append(", \"").append(source.getText()).append("\"));"); source.recycle(); + allocator.recycleAll(); } private void recycle(List list) { diff --git a/app/src/main/java/com/stardust/scriptdroid/record/inputevent/TouchRecorder.java b/app/src/main/java/com/stardust/scriptdroid/record/inputevent/TouchRecorder.java index e497bd6a..b5971f5b 100644 --- a/app/src/main/java/com/stardust/scriptdroid/record/inputevent/TouchRecorder.java +++ b/app/src/main/java/com/stardust/scriptdroid/record/inputevent/TouchRecorder.java @@ -18,8 +18,8 @@ public class TouchRecorder extends InputEventToJsRecorder { } private void setUpTriggers() { - setStartTriggerKey(Pref.def().getString(App.getResString(R.string.key_start_record_trigger), null)); - setStopTriggerKey(Pref.def().getString(App.getResString(R.string.key_stop_record_trigger), null)); + setStartTriggerKey(Pref.getStartRecordTrigger()); + setStopTriggerKey(Pref.getStopRecordTrigger()); } diff --git a/app/src/main/java/com/stardust/scriptdroid/scripts/ScriptFile.java b/app/src/main/java/com/stardust/scriptdroid/scripts/ScriptFile.java index 6c69b294..f2f3cc14 100644 --- a/app/src/main/java/com/stardust/scriptdroid/scripts/ScriptFile.java +++ b/app/src/main/java/com/stardust/scriptdroid/scripts/ScriptFile.java @@ -2,6 +2,7 @@ package com.stardust.scriptdroid.scripts; import android.os.Environment; +import com.android.dex.util.FileUtils; import com.stardust.pio.PFile; import java.io.File; @@ -24,7 +25,7 @@ public class ScriptFile extends File { } private void init() { - mSimplifiedName = PFile.getNameWithoutExtension(getPath()); + mSimplifiedName = PFile.getNameWithoutExtension(getName()); mSimplifyPath = getPath(); if (mSimplifyPath.startsWith(Environment.getExternalStorageDirectory().getPath())) { mSimplifyPath = mSimplifyPath.substring(Environment.getExternalStorageDirectory().getPath().length()); @@ -37,7 +38,14 @@ public class ScriptFile extends File { } public boolean renameTo(String newName) { - return renameTo(new File(getParent(), newName)); + if (isDirectory()) + return renameTo(new File(getParent(), newName)); + else + return renameTo(new File(getParent(), newName + getExtension())); + } + + private String getExtension() { + return PFile.getExtension(getName()); } public String getSimplifiedPath() { @@ -91,4 +99,7 @@ public class ScriptFile extends File { return mSimplifiedName; } + public boolean moveTo(ScriptFile to) { + return renameTo(new File(to, getName())); + } } diff --git a/app/src/main/java/com/stardust/scriptdroid/service/AccessibilityWatchDogService.java b/app/src/main/java/com/stardust/scriptdroid/service/AccessibilityWatchDogService.java index 4f31bcc5..56ff1060 100644 --- a/app/src/main/java/com/stardust/scriptdroid/service/AccessibilityWatchDogService.java +++ b/app/src/main/java/com/stardust/scriptdroid/service/AccessibilityWatchDogService.java @@ -4,12 +4,16 @@ import android.accessibilityservice.AccessibilityService; import android.os.Build; import android.util.Log; import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityNodeInfo; +import com.stardust.autojs.runtime.JavascriptInterface; import com.stardust.view.accessibility.AccessibilityDelegate; import com.stardust.scriptdroid.App; import com.stardust.scriptdroid.tool.AccessibilityServiceTool; import com.stardust.view.accessibility.AccessibilityServiceUtils; +import org.greenrobot.eventbus.EventBus; + import java.lang.ref.WeakReference; import java.util.Map; import java.util.SortedMap; @@ -26,7 +30,8 @@ public class AccessibilityWatchDogService extends AccessibilityService { private static final String TAG = "AccessibilityWatchDog"; private static final SortedMap mDelegates = new TreeMap<>(); - private static WeakReference instance; + private static final Object LOCK = new Object(); + private static AccessibilityWatchDogService instance; private Executor mExecutor = Executors.newSingleThreadExecutor(); public static void addDelegate(int uniquePriority, AccessibilityDelegate delegate) { @@ -38,9 +43,7 @@ public class AccessibilityWatchDogService extends AccessibilityService { } public static AccessibilityWatchDogService getInstance() { - if (instance == null) - return null; - return instance.get(); + return instance; } @Override @@ -58,24 +61,52 @@ public class AccessibilityWatchDogService extends AccessibilityService { }); } + @Override + public AccessibilityNodeInfo getRootInActiveWindow() { + try { + return super.getRootInActiveWindow(); + } catch (IllegalStateException e) { + e.printStackTrace(); + return null; + } + } + @Override public void onInterrupt() { } + @Override + public void onDestroy() { + instance = null; + super.onDestroy(); + } + @Override protected void onServiceConnected() { - super.onServiceConnected(); - // FIXME: 2017/2/12 有时在无障碍中开启服务后这里不会调用服务也不会运行,安卓的BUG??? Log.v(TAG, "onServiceConnected"); - instance = new WeakReference<>(this); + instance = this; + super.onServiceConnected(); + synchronized (LOCK) { + LOCK.notifyAll(); + } + // FIXME: 2017/2/12 有时在无障碍中开启服务后这里不会调用服务也不会运行,安卓的BUG??? } public static void disable() { - if (instance != null && instance.get() != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - instance.get().disableSelf(); + if (instance != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + instance.disableSelf(); } else { AccessibilityServiceTool.goToAccessibilitySetting(); } } + public static void waitForEnabled(long timeOut) { + synchronized (LOCK) { + try { + LOCK.wait(timeOut); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } } diff --git a/app/src/main/java/com/stardust/scriptdroid/tool/AccessibilityServiceTool.java b/app/src/main/java/com/stardust/scriptdroid/tool/AccessibilityServiceTool.java index eb6c3af7..c06841c0 100644 --- a/app/src/main/java/com/stardust/scriptdroid/tool/AccessibilityServiceTool.java +++ b/app/src/main/java/com/stardust/scriptdroid/tool/AccessibilityServiceTool.java @@ -1,7 +1,10 @@ package com.stardust.scriptdroid.tool; +import android.accessibilityservice.AccessibilityService; import android.content.ActivityNotFoundException; import android.content.Context; +import android.text.TextUtils; +import android.util.Log; import android.widget.Toast; import com.stardust.scriptdroid.Pref; @@ -11,6 +14,8 @@ import com.stardust.scriptdroid.R; import com.stardust.util.Shell; import com.stardust.view.accessibility.AccessibilityServiceUtils; +import java.util.Locale; + import static com.stardust.view.accessibility.AccessibilityServiceUtils.isAccessibilityServiceEnabled; /** @@ -20,8 +25,8 @@ import static com.stardust.view.accessibility.AccessibilityServiceUtils.isAccess public class AccessibilityServiceTool { public static void enableAccessibilityService() { - if (Pref.def().getBoolean(App.getApp().getString(R.string.key_enable_accessibility_service_by_root), false)) { - if (!enableAccessibilityServiceByRootAndWaitFor(AccessibilityWatchDogService.class, 3000)) { + if (Pref.enableAccessibilityServiceByRoot()) { + if (!enableAccessibilityServiceByRoot(AccessibilityWatchDogService.class)) { goToAccessibilitySetting(); } } else { @@ -41,28 +46,32 @@ public class AccessibilityServiceTool { } } - public static boolean enableAccessibilityServiceByRootAndWaitFor(Class accessibilityService, int timeout) { - Shell.execCommand("settings put secure enabled_accessibility_services %accessibility:" - + App.getApp().getPackageName() + "/" + accessibilityService.getName(), true); - long millis = System.currentTimeMillis(); - while (true) { - if (isAccessibilityServiceEnabled(App.getApp(), accessibilityService)) - return true; - try { - Thread.sleep(100); - } catch (InterruptedException e) { - e.printStackTrace(); - } - if (System.currentTimeMillis() - millis >= timeout) { - return false; - } + private static final String cmd = "enabled=$(settings get secure enabled_accessibility_services)\n" + + "pkg=%s\n" + + "if [[ $enabled == *$pkg* ]]\n" + + "then\n" + + "echo already_enabled\n" + + "else\n" + + "enabled=$pkg:$enabled\n" + + "settings put secure enabled_accessibility_services $enabled\n" + + "fi"; + + public static boolean enableAccessibilityServiceByRoot(Class accessibilityService) { + String serviceName = App.getApp().getPackageName() + "/" + accessibilityService.getName(); + return TextUtils.isEmpty(Shell.execCommand(String.format(Locale.getDefault(), cmd, serviceName), true).error); + } + + public static boolean enableAccessibilityServiceByRootAndWaitFor(long timeOut) { + if (enableAccessibilityServiceByRoot(AccessibilityWatchDogService.class)) { + AccessibilityWatchDogService.waitForEnabled(timeOut); } + return true; } public static void enableAccessibilityServiceByRootIfNeeded() { if (AccessibilityWatchDogService.getInstance() == null) - if (Pref.def().getBoolean(App.getApp().getString(R.string.key_enable_accessibility_service_by_root), false)) { - AccessibilityServiceTool.enableAccessibilityServiceByRootAndWaitFor(AccessibilityWatchDogService.class, 3000); + if (Pref.enableAccessibilityServiceByRoot()) { + AccessibilityServiceTool.enableAccessibilityServiceByRoot(AccessibilityWatchDogService.class); } } } diff --git a/app/src/main/java/com/stardust/scriptdroid/tool/UpdateChecker.java b/app/src/main/java/com/stardust/scriptdroid/tool/UpdateChecker.java new file mode 100644 index 00000000..93a69bc6 --- /dev/null +++ b/app/src/main/java/com/stardust/scriptdroid/tool/UpdateChecker.java @@ -0,0 +1,150 @@ +package com.stardust.scriptdroid.tool; + +import android.content.Context; +import android.text.TextUtils; +import android.util.Log; + +import com.android.volley.DefaultRetryPolicy; +import com.android.volley.Request; +import com.android.volley.RequestQueue; +import com.android.volley.Response; +import com.android.volley.VolleyError; +import com.android.volley.toolbox.StringRequest; +import com.android.volley.toolbox.Volley; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.stardust.pio.UncheckedIOException; + +import java.lang.reflect.Type; +import java.util.List; + +/** + * Created by Stardust on 2017/4/9. + */ + +public class UpdateChecker implements Response.Listener, Response.ErrorListener { + + private static final String LOG_TAG = UpdateChecker.class.getName(); + private RequestQueue mRequestQueue; + private static final String UPDATE_URL = "https://raw.githubusercontent.com/hyb1996/NoRootScriptDroid/master/version.json"; + + + public interface Callback { + + void onSuccess(CheckResult result); + + void onError(Exception exception); + + } + + private Callback mCallback; + private final int mTimeOut = 3000; + + public UpdateChecker(Context context, Callback callback) { + mCallback = callback; + mRequestQueue = Volley.newRequestQueue(context); + } + + private CheckResult parse(String json) { + Gson gson = new Gson(); + Type type = new TypeToken() { + }.getType(); + CheckResult result = gson.fromJson(json, type); + Log.i(LOG_TAG, result.toString()); + return result; + } + + + public void check() { + StringRequest request = new StringRequest(Request.Method.GET, UPDATE_URL, this, this); + request.setRetryPolicy(new DefaultRetryPolicy(mTimeOut, DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT)); + request.setTag("update-check"); + mRequestQueue.add(request); + } + + @Override + public void onErrorResponse(VolleyError error) { + error.printStackTrace(); + mCallback.onError(error); + } + + @Override + public void onResponse(String response) { + try { + CheckResult result = parse(response); + if (result.isValid()) { + mCallback.onSuccess(result); + } else { + mCallback.onError(new UpdateDataInvalidException()); + } + } catch (Exception e) { + e.printStackTrace(); + mCallback.onError(e); + } + } + + public void cancel() { + mRequestQueue.cancelAll("update-check"); + } + + public static class CheckResult { + + public int versionCode; + public String releaseNotes; + public String versionName; + public List downloads; + public List oldVersions; + public int deprecated; + + public boolean isValid() { + return downloads != null && !downloads.isEmpty() && versionCode > 0 + && !TextUtils.isEmpty(versionName) && !TextUtils.isEmpty(releaseNotes); + } + + @Override + public String toString() { + return "CheckResult{" + + "versionCode=" + versionCode + + ", releaseNotes='" + releaseNotes + '\'' + + ", versionName='" + versionName + '\'' + + ", downloads=" + downloads + + ", oldVersions=" + oldVersions + + ", deprecated=" + deprecated + + '}'; + } + + + } + + public static class OldVersion { + + public int versionCode; + public String issues; + + @Override + public String toString() { + return "OldVersion{" + + "versionCode=" + versionCode + + ", issues='" + issues + '\'' + + '}'; + } + } + + public static class Download { + + public String name; + public String url; + + @Override + public String toString() { + return "Download{" + + "name='" + name + '\'' + + ", url='" + url + '\'' + + '}'; + } + } + + public static class UpdateDataInvalidException extends RuntimeException { + + } +} diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/edit/EditActivity.java b/app/src/main/java/com/stardust/scriptdroid/ui/edit/EditActivity.java index 8b63157d..775620f2 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/edit/EditActivity.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/edit/EditActivity.java @@ -84,8 +84,6 @@ public class EditActivity extends Editor920Activity { public static final String EXTRA_CONTENT = "Still Love Eating 17.4.5"; - private static final String KEY_EDIT_ACTIVITY_FIRST_USE = "KEY_EDIT_ACTIVITY_FIRST_USE"; - private static final String ACTION_ON_RUN_FINISHED = "ACTION_ON_RUN_FINISHED"; private static final String EXTRA_EXCEPTION_MESSAGE = "EXTRA_EXCEPTION_MESSAGE"; @@ -173,14 +171,13 @@ public class EditActivity extends Editor920Activity { } private void openDrawerIfFirstUse() { - if (Pref.def().getBoolean(KEY_EDIT_ACTIVITY_FIRST_USE, true)) { + if (Pref.isEditActivityFirstUsing()) { mDrawerLayout.postDelayed(new Runnable() { @Override public void run() { mDrawerLayout.openDrawer(GravityCompat.END); } }, 1000); - Pref.def().edit().putBoolean(KEY_EDIT_ACTIVITY_FIRST_USE, false).apply(); } } diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/main/script_list/MyScriptListFragment.java b/app/src/main/java/com/stardust/scriptdroid/ui/main/script_list/MyScriptListFragment.java index 7b3f521c..bb92c851 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/main/script_list/MyScriptListFragment.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/main/script_list/MyScriptListFragment.java @@ -45,6 +45,7 @@ public class MyScriptListFragment extends Fragment { private ScriptFile mSelectedScriptFile; private MaterialDialog.InputCallback mFileNameInputCallback = new InputCallback(false); private MaterialDialog.InputCallback mDirectoryNameInputCallback = new InputCallback(true); + private int mSelectedPosition; @Override public void onCreate(@Nullable Bundle savedInstanceState) { @@ -82,14 +83,15 @@ public class MyScriptListFragment extends Fragment { }); mScriptListRecyclerView.setOnItemClickListener(new ScriptAndFolderListRecyclerView.OnScriptFileClickListener() { @Override - public void onClick(ScriptFile file) { + public void onClick(ScriptFile file, int position) { EditActivity.editFile(getContext(), file); } }); mScriptListRecyclerView.setOnItemLongClickListener(new ScriptAndFolderListRecyclerView.OnScriptFileLongClickListener() { @Override - public void onLongClick(ScriptFile file) { + public void onLongClick(ScriptFile file, int position) { mSelectedScriptFile = file; + mSelectedPosition = position; if (file.isDirectory()) { mDirectoryOperationDialog.show(); } else { @@ -226,6 +228,7 @@ public class MyScriptListFragment extends Fragment { @Override public void onInput(@NonNull MaterialDialog dialog, CharSequence input) { mSelectedScriptFile.renameTo(input.toString()); + StorageScriptProvider.getDefault().notifyDirectoryChanged(mScriptListRecyclerView.getCurrentDirectory()); onScriptFileOperated(); } }); diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/main/script_list/ScriptAndFolderListRecyclerView.java b/app/src/main/java/com/stardust/scriptdroid/ui/main/script_list/ScriptAndFolderListRecyclerView.java index 6e07d7cc..090b783d 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/main/script_list/ScriptAndFolderListRecyclerView.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/main/script_list/ScriptAndFolderListRecyclerView.java @@ -4,13 +4,13 @@ import android.content.Context; import android.os.Bundle; import android.os.Parcelable; import android.support.annotation.Nullable; -import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.util.AttributeSet; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.view.ViewTreeObserver; import android.widget.RelativeLayout; import android.widget.TextView; import android.workground.WrapContentLinearLayoutManager; @@ -20,8 +20,11 @@ import com.stardust.scriptdroid.autojs.AutoJs; import com.stardust.scriptdroid.scripts.ScriptFile; import com.stardust.scriptdroid.R; import com.stardust.scriptdroid.scripts.StorageScriptProvider; +import com.stardust.widget.ViewHolderMutableAdapter; +import com.stardust.widget.ViewHolderSupplier; import com.yqritc.recyclerviewflexibledivider.HorizontalDividerItemDecoration; + import org.greenrobot.eventbus.Subscribe; /** @@ -32,12 +35,12 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView { public interface OnScriptFileClickListener { - void onClick(ScriptFile file); + void onClick(ScriptFile file, int position); } public interface OnScriptFileLongClickListener { - void onLongClick(ScriptFile file); + void onLongClick(ScriptFile file, int position); } public interface FileProcessListener { @@ -47,6 +50,28 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView { void onFileListed(); } + public static final int VIEW_TYPE_DIRECTORY = 1; + public static final int VIEW_TYPE_FILE = 2; + + public static class ViewHolder extends RecyclerView.ViewHolder { + + TextView name; + + public ViewHolder(View itemView) { + super(itemView); + name = (TextView) itemView.findViewById(R.id.name); + } + + public void bind(ScriptFile file) { + if (file.isDirectory()) { + name.setText(file.getName()); + } else { + name.setText(file.getSimplifiedName()); + } + } + } + + private OnScriptFileClickListener mOnItemClickListener; private OnScriptFileLongClickListener mOnItemLongClickListener; private final OnClickListener mOnItemClickListenerProxy = new OnClickListener() { @@ -57,11 +82,11 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView { goBack(); return; } - ScriptFile file = mScriptFileList[getActualPosition(position)]; + ScriptFile file = mAdapter.getScriptFileAt(position); if (file.isDirectory()) { setCurrentDirectory(file, true); } else if (mOnItemClickListener != null) { - mOnItemClickListener.onClick(file); + mOnItemClickListener.onClick(file, position); } } }; @@ -70,7 +95,7 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView { public boolean onLongClick(View v) { if (mOnItemLongClickListener != null) { int position = getChildViewHolder(v).getAdapterPosition(); - mOnItemLongClickListener.onLongClick(mScriptFileList[getActualPosition(position)]); + mOnItemLongClickListener.onLongClick(mAdapter.getScriptFileAt(position), position); return true; } return false; @@ -81,12 +106,23 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView { @Override public void onClick(View v) { int position = getChildViewHolder((View) v.getParent()).getAdapterPosition(); - ScriptFile file = mScriptFileList[getActualPosition(position)]; + ScriptFile file = mAdapter.getScriptFileAt(position); AutoJs.getInstance().getScriptEngineService().execute(new FileScriptSource(file)); } }; + private final ViewHolderSupplier mDefaultViewHolderSupplier = new ViewHolderSupplier() { + @Override + public ViewHolder createViewHolder(ViewGroup parent, int viewType) { + switch (viewType) { + case VIEW_TYPE_FILE: + return new FileViewHolder(LayoutInflater.from(getContext()).inflate(R.layout.script_and_folder_list_recycler_view_file, parent, false)); + case VIEW_TYPE_DIRECTORY: + return new DefaultViewHolder(LayoutInflater.from(getContext()).inflate(R.layout.script_and_folder_list_recycler_view_directory, parent, false)); + } + return null; + } + }; - private ScriptFile[] mScriptFileList = new ScriptFile[0]; private ScriptFile mCurrentDirectory; private ScriptFile mRootDirectory; private Adapter mAdapter; @@ -119,12 +155,13 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView { new Thread(new Runnable() { @Override public void run() { - mScriptFileList = mStorageScriptProvider.getDirectoryScriptFiles(directory); + final ScriptFile[] scriptFiles = mStorageScriptProvider.getDirectoryScriptFiles(directory); post(new Runnable() { @Override public void run() { - mFileProcessListener.onFileListed(); - mAdapter.notifyDataSetChanged(); + mAdapter.setScripts(scriptFiles); + if (mFileProcessListener != null) + mFileProcessListener.onFileListed(); } }); } @@ -135,9 +172,8 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView { setCurrentDirectory(directory, !directory.equals(mRootDirectory)); } - private void setRootDirectory(ScriptFile folder) { - mRootDirectory = folder; - setCurrentDirectory(mRootDirectory, false); + private void setRootDirectory(ScriptFile directory) { + mRootDirectory = directory; } public void setFileProcessListener(FileProcessListener fileProcessListener) { @@ -168,6 +204,18 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView { mScriptFileOperationEnabled = scriptFileOperationEnabled; } + public void setViewHolderSupplier(ViewHolderSupplier supplier) { + mAdapter.setViewHolderSupplier(supplier); + } + + public OnClickListener getOnItemClickListenerProxy() { + return mOnItemClickListenerProxy; + } + + public OnLongClickListener getOnItemLongClickListenerProxy() { + return mOnItemLongClickListenerProxy; + } + private void goBack() { ScriptFile parent = mCurrentDirectory.getParentFile(); setCurrentDirectory(parent, !parent.equals(mRootDirectory)); @@ -181,10 +229,11 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView { .marginResId(R.dimen.script_and_folder_list_divider_left_margin, R.dimen.script_and_folder_list_divider_right_margin) .showLastDivider() .build()); - mAdapter = new Adapter(); + mAdapter = new Adapter(mDefaultViewHolderSupplier); setAdapter(mAdapter); } + @Override protected Parcelable onSaveInstanceState() { Bundle bundle = new Bundle(); @@ -208,6 +257,7 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView { super.onAttachedToWindow(); if (mStorageScriptProvider != null) mStorageScriptProvider.registerDirectoryChangeListener(this); + } @Override @@ -234,24 +284,28 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView { } } + + @Override + public Adapter getAdapter() { + return mAdapter; + } + private void updateCurrentDirectory() { setCurrentDirectory(mCurrentDirectory, mCanGoBack); } - private class Adapter extends RecyclerView.Adapter { + private void ensureCurrentDirectory() { + if (mCurrentDirectory == null && mRootDirectory != null) { + setCurrentDirectory(mRootDirectory, false); + } + } - private final int VIEW_TYPE_FOLDER = 1; - private final int VIEW_TYPE_FILE = 2; + public class Adapter extends ViewHolderMutableAdapter { - @Override - public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - switch (viewType) { - case VIEW_TYPE_FILE: - return new FileViewHolder(LayoutInflater.from(getContext()).inflate(R.layout.script_and_folder_list_recycler_view_file, parent, false)); - case VIEW_TYPE_FOLDER: - return new ViewHolder(LayoutInflater.from(getContext()).inflate(R.layout.script_and_folder_list_recycler_view_directory, parent, false)); - } - return null; + private ScriptFile[] mScriptFileList = new ScriptFile[0]; + + public Adapter(ViewHolderSupplier viewHolderSupplier) { + super(viewHolderSupplier); } @Override @@ -259,37 +313,41 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView { if (mCanGoBack && position == 0) { holder.name.setText(".."); } else - holder.bind(mScriptFileList[getActualPosition(position)]); + holder.bind(getScriptFileAt(position)); } @Override public int getItemCount() { + ensureCurrentDirectory(); return mScriptFileList.length + (mCanGoBack ? 1 : 0); } @Override public int getItemViewType(int position) { if (mCanGoBack && position == 0) { - return VIEW_TYPE_FOLDER; + return VIEW_TYPE_DIRECTORY; } - return mScriptFileList[getActualPosition(position)].isDirectory() ? VIEW_TYPE_FOLDER : VIEW_TYPE_FILE; + return getScriptFileAt(position).isDirectory() ? VIEW_TYPE_DIRECTORY : VIEW_TYPE_FILE; + } + + public ScriptFile getScriptFileAt(int position) { + return mScriptFileList[mCanGoBack ? position - 1 : position]; + } + + void setScripts(ScriptFile[] scriptFiles) { + mScriptFileList = scriptFiles; + notifyDataSetChanged(); } - } - private int getActualPosition(int position) { - return mCanGoBack ? position - 1 : position; } - private class ViewHolder extends RecyclerView.ViewHolder { + private class DefaultViewHolder extends ViewHolder { - TextView name; - - ViewHolder(View itemView) { + DefaultViewHolder(View itemView) { super(itemView); itemView.setOnClickListener(mOnItemClickListenerProxy); itemView.setOnLongClickListener(mOnItemLongClickListenerProxy); - name = (TextView) itemView.findViewById(R.id.name); if (!mScriptFileOperationEnabled) { setMarginRight(name, 0); } @@ -301,16 +359,9 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView { view.setLayoutParams(layoutParams); } - public void bind(ScriptFile file) { - if (file.isDirectory()) { - name.setText(file.getName()); - } else { - name.setText(file.getSimplifiedName()); - } - } } - private class FileViewHolder extends ViewHolder { + private class FileViewHolder extends DefaultViewHolder { FileViewHolder(View itemView) { super(itemView); diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/main/script_list/ScriptFileChooserDialogBuilder.java b/app/src/main/java/com/stardust/scriptdroid/ui/main/script_list/ScriptFileChooserDialogBuilder.java index 52e0c173..f53291ad 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/main/script_list/ScriptFileChooserDialogBuilder.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/main/script_list/ScriptFileChooserDialogBuilder.java @@ -52,7 +52,7 @@ public class ScriptFileChooserDialogBuilder extends MaterialDialog.Builder { if (mFileCallback != null) { mScriptListWithProgressBarView.setOnItemClickListener(new ScriptAndFolderListRecyclerView.OnScriptFileClickListener() { @Override - public void onClick(ScriptFile file) { + public void onClick(ScriptFile file, int position) { mFileCallback.onFileSelection(dialog, file); } }); diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/main/task/TaskListRecyclerView.java b/app/src/main/java/com/stardust/scriptdroid/ui/main/task/TaskListRecyclerView.java index 7e6a0ec7..a3e4a901 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/main/task/TaskListRecyclerView.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/main/task/TaskListRecyclerView.java @@ -128,7 +128,7 @@ public class TaskListRecyclerView extends ThemeColorRecyclerView implements Java @Override public void onBindViewHolder(ViewHolder holder, int position) { - holder.bind(mScriptEngines.get(position).getExecutedScript()); + holder.bind((ScriptSource) mScriptEngines.get(position).getTag("script")); } @Override diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/main/task/TaskManagerFragment.java b/app/src/main/java/com/stardust/scriptdroid/ui/main/task/TaskManagerFragment.java index 768b23d0..334bfd29 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/main/task/TaskManagerFragment.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/main/task/TaskManagerFragment.java @@ -46,10 +46,10 @@ public class TaskManagerFragment extends Fragment { @Override public void onSomethingChanged() { final boolean noRunningScript = mTaskListRecyclerView.getAdapter().getItemCount() == 0; - mNoRunningScriptNotice.setVisibility(noRunningScript ? View.VISIBLE : View.GONE); mCloseAllView.postDelayed(new Runnable() { @Override public void run() { + mNoRunningScriptNotice.setVisibility(noRunningScript ? View.VISIBLE : View.GONE); mCloseAllView.setVisibility(noRunningScript ? View.GONE : View.VISIBLE); } }, 150); diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/settings/SettingsActivity.java b/app/src/main/java/com/stardust/scriptdroid/ui/settings/SettingsActivity.java index e2a81707..e5d7292a 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/settings/SettingsActivity.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/settings/SettingsActivity.java @@ -11,9 +11,11 @@ import android.view.View; import android.widget.Toast; import com.stardust.scriptdroid.Pref; +import com.stardust.scriptdroid.tool.UpdateChecker; import com.stardust.scriptdroid.ui.BaseActivity; import com.stardust.scriptdroid.ui.error.IssueReporterActivity; import com.stardust.scriptdroid.ui.main.MainActivity; +import com.stardust.scriptdroid.ui.update.UpdateCheckDialog; import com.stardust.util.IntentUtil; import com.stardust.util.MapEntries; import com.stardust.scriptdroid.R; @@ -115,6 +117,12 @@ public class SettingsActivity extends BaseActivity { EventBus.getDefault().post(new MessageEvent(MainActivity.MESSAGE_CLEAR_BACKGROUND_SETTINGS)); } }) + .entry(getString(R.string.text_check_update), new Runnable() { + @Override + public void run() { + new UpdateCheckDialog(getActivity()).show(); + } + }) .entry(getString(R.string.text_issue_report), new Runnable() { @Override public void run() { diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/update/UpdateCheckDialog.java b/app/src/main/java/com/stardust/scriptdroid/ui/update/UpdateCheckDialog.java new file mode 100644 index 00000000..6dd015d0 --- /dev/null +++ b/app/src/main/java/com/stardust/scriptdroid/ui/update/UpdateCheckDialog.java @@ -0,0 +1,98 @@ +package com.stardust.scriptdroid.ui.update; + +import android.content.Context; +import android.os.AsyncTask; +import android.support.annotation.NonNull; +import android.widget.Toast; + +import com.afollestad.materialdialogs.DialogAction; +import com.afollestad.materialdialogs.MaterialDialog; +import com.stardust.scriptdroid.BuildConfig; +import com.stardust.scriptdroid.R; +import com.stardust.scriptdroid.tool.UpdateChecker; +import com.stardust.util.IntentUtil; + +import java.util.Timer; +import java.util.TimerTask; + +/** + * Created by Stardust on 2017/4/9. + */ + +public class UpdateCheckDialog implements UpdateChecker.Callback { + + private MaterialDialog mResultDialog; + private MaterialDialog mProgressDialog; + private Context mContext; + private UpdateChecker mUpdateChecker; + + + public UpdateCheckDialog(Context context) { + mContext = context; + mUpdateChecker = new UpdateChecker(context, this); + } + + public void show() { + mProgressDialog = new MaterialDialog.Builder(mContext) + .content(mContext.getString(R.string.text_checking_update)) + .progress(true, 0) + .cancelable(false) + .show(); + mUpdateChecker.check(); + } + + @Override + public void onSuccess(UpdateChecker.CheckResult result) { + mProgressDialog.dismiss(); + if (BuildConfig.VERSION_CODE >= result.versionCode) { + Toast.makeText(mContext, R.string.text_is_latest_version, Toast.LENGTH_SHORT).show(); + return; + } + mResultDialog = buildDialog(result); + mResultDialog.show(); + String updateSite = result.downloads.get(0).name; + final String updateUrl = result.downloads.get(0).url; + mResultDialog = new MaterialDialog.Builder(mContext) + .title(mContext.getString(R.string.text_new_version) + " " + result.versionName) + .content(result.releaseNotes) + .positiveText(updateSite) + .onPositive(new MaterialDialog.SingleButtonCallback() { + @Override + public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) { + IntentUtil.browse(mContext, updateUrl); + } + }) + .show(); + } + + private MaterialDialog buildDialog(final UpdateChecker.CheckResult result) { + String updateSite = result.downloads.get(0).name; + final String updateUrl = result.downloads.get(0).url; + MaterialDialog.Builder builder = new MaterialDialog.Builder(mContext) + .title(mContext.getString(R.string.text_new_version) + " " + result.versionName) + .content(result.releaseNotes) + .positiveText(updateSite) + .onPositive(new MaterialDialog.SingleButtonCallback() { + @Override + public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) { + IntentUtil.browse(mContext, updateUrl); + } + }); + if (result.downloads.size() > 1) { + builder.negativeText(result.downloads.get(1).name) + .onNegative(new MaterialDialog.SingleButtonCallback() { + @Override + public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) { + IntentUtil.browse(mContext, result.downloads.get(1).url); + } + }); + } + return builder.build(); + } + + @Override + public void onError(Exception exception) { + mProgressDialog.dismiss(); + Toast.makeText(mContext, R.string.text_check_update_error, Toast.LENGTH_SHORT).show(); + } +} diff --git a/app/src/main/java/com/stardust/widget/BindableViewHolder.java b/app/src/main/java/com/stardust/widget/BindableViewHolder.java new file mode 100644 index 00000000..2f381472 --- /dev/null +++ b/app/src/main/java/com/stardust/widget/BindableViewHolder.java @@ -0,0 +1,18 @@ +package com.stardust.widget; + +import android.support.v7.widget.RecyclerView; +import android.view.View; + +/** + * Created by Stardust on 2017/4/8. + */ + +public abstract class BindableViewHolder extends RecyclerView.ViewHolder{ + + + public BindableViewHolder(View itemView) { + super(itemView); + } + + public abstract void bind(DataType data); +} diff --git a/app/src/main/java/com/stardust/widget/ItemTouchHelperSimpleCallback.java b/app/src/main/java/com/stardust/widget/ItemTouchHelperSimpleCallback.java new file mode 100644 index 00000000..d294749f --- /dev/null +++ b/app/src/main/java/com/stardust/widget/ItemTouchHelperSimpleCallback.java @@ -0,0 +1,39 @@ +package com.stardust.widget; + +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.helper.ItemTouchHelper; + +/** + * Created by Stardust on 2017/4/6. + */ + +public class ItemTouchHelperSimpleCallback extends ItemTouchHelper.SimpleCallback { + + private boolean mLongPressDragEnabled, mItemViewSwipeEnabled; + + public ItemTouchHelperSimpleCallback(int dragDirs, int swipeDirs) { + super(dragDirs, swipeDirs); + mItemViewSwipeEnabled = swipeDirs != 0; + mLongPressDragEnabled = dragDirs != 0; + } + + @Override + public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { + return false; + } + + @Override + public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { + + } + + @Override + public boolean isLongPressDragEnabled() { + return mLongPressDragEnabled; + } + + @Override + public boolean isItemViewSwipeEnabled() { + return mItemViewSwipeEnabled; + } +} diff --git a/app/src/main/java/com/stardust/widget/ViewHolderMutableAdapter.java b/app/src/main/java/com/stardust/widget/ViewHolderMutableAdapter.java new file mode 100644 index 00000000..a451cc91 --- /dev/null +++ b/app/src/main/java/com/stardust/widget/ViewHolderMutableAdapter.java @@ -0,0 +1,28 @@ +package com.stardust.widget; + +import android.support.v7.widget.RecyclerView; +import android.view.ViewGroup; + +/** + * Created by Stardust on 2017/4/8. + */ + +public abstract class ViewHolderMutableAdapter extends RecyclerView.Adapter { + + private ViewHolderSupplier mViewHolderSupplier; + + public ViewHolderMutableAdapter(ViewHolderSupplier viewHolderSupplier) { + mViewHolderSupplier = viewHolderSupplier; + } + + @Override + public VH onCreateViewHolder(ViewGroup parent, int viewType) { + return mViewHolderSupplier.createViewHolder(parent, viewType); + } + + public void setViewHolderSupplier(ViewHolderSupplier viewHolderSupplier) { + mViewHolderSupplier = viewHolderSupplier; + notifyDataSetChanged(); + } + +} diff --git a/app/src/main/java/com/stardust/widget/ViewHolderSupplier.java b/app/src/main/java/com/stardust/widget/ViewHolderSupplier.java new file mode 100644 index 00000000..2d67c760 --- /dev/null +++ b/app/src/main/java/com/stardust/widget/ViewHolderSupplier.java @@ -0,0 +1,14 @@ +package com.stardust.widget; + +import android.support.v7.widget.RecyclerView; +import android.view.ViewGroup; + +/** + * Created by Stardust on 2017/4/8. + */ + +public abstract class ViewHolderSupplier { + + public abstract VH createViewHolder(ViewGroup parent, int viewType); + +} diff --git a/app/src/main/res/drawable/ic_folder_outline_white.png b/app/src/main/res/drawable/ic_folder_outline_white.png new file mode 100644 index 00000000..9b892cce Binary files /dev/null and b/app/src/main/res/drawable/ic_folder_outline_white.png differ diff --git a/app/src/main/res/layout/floating_script_list_recycler_view_directory.xml b/app/src/main/res/layout/floating_script_list_recycler_view_directory.xml new file mode 100644 index 00000000..c28caf2b --- /dev/null +++ b/app/src/main/res/layout/floating_script_list_recycler_view_directory.xml @@ -0,0 +1,37 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/floating_script_list_recycler_view_file.xml b/app/src/main/res/layout/floating_script_list_recycler_view_file.xml new file mode 100644 index 00000000..1d001bce --- /dev/null +++ b/app/src/main/res/layout/floating_script_list_recycler_view_file.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/floating_script_list_recycler_view_item.xml b/app/src/main/res/layout/floating_script_list_recycler_view_item.xml deleted file mode 100644 index 57d11d2c..00000000 --- a/app/src/main/res/layout/floating_script_list_recycler_view_item.xml +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/values-en/strings.xml b/app/src/main/res/values-en/strings.xml index 3dcc1a91..c44c5003 100644 --- a/app/src/main/res/values-en/strings.xml +++ b/app/src/main/res/values-en/strings.xml @@ -158,6 +158,9 @@ 请选择要导入的脚本 刷新 ω<*)]]> + 正在检查更新 + 新版本 + 已经是最新版本 None Volume Up diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8033489d..4d11ec75 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -194,6 +194,11 @@ 清空预执行脚本 重置脚本文件选择 将在脚本文件执行前执行 + 正在检查更新 + 新版本 + 检查更新失败Orz + 检查更新 + 已经是最新版本 diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index 44114da6..c0f15410 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -67,13 +67,15 @@ android:entries="@array/run_mode_keys" android:entryValues="@array/run_mode_values" android:key="@string/key_run_mode" - android:title="@string/text_command_run_mode" android:summary="@string/summary_command_run_mode" + android:title="@string/text_command_run_mode" /> + + diff --git a/autojs/src/main/assets/javascript_engine_init.js b/autojs/src/main/assets/javascript_engine_init.js index 866e6101..8b026cb0 100644 --- a/autojs/src/main/assets/javascript_engine_init.js +++ b/autojs/src/main/assets/javascript_engine_init.js @@ -1,5 +1,5 @@ -if(__engine__ == "rhino"){ +if(__engine_name__ == "rhino"){ __importClassOld__ = importClass; var importClass = function(pack){ if(typeof(pack) == "string"){ @@ -167,9 +167,9 @@ var scrollDown = function(a, b, c, d){ var input = function(a, b){ if(arguments.length == 1){ - return __runtime__.automator.setText(__runtime__.editable(-1), a); + return __runtime__.automator.setText(__runtime__.automator.editable(-1), a); }else{ - return __runtime__.automator.setText(__runtime__.editable(a), b); + return __runtime__.automator.setText(__runtime__.automator.editable(a), b); } } @@ -246,14 +246,18 @@ var Text = function(text){ return shell("input text " + text, true).code == 1; } -var __selector__ = __runtime__.selector(); +var selector = function(){ + return __runtime__.selector(__engine__); +} + +var __selector__ = selector(); var __obj__ = new java.lang.Object(); for(var x in __selector__){ if(!__obj__[x] && !this[x]){ this[x] = (function(method) { return function(){ - var s = __runtime__.selector(); + var s = selector(); //这里不知道怎么写。尴尬。只能写成这样。 if(arguments.length == 0){ return s[method](); @@ -274,8 +278,16 @@ for(var x in __selector__){ } -var open = function(path, mode){ - return com.stardust.pio.PFile.open(path, mode); +var open = function(path, mode, encoding, bufferSize){ + if(arguments.length == 1){ + return com.stardust.pio.PFile.open(path); + }else if(arguments.length == 2){ + return com.stardust.pio.PFile.open(path, mode); + }else if(arguments.length == 3){ + return com.stardust.pio.PFile.open(path, mode, encoding); + }else if(arguments.length == 4){ + return com.stardust.pio.PFile.open(path, mode, encoding, bufferSize); + } } __importClassOld__(com.stardust.autojs.runtime.api.Shell); diff --git a/autojs/src/main/java/com/stardust/autojs/ScriptEngineService.java b/autojs/src/main/java/com/stardust/autojs/ScriptEngineService.java index 90336039..49f1dbaf 100644 --- a/autojs/src/main/java/com/stardust/autojs/ScriptEngineService.java +++ b/autojs/src/main/java/com/stardust/autojs/ScriptEngineService.java @@ -1,6 +1,7 @@ package com.stardust.autojs; import android.content.Context; +import android.util.Log; import com.stardust.autojs.engine.JavaScriptEngine; import com.stardust.autojs.engine.JavaScriptEngineManager; @@ -10,6 +11,7 @@ import com.stardust.autojs.runtime.api.Console; import com.stardust.autojs.script.ScriptSource; import java.text.DateFormat; +import java.util.Arrays; import java.util.Date; import java.util.LinkedHashSet; import java.util.Set; @@ -20,6 +22,7 @@ import java.util.Set; public class ScriptEngineService { + private static final String LOG_TAG = "ScriptEngineService"; private static ScriptEngineService instance; public static ScriptEngineService getInstance() { @@ -73,7 +76,9 @@ public class ScriptEngineService { } public JavaScriptEngine createScriptEngine() { - return mJavaScriptEngineManager.createEngine(); + JavaScriptEngine engine = mJavaScriptEngineManager.createEngine(); + Log.i(LOG_TAG, Arrays.toString(Thread.currentThread().getStackTrace())); + return engine; } public void registerEngineLifecycleCallback(JavaScriptEngineManager.EngineLifecycleCallback engineLifecycleCallback) { diff --git a/autojs/src/main/java/com/stardust/autojs/ScriptExecutionTask.java b/autojs/src/main/java/com/stardust/autojs/ScriptExecutionTask.java index 0d14c805..32f58756 100644 --- a/autojs/src/main/java/com/stardust/autojs/ScriptExecutionTask.java +++ b/autojs/src/main/java/com/stardust/autojs/ScriptExecutionTask.java @@ -40,6 +40,7 @@ public class ScriptExecutionTask implements Serializable { runtime.ensureAccessibilityServiceEnabled(); } mExecutionListener.onStart(engine, mScriptSource); + engine.setTag("script", mScriptSource); mExecutionListener.onSuccess(engine, mScriptSource, engine.execute(mScriptSource)); } catch (Exception e) { mExecutionListener.onException(engine, mScriptSource, e); diff --git a/autojs/src/main/java/com/stardust/autojs/engine/JavaScriptEngine.java b/autojs/src/main/java/com/stardust/autojs/engine/JavaScriptEngine.java index d9c86852..e3896352 100644 --- a/autojs/src/main/java/com/stardust/autojs/engine/JavaScriptEngine.java +++ b/autojs/src/main/java/com/stardust/autojs/engine/JavaScriptEngine.java @@ -21,12 +21,14 @@ public interface JavaScriptEngine { Object execute(ScriptSource scriptSource); - ScriptSource getExecutedScript(); - void forceStop(); void destroy(); + void setTag(String key, Object value); + + Object getTag(String key); + /** * @hide */ diff --git a/autojs/src/main/java/com/stardust/autojs/engine/JavaScriptEngineManager.java b/autojs/src/main/java/com/stardust/autojs/engine/JavaScriptEngineManager.java index 8eb19d15..aea66bee 100644 --- a/autojs/src/main/java/com/stardust/autojs/engine/JavaScriptEngineManager.java +++ b/autojs/src/main/java/com/stardust/autojs/engine/JavaScriptEngineManager.java @@ -44,13 +44,17 @@ public abstract class JavaScriptEngineManager { JavaScriptEngine engine = createEngineInner(); putProperties(engine); engine.init(); + addEngine(engine); + return engine; + } + + private void addEngine(JavaScriptEngine engine) { synchronized (mEngines) { mEngines.add(engine); - if(mEngineLifecycleCallback != null){ + if (mEngineLifecycleCallback != null) { mEngineLifecycleCallback.onEngineCreate(engine); } } - return engine; } public void put(String varName, Object value) { @@ -82,7 +86,7 @@ public abstract class JavaScriptEngineManager { void removeEngine(JavaScriptEngine engine) { synchronized (mEngines) { mEngines.remove(engine); - if(mEngineLifecycleCallback != null){ + if (mEngineLifecycleCallback != null) { mEngineLifecycleCallback.onEngineRemove(engine); } } diff --git a/autojs/src/main/java/com/stardust/autojs/engine/RhinoJavaScriptEngine.java b/autojs/src/main/java/com/stardust/autojs/engine/RhinoJavaScriptEngine.java index 9e8ec7ca..860a4f46 100644 --- a/autojs/src/main/java/com/stardust/autojs/engine/RhinoJavaScriptEngine.java +++ b/autojs/src/main/java/com/stardust/autojs/engine/RhinoJavaScriptEngine.java @@ -1,9 +1,13 @@ package com.stardust.autojs.engine; +import android.util.Log; + import com.stardust.autojs.rhino_android.AndroidContextFactory; import com.stardust.autojs.rhino_android.RhinoAndroidHelper; +import com.stardust.autojs.runtime.ScriptRuntime; import com.stardust.autojs.runtime.ScriptStopException; import com.stardust.autojs.script.ScriptSource; +import com.stardust.view.accessibility.AccessibilityNodeInfoAllocator; import org.mozilla.javascript.Context; import org.mozilla.javascript.ContextFactory; @@ -12,6 +16,12 @@ import org.mozilla.javascript.Scriptable; import org.mozilla.javascript.ScriptableObject; import java.io.File; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Map; +import java.util.Timer; +import java.util.TimerTask; /** * Created by Stardust on 2017/4/2. @@ -19,17 +29,20 @@ import java.io.File; public class RhinoJavaScriptEngine implements JavaScriptEngine { + private static final String LOG_TAG = "RhinoJavaScriptEngine"; + private Context mContext; private Scriptable mScriptable; private Thread mThread; private RhinoJavaScriptEngineManager mEngineManager; - private ScriptSource mScriptSource; + private Map mTags = new Hashtable<>(); public RhinoJavaScriptEngine(RhinoJavaScriptEngineManager engineManager) { mEngineManager = engineManager; mThread = Thread.currentThread(); mContext = createContext(); mScriptable = createScope(mContext); + setTag("create-traces", Arrays.toString(Thread.currentThread().getStackTrace())); } @Override @@ -39,15 +52,11 @@ public class RhinoJavaScriptEngine implements JavaScriptEngine { @Override public Object execute(ScriptSource source) { - mScriptSource = source; + setTag("execute-traces", Arrays.toString(Thread.currentThread().getStackTrace())); + setTag("execute-source", source); return mContext.evaluateString(mScriptable, source.getScript(), "