Add: Volume Changing to stop scripts, Fix: Automator ANR

This commit is contained in:
hyb1996
2017-03-20 16:04:59 +08:00
parent c9927a3ce3
commit 1f05bcce98
47 changed files with 497 additions and 141 deletions

View File

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

View File

@@ -26,6 +26,16 @@ launchApp("微信");
### currentActivity()
返回最近一次监测到的正在运行的Activity的名称一般可以认为就是当前正在运行的Activity的名称。
### getPackageName(appName)
* appName \<String\> 应用名称
获取应用的包名。例如getPackageName("QQ")为"com.tencent.mobileqq"。如果有相同名称的应用,只返回其中某一个的包名。如果不存在这个名称的应用,会返回空字符串。
### openAppSetting(packageName)
* packageName \<String\> 应用包名
打开某个应用的应用详情页也就是管理应用权限和可以停止其运行的页面。如果应用包名不存在则返回false否则返回true。
### setClip(text)
* text \<String\> 文本

View File

@@ -1,4 +1,10 @@
**自动操作的函数都需要开启"自动操作服务"才能执行,否则执行到相应函数时脚本会停止运行。**
### auto模式
如果代码的第一行是
```
"auto";
```
那么脚本运行前会先确保自动操作服务已开启。
您也可以在设置中开启"使用Root权限自动开启自动操作服务",从而在运行到相应语句时可以自动开启。
### click(text[, i])

View File

@@ -135,6 +135,14 @@ var setClip = function(text){
droid.setClip(text);
}
var getPackageName = function(appName){
return droid.getPackageName(appName);
}
var openAppSetting = function(packageName){
return droid.openAppSetting(packageName);
}
var Tap = function(x, y){
return shell("input tap " + x + " " + y, true).code == 1;
}
@@ -202,7 +210,6 @@ var Text = function(text){
return shell("input text " + text, true).code == 1;
}
var __selector__ = droid.selector();
var __obj__ = new java.lang.Object();

View File

@@ -16,6 +16,7 @@ container.addView(btnOk);
activity.setContentView(container);
btnOk.setOnClickListener(function(view){
activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("mqqwpa://im/chat?chat_type=wpa&uin=" + qq.getText())));
activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("mqqwpa://im/chat?chat_type=wpa&uin=" + qq.getText()))
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
activity.finish();
});

View File

@@ -5,8 +5,12 @@ importClass(com.afollestad.materialdialogs.MaterialDialog);
new MaterialDialog.Builder(activity)
.title("简单计算器")
.input("请输入算式", "1+1", function(dialog, input){
eval("var ans = (" + input + ")");
toast(ans);
try{
eval("var ans = (" + input + ")");
toast(ans);
}catch(e){
toast("式子错误");
}
})
.positiveText("计算")
.dismissListener(function(dialog){

View File

@@ -1,3 +1,4 @@
"auto";
launch("com.tencent.mobileqq");
toast("请打开一个聊天窗口");
toast("出现红包时将会自动拆开并关闭");

View File

@@ -1,15 +1,10 @@
"auto";
importClass(android.content.Intent);
importClass(android.net.Uri);
importClass(android.provider.Settings);
function 打开App设置(packageName){
var intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
var uri = Uri.fromParts("package", packageName, null);
intent.setData(uri);
context.startActivity(intent);
}
打开App设置("com.tencent.mobileqq");
openAppSetting("com.tencent.mobileqq");
while(!currentPackage().equals("com.android.settings"));
while(!click("通知"));
while(!click("全部阻止"));

View File

@@ -1,3 +1,4 @@
"auto";
launch("com.tencent.mm");
while(!click("发现"));
while(!click("扫一扫"));

View File

@@ -1,3 +1,4 @@
"auto";
function 打开正在运行的服务(){
launch("com.android.settings");

View File

@@ -1,2 +1,3 @@
"auto";
launchApp("支付宝");
while(!click("扫一扫"));

View File

@@ -1,3 +1,5 @@
"auto";
function 下滑(){
className("AbsListView").scrollable().scrollForward();
}

View File

@@ -1,3 +1,5 @@
"auto";
launchApp("QQ");
toast("打开一个聊天窗口,并点击下面的图片按钮");
for(i = 0; i < 100;i++){

View File

@@ -1,3 +1,5 @@
"auto";
while(true){
if(id("i4").untilFindOne().parent().parent().click()){
sleep(700);

View File

@@ -0,0 +1,15 @@
"auto";
function 取消关注(){
id("af9").longClickable().longClick();
click("取消关注");
click("不再关注");
}
toast("请在10秒内打开订阅号界面");
toast("10秒后如果没有反应请稍微滑动一下页面");
sleep(10 * 1000);
while(true){
取消关注();
}

View File

@@ -1,3 +1,5 @@
"auto";
launchApp("网易云音乐");
id("kp").click();
text("签到").className("TextView").click();

View File

@@ -43,6 +43,11 @@ public class Pref {
return def().getBoolean(getString(R.string.key_use_volume_control_record), false);
}
public static boolean isRunningVolumeControlEnable() {
return def().getBoolean(getString(R.string.key_use_volume_control_running), false);
}
private static String getString(int id) {
return App.getApp().getString(id);
}
@@ -58,4 +63,5 @@ public class Pref {
public static boolean isFirstUsing() {
return getDisposableBoolean("isFirstUsing", true);
}
}

View File

@@ -1,16 +1,20 @@
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;
import java.io.File;
@@ -32,6 +36,8 @@ public class Droid {
public static final String UI = "\"ui\";";
public static final String AUTO = "\"auto\";";
public interface OnRunFinishedListener extends Serializable {
void onRunFinished(Object result);
@@ -63,8 +69,18 @@ public class Droid {
}
};
private static Droid instance = new Droid();
private VolumeChangeObverseService.OnVolumeChangeListener mOnVolumeChangeListener = new VolumeChangeObverseService.OnVolumeChangeListener() {
@Override
public void onVolumeChange() {
if (Pref.isRunningVolumeControlEnable()) {
stopAllAndToast();
}
}
};
private Droid() {
VolumeChangeObverseService.addOnVolumeChangeListener(mOnVolumeChangeListener);
}
public static Droid getInstance() {
@@ -107,6 +123,7 @@ public class Droid {
}
public void runScript(final String script, OnRunFinishedListener listener, RunningConfig config) {
App.getApp().startService(new Intent(App.getApp(), VolumeChangeObverseService.class));
listener = listener == null ? DEFAULT_LISTENER : listener;
if (config.runInNewThread) {
if (script.startsWith(UI)) {
@@ -125,6 +142,15 @@ public class Droid {
return JAVA_SCRIPT_ENGINE.stopAll();
}
public void stopAllAndToast() {
int n = stopAll();
if (n > 0)
RUNTIME.toast(String.format(App.getResString(R.string.text_already_stop_n_scripts), n));
else
RUNTIME.toast(App.getResString(R.string.text_no_running_script));
}
private void checkFile(File file) {
if (file == null) {
throw new NullPointerException("file = null");
@@ -151,6 +177,8 @@ public class Droid {
@Override
public void run() {
try {
if (mScript.startsWith(AUTO))
DroidRuntime.getRuntime().ensureAccessibilityServiceEnable();
mOnRunFinishedListener.onRunFinished(JAVA_SCRIPT_ENGINE.execute(mScript));
} catch (Exception e) {
mOnRunFinishedListener.onException(e);

View File

@@ -26,6 +26,7 @@ import com.stardust.scriptdroid.accessibility.AccessibilityInfoProvider;
import com.stardust.scriptdroid.droid.runtime.action.ActionTarget;
import com.stardust.scriptdroid.tool.AccessibilityServiceTool;
import com.stardust.scriptdroid.service.AccessibilityWatchDogService;
import com.stardust.scriptdroid.tool.IntentTool;
import com.stardust.theme.dialog.ThemeColorMaterialDialogBuilder;
import com.jraska.console.Console;
import com.stardust.scriptdroid.App;
@@ -77,28 +78,34 @@ public class DroidRuntime {
mUIHandler = new Handler(App.getApp().getMainLooper());
}
public void launchPackage(String packageName) {
PackageManager packageManager = App.getApp().getPackageManager();
App.getApp().startActivity(packageManager.getLaunchIntentForPackage(packageName));
public boolean launchPackage(String packageName) {
try {
PackageManager packageManager = App.getApp().getPackageManager();
App.getApp().startActivity(packageManager.getLaunchIntentForPackage(packageName));
return true;
} catch (Exception e) {
return false;
}
}
public void launch(String packageName, String className) {
App.getApp().startActivity(new Intent().setClassName(packageName, className).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
public boolean launchApp(String appName) {
return launchPackage(getPackageName(appName));
}
public void launchApp(String appName) {
public String getPackageName(String appName) {
PackageManager packageManager = App.getApp().getPackageManager();
List<ApplicationInfo> installedApplications = packageManager.getInstalledApplications(PackageManager.GET_META_DATA);
for (ApplicationInfo applicationInfo : installedApplications) {
if (packageManager.getApplicationLabel(applicationInfo).toString().equals(appName)) {
launchPackage(applicationInfo.packageName);
break;
return applicationInfo.processName;
}
}
return "";
}
public String[] getPackageName(String appName) {
return new String[0];
public boolean openAppSetting(String packageName){
return IntentTool.goToAppSetting(App.getApp(), packageName);
}
public ActionTarget text(String text, int i) {

View File

@@ -9,7 +9,7 @@ import android.view.accessibility.AccessibilityNodeInfo;
public abstract class Action {
private boolean mPerformUtilSucceed = false;
private Object mResult;
private volatile Object mResult = false;
public Action(boolean performUtilSucceed) {
mPerformUtilSucceed = performUtilSucceed;

View File

@@ -12,6 +12,9 @@ import com.stardust.scriptdroid.App;
import com.stardust.scriptdroid.droid.runtime.DroidRuntime;
import com.stardust.view.accessibility.AccessibilityDelegate;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
/**
* Created by Stardust on 2017/1/21.
@@ -27,12 +30,14 @@ public class ActionPerformAccessibilityDelegate implements AccessibilityDelegate
private static Action action;
private Executor mExecutor = Executors.newFixedThreadPool(5);
public static void setAction(Action action) {
synchronized (ACTION_LOCK) {
ActionPerformAccessibilityDelegate.action = action;
}
}
@Override
public boolean onAccessibilityEvent(AccessibilityService service, AccessibilityEvent event) {
synchronized (ACTION_LOCK) {
@@ -43,18 +48,27 @@ public class ActionPerformAccessibilityDelegate implements AccessibilityDelegate
Log.v(TAG, "root = null");
return false;
}
Log.i(TAG, "perform action:" + action);
if (action.perform(root)) {
action.setResult(true);
onActionPerformed();
} else if (!action.performUtilSucceed()) {
action.setResult(false);
onActionPerformed();
}
performAction(root, action);
return false;
}
}
private void performAction(final AccessibilityNodeInfo root, final Action action) {
mExecutor.execute(new Runnable() {
@Override
public void run() {
Log.i(TAG, "perform action:" + action);
if (action.perform(root)) {
action.setResult(true);
onActionPerformed();
} else if (!action.performUtilSucceed()) {
action.setResult(false);
onActionPerformed();
}
}
});
}
private void onActionPerformed() {
synchronized (ACTION_LOCK) {

View File

@@ -9,6 +9,7 @@ import android.view.View;
import com.stardust.scriptdroid.App;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.layout_inspector.view.LayoutInspectView;
import com.stardust.scriptdroid.tool.IntentTool;
import com.stardust.view.Floaty;
import com.stardust.view.ResizableFloaty;
@@ -30,16 +31,17 @@ public class FloatingWindowManger {
public static void goToFloatingWindowPermissionSetting() {
String packageName = App.getApp().getPackageName();
Intent intent;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + packageName))
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
App.getApp().startActivity(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + packageName))
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
} catch (Exception e) {
IntentTool.goToAppSetting(App.getApp());
}
} else {
intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.parse("package:" + packageName))
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
IntentTool.goToAppSetting(App.getApp());
}
App.getApp().startActivity(intent);
}
private static boolean hasFloatingWindowPermission() {
@@ -56,6 +58,6 @@ public class FloatingWindowManger {
public static void hideFloatingWindow() {
if (HoverMenuService.isServiceRunning())
HoverMenuService.stopService();
App.getApp().stopService(new Intent(App.getApp(), HoverMenuService.class));
}
}

View File

@@ -54,7 +54,6 @@ public class HoverMenuService extends Service {
public static final String MESSAGE_MENU_EXPANDING = "MESSAGE_MENU_EXPANDING";
public static final String MESSAGE_MENU_EXIT = "MESSAGE_MENU_EXIT";
private static HoverMenuService service = null;
private static boolean sIsRunning;
public static void startService(Context context) {
@@ -66,13 +65,6 @@ public class HoverMenuService extends Service {
return sIsRunning;
}
public static void stopService() {
if (isServiceRunning() && service != null) {
service.stopSelf();
setIsRunning(false);
}
}
private static void setIsRunning(boolean isRunning) {
sIsRunning = isRunning;
EventBus.getDefault().post(new ServiceStateChangedEvent(sIsRunning));
@@ -105,20 +97,18 @@ public class HoverMenuService extends Service {
@Override
public void onCreate() {
super.onCreate();
if (service != null) {
stopSelf();
return;
}
service = this;
EventBus.getDefault().register(this);
mPrefs = getSharedPreferences(PREF_FILE, Context.MODE_PRIVATE);
tryInitViews();
}
private void tryInitViews() {
try {
initViews();
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(this, R.string.text_no_floating_window_permission, Toast.LENGTH_SHORT).show();
FloatingWindowManger.goToFloatingWindowPermissionSetting();
stopService();
}
}
@@ -171,6 +161,8 @@ public class HoverMenuService extends Service {
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (mWindowHoverMenu == null)
tryInitViews();
if (mWindowHoverMenu != null)
mWindowHoverMenu.show();
return START_STICKY;
@@ -183,8 +175,6 @@ public class HoverMenuService extends Service {
if (EventBus.getDefault().isRegistered(this))
EventBus.getDefault().unregister(this);
setIsRunning(false);
if (service == this)
service = null;
}

View File

@@ -78,11 +78,7 @@ public class MainMenuNavigatorContent implements NavigatorContent {
@ViewBinding.Click(R.id.stop_all_running_scripts)
private void stopAllRunningScripts() {
int n = Droid.getInstance().stopAll();
if (n > 0)
Toast.makeText(mView.getContext(), String.format(mView.getContext().getString(R.string.text_already_stop_n_scripts), n), Toast.LENGTH_SHORT).show();
else
Toast.makeText(mView.getContext(), R.string.text_no_running_script, Toast.LENGTH_SHORT).show();
Droid.getInstance().stopAllAndToast();
}
@ViewBinding.Click(R.id.open_launcher)

View File

@@ -1,6 +1,7 @@
package com.stardust.scriptdroid.external.floating_window.content;
import android.content.Context;
import android.content.Intent;
import android.support.annotation.NonNull;
import android.support.v7.widget.SwitchCompat;
import android.view.View;
@@ -8,6 +9,8 @@ import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.stardust.scriptdroid.App;
import com.stardust.scriptdroid.Pref;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.accessibility.AccessibilityEventHelper;
import com.stardust.scriptdroid.external.floating_window.HoverMenuService;
@@ -15,6 +18,7 @@ import com.stardust.scriptdroid.record.Recorder;
import com.stardust.scriptdroid.record.accessibility.AccessibilityActionRecorder;
import com.stardust.scriptdroid.record.inputevent.InputEventConverter;
import com.stardust.scriptdroid.record.inputevent.TouchRecorder;
import com.stardust.scriptdroid.service.VolumeChangeObverseService;
import com.stardust.scriptdroid.ui.main.MainActivity;
import com.stardust.util.MessageEvent;
import com.stardust.view.ViewBinder;
@@ -53,10 +57,26 @@ public class RecordNavigatorContent implements NavigatorContent, Recorder.OnStat
private Recorder mRecorder;
private Context mContext;
private VolumeChangeObverseService.OnVolumeChangeListener mOnVolumeChangeListener = new VolumeChangeObverseService.OnVolumeChangeListener() {
@Override
public void onVolumeChange() {
if (Pref.isRecordVolumeControlEnable()) {
if (mRecorder == null) {
startRecord();
} else if (mRecorder.getState() == Recorder.STATE_RECORDING) {
stopRecord();
}
}
}
};
public RecordNavigatorContent(Context context) {
mContext = context;
mView = View.inflate(context, R.layout.floating_window_record, null);
ViewBinder.bind(this);
EventBus.getDefault().register(this);
App.getApp().startService(new Intent(App.getApp(), VolumeChangeObverseService.class));
VolumeChangeObverseService.addOnVolumeChangeListener(mOnVolumeChangeListener);
}
@NonNull
@@ -67,16 +87,12 @@ public class RecordNavigatorContent implements NavigatorContent, Recorder.OnStat
@Override
public void onShown(@NonNull Navigator navigator) {
if (!EventBus.getDefault().isRegistered(this)) {
EventBus.getDefault().register(this);
}
}
@Override
public void onHidden() {
if (EventBus.getDefault().isRegistered(this)) {
EventBus.getDefault().unregister(this);
}
}
@ViewBinding.Click(R.id.sw_root_container)
@@ -145,6 +161,9 @@ public class RecordNavigatorContent implements NavigatorContent, Recorder.OnStat
public void onMessageEvent(MessageEvent event) {
if (event.message.equals(HoverMenuService.MESSAGE_MENU_EXPANDING)) {
pauseRecord();
} else if (event.message.equals(HoverMenuService.MESSAGE_MENU_EXIT)) {
EventBus.getDefault().unregister(this);
VolumeChangeObverseService.removeOnVolumeChangeListener(mOnVolumeChangeListener);
}
}

View File

@@ -49,7 +49,6 @@ public class AccessibilityActionRecordNotification {
case ACTION_DELETE:
AccessibilityActionRecordNotification.cancelNotification();
stopRecordIfNeeded(context);
VolumeChangeObverseService.stopServiceIfNeeded();
break;
case ACTION_REDO:
redoRecord(context);
@@ -93,7 +92,7 @@ public class AccessibilityActionRecordNotification {
.setCustomContentView(AccessibilityActionRecordSwitchView.getInstance());
}
showNotification(builder.build());
VolumeChangeObverseService.startServiceIfNeeded(App.getApp());
App.getApp().startService(new Intent(App.getApp(), VolumeChangeObverseService.class));
}
private static void showNotification(Notification notification) {

View File

@@ -4,6 +4,7 @@ import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
@@ -50,8 +51,11 @@ public class LayoutHierarchyView extends MultiLevelListView {
private Paint mPaint;
private int mStatusBarHeight;
private NodeInfo mClickedNodeInfo;
private View mClickedView;
private Drawable mOriginalBackground;
private boolean mShowClickedNodeBounds;
private int mClickedColor = 0x77c4c4c4;
public LayoutHierarchyView(Context context) {
super(context);
@@ -72,6 +76,11 @@ public class LayoutHierarchyView extends MultiLevelListView {
mShowClickedNodeBounds = showClickedNodeBounds;
}
public void setClickedColor(int clickedColor) {
mClickedColor = clickedColor;
}
private void init() {
mAdapter = new Adapter();
@@ -83,18 +92,28 @@ public class LayoutHierarchyView extends MultiLevelListView {
setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClicked(MultiLevelListView parent, View view, Object item, ItemInfo itemInfo) {
mClickedNodeInfo = (NodeInfo) item;
invalidate();
setClickedItem(view, (NodeInfo) item);
}
@Override
public void onGroupItemClicked(MultiLevelListView parent, View view, Object item, ItemInfo itemInfo) {
mClickedNodeInfo = (NodeInfo) item;
invalidate();
setClickedItem(view, (NodeInfo) item);
}
});
}
private void setClickedItem(View view, NodeInfo item) {
mClickedNodeInfo = item;
if (mClickedView == null) {
mOriginalBackground = view.getBackground();
} else {
mClickedView.setBackground(mOriginalBackground);
}
view.setBackgroundColor(mClickedColor);
mClickedView = view;
invalidate();
}
private void initPaint() {
mPaint = new Paint();
mPaint.setColor(Color.DKGRAY);

View File

@@ -14,6 +14,8 @@ import com.stardust.scriptdroid.record.accessibility.AccessibilityActionRecorder
import com.stardust.scriptdroid.Pref;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
/**
@@ -22,32 +24,27 @@ import java.lang.ref.WeakReference;
public class VolumeChangeObverseService extends Service {
public interface OnVolumeChangeListener {
void onVolumeChange();
}
private static final String ACTION_VOLUME_CHANGE = "android.media.VOLUME_CHANGED_ACTION";
private static List<OnVolumeChangeListener> mOnVolumeChangeListenerList = new ArrayList<>();
public static void addOnVolumeChangeListener(OnVolumeChangeListener listener) {
mOnVolumeChangeListenerList.add(listener);
}
public static void removeOnVolumeChangeListener(OnVolumeChangeListener listener) {
mOnVolumeChangeListenerList.remove(listener);
}
private VolumeChangeReceiver mVolumeChangeReceiver;
private static VolumeChangeObverseService instance;
public static void stopServiceIfNeeded() {
if (instance != null) {
instance.stopSelf();
instance = null;
}
}
public static void startServiceIfNeeded(Context context) {
if (Pref.isRecordVolumeControlEnable() && instance == null) {
context.startService(new Intent(context, VolumeChangeObverseService.class));
}
}
@Override
public void onCreate() {
super.onCreate();
if (instance != null) {
instance.stopSelf();
}
instance = this;
mVolumeChangeReceiver = new VolumeChangeReceiver();
registerReceiver(mVolumeChangeReceiver, new IntentFilter(ACTION_VOLUME_CHANGE));
}
@@ -61,7 +58,6 @@ public class VolumeChangeObverseService extends Service {
@Override
public void onDestroy() {
super.onDestroy();
instance = null;
unregisterReceiver(mVolumeChangeReceiver);
}
@@ -76,10 +72,8 @@ public class VolumeChangeObverseService extends Service {
return;
}
mLastChangeMillis = System.currentTimeMillis();
if (AccessibilityActionRecorder.getInstance().getState() == Recorder.STATE_STOPPED) {
AccessibilityActionRecordNotification.startRecord(VolumeChangeObverseService.this);
} else {
AccessibilityActionRecordNotification.stopRecord(VolumeChangeObverseService.this);
for (OnVolumeChangeListener listener : mOnVolumeChangeListenerList) {
listener.onVolumeChange();
}
}
}

View File

@@ -1,5 +1,6 @@
package com.stardust.scriptdroid.tool;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.widget.Toast;
@@ -32,7 +33,11 @@ public class AccessibilityServiceTool {
if (Pref.isFirstGoToAccessibilitySetting()) {
Toast.makeText(context, context.getString(R.string.text_please_choose) + context.getString(R.string._app_name), Toast.LENGTH_LONG).show();
}
AccessibilityServiceUtils.goToAccessibilitySetting(context);
try {
AccessibilityServiceUtils.goToAccessibilitySetting(context);
} catch (ActivityNotFoundException e) {
Toast.makeText(context, context.getString(R.string.go_to_accessibility_settings) + context.getString(R.string._app_name), Toast.LENGTH_LONG).show();
}
}
public static boolean enableAccessibilityServiceByRootAndWaitFor(Class<AccessibilityWatchDogService> accessibilityService, int timeout) {

View File

@@ -1,10 +1,12 @@
package com.stardust.scriptdroid.tool;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.support.annotation.Nullable;
import com.stardust.scriptdroid.App;
import com.stardust.scriptdroid.R;
/**
@@ -70,4 +72,20 @@ public class IntentTool {
.setType("text/plain"));
}
public static boolean goToAppSetting(Context context, String packageName) {
try {
Intent i = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
i.addCategory(Intent.CATEGORY_DEFAULT);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.setData(Uri.parse("package:" + packageName));
context.startActivity(i);
return true;
} catch (ActivityNotFoundException ignored) {
return false;
}
}
public static boolean goToAppSetting(Context context) {
return goToAppSetting(context, context.getPackageName());
}
}

View File

@@ -333,4 +333,13 @@ public class EditActivity extends Editor920Activity {
unregisterReceiver(mOnRunFinishedReceiver);
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
try{
super.onRestoreInstanceState(savedInstanceState);
}catch (RuntimeException e){
// FIXME: 2017/3/20
e.printStackTrace();
}
}
}

View File

@@ -50,12 +50,14 @@ public class EditSideMenuFragment extends Fragment {
return inflater.inflate(R.layout.fragment_edit_side_menu, container, false);
}
@Override
protected void afterCreateView() {
setUpUI();
}
@Override
public void onStart() {
super.onStart();
if (mFloatingWindowSwitch == null) {
setUpUI();
}
syncSwitchState();
}

View File

@@ -21,7 +21,6 @@ import java.lang.reflect.Method;
public class IssueReportActivity extends IssueReporterActivity {
private boolean mCrash = false;
private Method mReportIssue, mValidateInput;
private boolean mReportFailed = false;

View File

@@ -371,7 +371,8 @@ public class MainActivity extends BaseActivity implements FileChooserDialog.File
context.startActivity(intent);
}
public void OnAppBarClick(View view) {
@ViewBinding.Click(R.id.toolbar)
public void OnToolbarClick() {
new ImageSelector(this, mActivityResultIntermediary, new ImageSelector.ImageSelectorCallback() {
@Override
public void onImageSelected(ImageSelector selector, String path) {

View File

@@ -52,13 +52,15 @@ public class SlideMenuFragment extends Fragment {
return inflater.inflate(R.layout.fragment_slide_menu, container, false);
}
@Override
protected void afterCreateView() {
setUpSwitchCompat();
ViewBinder.bind(this);
}
@Override
public void onStart() {
super.onStart();
if (mAutoOperateServiceSwitch == null) {
setUpSwitchCompat();
ViewBinder.bind(this);
}
syncSwitchState();
}

View File

@@ -43,16 +43,7 @@ public class MyScriptListFragment extends Fragment implements BackPressedHandler
}
@Override
public void onStart() {
super.onStart();
init();
}
private void init() {
setUpScriptList();
}
private void setUpScriptList() {
protected void afterCreateView() {
mScriptListRecyclerView = $(R.id.script_list);
mScriptFileList = ScriptFileList.getImpl();
mNoScriptHint = $(R.id.hint_no_script);
@@ -69,6 +60,14 @@ public class MyScriptListFragment extends Fragment implements BackPressedHandler
mScriptListRecyclerView.setScriptFileList(mScriptFileList);
}
private void init() {
setUpScriptList();
}
private void setUpScriptList() {
}
@Override
public boolean onBackPressed() {

View File

@@ -8,6 +8,8 @@ import android.content.pm.PackageManager;
import android.net.Uri;
import android.widget.Toast;
import static com.stardust.scriptdroid.tool.IntentTool.goToAppSetting;
/**
* Created by Stardust on 2017/3/10.
*/
@@ -17,23 +19,12 @@ public class FloatingWindowUtils {
public static boolean checkFloatingWindowPermission(Context context, int messageResId) {
if (!isFloatingWindowPermitted(context)) {
Toast.makeText(context, messageResId, Toast.LENGTH_SHORT).show();
goToAppSetting(context);
goToAppSetting(context, context.getPackageName());
return false;
}
return true;
}
private static void goToAppSetting(Context context) {
try {
Intent i = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
i.addCategory(Intent.CATEGORY_DEFAULT);
i.setData(Uri.parse("package:" + context.getPackageName()));
context.startActivity(i);
} catch (ActivityNotFoundException ignored) {
}
}
public static boolean isFloatingWindowPermitted(Context context) {
PackageManager pm = context.getPackageManager();
return pm.checkPermission(Manifest.permission.SYSTEM_ALERT_WINDOW, context.getPackageName())

View File

@@ -24,7 +24,6 @@
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:onClick="OnAppBarClick"
android:title="@string/_app_name"
app:popupTheme="@style/AppTheme.PopupOverlay">

View File

@@ -0,0 +1,182 @@
<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="copyright">Copyright©2016 All right reserves.</string>
<string name="developer">星尘幻影</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="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="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_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="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="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="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_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-array name="record_control_keys">
<item></item>
<item>音量上键</item>
<item>音量下键</item>
<item>照相键</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>
</resources>

View File

@@ -165,6 +165,10 @@
<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="go_to_accessibility_settings"><![CDATA[请打开设置->无障碍服务->免Root脚本精灵并开启]]></string>
<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-array name="record_control_keys">
<item></item>

View File

@@ -14,21 +14,29 @@
<com.stardust.theme.preference.ThemeColorPreferenceCategory android:title="@string/text_script_record_with_root">
<com.afollestad.materialdialogs.prefs.MaterialListPreference
android:key="@string/key_start_record_trigger"
android:defaultValue="@string/text_none"
android:entries="@array/record_control_keys"
android:entryValues="@array/record_control_values"
android:key="@string/key_start_record_trigger"
android:title="@string/text_use_key_to_start_record"
/>
<com.afollestad.materialdialogs.prefs.MaterialListPreference
android:key="@string/key_stop_record_trigger"
android:defaultValue="@string/text_none"
android:entries="@array/record_control_keys"
android:entryValues="@array/record_control_values"
android:key="@string/key_stop_record_trigger"
android:title="@string/text_use_key_to_stop_record"
/>
</com.stardust.theme.preference.ThemeColorPreferenceCategory>
<com.stardust.theme.preference.ThemeColorPreferenceCategory android:title="@string/text_script_running">
<com.stardust.theme.preference.ThemeColorSwitchPreference
android:defaultValue="false"
android:key="@string/key_use_volume_control_running"
android:title="@string/text_use_volume_to_stop_running"/>
</com.stardust.theme.preference.ThemeColorPreferenceCategory>
<com.stardust.theme.preference.ThemeColorPreferenceCategory android:title="@string/text_edit">
<com.afollestad.materialdialogs.prefs.MaterialEditTextPreference

View File

@@ -11,6 +11,8 @@ import org.mozilla.javascript.ImporterTopLevel;
import java.lang.reflect.Array;
import java.util.Arrays;
import static org.junit.Assert.assertEquals;
/**
* Example local unit test, which will execute on the development machine (host).
*
@@ -18,10 +20,14 @@ import java.util.Arrays;
*/
public class ExampleUnitTest {
// TODO: 2017/3/3 自定义函数
// TODO: 2017/3/19 翻译
// FIXME: 2017/3/19 开始运行的提示覆盖问题
// TODO: 2017/3/19
@Test
public void test() {
assertEquals(1, 1);
Context context = Context.enter();
context.setOptimizationLevel(-1);
context.setLanguageVersion(Context.VERSION_1_7);