尝试修复某些设备上死机和重启的问题。修复在4.4上无法显示悬浮窗的问题。增加英文语言。增加获取WebView内容。

This commit is contained in:
hyb1996 2017-03-21 18:55:27 +08:00
parent 50d53fdec7
commit feff05e11c
28 changed files with 425 additions and 264 deletions

2
.gitignore vendored
View File

@ -7,4 +7,4 @@
/build
/captures
.externalNativeBuild
.apk
*.apk

View File

@ -8,8 +8,8 @@ android {
applicationId "com.stardust.scriptdroid"
minSdkVersion 19
targetSdkVersion 23
versionCode 106
versionName "2.0.3 Beta"
versionCode 108
versionName "2.0.5 Beta"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
multiDexEnabled true

View File

@ -0,0 +1,18 @@
function 下滑(){
className("ListView").scrollForward();
}
function 尝试点赞(btn){
btn.click();
sleep(300);
if(!click("赞"))
btn.click();
}
while(true){
var c = className("ImageView").desc("评论").untilFind();
c.each(function(btn){
尝试点赞(btn);
});
下滑();
}

View File

@ -1,6 +1,7 @@
package com.stardust.app;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
@ -16,6 +17,7 @@ public abstract class Fragment extends android.support.v4.app.Fragment {
private View mView;
@NonNull
public View getView() {
return mView;
}
@ -36,14 +38,9 @@ public abstract class Fragment extends android.support.v4.app.Fragment {
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
mView = createView(inflater, container, savedInstanceState);
afterCreateView();
return mView;
}
protected void afterCreateView() {
}
@Nullable
public abstract View createView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState);

View File

@ -4,16 +4,35 @@ import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import com.stardust.automator.AccessibilityEventCommandHost;
/**
* Created by Stardust on 2017/1/31.
*/
public class Pref {
private static final SharedPreferences DISPOSABLE_BOOLEAN = App.getApp().getSharedPreferences("DISPOSABLE_BOOLEAN", Context.MODE_PRIVATE);
public static final String SAMPLE_SCRIPTS_COPIED = "SAMPLE_SCRIPTS_COPIED";
private static final String KEY_MAX_TEXT_LENGTH_FOR_CODE_COMPLETION = "KEY_MAX_TEXT_LENGTH_FOR_CODE_COMPLETION";
public static final String KEY_DRAWER_HEADER_IMAGE_PATH = "KEY_DRAWER_HEADER_IMAGE_PATH";
public static final String KEY_APP_BAR_IMAGE_PATH = "KEY_APP_BAR_IMAGE_PATH";
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))) {
AccessibilityEventCommandHost.getInstance().setRunMode(getRunModeFromValue(sharedPreferences.getString(key, null)));
}
}
};
private static int getRunModeFromValue(String value) {
switch (value) {
case "KEY_THREAD_POOL":
return AccessibilityEventCommandHost.RUN_MODE_THREAD_POOL;
case "KEY_NEW_THREAD_EVERY_TIME":
return AccessibilityEventCommandHost.RUN_MODE_NEW_THREAD_EVERY_TIME;
default:
return AccessibilityEventCommandHost.RUN_MODE_SINGLE_THREAD;
}
}
public static SharedPreferences def() {
return PreferenceManager.getDefaultSharedPreferences(App.getApp());
@ -64,4 +83,23 @@ public class Pref {
return getDisposableBoolean("isFirstUsing", true);
}
public static String getDrawerHeaderImagePath() {
return def().getString(KEY_DRAWER_HEADER_IMAGE_PATH, null);
}
public static void setDrawerHeaderImagePath(String path) {
def().edit().putString(KEY_DRAWER_HEADER_IMAGE_PATH, path).apply();
}
public static String getAppBarImagePath() {
return def().getString(KEY_APP_BAR_IMAGE_PATH, null);
}
public static void setAppBarImagePath(String path) {
def().edit().putString(KEY_APP_BAR_IMAGE_PATH, path).apply();
}
static {
def().registerOnSharedPreferenceChangeListener(onSharedPreferenceChangeListener);
}
}

View File

@ -2,17 +2,12 @@ package com.stardust.scriptdroid.droid;
import android.content.Intent;
import android.support.annotation.NonNull;
import android.util.Log;
import android.widget.Toast;
import com.jraska.console.timber.ConsoleTree;
import com.stardust.scriptdroid.App;
import com.stardust.scriptdroid.Pref;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.droid.runtime.DroidRuntime;
import com.stardust.scriptdroid.droid.runtime.ScriptStopException;
import com.stardust.scriptdroid.droid.script.JavaScriptEngine;
import com.stardust.scriptdroid.droid.script.RhinoJavaScriptEngine;
import com.stardust.scriptdroid.droid.script.ScriptExecuteActivity;
import com.stardust.scriptdroid.service.VolumeChangeObverseService;
import com.stardust.scriptdroid.tool.FileUtils;
@ -21,7 +16,6 @@ import java.io.File;
import java.io.FileNotFoundException;
import java.io.Serializable;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import timber.log.Timber;
@ -102,7 +96,7 @@ public class Droid {
}
public void runScriptFile(File file, OnRunFinishedListener listener) {
Timber.v(DateFormat.getTimeInstance().format(new Date()) + "/" + App.getResString(R.string.text_start_running) + file);
Timber.v(DateFormat.getTimeInstance().format(new Date()) + " " + App.getResString(R.string.text_start_running) + " " + file);
listener = listener == null ? DEFAULT_LISTENER : listener;
try {
checkFile(file);
@ -178,7 +172,7 @@ public class Droid {
public void run() {
try {
if (mScript.startsWith(AUTO))
DroidRuntime.getRuntime().ensureAccessibilityServiceEnable();
DroidRuntime.getRuntime().ensureAccessibilityServiceEnabled();
mOnRunFinishedListener.onRunFinished(JAVA_SCRIPT_ENGINE.execute(mScript));
} catch (Exception e) {
mOnRunFinishedListener.onException(e);

View File

@ -12,7 +12,6 @@ import android.os.Environment;
import android.os.Handler;
import android.support.annotation.Nullable;
import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.style.ForegroundColorSpan;
import android.util.Log;
@ -201,7 +200,7 @@ public class DroidRuntime {
}
private <T> T performAction(Action action) {
ensureAccessibilityServiceEnable();
ensureAccessibilityServiceEnabled();
ActionPerformAccessibilityDelegate.setAction(action);
synchronized (mActionPerformLock) {
try {
@ -214,7 +213,7 @@ public class DroidRuntime {
return (T) action.getResult();
}
public void ensureAccessibilityServiceEnable() {
public void ensureAccessibilityServiceEnabled() {
if (AccessibilityWatchDogService.getInstance() == null) {
String errorMessage = null;
if (AccessibilityServiceUtils.isAccessibilityServiceEnabled(App.getApp(), AccessibilityWatchDogService.class)) {
@ -263,12 +262,12 @@ public class DroidRuntime {
}
public String currentPackage() {
ensureAccessibilityServiceEnable();
ensureAccessibilityServiceEnabled();
return AccessibilityInfoProvider.getInstance().getLatestPackage();
}
public String currentActivity() {
ensureAccessibilityServiceEnable();
ensureAccessibilityServiceEnabled();
return AccessibilityInfoProvider.getInstance().getLatestActivity();
}

View File

@ -1,9 +1,7 @@
package com.stardust.scriptdroid.droid.runtime;
import android.accessibilityservice.AccessibilityService;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.util.Log;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
@ -69,12 +67,16 @@ public class UiSelector extends UiGlobalSelector {
private static final String TAG = "UiSelector";
public UiObjectCollection find() {
DroidRuntime.getRuntime().ensureAccessibilityServiceEnable();
ensureAccessibilityServiceEnabled();
FindCommand command = new FindCommand();
AccessibilityEventCommandHost.getInstance().executeAndWaitForEvent(command);
return command.result;
}
private void ensureAccessibilityServiceEnabled(){
DroidRuntime.getRuntime().ensureAccessibilityServiceEnabled();
}
@NonNull
public UiObjectCollection untilFind() {

View File

@ -30,7 +30,7 @@ public class ActionPerformAccessibilityDelegate implements AccessibilityDelegate
private static Action action;
private Executor mExecutor = Executors.newFixedThreadPool(5);
//private Executor mExecutor = Executors.newFixedThreadPool(5);
public static void setAction(Action action) {
synchronized (ACTION_LOCK) {
@ -54,7 +54,7 @@ public class ActionPerformAccessibilityDelegate implements AccessibilityDelegate
}
private void performAction(final AccessibilityNodeInfo root, final Action action) {
mExecutor.execute(new Runnable() {
new Runnable() {
@Override
public void run() {
Log.i(TAG, "perform action:" + action);
@ -66,7 +66,7 @@ public class ActionPerformAccessibilityDelegate implements AccessibilityDelegate
onActionPerformed();
}
}
});
}.run();
}

View File

@ -17,10 +17,12 @@ import com.stardust.hover.SimpleHoverMenuTransitionListener;
import com.stardust.hover.WindowHoverMenu;
import com.stardust.scriptdroid.App;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.droid.runtime.DroidRuntime;
import com.stardust.scriptdroid.external.floating_window.view.FloatingLayoutBoundsView;
import com.stardust.scriptdroid.external.floating_window.view.FloatingLayoutHierarchyView;
import com.stardust.scriptdroid.layout_inspector.LayoutInspector;
import com.stardust.scriptdroid.layout_inspector.NodeInfo;
import com.stardust.scriptdroid.tool.AccessibilityServiceTool;
import com.stardust.theme.ThemeColorManagerCompat;
import com.stardust.util.MessageEvent;
@ -165,6 +167,7 @@ public class HoverMenuService extends Service {
tryInitViews();
if (mWindowHoverMenu != null)
mWindowHoverMenu.show();
AccessibilityServiceTool.enableAccessibilityServiceByRootIfNeeded();
return START_STICKY;
}

View File

@ -132,7 +132,7 @@ public class AccessibilityActionRecordNotification {
public static void startRecord(Context context) {
if (AccessibilityWatchDogService.getInstance() == null) {
Toast.makeText(context, R.string.text_need_enable_accessibility_service, Toast.LENGTH_SHORT).show();
Toast.makeText(context, R.string.text_need_enable_accessibility_service_to_record, Toast.LENGTH_SHORT).show();
return;
}
AccessibilityActionRecorder.getInstance().start();

View File

@ -57,4 +57,11 @@ public class AccessibilityServiceTool {
}
}
}
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);
}
}
}

View File

@ -50,8 +50,11 @@ public class EditSideMenuFragment extends Fragment {
return inflater.inflate(R.layout.fragment_edit_side_menu, container, false);
}
@Override
protected void afterCreateView() {
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
setUpUI();
}

View File

@ -32,7 +32,6 @@ import com.stardust.app.OnActivityResultDelegate;
import com.stardust.scriptdroid.Pref;
import com.stardust.scriptdroid.droid.script.file.ScriptFile;
import com.stardust.scriptdroid.droid.script.file.ScriptFileList;
import com.stardust.scriptdroid.droid.script.file.SharedPrefScriptFileList;
import com.stardust.scriptdroid.external.notification.record.AccessibilityActionRecordNotification;
import com.stardust.scriptdroid.record.inputevent.InputEventRecorder;
import com.stardust.scriptdroid.record.inputevent.InputEventToJsRecorder;
@ -99,7 +98,7 @@ public class MainActivity extends BaseActivity implements FileChooserDialog.File
private void goToAccessibilityPermissionSettingIfDisabled() {
if (!AccessibilityServiceUtils.isAccessibilityServiceEnabled(this, AccessibilityWatchDogService.class)) {
new NotRemindAgainDialog.Builder(this, "goToAccessibilityPermissionSettingIfDisabled")
.title(R.string.text_alert)
.title(R.string.text_need_to_enable_accessibility_service)
.content(R.string.explain_accessibility_permission)
.positiveText(R.string.text_go_to_setting)
.negativeText(R.string.text_cancel)
@ -157,11 +156,11 @@ public class MainActivity extends BaseActivity implements FileChooserDialog.File
private void setUpDrawerHeader() {
TextView version = $(R.id.version);
version.setText("Version " + BuildConfig.VERSION_NAME);
String path = Pref.def().getString(Pref.KEY_DRAWER_HEADER_IMAGE_PATH, null);
String path = Pref.getDrawerHeaderImagePath();
if (path != null) {
setDrawerHeaderImage(path);
}
path = Pref.def().getString(Pref.KEY_APP_BAR_IMAGE_PATH, null);
path = Pref.getAppBarImagePath();
if (path != null) {
setAppBarImage(path);
}
@ -236,7 +235,7 @@ public class MainActivity extends BaseActivity implements FileChooserDialog.File
@ViewBinding.Click(R.id.record)
private void startScriptRecord() {
if (AccessibilityWatchDogService.getInstance() == null) {
Snackbar.make(mDrawerLayout, R.string.text_need_enable_accessibility_service, Snackbar.LENGTH_SHORT).show();
Snackbar.make(mDrawerLayout, R.string.text_need_enable_accessibility_service_to_record, Snackbar.LENGTH_SHORT).show();
return;
}
AccessibilityActionRecordNotification.showOrUpdateNotification();
@ -270,7 +269,7 @@ public class MainActivity extends BaseActivity implements FileChooserDialog.File
@Override
public void onImageSelected(ImageSelector selector, String path) {
setDrawerHeaderImage(path);
Pref.def().edit().putString(Pref.KEY_DRAWER_HEADER_IMAGE_PATH, path).apply();
Pref.setDrawerHeaderImagePath(path);
mActivityResultIntermediary.removeDelegate(selector);
}
}).select();
@ -376,7 +375,7 @@ public class MainActivity extends BaseActivity implements FileChooserDialog.File
new ImageSelector(this, mActivityResultIntermediary, new ImageSelector.ImageSelectorCallback() {
@Override
public void onImageSelected(ImageSelector selector, String path) {
Pref.def().edit().putString(Pref.KEY_APP_BAR_IMAGE_PATH, path).apply();
Pref.setAppBarImagePath(path);
setAppBarImage(path);
mActivityResultIntermediary.removeDelegate(selector);
}

View File

@ -52,8 +52,9 @@ public class SlideMenuFragment extends Fragment {
return inflater.inflate(R.layout.fragment_slide_menu, container, false);
}
@Override
protected void afterCreateView() {
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
setUpSwitchCompat();
ViewBinder.bind(this);
}
@ -124,9 +125,9 @@ public class SlideMenuFragment extends Fragment {
private void stopAllRunningScripts() {
int n = Droid.getInstance().stopAll();
if (n > 0)
Snackbar.make(getActivityContentView(), String.format(getString(R.string.text_already_stop_n_scripts), n), Snackbar.LENGTH_SHORT).show();
Snackbar.make(getView(), String.format(getString(R.string.text_already_stop_n_scripts), n), Snackbar.LENGTH_SHORT).show();
else
Snackbar.make(getActivityContentView(), R.string.text_no_running_script, Snackbar.LENGTH_SHORT).show();
Snackbar.make(getView(), R.string.text_no_running_script, Snackbar.LENGTH_SHORT).show();
}
@Override

View File

@ -43,7 +43,8 @@ public class MyScriptListFragment extends Fragment implements BackPressedHandler
}
@Override
protected void afterCreateView() {
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mScriptListRecyclerView = $(R.id.script_list);
mScriptFileList = ScriptFileList.getImpl();
mNoScriptHint = $(R.id.hint_no_script);
@ -60,15 +61,6 @@ public class MyScriptListFragment extends Fragment implements BackPressedHandler
mScriptListRecyclerView.setScriptFileList(mScriptFileList);
}
private void init() {
setUpScriptList();
}
private void setUpScriptList() {
}
@Override
public boolean onBackPressed() {
if (mScriptListRecyclerView.getScriptFileOperationPopupMenu().isShowing()) {

View File

@ -73,9 +73,8 @@ public abstract class ScriptFileOperation {
@Override
public void operate(RecyclerView recyclerView, ScriptFileList scriptFileList, int position) {
Context context = recyclerView.getContext();
ScriptFile scriptFile = scriptFileList.get(position);
EditActivity.editFile(context, scriptFile.name, scriptFile.path);
EditActivity.editFile(App.getApp(), scriptFile.name, scriptFile.path);
}
}
@ -87,10 +86,9 @@ public abstract class ScriptFileOperation {
@Override
public void operate(RecyclerView recyclerView, ScriptFileList scriptFileList, int position) {
Context context = recyclerView.getContext();
ScriptFile scriptFile = scriptFileList.get(position);
Uri uri = Uri.parse("file://" + scriptFile.path);
context.startActivity(new Intent(Intent.ACTION_VIEW).setDataAndType(uri, "text/plain"));
App.getApp().startActivity(new Intent(Intent.ACTION_VIEW).setDataAndType(uri, "text/plain"));
}
}
@ -125,9 +123,8 @@ public abstract class ScriptFileOperation {
@Override
public void operate(RecyclerView recyclerView, ScriptFileList scriptFileList, int position) {
Context context = recyclerView.getContext();
ScriptFile scriptFile = scriptFileList.get(position);
new Shortcut(context).name(scriptFile.name)
new Shortcut(App.getApp()).name(scriptFile.name)
.targetClass(ShortcutActivity.class)
.icon(R.drawable.ic_robot_green)
.extras(new Intent().putExtra("path", scriptFile.path))

View File

@ -39,7 +39,8 @@ public class SampleScriptListFragment extends Fragment {
}
@Override
protected void afterCreateView() {
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mSampleScriptListRecyclerView = $(R.id.script_list);
mSampleScriptListRecyclerView.setSamples(SampleFileManager.getInstance().getSamplesFromAssets(getContext().getAssets(), "sample"));
mSampleScriptListRecyclerView.setOnItemLongClickListener(new SampleScriptListRecyclerView.OnItemLongClickListener() {

View File

@ -110,9 +110,8 @@ public class SettingsActivity extends BaseActivity {
.entry(getString(R.string.text_reset_background), new Runnable() {
@Override
public void run() {
Pref.def().edit().putString(Pref.KEY_APP_BAR_IMAGE_PATH, null)
.putString(Pref.KEY_DRAWER_HEADER_IMAGE_PATH, null)
.apply();
Pref.setAppBarImagePath(null);
Pref.setDrawerHeaderImagePath(null);
Toast.makeText(getActivity(), R.string.text_restart_app_to_apply, Toast.LENGTH_SHORT).show();
}
})

View File

@ -3,7 +3,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:foreground="?android:selectableItemBackground"
android:foreground="?android:attr/selectableItemBackground"
android:orientation="vertical"
android:paddingBottom="12dp"
android:paddingLeft="16dp"

View File

@ -9,7 +9,7 @@
android:id="@+id/layout_hierarchy"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?selectableItemBackground"
android:background="?android:attr/selectableItemBackground"
android:padding="16dp"
android:text="@string/text_layout_hierarchy"
android:textColor="@android:color/primary_text_dark"
@ -24,7 +24,7 @@
android:id="@+id/layout_bounds"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?selectableItemBackground"
android:background="?android:attr/selectableItemBackground"
android:padding="16dp"
android:text="@string/text_layout_bounds"
android:textColor="@android:color/primary_text_dark"
@ -39,7 +39,7 @@
android:id="@+id/stop_all_running_scripts"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?selectableItemBackground"
android:background="?android:attr/selectableItemBackground"
android:padding="16dp"
android:text="@string/text_close_all_running_scripts"
android:textColor="@android:color/primary_text_dark"
@ -54,7 +54,7 @@
android:id="@+id/open_launcher"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?selectableItemBackground"
android:background="?android:attr/selectableItemBackground"
android:padding="16dp"
android:text="@string/text_open_launcher"
android:textColor="@android:color/primary_text_dark"
@ -69,7 +69,7 @@
android:id="@+id/current_package"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?selectableItemBackground"
android:background="?android:attr/selectableItemBackground"
android:padding="16dp"
android:textColor="@android:color/primary_text_dark"
android:textSize="16sp"/>
@ -83,7 +83,7 @@
android:id="@+id/current_activity"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?selectableItemBackground"
android:background="?android:attr/selectableItemBackground"
android:padding="16dp"
android:textColor="@android:color/primary_text_dark"
android:textSize="16sp"/>

View File

@ -1,5 +1,6 @@
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
@ -24,7 +25,7 @@
android:id="@+id/sw_root_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?selectableItemBackground"
android:background="?android:attr/selectableItemBackground"
android:gravity="center_vertical"
android:padding="16dp">
@ -32,7 +33,9 @@
android:id="@+id/sw_recorded_by_root"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"/>
android:layout_alignParentRight="true"
android:textOn="@string/text_on"
android:textOff="@string/text_off"/>
<TextView
android:layout_width="wrap_content"
@ -54,7 +57,7 @@
android:id="@+id/sw_record_toast_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?selectableItemBackground"
android:background="?android:attr/selectableItemBackground"
android:gravity="center_vertical"
android:padding="16dp">
@ -62,7 +65,9 @@
android:id="@+id/sw_record_toast"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"/>
android:layout_alignParentRight="true"
android:textOn="@string/text_on"
android:textOff="@string/text_off"/>
<TextView
android:layout_width="wrap_content"
@ -84,7 +89,7 @@
android:id="@+id/start_or_pause"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?selectableItemBackground"
android:background="?android:attr/selectableItemBackground"
android:gravity="center_vertical"
android:paddingBottom="16dp"
android:paddingLeft="8dp"
@ -116,7 +121,7 @@
android:id="@+id/stop_record"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?selectableItemBackground"
android:background="?android:attr/selectableItemBackground"
android:gravity="center_vertical"
android:paddingBottom="16dp"
android:paddingLeft="8dp"

View File

@ -1,182 +1,171 @@
<resources>
<string name="_app_name">UiAutomator</string>
<string name="action_settings">设置</string>
<string name="action_disable_service">关闭服务</string>
<string name="text_accessibility_service_description">使脚本自动操作(点击、长按、滑动等)所需,若关闭则只能执行不涉及自动操作的脚本。</string>
<string name="text_new_file">新建文件</string>
<string name="text_import_from_file">从文件导入</string>
<string name="action_exit">退出</string>
<string name="text_service_disabled">服务已关闭</string>
<string name="text_file_manager_not_found">找不到文件管理器T.T</string>
<string name="text_file_create_fail">文件创建失败</string>
<string name="text_please_input_name">请输入名称</string>
<string name="text_name">名称</string>
<string name="text_go_to_setting">去设置</string>
<string name="explain_accessibility_permission">软件需要打开\"自动操作服务\"才能运行,请在随后的设置中选择\"免Root脚本精灵\"并开启服务。\n您也可以稍后在侧拉菜单中设置。</string>
<string name="text_cancel">取消</string>
<string name="text_path_is_empty">路径为空</string>
<string name="text_file_not_exists">文件不存在</string>
<string name="text_no_file_rw_permission">无文件读写权限</string>
<string name="action_test">内嵌920测试</string>
<string name="text_no_accessibility_permission">自动操作服务未启动,脚本已停止运行</string>
<string name="text_drawer_close">关闭侧拉菜单</string>
<string name="text_drawer_open">打开侧拉菜单</string>
<string name="text_undo">撤销</string>
<string name="text_redo">重做</string>
<string name="text_save">保存</string>
<string name="text_run">运行</string>
<string name="text_alert">提示</string>
<string name="edit_exit_without_save_warn">内容尚未保存,您确定要退出吗?</string>
<string name="text_save_and_exit">保存并退出</string>
<string name="text_exit_directly">直接退出</string>
<string name="text_setting">设置</string>
<string name="text_exit">退出</string>
<string name="text_auto_operate_service">自动操作服务</string>
<string name="text_syntax_and_api">帮助</string>
<string name="text_close_all_running_scripts">关闭所有正在运行的脚本</string>
<string name="text_about">关于</string>
<string name="text_licenses">开放源代码许可</string>
<string name="text_do_not_remind_again">不再提示</string>
<string name="text_sample_alipay_scan">支付宝扫一扫</string>
<string name="text_sample_open_running_services">示例:打开正在运行的服务(安卓6.0+)</string>
<string name="text_sample_simple_calculator">示例:简单计算器</string>
<string name="action_settings">Settings</string>
<string name="action_disable_service">Disable Service</string>
<string name="text_accessibility_service_description">Required by the script automatic operation (click, long press, slide, etc.).</string>
<string name="text_new_file">New File</string>
<string name="text_import_from_file">Import File</string>
<string name="action_exit">Exit</string>
<string name="text_service_disabled">Service disabled.</string>
<string name="text_file_manager_not_found">No file explorer T.T</string>
<string name="text_file_create_fail">File creation failed</string>
<string name="text_please_input_name">Input name</string>
<string name="text_name">Name</string>
<string name="text_go_to_setting">Go to setting</string>
<string name="explain_accessibility_permission">Need to enable the Accessibility service.\nYou can also enable it later in the side menu.</string>
<string name="text_cancel">Cancel</string>
<string name="text_path_is_empty">Path is empty</string>
<string name="text_file_not_exists">File dost not exist</string>
<string name="text_no_file_rw_permission">No file read and write permissions</string>
<string name="text_no_accessibility_permission">The accessibility service is disabled and the script has stopped</string>
<string name="text_drawer_close">Close drawer</string>
<string name="text_drawer_open">Open drawer</string>
<string name="text_undo">Undo</string>
<string name="text_redo">Redo</string>
<string name="text_save">Save</string>
<string name="text_run">Run</string>
<string name="text_alert">Prompt</string>
<string name="edit_exit_without_save_warn">The content has not been saved, are you sure you want to exit?</string>
<string name="text_save_and_exit">Save &amp; Exit</string>
<string name="text_exit_directly">Exit</string>
<string name="text_setting">Settings</string>
<string name="text_exit">Exit</string>
<string name="text_auto_operate_service">Accessibility Service</string>
<string name="text_syntax_and_api">Help</string>
<string name="text_close_all_running_scripts">Stop all running scripts</string>
<string name="text_about">About</string>
<string name="text_licenses">Open Sources Licenses</string>
<string name="text_do_not_remind_again">Don\'t show again</string>
<string name="copyright">Copyright©2016 All right reserves.</string>
<string name="developer">星尘幻影</string>
<string name="developer">Stardust</string>
<string name="qq">946994919</string>
<string name="email">hybbbb1996@gmail.com</string>
<string name="github">软件源代码</string>
<string name="text_already_copy_to_clip">已复制到剪贴板</string>
<string name="donate_developer">打赏作者</string>
<string name="text_email">邮箱</string>
<string name="github">Source Code</string>
<string name="text_already_copy_to_clip">Copied</string>
<string name="donate_developer">Donate</string>
<string name="text_email">Email</string>
<string name="my_github">https://github.com/hyb1996/NoRootScriptDroid</string>
<string name="share_app">[免Root脚本精灵]下载地址http://www.coolapk.com/apk/com.stardust.scriptdroid </string>
<string name="text_floating_window">悬浮窗</string>
<string name="text_assist_service_notification">通知栏点击区域辅助开关</string>
<string name="text_others">其他</string>
<string name="text_assist_mode_enabled">点击区域辅助服务已开启(点击关闭)</string>
<string name="text_assist_mode_disabled">点击区域辅助服务已关闭(点击开启)</string>
<string name="text_error_report">错误报告</string>
<string name="text_sample_qq_hongbao">示例QQ自动抢红包</string>
<string name="text_press_again_to_exit">再按一次退出程序</string>
<string name="text_common_function">常用函数</string>
<string name="sorry_for_crash">很抱歉(ಥ _ ಥ)程序遇到未知错误,即将停止运行\n错误代码</string>
<string name="text_no_running_script">没有正在运行的脚本</string>
<string name="text_already_stop_n_scripts">已停止%d个正在运行的脚本</string>
<string name="text_start_running">开始运行</string>
<string name="text_open_by_other_apps">用其他应用打开</string>
<string name="text_rename">重命名</string>
<string name="text_rename_file_meanwhile">同时重命名原文件</string>
<string name="text_please_input_new_name">请输入新名称</string>
<string name="text_send_shortcut">创建桌面快捷方式</string>
<string name="text_already_create">已创建</string>
<string name="text_delete">删除</string>
<string name="text_delete_absolutly">彻底删除</string>
<string name="text_already_delete">已删除</string>
<string name="text_delete_failed">文件删除失败</string>
<string name="text_choose_file">选择一个文件</string>
<string name="folder_name">/脚本/</string>
<string name="text_error">错误</string>
<string name="text_load_failed">还没有文档/(ㄒoㄒ)/~~</string>
<string name="text_copy_debug_info">复制调试信息</string>
<string name="text_it_is_the_developer_of_app">这是软件开发者(。・・)</string>
<string name="text_lll">略略略</string>
<string name="text_choose_email_app">请选择邮件应用</string>
<string name="text_assist_clip">点击定位剪贴板</string>
<string name="text_script_stopped">脚本已停止</string>
<string name="assist_mode_notice">\"点击区域辅助服务\"是在要点击的区域不是文本时使用的,参见\"帮助\"。\"点击区域辅助服务\"只有在\"自动操作服务\"开启时才有效。</string>
<string name="text_please_choose">请选择</string>
<string name="text_crash">崩溃了o(≧口≦)o</string>
<string name="crash_feedback">点击\"退出\"退出程序(ಥ _ ಥ)或者提交错误报告或者复制调试信息反馈给开发者(≧∇≦)ノ</string>
<string name="text_cannot_create_dialog_when_app_invisible">无法在后台显示弹框,脚本已停止运行</string>
<string name="text_sample_for_qq_chat">示例QQ强制聊天</string>
<string name="text_re_import_samples">重新导入示例脚本文件</string>
<string name="text_re_import_succeed">导入成功</string>
<string name="text_fail">失败</string>
<string name="text_clear">清空</string>
<string name="text_console">控制台</string>
<string name="text_sample_wechat_scan">微信扫一扫</string>
<string name="text_report_bug">提交错误报告</string>
<string name="share_app">[UiAutomator]Downloadhttp://www.coolapk.com/apk/com.stardust.scriptdroid </string>
<string name="text_floating_window">Floating Window</string>
<string name="text_others">Others</string>
<string name="text_error_report">Bug Report</string>
<string name="text_press_again_to_exit">Press again to exit</string>
<string name="text_common_function">Common using functions</string>
<string name="text_no_running_script">No running scipts</string>
<string name="text_already_stop_n_scripts">%d script(s) is(are) stopped</string>
<string name="text_start_running">Running</string>
<string name="text_open_by_other_apps">Open by other apps</string>
<string name="text_rename">Rename</string>
<string name="text_rename_file_meanwhile">Rename file</string>
<string name="text_please_input_new_name">Input new name</string>
<string name="text_send_shortcut">Create shortcut</string>
<string name="text_already_create">Created</string>
<string name="text_delete">Delete</string>
<string name="text_delete_absolutly">Delete file</string>
<string name="text_already_delete">Deleted</string>
<string name="text_delete_failed">File deletion failed</string>
<string name="text_choose_file">Choose a file</string>
<string name="folder_name">/Scripts/</string>
<string name="text_error">Error</string>
<string name="text_load_failed">There is no documentation yet/(ㄒoㄒ)/~~</string>
<string name="text_copy_debug_info">Copy debugging log</string>
<string name="text_it_is_the_developer_of_app">This is a software developer(。・・)</string>
<string name="text_lll">lol</string>
<string name="text_choose_email_app">Choose a email application</string>
<string name="text_script_stopped">Script stopped</string>
<string name="text_please_choose">Please choose </string>
<string name="text_crash">Crash~ o(≧口≦)o</string>
<string name="crash_feedback">(ಥ _ ಥ)Exit or submit a bug report or copy debugging log to the developer(≧∇≦)ノ</string>
<string name="text_fail">Failed</string>
<string name="text_clear">Clear</string>
<string name="text_console">Console</string>
<string name="text_report_bug">Submit Bug report</string>
<string name="text_bug_report">Bug Report</string>
<string name="text_report_fail">提交失败</string>
<string name="text_report_succeed">提交成功</string>
<string name="edit_and_run_handle_intent_error">无法处理文件</string>
<string name="text_report_fail">Submission Failed</string>
<string name="text_report_succeed">Submitted successfully</string>
<string name="edit_and_run_handle_intent_error">Cannot process file</string>
<string name="text_crash_en">Crash</string>
<string name="text_issue_report">问题反馈</string>
<string name="text_script_record">录制脚本</string>
<string name="hint_start_record">在通知栏中开始录制</string>
<string name="text_start_record">开始录制</string>
<string name="text_stop_record">停止录制</string>
<string name="text_not_recording">录制未开始</string>
<string name="text_pause_record">暂停录制</string>
<string name="text_resume_record">继续录制</string>
<string name="text_recorded">录制结束</string>
<string name="text_copy_to_clip">复制到剪贴板</string>
<string name="text_file_write_fail">文件写入失败</string>
<string name="text_need_enable_accessibility_service">需要打开\"自动操作服务“才能录制脚本</string>
<string name="text_join_qq_group">加入QQ交流群</string>
<string name="text_copied">已复制到剪贴板</string>
<string name="text_close">关闭</string>
<string name="text_re_record">重新录制</string>
<string name="text_use_volume_control_record">使用音量键控制</string>
<string name="summary_use_volume_control_record">开启后每次音量变化会开始或停止脚本录制</string>
<string name="text_issue_report">Feedback</string>
<string name="text_script_record">Record touches</string>
<string name="text_start_record">Start</string>
<string name="text_stop_record">Stop</string>
<string name="text_not_recording">Recording is not started</string>
<string name="text_pause_record">Pause</string>
<string name="text_resume_record">Resume</string>
<string name="text_recorded">Recording stopped</string>
<string name="text_copy_to_clip">Copy</string>
<string name="text_file_write_fail">File writing failed</string>
<string name="text_need_enable_accessibility_service_to_record">Need to enable the Accessibility Service</string>
<string name="text_join_qq_group">Join in QQ Group</string>
<string name="text_copied">Copied</string>
<string name="text_close">Close</string>
<string name="text_use_volume_control_record">Use the volume keys to control</string>
<string name="summary_use_volume_control_record">Stop or start recording when volume changes</string>
<string name="key_use_volume_control_record">key_use_volume_control_record</string>
<string name="text_mobile_qq_not_installed">未安装手机QQ</string>
<string name="text_edit">编辑</string>
<string name="text_mobile_qq_not_installed">Not installed mobile QQ</string>
<string name="text_edit">Edit</string>
<string name="key_max_length_for_code_completion">key_max_length_for_code_completion</string>
<string name="text_max_length_for_code_completion">代码补全最大文件长度</string>
<string name="text_file_exists">文件已存在</string>
<string name="text_accessibility_service">无障碍服务</string>
<string name="text_enable_accessibility_service_by_root">通过Root权限自动启用服务</string>
<string name="text_auto_operate_service_enabled_but_not_running">自动操作服务已启用但并未运行这可能是安卓的BUG您可能需要重启手机</string>
<string name="text_max_length_for_code_completion">Maximum file length of code complements</string>
<string name="text_file_exists">The file exists</string>
<string name="text_accessibility_service">Accessibility Service</string>
<string name="text_enable_accessibility_service_by_root">Enable service automatically with root</string>
<string name="text_auto_operate_service_enabled_but_not_running">Accessibility service is enabled but not running. This may be Android\'s BUG. You may need to restart your phone</string>
<string name="key_enable_accessibility_service_by_root">key_enable_accessibility_service_by_root</string>
<string name="text_enable_accessibility_service_by_root_timeout">使用Root权限启动自动操作服务超时</string>
<string name="summary_enable_accessibility_service_by_root">开启后运行脚本会使用Root权限自动开启自动操作服务</string>
<string name="text_appearance">外观</string>
<string name="text_theme_color">主题色</string>
<string name="text_select_image">选择图片</string>
<string name="text_help">帮助</string>
<string name="text_root_script_record">录制脚本(root)</string>
<string name="hint_start_root_record">使用音量上键,音量下键结束录制</string>
<string name="text_no_floating_window_permission">没有悬浮窗权限</string>
<string name="text_node_info">节点信息</string>
<string name="text_layout_hierarchy">布局层次分析</string>
<string name="text_layout_bounds">布局范围查看</string>
<string name="text_no_accessibility_permission_to_capture">无障碍服务未启动</string>
<string name="text_sample_script">示例脚本</string>
<string name="text_my_script">我的脚本</string>
<string name="hint_no_script">点击右上角新建第一个脚本吧~(。・・)</string>
<string name="text_reset_background">重置背景图片设置</string>
<string name="text_restart_app_to_apply">重启软件生效</string>
<string name="text_record_with_root">使用root权限录制</string>
<string name="text_record_msg">录制提示</string>
<string name="text_text_changed">文字改变</string>
<string name="text_scrolled">滑动</string>
<string name="text_long_clicked">长按</string>
<string name="text_clicked">点击</string>
<string name="text_open_launcher">打开主界面</string>
<string name="text_copy_to_my_scripts">导入到我的脚本</string>
<string name="text_import_succeed">导入成功</string>
<string name="text_no_root_script_record">免Root脚本录制</string>
<string name="text_script_record_with_root">Root脚本录制</string>
<string name="text_use_key_to_start_record">开始录制按键</string>
<string name="text_use_key_to_stop_record">结束录制按键</string>
<string name="text_enable_accessibility_service_by_root_timeout">Start the accessibility service timeout</string>
<string name="summary_enable_accessibility_service_by_root">Enable accessibility service automatically when needed</string>
<string name="text_appearance">Appearance</string>
<string name="text_theme_color">Theme Color</string>
<string name="text_select_image">Choose a picture</string>
<string name="text_help">Help</string>
<string name="text_no_floating_window_permission">No floating window permission</string>
<string name="text_node_info">Node info</string>
<string name="text_layout_hierarchy">View layout hierarchy</string>
<string name="text_layout_bounds">View layout bounds</string>
<string name="text_no_accessibility_permission_to_capture">Accessibility service is not activated</string>
<string name="text_sample_script">Sample Scripts</string>
<string name="text_my_script">My Scripts</string>
<string name="hint_no_script">Click ADD to create your first script~(。・・)</string>
<string name="text_reset_background">Reset background settings</string>
<string name="text_restart_app_to_apply">Restart to apply</string>
<string name="text_record_with_root">Recording with Rooting</string>
<string name="text_record_msg">Recording Prompt</string>
<string name="text_text_changed">Text Changed</string>
<string name="text_scrolled">Scrolled</string>
<string name="text_long_clicked">Long Clicked</string>
<string name="text_clicked">Clicked</string>
<string name="text_open_launcher">Open Application</string>
<string name="text_copy_to_my_scripts">Import to my scripts</string>
<string name="text_import_succeed">Import successful</string>
<string name="text_no_root_script_record">Record without root</string>
<string name="text_script_record_with_root">Record with root</string>
<string name="text_use_key_to_start_record">Key to start</string>
<string name="text_use_key_to_stop_record">Key to stop</string>
<string name="text_none">NONE</string>
<string name="key_start_record_trigger">key_start_record_trigger</string>
<string name="key_stop_record_trigger">key_stop_record_trigger</string>
<string name="text_current_activity">当前活动:</string>
<string name="text_current_package">当前应用包名:</string>
<string name="text_current_activity">Current Activity:</string>
<string name="text_current_package">Current Package:</string>
<string name="go_to_accessibility_settings"><![CDATA[Settings->Accessibility Services->UiAutomator]]></string>
<string name="text_script_running">Script</string>
<string name="key_use_volume_control_running">key_use_volume_control_running</string>
<string name="text_use_volume_to_stop_running">Stop all scripts when volume changes</string>
<string name="text_need_to_enable_accessibility_service">Need to enable Accessibility Service</string>
<string name="text_advanced">Advanced</string>
<string name="text_command_run_mode">Auto operation function running mode</string>
<string name="summary_command_run_mode">If the app responses slowly when running script, choose Thread Pool or Create Thread. But it may causes rebooting of the device</string>
<string name="text_on">ON</string>
<string name="text_off">OFF</string>
<string-array name="record_control_keys">
<item></item>
<item>音量上键</item>
<item>音量下键</item>
<item>照相键</item>
<item>None</item>
<item>Volume Up</item>
<item>Volume Down</item>
<item>Camera</item>
</string-array>
<string-array name="record_control_values">
<item>NONE</item>
<item>KEY_VOLUMEUP</item>
<item>KEY_VOLUMEDOWN</item>
<item>KEY_CAMERA</item>
<string-array name="run_mode_keys">
<item>Single Thread</item>
<item>Create New Thread Every Time</item>
<item>Thread Pool</item>
</string-array>
</resources>

View File

@ -112,7 +112,7 @@
<string name="text_recorded">录制结束</string>
<string name="text_copy_to_clip">复制到剪贴板</string>
<string name="text_file_write_fail">文件写入失败</string>
<string name="text_need_enable_accessibility_service">需要打开\"自动操作服务“才能录制脚本</string>
<string name="text_need_enable_accessibility_service_to_record">需要打开\"自动操作服务“才能录制脚本</string>
<string name="text_join_qq_group">加入QQ交流群</string>
<string name="text_copied">已复制到剪贴板</string>
<string name="text_close">关闭</string>
@ -169,6 +169,14 @@
<string name="text_script_running">脚本运行</string>
<string name="key_use_volume_control_running">key_use_volume_control_running</string>
<string name="text_use_volume_to_stop_running">每次音量键变化停止所有脚本</string>
<string name="text_need_to_enable_accessibility_service">需要启用无障碍服务</string>
<string name="text_advanced">高级</string>
<string name="key_run_mode">运行方式</string>
<string name="text_command_run_mode">自动操作函数执行方式</string>
<string name="summary_command_run_mode">如果运行脚本后界面卡顿请尝试多线程或线程池,但这可能导致设备重启</string>
<string name="key_single_thread">KEY_SINGLE_THREAD</string>
<string name="text_on">已开启</string>
<string name="text_off">已关闭</string>
<string-array name="record_control_keys">
<item></item>
@ -183,4 +191,16 @@
<item>KEY_VOLUMEDOWN</item>
<item>KEY_CAMERA</item>
</string-array>
<string-array name="run_mode_keys">
<item>单线程</item>
<item>每次都创建新线程</item>
<item>线程池</item>
</string-array>
<string-array name="run_mode_values">
<item>KEY_SINGLE_THREAD</item>
<item>KEY_NEW_THREAD_EVERY_TIME</item>
<item>KEY_THREAD_POOL</item>
</string-array>
</resources>

View File

@ -3,6 +3,7 @@
android:accessibilityEventTypes="typeAllMask"
android:accessibilityFeedbackType="feedbackGeneric"
android:accessibilityFlags="flagIncludeNotImportantViews|flagReportViewIds|flagRetrieveInteractiveWindows"
android:canRequestEnhancedWebAccessibility="true"
android:canRetrieveWindowContent="true"
android:description="@string/text_accessibility_service_description"
android:notificationTimeout="100"/>

View File

@ -60,6 +60,18 @@
<Preference android:title="@string/text_reset_background"/>
</com.stardust.theme.preference.ThemeColorPreferenceCategory>
<com.stardust.theme.preference.ThemeColorPreferenceCategory android:title="@string/text_advanced">
<com.afollestad.materialdialogs.prefs.MaterialListPreference
android:defaultValue="@string/key_single_thread"
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"
/>
</com.stardust.theme.preference.ThemeColorPreferenceCategory>
<com.stardust.theme.preference.ThemeColorPreferenceCategory android:title="@string/text_about">
<Preference android:title="@string/text_issue_report"/>

View File

@ -9,7 +9,14 @@ import org.mozilla.javascript.Context;
import org.mozilla.javascript.ImporterTopLevel;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import static org.junit.Assert.assertEquals;
@ -20,26 +27,80 @@ import static org.junit.Assert.assertEquals;
*/
public class ExampleUnitTest {
// TODO: 2017/3/3 自定义函数
// TODO: 2017/3/19 翻译
// FIXME: 2017/3/19 开始运行的提示覆盖问题
// TODO: 2017/3/19
// TODO: 2017/3/19
Counter counter = new Counter(5);
private List<Integer> mIntegers = new ArrayList<>();
@Test
public void test() {
assertEquals(1, 1);
Context context = Context.enter();
context.setOptimizationLevel(-1);
context.setLanguageVersion(Context.VERSION_1_7);
context.setInstructionObserverThreshold(10000);
ImporterTopLevel importerTopLevel = new ImporterTopLevel();
importerTopLevel.initStandardObjects(context, false);
context.evaluateString(importerTopLevel, "var a = 1;var b = function(){};", "<init>", 1, null);
String[] ids = (String[]) importerTopLevel.getIds();
System.out.println(ids[0].getClass());
System.out.println(Arrays.toString(ids));
for(Object id : ids){
System.out.println(importerTopLevel.get(id));
ExecutorService executor = Executors.newFixedThreadPool(10);
executor.execute(new Task(1, 100));
executor.execute(new Task(2, 1000));
System.out.println(0);
executor.execute(new Task(3, 100));
executor.execute(new Task(4, 100));
executor.execute(new Task(5, 100));
System.out.println(100);
counter.lock();
}
private class Task implements Runnable {
public Task(int i, int delay) {
this.i = i;
this.delay = delay;
}
private final int i, delay;
@Override
public void run() {
if (delay > 0)
try {
Thread.sleep(delay);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(i);
synchronized (mIntegers) {
mIntegers.add(i);
for (Integer integer : mIntegers) {
System.out.println(i + ":" + integer);
}
}
counter.minus();
}
}
private static class Counter {
private final Object lock = new Object();
public Counter(int i) {
this.i = i;
}
private volatile int i;
void minus() {
i--;
if (i == 0) {
synchronized (lock) {
lock.notify();
}
}
}
void lock() {
synchronized (lock) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}

View File

@ -31,31 +31,50 @@ public class AccessibilityEventCommandHost implements AccessibilityDelegate {
private static final String TAG = "CommandHostDelegate";
public static final int RUN_MODE_SINGLE_THREAD = 0;
public static final int RUN_MODE_THREAD_POOL = 1;
public static final int RUN_MODE_NEW_THREAD_EVERY_TIME = 2;
private final Queue<Command> mCommands = new LinkedList<>();
private Executor mExecutor = Executors.newFixedThreadPool(5);
private int mRunMode = 0;
@Override
public boolean onAccessibilityEvent(final AccessibilityService service, final AccessibilityEvent event) {
synchronized (mCommands) {
if (!mCommands.isEmpty()) {
Log.v(TAG, "execute " + mCommands.size() + " commands");
Log.v(TAG, "will execute " + mCommands.size() + " commands");
}
while (!mCommands.isEmpty()) {
final Command command = mCommands.poll();
mExecutor.execute(new Runnable() {
@Override
public void run() {
command.execute(service, event);
synchronized (command) {
command.notify();
}
}
});
executeCommand(command, service, event);
}
}
return false;
}
private void executeCommand(final Command command, final AccessibilityService service, final AccessibilityEvent event) {
Runnable r = new Runnable() {
@Override
public void run() {
Log.v(TAG, "executing " + command);
command.execute(service, event);
synchronized (command) {
Log.v(TAG, "notify " + mCommands.size() + " commands");
command.notify();
}
}
};
if (mRunMode == RUN_MODE_SINGLE_THREAD) {
r.run();
} else if (mRunMode == RUN_MODE_NEW_THREAD_EVERY_TIME) {
new Thread(r).start();
} else {
mExecutor.execute(r);
}
}
public void executeAndWaitForEvent(Command command) {
synchronized (mCommands) {
@ -70,4 +89,8 @@ public class AccessibilityEventCommandHost implements AccessibilityDelegate {
}
}
public void setRunMode(int mode) {
mRunMode = mode;
}
}