Added getTexts and action recorder, fixed github issue report token
@ -7,8 +7,8 @@ android {
|
||||
applicationId "com.stardust.scriptdroid"
|
||||
minSdkVersion 19
|
||||
targetSdkVersion 23
|
||||
versionCode 22
|
||||
versionName "1.17.0213"
|
||||
versionCode 25
|
||||
versionName "1.17.0215"
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
buildTypes {
|
||||
@ -25,6 +25,10 @@ android {
|
||||
dataBinding {
|
||||
enabled = true
|
||||
}
|
||||
lintOptions {
|
||||
disable 'MissingTranslation'
|
||||
disable 'ExtraTranslation'
|
||||
}
|
||||
android.applicationVariants.all { variant ->
|
||||
variant.outputs.each { output ->
|
||||
def file = output.outputFile
|
||||
|
||||
@ -17,8 +17,9 @@
|
||||
android:theme="@style/AppTheme"
|
||||
tools:replace="android:label">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:name=".ui.main.MainActivity"
|
||||
android:label="@string/_app_name"
|
||||
android:launchMode="singleTask"
|
||||
android:theme="@style/AppTheme.NoActionBar">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
@ -28,7 +29,7 @@
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".ShortcutActivity"
|
||||
android:name=".external.shortcut.ShortcutActivity"
|
||||
android:theme="@style/AppTheme.NoActionBar">
|
||||
|
||||
<intent-filter>
|
||||
@ -38,7 +39,7 @@
|
||||
</activity>
|
||||
|
||||
<service
|
||||
android:name=".droid.runtime.action.ActionPerformService"
|
||||
android:name=".service.AccessibilityWatchDogService"
|
||||
android:enabled="true"
|
||||
android:exported="true"
|
||||
android:label="@string/_app_name"
|
||||
@ -53,7 +54,7 @@
|
||||
</service>
|
||||
|
||||
<service
|
||||
android:name="com.stardust.scriptdroid.tile.BoundsAssistEnableTileService"
|
||||
android:name=".external.tile.BoundsAssistEnableTileService"
|
||||
android:icon="@drawable/ic_robot_head"
|
||||
android:label="脚本辅助"
|
||||
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
|
||||
@ -73,21 +74,22 @@
|
||||
android:resource="@xml/provider_paths"/>
|
||||
</provider>
|
||||
|
||||
<activity android:name=".EditActivity"/>
|
||||
<activity android:name=".DocumentActivity"/>
|
||||
<activity android:name=".AboutActivity"/>
|
||||
<activity android:name=".SettingsActivity"/>
|
||||
<activity android:name=".droid.ConsoleActivity"/>
|
||||
<activity android:name=".ErrorReportActivity"/>
|
||||
<activity android:name=".ui.edit.EditActivity"/>
|
||||
<activity android:name=".ui.help.DocumentActivity"/>
|
||||
<activity android:name=".ui.settings.AboutActivity"/>
|
||||
<activity android:name=".ui.settings.SettingsActivity"/>
|
||||
<activity android:name=".ui.console.ConsoleActivity"/>
|
||||
<activity android:name=".ui.error.ErrorReportActivity"/>
|
||||
<activity
|
||||
android:name=".IssueReportActivity"
|
||||
android:name=".ui.error.IssueReportActivity"
|
||||
android:theme="@style/IssueReportTheme"/>
|
||||
<activity android:name=".droid.script.ScriptExecuteActivity"/>
|
||||
|
||||
<service android:name=".AssistModeSwitchService"/>
|
||||
<service android:name=".external.notification.bounds_assist.BoundsAssistSwitchNotificationHandleService"/>
|
||||
<service android:name=".external.notification.record.ActionRecordNotificationHandleService"/>
|
||||
|
||||
<activity
|
||||
android:name=".EditAndRunIntentActivity"
|
||||
android:name=".ui.edit.EditAndRunIntentActivity"
|
||||
android:icon="@drawable/ic_edit_green_48dp"
|
||||
android:label="编辑与运行脚本">
|
||||
|
||||
@ -126,7 +128,7 @@
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".ImportIntentActivity"
|
||||
android:name=".ui.edit.ImportIntentActivity"
|
||||
android:icon="@drawable/ic_folder_open_outline_green"
|
||||
android:label="导入脚本文件">
|
||||
|
||||
|
||||
@ -120,4 +120,8 @@ var clearConsole = function(){
|
||||
var shell = function(cmd, root){
|
||||
root = root ? 1 : 0;
|
||||
droid.shell(cmd, root);
|
||||
}
|
||||
|
||||
var getTexts = function(){
|
||||
return droid.getTexts();
|
||||
}
|
||||
@ -5,21 +5,27 @@ import android.app.Application;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
import com.stardust.scriptdroid.droid.runtime.action.ActionPerformAccessibilityDelegate;
|
||||
import com.stardust.scriptdroid.record.AccessibilityRecorderDelegate;
|
||||
import com.stardust.scriptdroid.service.AccessibilityWatchDogService;
|
||||
import com.stardust.scriptdroid.ui.error.ErrorReportActivity;
|
||||
import com.stardust.util.CrashHandler;
|
||||
import com.stardust.util.StateObserver;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/1/27.
|
||||
*/
|
||||
|
||||
public class App extends Application {
|
||||
|
||||
private static App instance;
|
||||
private static WeakReference<App> instance;
|
||||
private static StateObserver stateObserver;
|
||||
private static Activity currentActivity;
|
||||
private static WeakReference<Activity> currentActivity;
|
||||
|
||||
public static App getApp() {
|
||||
return instance;
|
||||
return instance.get();
|
||||
}
|
||||
|
||||
public static StateObserver getStateObserver() {
|
||||
@ -29,13 +35,24 @@ public class App extends Application {
|
||||
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
Thread.setDefaultUncaughtExceptionHandler(new CrashHandler(ErrorReportActivity.class));
|
||||
instance = this;
|
||||
if (!BuildConfig.DEBUG)
|
||||
Thread.setDefaultUncaughtExceptionHandler(new CrashHandler(ErrorReportActivity.class));
|
||||
instance = new WeakReference<>(this);
|
||||
stateObserver = new StateObserver(PreferenceManager.getDefaultSharedPreferences(this));
|
||||
registerActivityLifecycleCallback();
|
||||
initAccessibilityServiceDelegates();
|
||||
}
|
||||
|
||||
private void initAccessibilityServiceDelegates() {
|
||||
AccessibilityWatchDogService.addDelegateIfNeeded(100, ActionPerformAccessibilityDelegate.class);
|
||||
AccessibilityWatchDogService.addDelegateIfNeeded(200, AccessibilityRecorderDelegate.getInstance());
|
||||
}
|
||||
|
||||
private void registerActivityLifecycleCallback() {
|
||||
registerActivityLifecycleCallbacks(new SimpleActivityLifecycleCallbacks() {
|
||||
@Override
|
||||
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
|
||||
currentActivity = activity;
|
||||
currentActivity = new WeakReference<>(activity);
|
||||
}
|
||||
|
||||
|
||||
@ -46,14 +63,14 @@ public class App extends Application {
|
||||
|
||||
@Override
|
||||
public void onActivityResumed(Activity activity) {
|
||||
currentActivity = activity;
|
||||
currentActivity = new WeakReference<>(activity);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
public static Activity currentActivity() {
|
||||
return currentActivity;
|
||||
return currentActivity.get();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -1,71 +0,0 @@
|
||||
package com.stardust.scriptdroid;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.design.widget.FloatingActionButton;
|
||||
import android.view.View;
|
||||
import android.widget.EditText;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.heinrichreimersoftware.androidissuereporter.IssueReporterActivity;
|
||||
import com.heinrichreimersoftware.androidissuereporter.model.github.GithubTarget;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/2/13.
|
||||
*/
|
||||
|
||||
public class IssueReportActivity extends IssueReporterActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
handleIntent();
|
||||
findViewById(com.heinrichreimersoftware.androidissuereporter.R.id.air_optionAnonymous).performClick();
|
||||
((EditText) findViewById(R.id.air_inputTitle)).setText(R.string.text_bug_report);
|
||||
getSupportActionBar().setTitle(R.string.text_report_bug);
|
||||
FloatingActionButton send = (FloatingActionButton) this.findViewById(com.heinrichreimersoftware.androidissuereporter.R.id.air_buttonSend);
|
||||
try {
|
||||
final Method reportIssue = IssueReporterActivity.class.getDeclaredMethod("reportIssue");
|
||||
reportIssue.setAccessible(true);
|
||||
send.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
try {
|
||||
reportIssue.invoke(IssueReportActivity.this);
|
||||
Toast.makeText(IssueReportActivity.this, R.string.text_report_succeed, Toast.LENGTH_SHORT).show();
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
Toast.makeText(IssueReportActivity.this, R.string.text_report_fail, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
exit();
|
||||
}
|
||||
});
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void handleIntent() {
|
||||
final String errorDetail = getIntent().getStringExtra("error");
|
||||
((EditText) findViewById(R.id.air_inputDescription)).setText(errorDetail);
|
||||
}
|
||||
|
||||
private void exit() {
|
||||
finishAffinity();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GithubTarget getTarget() {
|
||||
return new GithubTarget("hyb1996", "NoRootScriptDroid");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getGuestToken() {
|
||||
return "cd403d68a9f3a3590a14408d055c55180e7af7d3";
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
package com.stardust.scriptdroid.droid.assist;
|
||||
package com.stardust.scriptdroid.bounds_assist;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/2/4.
|
||||
@ -1,4 +1,4 @@
|
||||
package com.stardust.scriptdroid.droid.assist;
|
||||
package com.stardust.scriptdroid.bounds_assist;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.preference.PreferenceManager;
|
||||
@ -17,7 +17,7 @@ import com.stardust.scriptdroid.R;
|
||||
*/
|
||||
|
||||
public class BoundsAssistant {
|
||||
public static final String KEY_ASSIST_MODE_ENABLE = "ASSIST_MODE_ENABLE";
|
||||
public static final String KEY_BOUNDS_ASSIST_ENABLE = "ASSIST_MODE_ENABLE";
|
||||
|
||||
|
||||
private static boolean assistModeEnable;
|
||||
@ -32,7 +32,7 @@ public class BoundsAssistant {
|
||||
showAssistModeInfoDialog();
|
||||
}
|
||||
BoundsAssistant.assistModeEnable = assistModeEnable;
|
||||
App.getStateObserver().setState(KEY_ASSIST_MODE_ENABLE, assistModeEnable);
|
||||
App.getStateObserver().setState(KEY_BOUNDS_ASSIST_ENABLE, assistModeEnable);
|
||||
}
|
||||
|
||||
private static void showAssistModeInfoDialog() {
|
||||
@ -59,21 +59,25 @@ public class BoundsAssistant {
|
||||
}
|
||||
}
|
||||
|
||||
private static Rect getBoundsInScreen(AccessibilityNodeInfo nodeInfo) {
|
||||
public static Rect getBoundsInScreen(AccessibilityNodeInfo nodeInfo) {
|
||||
Rect rect = new Rect();
|
||||
nodeInfo.getBoundsInScreen(rect);
|
||||
return rect;
|
||||
}
|
||||
|
||||
private static void saveAndAlertBounds(Rect rect) {
|
||||
String str = rect.toString().replace('-', ',').replace(" ", "").substring(4);
|
||||
String str = boundsToString(rect);
|
||||
boundsAssistClipList.add(str);
|
||||
Toast.makeText(App.getApp(), str, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
public static String boundsToString(Rect rect) {
|
||||
return rect.toString().replace('-', ',').replace(" ", "").substring(4);
|
||||
}
|
||||
|
||||
|
||||
static {
|
||||
assistModeEnable = PreferenceManager.getDefaultSharedPreferences(App.getApp()).getBoolean(KEY_ASSIST_MODE_ENABLE, false);
|
||||
assistModeEnable = PreferenceManager.getDefaultSharedPreferences(App.getApp()).getBoolean(KEY_BOUNDS_ASSIST_ENABLE, false);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
package com.stardust.scriptdroid.droid.assist;
|
||||
package com.stardust.scriptdroid.bounds_assist;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
@ -13,14 +13,17 @@ import com.afollestad.materialdialogs.MaterialDialog;
|
||||
import com.jraska.console.Console;
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.droid.ConsoleActivity;
|
||||
import com.stardust.scriptdroid.ui.console.ConsoleActivity;
|
||||
import com.stardust.scriptdroid.droid.runtime.action.Action;
|
||||
import com.stardust.scriptdroid.droid.runtime.action.ActionFactory;
|
||||
import com.stardust.scriptdroid.droid.runtime.action.ActionPerformService;
|
||||
import com.stardust.scriptdroid.droid.runtime.action.ActionPerformAccessibilityDelegate;
|
||||
import com.stardust.scriptdroid.droid.runtime.action.ActionTarget;
|
||||
import com.stardust.scriptdroid.droid.runtime.action.GetTextAction;
|
||||
import com.stardust.scriptdroid.droid.runtime.api.IDroidRuntime;
|
||||
import com.stardust.scriptdroid.service.AccessibilityWatchDogService;
|
||||
import com.stardust.scriptdroid.tool.Shell;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import timber.log.Timber;
|
||||
@ -166,22 +169,40 @@ public class DroidRuntime implements IDroidRuntime {
|
||||
}
|
||||
|
||||
private boolean performAction(Action action) {
|
||||
if (ActionPerformService.getInstance() == null) {
|
||||
if (AccessibilityWatchDogService.getInstance() == null) {
|
||||
toast(App.getApp().getString(R.string.text_no_accessibility_permission));
|
||||
throw new ScriptStopException(App.getApp().getString(R.string.text_no_accessibility_permission));
|
||||
}
|
||||
ActionPerformService.setAction(action);
|
||||
ActionPerformAccessibilityDelegate.setAction(action);
|
||||
synchronized (mActionPerformLock) {
|
||||
try {
|
||||
mActionPerformLock.wait();
|
||||
} catch (InterruptedException e) {
|
||||
ActionPerformService.setActions(ActionPerformService.NO_ACTION);
|
||||
ActionPerformAccessibilityDelegate.setAction(ActionPerformAccessibilityDelegate.NO_ACTION);
|
||||
throw new ScriptStopException(App.getApp().getString(R.string.text_script_stopped), e);
|
||||
}
|
||||
}
|
||||
return mActionPerformResult;
|
||||
}
|
||||
|
||||
public List<String> getTexts() {
|
||||
if (AccessibilityWatchDogService.getInstance() == null) {
|
||||
toast(App.getApp().getString(R.string.text_no_accessibility_permission));
|
||||
throw new ScriptStopException(App.getApp().getString(R.string.text_no_accessibility_permission));
|
||||
}
|
||||
GetTextAction.result = Collections.EMPTY_LIST;
|
||||
ActionPerformAccessibilityDelegate.setAction(new GetTextAction());
|
||||
synchronized (mActionPerformLock) {
|
||||
try {
|
||||
mActionPerformLock.wait();
|
||||
return GetTextAction.result;
|
||||
} catch (InterruptedException e) {
|
||||
ActionPerformAccessibilityDelegate.setAction(ActionPerformAccessibilityDelegate.NO_ACTION);
|
||||
throw new ScriptStopException(App.getApp().getString(R.string.text_script_stopped), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toast(final String text) {
|
||||
mUIHandler.post(new Runnable() {
|
||||
|
||||
@ -0,0 +1,55 @@
|
||||
package com.stardust.scriptdroid.droid.runtime.action;
|
||||
|
||||
import android.accessibilityservice.AccessibilityService;
|
||||
import android.util.Log;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
|
||||
import com.stardust.scriptdroid.droid.runtime.DroidRuntime;
|
||||
import com.stardust.scriptdroid.service.AccessibilityDelegate;
|
||||
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/1/21.
|
||||
*/
|
||||
|
||||
public class ActionPerformAccessibilityDelegate implements AccessibilityDelegate {
|
||||
|
||||
private static final String TAG = "ActionPerformDelegate";
|
||||
|
||||
public static final Action NO_ACTION = null;
|
||||
|
||||
private static Action action;
|
||||
|
||||
public static void setAction(Action action) {
|
||||
synchronized (ActionPerformAccessibilityDelegate.class) {
|
||||
ActionPerformAccessibilityDelegate.action = action;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onAccessibilityEvent(AccessibilityService service, AccessibilityEvent event) {
|
||||
if (action == NO_ACTION)
|
||||
return false;
|
||||
AccessibilityNodeInfo root = service.getRootInActiveWindow();
|
||||
if (root == null) {
|
||||
Log.v(TAG, "root = null");
|
||||
}
|
||||
Log.i(TAG, "perform action:" + action);
|
||||
if (action.perform(root)) {
|
||||
onActionPerformed(true);
|
||||
} else if (!action.performUtilSucceed()) {
|
||||
onActionPerformed(false);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private void onActionPerformed(boolean succeed) {
|
||||
synchronized (ActionPerformAccessibilityDelegate.class) {
|
||||
action = NO_ACTION;
|
||||
DroidRuntime.getRuntime().notifyActionPerformed(succeed);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,123 +0,0 @@
|
||||
package com.stardust.scriptdroid.droid.runtime.action;
|
||||
|
||||
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.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.droid.assist.BoundsAssistant;
|
||||
import com.stardust.scriptdroid.droid.runtime.DroidRuntime;
|
||||
import com.stardust.view.accessibility.AccessibilityServiceUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/1/21.
|
||||
*/
|
||||
|
||||
public class ActionPerformService extends AccessibilityService {
|
||||
|
||||
private static final String TAG = "ActionPerformService";
|
||||
private static volatile ActionPerformService instance;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static final List<Action> NO_ACTION = Collections.EMPTY_LIST;
|
||||
public static final int STATE_INACTIVE = -1;
|
||||
public static final int STATE_PERFORM = 0;
|
||||
|
||||
public static final List<Action> actions = new ArrayList<>();
|
||||
private static int state = STATE_INACTIVE;
|
||||
|
||||
public static void setActions(Collection<Action> collection) {
|
||||
synchronized (actions) {
|
||||
actions.clear();
|
||||
actions.addAll(collection);
|
||||
state = actions.size() > 0 ? STATE_PERFORM : STATE_INACTIVE;
|
||||
}
|
||||
}
|
||||
|
||||
public static void setAction(Action action) {
|
||||
setActions(Collections.singletonList(action));
|
||||
}
|
||||
|
||||
public static ActionPerformService getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAccessibilityEvent(AccessibilityEvent event) {
|
||||
Log.v(TAG, "onAccessibilityEvent: state=" + state + " event=" + event);
|
||||
BoundsAssistant.performAssistance(event);
|
||||
if (state == STATE_INACTIVE)
|
||||
return;
|
||||
AccessibilityNodeInfo root = getRootInActiveWindow();
|
||||
if (root == null) {
|
||||
Log.v(TAG, "root = null");
|
||||
}
|
||||
Action action = nextAction();
|
||||
if (action == null) {
|
||||
onActionPerformed(true);
|
||||
} else {
|
||||
Log.i(TAG, "perform action:" + action);
|
||||
if (action.perform(root)) {
|
||||
state++;
|
||||
} else if (!action.performUtilSucceed()) {
|
||||
onActionPerformed(false);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void onActionPerformed(boolean succeed) {
|
||||
state = STATE_INACTIVE;
|
||||
synchronized (actions) {
|
||||
actions.clear();
|
||||
}
|
||||
DroidRuntime.getRuntime().notifyActionPerformed(succeed);
|
||||
}
|
||||
|
||||
private Action nextAction() {
|
||||
synchronized (actions) {
|
||||
if (state >= actions.size()) {
|
||||
return null;
|
||||
}
|
||||
return actions.get(state);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInterrupt() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceConnected() {
|
||||
// FIXME: 2017/2/12 有时在无障碍中开启服务后这里不会调用服务也不会运行,安卓的BUG???
|
||||
Log.v(TAG, "onServiceConnected");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
Log.v(TAG, "onCreate");
|
||||
instance = this;
|
||||
}
|
||||
|
||||
public static void disable() {
|
||||
if (instance != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
instance.disableSelf();
|
||||
} else {
|
||||
AccessibilityServiceUtils.goToAccessibilitySetting(App.getApp());
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isEnable() {
|
||||
return AccessibilityServiceUtils.isAccessibilityServiceEnabled(App.getApp(), ActionPerformService.class);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
package com.stardust.scriptdroid.droid.runtime.action;
|
||||
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/2/14.
|
||||
*/
|
||||
|
||||
public class GetTextAction extends Action {
|
||||
|
||||
public static List<String> result;
|
||||
|
||||
@Override
|
||||
public boolean perform(AccessibilityNodeInfo root) {
|
||||
List<String> texts = new ArrayList<>();
|
||||
getText(root, texts);
|
||||
result = texts;
|
||||
return true;
|
||||
}
|
||||
|
||||
private void getText(AccessibilityNodeInfo nodeInfo, List<String> texts) {
|
||||
CharSequence text = nodeInfo.getText();
|
||||
if (text != null && text.length() != 0) {
|
||||
texts.add(text.toString());
|
||||
}
|
||||
for (int i = 0; i < nodeInfo.getChildCount(); i++) {
|
||||
AccessibilityNodeInfo child = nodeInfo.getChild(i);
|
||||
if (child != null) {
|
||||
getText(child, texts);
|
||||
child.recycle();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -11,6 +11,8 @@ import java.io.StringReader;
|
||||
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/1/27.
|
||||
@ -70,7 +72,7 @@ public class DuktapeJavaScriptEngine implements JavaScriptEngine {
|
||||
public void removeAndStop(Thread thread) {
|
||||
synchronized (mThreadDuktapeEngineMap) {
|
||||
DuktapeEngine engine = mThreadDuktapeEngineMap.remove(thread);
|
||||
stop(engine, thread);
|
||||
forceStop(engine, thread);
|
||||
}
|
||||
}
|
||||
|
||||
@ -84,14 +86,21 @@ public class DuktapeJavaScriptEngine implements JavaScriptEngine {
|
||||
}
|
||||
}
|
||||
|
||||
private void stop(DuktapeEngine engine, Thread thread) {
|
||||
if (engine != null)
|
||||
engine.destory();
|
||||
|
||||
private void forceStop(final DuktapeEngine engine, Thread thread) {
|
||||
try {
|
||||
thread.interrupt();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (engine != null) {
|
||||
new Timer().schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
engine.destory();
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
private void add(DuktapeEngine duktapeEngine, Thread thread) {
|
||||
@ -110,7 +119,7 @@ public class DuktapeJavaScriptEngine implements JavaScriptEngine {
|
||||
int n;
|
||||
synchronized (mThreadDuktapeEngineMap) {
|
||||
for (Map.Entry<Thread, DuktapeEngine> entry : mThreadDuktapeEngineMap.entrySet()) {
|
||||
stop(entry.getValue(), entry.getKey());
|
||||
forceStop(entry.getValue(), entry.getKey());
|
||||
}
|
||||
n = mThreadDuktapeEngineMap.size();
|
||||
mThreadDuktapeEngineMap.clear();
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
package com.stardust.scriptdroid.ui;
|
||||
package com.stardust.scriptdroid.external.notification.bounds_assist;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
@ -7,9 +7,8 @@ import android.preference.PreferenceManager;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.AssistModeSwitchService;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.droid.assist.BoundsAssistant;
|
||||
import com.stardust.scriptdroid.bounds_assist.BoundsAssistant;
|
||||
import com.stardust.util.StateObserver;
|
||||
|
||||
|
||||
@ -17,36 +16,35 @@ import com.stardust.util.StateObserver;
|
||||
* Created by Stardust on 2017/2/2.
|
||||
*/
|
||||
|
||||
public class AssistModeSwitchNotification {
|
||||
public class BoundsAssistSwitchNotification {
|
||||
|
||||
private static final int NOTIFY_ID = 11126;
|
||||
public static final String KEY_ASSIST_MODE_NOTIFICATION = "KEY_ASSIST_MODE_NOTIFICATION";
|
||||
public static final String KEY_BOUNDS_ASSIST_SWITCH_NOTIFICATION_ENABLE = "KEY_BOUNDS_ASSIST_SWITCH_NOTIFICATION_ENABLE";
|
||||
|
||||
private static boolean enable = false;
|
||||
private static Notification notification;
|
||||
|
||||
public static boolean isEnable() {
|
||||
return enable;
|
||||
}
|
||||
|
||||
static {
|
||||
App.getStateObserver().register(KEY_ASSIST_MODE_NOTIFICATION, new StateObserver.OnBooleanStateChangedListener() {
|
||||
App.getStateObserver().register(KEY_BOUNDS_ASSIST_SWITCH_NOTIFICATION_ENABLE, new StateObserver.OnStateChangedListener() {
|
||||
@Override
|
||||
public void onStateChanged(Boolean newState) {
|
||||
public void onStateChanged(boolean newState) {
|
||||
setEnable(newState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initState(Boolean state) {
|
||||
public void initState(boolean state) {
|
||||
enable = state;
|
||||
if (enable) {
|
||||
showNotification();
|
||||
}
|
||||
}
|
||||
});
|
||||
App.getStateObserver().register(BoundsAssistant.KEY_ASSIST_MODE_ENABLE, new StateObserver.OnBooleanStateChangedListener() {
|
||||
App.getStateObserver().register(BoundsAssistant.KEY_BOUNDS_ASSIST_ENABLE, new StateObserver.OnStateChangedListener() {
|
||||
@Override
|
||||
public void onStateChanged(Boolean newState) {
|
||||
public void onStateChanged(boolean newState) {
|
||||
if (enable) {
|
||||
setEnable(false);
|
||||
setEnable(true);
|
||||
@ -54,17 +52,17 @@ public class AssistModeSwitchNotification {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initState(Boolean state) {
|
||||
public void initState(boolean state) {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void setEnable(boolean enable) {
|
||||
if (AssistModeSwitchNotification.enable == enable)
|
||||
if (BoundsAssistSwitchNotification.enable == enable)
|
||||
return;
|
||||
AssistModeSwitchNotification.enable = enable;
|
||||
PreferenceManager.getDefaultSharedPreferences(App.getApp()).edit().putBoolean(KEY_ASSIST_MODE_NOTIFICATION, enable).apply();
|
||||
BoundsAssistSwitchNotification.enable = enable;
|
||||
PreferenceManager.getDefaultSharedPreferences(App.getApp()).edit().putBoolean(KEY_BOUNDS_ASSIST_SWITCH_NOTIFICATION_ENABLE, enable).apply();
|
||||
if (enable) {
|
||||
showNotification();
|
||||
} else {
|
||||
@ -74,14 +72,14 @@ public class AssistModeSwitchNotification {
|
||||
|
||||
|
||||
private static void showNotification() {
|
||||
notification = new NotificationCompat.Builder(App.getApp())
|
||||
Notification notification = new NotificationCompat.Builder(App.getApp())
|
||||
.setAutoCancel(false)
|
||||
.setSmallIcon(R.drawable.ic_robot_head)
|
||||
.setDeleteIntent(AssistModeSwitchService.getDeletePendingIntent())
|
||||
.setDeleteIntent(BoundsAssistSwitchNotificationHandleService.getDeletePendingIntent())
|
||||
.setContentText(BoundsAssistant.isAssistModeEnable() ?
|
||||
App.getApp().getString(R.string.text_assist_mode_enabled) :
|
||||
App.getApp().getString(R.string.text_assist_mode_disabled))
|
||||
.setContentIntent(AssistModeSwitchService.getStartIntent())
|
||||
.setContentIntent(BoundsAssistSwitchNotificationHandleService.getStartIntent())
|
||||
.build();
|
||||
showNotification(notification);
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
package com.stardust.scriptdroid;
|
||||
package com.stardust.scriptdroid.external.notification.bounds_assist;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
@ -6,17 +6,18 @@ import android.content.Intent;
|
||||
import android.os.IBinder;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import com.stardust.scriptdroid.droid.assist.BoundsAssistant;
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.bounds_assist.BoundsAssistant;
|
||||
|
||||
import static com.stardust.scriptdroid.ui.AssistModeSwitchNotification.KEY_ASSIST_MODE_NOTIFICATION;
|
||||
import static com.stardust.scriptdroid.external.notification.bounds_assist.BoundsAssistSwitchNotification.KEY_BOUNDS_ASSIST_SWITCH_NOTIFICATION_ENABLE;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/2/2.
|
||||
*/
|
||||
public class AssistModeSwitchService extends Service {
|
||||
public class BoundsAssistSwitchNotificationHandleService extends Service {
|
||||
|
||||
|
||||
private static final String EXTRA_INTENT_VALID = "intentValid";
|
||||
private static final String EXTRA_INTENT_VALID = "BoundsAssistSwitchNotificationHandleService.intentValid";
|
||||
private static final String EXTRA_ACTION = "action";
|
||||
|
||||
private static final int ACTION_TOGGLE_ASSIST_MODE = 1;
|
||||
@ -24,7 +25,7 @@ public class AssistModeSwitchService extends Service {
|
||||
|
||||
|
||||
public static PendingIntent getStartIntent() {
|
||||
Intent intent = new Intent(App.getApp(), AssistModeSwitchService.class)
|
||||
Intent intent = new Intent(App.getApp(), BoundsAssistSwitchNotificationHandleService.class)
|
||||
.putExtra(EXTRA_INTENT_VALID, true)
|
||||
.putExtra(EXTRA_ACTION, ACTION_TOGGLE_ASSIST_MODE);
|
||||
return PendingIntent.getService(App.getApp(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
@ -32,7 +33,7 @@ public class AssistModeSwitchService extends Service {
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
boolean intentValid = intent.getBooleanExtra("intentValid", false);
|
||||
boolean intentValid = intent.getBooleanExtra(EXTRA_INTENT_VALID, false);
|
||||
if (intentValid) {
|
||||
performAction(intent.getIntExtra(EXTRA_ACTION, 0));
|
||||
}
|
||||
@ -46,7 +47,7 @@ public class AssistModeSwitchService extends Service {
|
||||
BoundsAssistant.setAssistModeEnable(!BoundsAssistant.isAssistModeEnable());
|
||||
break;
|
||||
case ACTION_CANCEL_ASSIST_MODE_NOTIFICATION:
|
||||
App.getStateObserver().setState(KEY_ASSIST_MODE_NOTIFICATION, false);
|
||||
App.getStateObserver().setState(KEY_BOUNDS_ASSIST_SWITCH_NOTIFICATION_ENABLE, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -58,7 +59,7 @@ public class AssistModeSwitchService extends Service {
|
||||
}
|
||||
|
||||
public static PendingIntent getDeletePendingIntent() {
|
||||
Intent deleteIntent = new Intent(App.getApp(), AssistModeSwitchService.class)
|
||||
Intent deleteIntent = new Intent(App.getApp(), BoundsAssistSwitchNotificationHandleService.class)
|
||||
.putExtra(EXTRA_INTENT_VALID, true)
|
||||
.putExtra(EXTRA_ACTION, ACTION_CANCEL_ASSIST_MODE_NOTIFICATION);
|
||||
return PendingIntent.getService(App.getApp(), 0, deleteIntent, PendingIntent.FLAG_ONE_SHOT);
|
||||
@ -0,0 +1,123 @@
|
||||
package com.stardust.scriptdroid.external.notification.record;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
import android.content.Intent;
|
||||
import android.os.IBinder;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.record.AccessibilityRecorderDelegate;
|
||||
import com.stardust.scriptdroid.service.AccessibilityWatchDogService;
|
||||
import com.stardust.scriptdroid.ui.main.MainActivity;
|
||||
|
||||
import static com.stardust.scriptdroid.external.notification.record.ActionRecordSwitchView.PAUSED;
|
||||
import static com.stardust.scriptdroid.external.notification.record.ActionRecordSwitchView.RECORDING;
|
||||
import static com.stardust.scriptdroid.external.notification.record.ActionRecordSwitchView.STOPPED;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/2/15.
|
||||
*/
|
||||
|
||||
public class ActionRecordNotificationHandleService extends Service {
|
||||
|
||||
|
||||
private static final String EXTRA_INTENT_VALID = "ActionRecordNotificationHandleService.intentValid";
|
||||
private static final String EXTRA_ACTION = "action";
|
||||
private static final int ACTION_STOP = 17771;
|
||||
private static final int ACTION_START_OR_PAUSE = 17772;
|
||||
private static final int ACTION_DELETE = 17773;
|
||||
|
||||
public static PendingIntent getStartOrPauseIntent() {
|
||||
Intent intent = new Intent(App.getApp(), ActionRecordNotificationHandleService.class)
|
||||
.putExtra(EXTRA_INTENT_VALID, true)
|
||||
.putExtra(EXTRA_ACTION, ACTION_START_OR_PAUSE);
|
||||
return PendingIntent.getService(App.getApp(), ACTION_START_OR_PAUSE, intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
}
|
||||
|
||||
public static PendingIntent getStopIntent() {
|
||||
Intent intent = new Intent(App.getApp(), ActionRecordNotificationHandleService.class)
|
||||
.putExtra(EXTRA_INTENT_VALID, true)
|
||||
.putExtra(EXTRA_ACTION, ACTION_STOP);
|
||||
return PendingIntent.getService(App.getApp(), ACTION_STOP, intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
}
|
||||
|
||||
public static PendingIntent getDeleteIntent() {
|
||||
Intent intent = new Intent(App.getApp(), ActionRecordNotificationHandleService.class)
|
||||
.putExtra(EXTRA_INTENT_VALID, true)
|
||||
.putExtra(EXTRA_ACTION, ACTION_DELETE);
|
||||
return PendingIntent.getService(App.getApp(), ACTION_DELETE, intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
boolean intentValid = intent.getBooleanExtra(EXTRA_INTENT_VALID, false);
|
||||
if (intentValid) {
|
||||
performAction(intent.getIntExtra(EXTRA_ACTION, 0));
|
||||
}
|
||||
stopSelf();
|
||||
return super.onStartCommand(intent, flags, startId);
|
||||
}
|
||||
|
||||
private void performAction(int action) {
|
||||
switch (action) {
|
||||
case ACTION_STOP:
|
||||
stopRecord();
|
||||
break;
|
||||
case ACTION_START_OR_PAUSE:
|
||||
startOrPauseRecord();
|
||||
break;
|
||||
case ACTION_DELETE:
|
||||
stopRecordIfNeeded();
|
||||
}
|
||||
collapseNotificationBar();
|
||||
}
|
||||
|
||||
private void collapseNotificationBar() {
|
||||
sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
|
||||
}
|
||||
|
||||
private void stopRecordIfNeeded() {
|
||||
if (AccessibilityRecorderDelegate.getInstance().getState() != STOPPED) {
|
||||
stopRecord();
|
||||
}
|
||||
}
|
||||
|
||||
private void startOrPauseRecord() {
|
||||
int state = AccessibilityRecorderDelegate.getInstance().getState();
|
||||
if (state == PAUSED) {
|
||||
AccessibilityRecorderDelegate.getInstance().resumeRecord();
|
||||
ActionRecordSwitchView.getInstance().setState(RECORDING);
|
||||
} else if (state == RECORDING) {
|
||||
AccessibilityRecorderDelegate.getInstance().pauseRecord();
|
||||
ActionRecordSwitchView.getInstance().setState(PAUSED);
|
||||
} else {
|
||||
//state == STOPPED
|
||||
if (AccessibilityWatchDogService.getInstance() == null) {
|
||||
Toast.makeText(this, R.string.text_need_enable_accessibility_service, Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
AccessibilityRecorderDelegate.getInstance().startRecord();
|
||||
ActionRecordSwitchView.getInstance().setState(RECORDING);
|
||||
Toast.makeText(this, R.string.text_start_record, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
private void stopRecord() {
|
||||
if (AccessibilityRecorderDelegate.getInstance().getState() != STOPPED) {
|
||||
String script = AccessibilityRecorderDelegate.getInstance().stopRecord();
|
||||
ActionRecordSwitchView.getInstance().setState(STOPPED);
|
||||
MainActivity.onActionRecordStopped(this, script);
|
||||
} else {
|
||||
Toast.makeText(App.getApp(), R.string.text_not_recording, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
package com.stardust.scriptdroid.external.notification.record;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.content.Context;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.R;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/2/14.
|
||||
*/
|
||||
|
||||
public class ActionRecordSwitchNotification {
|
||||
|
||||
private static final int NOTIFY_ID = 22236;
|
||||
private static NotificationCompat.Builder builder;
|
||||
|
||||
|
||||
public static void showOrUpdateNotification() {
|
||||
if (builder == null) {
|
||||
builder = new NotificationCompat.Builder(App.getApp())
|
||||
.setAutoCancel(false)
|
||||
.setSmallIcon(R.drawable.ic_robot_head)
|
||||
.setDeleteIntent(ActionRecordNotificationHandleService.getDeleteIntent())
|
||||
.setCustomContentView(ActionRecordSwitchView.getInstance());
|
||||
}
|
||||
showNotification(builder.build());
|
||||
}
|
||||
|
||||
private static void showNotification(Notification notification) {
|
||||
NotificationManager notificationManager = (NotificationManager) App.getApp().getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
notificationManager.notify(NOTIFY_ID, notification);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
package com.stardust.scriptdroid.external.notification.record;
|
||||
|
||||
import android.widget.RemoteViews;
|
||||
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.R;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/2/14.
|
||||
*/
|
||||
|
||||
public class ActionRecordSwitchView extends RemoteViews {
|
||||
|
||||
private static ActionRecordSwitchView instance;
|
||||
|
||||
public static final int STOPPED = 0;
|
||||
public static final int PAUSED = 1;
|
||||
public static final int RECORDING = 2;
|
||||
|
||||
public static ActionRecordSwitchView getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new ActionRecordSwitchView();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
private ActionRecordSwitchView() {
|
||||
super(App.getApp().getPackageName(), R.layout.remote_views_record_switch);
|
||||
setUpOnClick();
|
||||
}
|
||||
|
||||
public void setState(int state) {
|
||||
switch (state) {
|
||||
case STOPPED:
|
||||
setImageViewResource(R.id.img_start_or_pause, R.drawable.ic_play_arrow_grey600_48dp);
|
||||
setTextViewText(R.id.text_start_or_pause, App.getApp().getString(R.string.text_start_record));
|
||||
break;
|
||||
case RECORDING:
|
||||
setImageViewResource(R.id.img_start_or_pause, R.drawable.ic_pause_grey600_48dp);
|
||||
setTextViewText(R.id.text_start_or_pause, App.getApp().getString(R.string.text_pause_record));
|
||||
break;
|
||||
case PAUSED:
|
||||
setImageViewResource(R.id.img_start_or_pause, R.drawable.ic_play_arrow_grey600_48dp);
|
||||
setTextViewText(R.id.text_start_or_pause, App.getApp().getString(R.string.text_resume_record));
|
||||
break;
|
||||
}
|
||||
ActionRecordSwitchNotification.showOrUpdateNotification();
|
||||
}
|
||||
|
||||
private void setUpOnClick() {
|
||||
setOnClickPendingIntent(R.id.stop, ActionRecordNotificationHandleService.getStopIntent());
|
||||
setOnClickPendingIntent(R.id.start_or_pause, ActionRecordNotificationHandleService.getStartOrPauseIntent());
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
package com.stardust.scriptdroid.shortcut;
|
||||
package com.stardust.scriptdroid.external.shortcut;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@ -1,18 +1,17 @@
|
||||
package com.stardust.scriptdroid;
|
||||
package com.stardust.scriptdroid.external.shortcut;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.droid.Droid;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.function.BooleanSupplier;
|
||||
|
||||
import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
|
||||
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||
@ -1,11 +1,11 @@
|
||||
package com.stardust.scriptdroid.tile;
|
||||
package com.stardust.scriptdroid.external.tile;
|
||||
|
||||
import android.os.Build;
|
||||
import android.service.quicksettings.Tile;
|
||||
import android.service.quicksettings.TileService;
|
||||
import android.support.annotation.RequiresApi;
|
||||
|
||||
import com.stardust.scriptdroid.droid.assist.BoundsAssistant;
|
||||
import com.stardust.scriptdroid.bounds_assist.BoundsAssistant;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/1/26.
|
||||
@ -1,67 +0,0 @@
|
||||
package com.stardust.scriptdroid.file;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
|
||||
import com.stardust.scriptdroid.R;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import static android.app.Activity.RESULT_OK;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/1/23.
|
||||
*/
|
||||
|
||||
public class FileChooser {
|
||||
|
||||
public interface FileManagerNotFoundHandler {
|
||||
void handle(ActivityNotFoundException e, String mimeType);
|
||||
}
|
||||
|
||||
public interface OnFileChoseListener {
|
||||
void onFileChose(InputStream inputStream);
|
||||
}
|
||||
|
||||
private static final int FILE_CHOOSE = 1209;
|
||||
private Activity mActivity;
|
||||
|
||||
private OnFileChoseListener mOnFileChoseListener;
|
||||
|
||||
public FileChooser(Activity activity) {
|
||||
mActivity = activity;
|
||||
}
|
||||
|
||||
public void setOnFileChoseListener(OnFileChoseListener onFileChoseListener) {
|
||||
mOnFileChoseListener = onFileChoseListener;
|
||||
}
|
||||
|
||||
|
||||
public void startFileManagerToChoose(String mimeType, FileManagerNotFoundHandler handler) {
|
||||
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
|
||||
intent.setType(mimeType);
|
||||
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
try {
|
||||
mActivity.startActivityForResult(Intent.createChooser(intent, mActivity.getString(R.string.text_choose_file)), FILE_CHOOSE);
|
||||
} catch (ActivityNotFoundException ex) {
|
||||
handler.handle(ex, mimeType);
|
||||
}
|
||||
}
|
||||
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if (requestCode == FILE_CHOOSE && resultCode == RESULT_OK) {
|
||||
Uri uri = data.getData();
|
||||
ContentResolver cr = mActivity.getContentResolver();
|
||||
try {
|
||||
InputStream inputStream = cr.openInputStream(uri);
|
||||
mOnFileChoseListener.onFileChose(inputStream);
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -176,4 +176,26 @@ public class FileUtils {
|
||||
}
|
||||
|
||||
|
||||
public static boolean writeString(String path, String text) {
|
||||
return writeString(new File(path), text);
|
||||
}
|
||||
|
||||
public static boolean writeString(File file, String text) {
|
||||
try {
|
||||
return writeString(new FileOutputStream(file), text);
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean writeString(OutputStream outputStream, String text) {
|
||||
try {
|
||||
outputStream.write(text.getBytes());
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -16,7 +16,7 @@ import java.util.Map;
|
||||
/**
|
||||
* Created by Stardust on 2017/1/30.
|
||||
*/
|
||||
public class SampleFileTool {
|
||||
public class SampleFileManager {
|
||||
|
||||
private static final Map<String, Integer> SAMPLES = new MapEntries<>(new LinkedHashMap<String, Integer>())
|
||||
.entry("sample_open_running_services.js", R.string.text_sample_open_running_services)
|
||||
@ -27,9 +27,9 @@ public class SampleFileTool {
|
||||
.entry("sample_alipay_scan.js", R.string.text_sample_alipay_scan)
|
||||
.map();
|
||||
|
||||
private static SampleFileTool instance = new SampleFileTool();
|
||||
private static SampleFileManager instance = new SampleFileManager();
|
||||
|
||||
public static SampleFileTool getInstance() {
|
||||
public static SampleFileManager getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
@ -0,0 +1,95 @@
|
||||
package com.stardust.scriptdroid.record;
|
||||
|
||||
import android.accessibilityservice.AccessibilityService;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
|
||||
import com.stardust.scriptdroid.service.AccessibilityDelegate;
|
||||
|
||||
import static com.stardust.scriptdroid.external.notification.record.ActionRecordSwitchView.PAUSED;
|
||||
import static com.stardust.scriptdroid.external.notification.record.ActionRecordSwitchView.RECORDING;
|
||||
import static com.stardust.scriptdroid.external.notification.record.ActionRecordSwitchView.STOPPED;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/2/14.
|
||||
*/
|
||||
|
||||
public class AccessibilityRecorderDelegate implements AccessibilityDelegate {
|
||||
|
||||
private static final int PRIORITY = 200;
|
||||
private static final long RECORD_TIME_OUT = 10 * 60 * 1000;
|
||||
|
||||
private static AccessibilityRecorderDelegate instance;
|
||||
private int mState = STOPPED;
|
||||
|
||||
public static AccessibilityRecorderDelegate getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new AccessibilityRecorderDelegate();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
private ActionRecorder mRecorder = new ActionRecorder();
|
||||
private long mRecordStartMillis;
|
||||
|
||||
public void startRecord() {
|
||||
if (mState != STOPPED) {
|
||||
throw new IllegalStateException("Recording");
|
||||
}
|
||||
mState = RECORDING;
|
||||
mRecorder = new ActionRecorder();
|
||||
mRecordStartMillis = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
|
||||
public String stopRecord() {
|
||||
if (mState == STOPPED) {
|
||||
throw new IllegalStateException("Not recording");
|
||||
}
|
||||
mState = STOPPED;
|
||||
String script = mRecorder.getScript();
|
||||
mRecorder = null;
|
||||
return script;
|
||||
}
|
||||
|
||||
|
||||
public void pauseRecord() {
|
||||
if (mState != RECORDING) {
|
||||
throw new IllegalStateException("Not recording");
|
||||
}
|
||||
mState = PAUSED;
|
||||
}
|
||||
|
||||
public void resumeRecord() {
|
||||
if (mState != PAUSED) {
|
||||
throw new IllegalStateException("Not paused");
|
||||
}
|
||||
mRecorder.onResume();
|
||||
mState = RECORDING;
|
||||
}
|
||||
|
||||
public void stopRecordIfNeeded() {
|
||||
if (mRecorder != null) {
|
||||
mRecorder = null;
|
||||
}
|
||||
}
|
||||
|
||||
public int getState() {
|
||||
return mState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onAccessibilityEvent(AccessibilityService service, AccessibilityEvent event) {
|
||||
if (mState == RECORDING) {
|
||||
mRecorder.record(event);
|
||||
checkTimeOut();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void checkTimeOut() {
|
||||
if (System.currentTimeMillis() - mRecordStartMillis > RECORD_TIME_OUT) {
|
||||
stopRecord();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,102 @@
|
||||
package com.stardust.scriptdroid.record;
|
||||
|
||||
import android.os.Build;
|
||||
import android.util.SparseArray;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
|
||||
import com.stardust.util.SparseArrayEntries;
|
||||
|
||||
import static com.stardust.scriptdroid.bounds_assist.BoundsAssistant.boundsToString;
|
||||
import static com.stardust.scriptdroid.bounds_assist.BoundsAssistant.getBoundsInScreen;
|
||||
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/2/14.
|
||||
*/
|
||||
|
||||
public class ActionRecorder {
|
||||
|
||||
private static final SparseArray<EventToScriptConverter> CONVERTER_MAP = new SparseArrayEntries<EventToScriptConverter>()
|
||||
.entry(AccessibilityEvent.TYPE_VIEW_CLICKED, new DoUtilSucceedConverter("click"))
|
||||
.entry(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED, new DoUtilSucceedConverter("longClick"))
|
||||
.entry(AccessibilityEvent.TYPE_VIEW_SCROLLED, new DoOnceConverter("//scroll???"))
|
||||
.sparseArray();
|
||||
|
||||
static {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
CONVERTER_MAP.put(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED, new DoOnceConverter("contextClick"));
|
||||
}
|
||||
}
|
||||
|
||||
private StringBuilder mScript = new StringBuilder();
|
||||
private boolean mFirstAction = true;
|
||||
|
||||
public void record(AccessibilityEvent event) {
|
||||
EventToScriptConverter converter = CONVERTER_MAP.get(event.getEventType());
|
||||
if (converter != null) {
|
||||
if (mFirstAction) {
|
||||
mFirstAction = false;
|
||||
return;
|
||||
}
|
||||
converter.onAccessibilityEvent(event, mScript);
|
||||
mScript.append("\n");
|
||||
}
|
||||
}
|
||||
|
||||
public String getScript() {
|
||||
return mScript.toString();
|
||||
}
|
||||
|
||||
public void onResume() {
|
||||
mFirstAction = true;
|
||||
}
|
||||
|
||||
interface EventToScriptConverter {
|
||||
|
||||
void onAccessibilityEvent(AccessibilityEvent event, StringBuilder sb);
|
||||
}
|
||||
|
||||
private static abstract class BoundsEventConverter implements EventToScriptConverter {
|
||||
|
||||
@Override
|
||||
public void onAccessibilityEvent(AccessibilityEvent event, StringBuilder sb) {
|
||||
AccessibilityNodeInfo source = event.getSource();
|
||||
String bounds = boundsToString(getBoundsInScreen(source));
|
||||
source.recycle();
|
||||
onAccessibilityEvent(event, bounds, sb);
|
||||
}
|
||||
|
||||
protected abstract void onAccessibilityEvent(AccessibilityEvent event, String bounds, StringBuilder sb);
|
||||
|
||||
}
|
||||
|
||||
private static class DoOnceConverter extends BoundsEventConverter {
|
||||
|
||||
private String mActionFunction;
|
||||
|
||||
DoOnceConverter(String actionFunction) {
|
||||
mActionFunction = actionFunction;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAccessibilityEvent(AccessibilityEvent event, String bounds, StringBuilder sb) {
|
||||
sb.append(mActionFunction).append(bounds).append(";");
|
||||
}
|
||||
}
|
||||
|
||||
private static class DoUtilSucceedConverter extends BoundsEventConverter {
|
||||
|
||||
private String mActionFunction;
|
||||
|
||||
DoUtilSucceedConverter(String actionFunction) {
|
||||
mActionFunction = actionFunction;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAccessibilityEvent(AccessibilityEvent event, String bounds, StringBuilder sb) {
|
||||
sb.append("while(!").append(mActionFunction).append(bounds).append(");");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
package com.stardust.scriptdroid.service;
|
||||
|
||||
import android.accessibilityservice.AccessibilityService;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/2/14.
|
||||
*/
|
||||
|
||||
public interface AccessibilityDelegate {
|
||||
|
||||
boolean onAccessibilityEvent(AccessibilityService service, AccessibilityEvent event);
|
||||
|
||||
}
|
||||
@ -0,0 +1,99 @@
|
||||
package com.stardust.scriptdroid.service;
|
||||
|
||||
import android.accessibilityservice.AccessibilityService;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.view.accessibility.AccessibilityServiceUtils;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/2/14.
|
||||
*/
|
||||
|
||||
public class AccessibilityWatchDogService extends AccessibilityService {
|
||||
|
||||
private static final String TAG = "AccessibilityWatchDog";
|
||||
|
||||
private static final SortedMap<Integer, AccessibilityDelegate> mDelegates = new TreeMap<>();
|
||||
private static AccessibilityWatchDogService instance;
|
||||
|
||||
public static void addDelegate(AccessibilityDelegate delegate, int uniquePriority) {
|
||||
synchronized (mDelegates) {
|
||||
mDelegates.put(uniquePriority, delegate);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean containsPriority(int priority) {
|
||||
synchronized (mDelegates) {
|
||||
return mDelegates.containsKey(priority);
|
||||
}
|
||||
}
|
||||
|
||||
public static AccessibilityDelegate getDelegate(int priority) {
|
||||
synchronized (mDelegates) {
|
||||
return mDelegates.get(priority);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addDelegateIfNeeded(int priority, Class<? extends AccessibilityDelegate> delegateClass) {
|
||||
try {
|
||||
addDelegateIfNeeded(priority, delegateClass.newInstance());
|
||||
} catch (InstantiationException | IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addDelegateIfNeeded(int priority, AccessibilityDelegate delegate) {
|
||||
synchronized (mDelegates) {
|
||||
if (!mDelegates.containsKey(priority)) {
|
||||
mDelegates.put(priority, delegate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isEnable() {
|
||||
return AccessibilityServiceUtils.isAccessibilityServiceEnabled(App.getApp(), AccessibilityWatchDogService.class);
|
||||
}
|
||||
|
||||
public static AccessibilityWatchDogService getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void onAccessibilityEvent(AccessibilityEvent event) {
|
||||
Log.v(TAG, "onAccessibilityEvent: " + event);
|
||||
synchronized (mDelegates) {
|
||||
for (Map.Entry<Integer, AccessibilityDelegate> entry : mDelegates.entrySet()) {
|
||||
if (entry.getValue().onAccessibilityEvent(this, event))
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInterrupt() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onServiceConnected() {
|
||||
super.onServiceConnected();
|
||||
// FIXME: 2017/2/12 有时在无障碍中开启服务后这里不会调用服务也不会运行,安卓的BUG???
|
||||
Log.v(TAG, "onServiceConnected");
|
||||
instance = this;
|
||||
}
|
||||
|
||||
public static void disable() {
|
||||
if (instance != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
instance.disableSelf();
|
||||
} else {
|
||||
AccessibilityServiceUtils.goToAccessibilitySetting(App.getApp());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -47,4 +47,5 @@ public class IntentTool {
|
||||
.putExtra(Intent.EXTRA_TEXT, text)
|
||||
.setType("text/plain"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
package com.stardust.scriptdroid;
|
||||
package com.stardust.scriptdroid.ui;
|
||||
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
@ -9,6 +9,8 @@ import android.support.v7.widget.Toolbar;
|
||||
import android.view.View;
|
||||
|
||||
|
||||
import com.stardust.scriptdroid.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
@ -1,4 +1,4 @@
|
||||
package com.stardust.scriptdroid.droid;
|
||||
package com.stardust.scriptdroid.ui.console;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
@ -10,7 +10,7 @@ import android.view.MenuItem;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.jraska.console.Console;
|
||||
import com.stardust.scriptdroid.BaseActivity;
|
||||
import com.stardust.scriptdroid.ui.BaseActivity;
|
||||
import com.stardust.scriptdroid.R;
|
||||
|
||||
/**
|
||||
@ -1,4 +1,4 @@
|
||||
package com.stardust.scriptdroid;
|
||||
package com.stardust.scriptdroid.ui.edit;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@ -18,12 +18,14 @@ import com.jecelyin.editor.v2.common.SaveListener;
|
||||
import com.jecelyin.editor.v2.ui.EditorDelegate;
|
||||
import com.jecelyin.editor.v2.view.EditorView;
|
||||
import com.jecelyin.editor.v2.view.menu.MenuDef;
|
||||
import com.stardust.scriptdroid.Pref;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.droid.Droid;
|
||||
import com.stardust.scriptdroid.editor920.Editor920Activity;
|
||||
import com.stardust.scriptdroid.ui.AssistClipListRecyclerView;
|
||||
import com.stardust.scriptdroid.ui.EditSideMenuFragment;
|
||||
import com.stardust.scriptdroid.ui.FunctionListRecyclerView;
|
||||
import com.stardust.scriptdroid.widget.ToolbarMenuItem;
|
||||
import com.stardust.scriptdroid.ui.edit.sidemenu.AssistClipListRecyclerView;
|
||||
import com.stardust.scriptdroid.ui.edit.sidemenu.EditSideMenuFragment;
|
||||
import com.stardust.scriptdroid.ui.edit.sidemenu.FunctionListRecyclerView;
|
||||
import com.stardust.scriptdroid.ui.edit.editor920.Editor920Activity;
|
||||
import com.stardust.widget.ToolbarMenuItem;
|
||||
import com.stardust.util.SparseArrayEntries;
|
||||
import com.stardust.view.ViewBinder;
|
||||
import com.stardust.view.ViewBinding;
|
||||
@ -1,12 +1,13 @@
|
||||
package com.stardust.scriptdroid;
|
||||
package com.stardust.scriptdroid.ui.edit;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.TextUtils;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.stardust.scriptdroid.BaseActivity;
|
||||
import com.stardust.scriptdroid.EditActivity;
|
||||
import com.stardust.scriptdroid.ui.BaseActivity;
|
||||
import com.stardust.scriptdroid.R;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/2/2.
|
||||
@ -17,7 +18,12 @@ public class EditAndRunIntentActivity extends BaseActivity {
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
handleIntent();
|
||||
try {
|
||||
handleIntent();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Toast.makeText(this, R.string.edit_and_run_handle_intent_error, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
|
||||
private void handleIntent() {
|
||||
@ -1,4 +1,4 @@
|
||||
package com.stardust.scriptdroid;
|
||||
package com.stardust.scriptdroid.ui.edit;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
@ -7,8 +7,11 @@ import android.support.annotation.Nullable;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.afollestad.materialdialogs.MaterialDialog;
|
||||
import com.stardust.scriptdroid.ui.BaseActivity;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.droid.script.file.ScriptFile;
|
||||
import com.stardust.scriptdroid.droid.script.file.SharedPrefScriptFileList;
|
||||
import com.stardust.scriptdroid.ui.main.MainActivity;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
package com.stardust.scriptdroid.editor920;
|
||||
package com.stardust.scriptdroid.ui.edit.editor920;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
package com.stardust.scriptdroid.ui;
|
||||
package com.stardust.scriptdroid.ui.edit.sidemenu;
|
||||
|
||||
import android.bug.WrapContentLinearLayoutManager;
|
||||
import android.content.Context;
|
||||
@ -11,9 +11,9 @@ import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.droid.assist.BoundsAssistClipList;
|
||||
import com.stardust.scriptdroid.droid.assist.SharedPrefBoundsAssistClipList;
|
||||
import com.stardust.scriptdroid.widget.ExpandableRecyclerView;
|
||||
import com.stardust.scriptdroid.bounds_assist.BoundsAssistClipList;
|
||||
import com.stardust.scriptdroid.bounds_assist.SharedPrefBoundsAssistClipList;
|
||||
import com.stardust.widget.ExpandableRecyclerView;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/2/4.
|
||||
@ -1,4 +1,4 @@
|
||||
package com.stardust.scriptdroid.ui;
|
||||
package com.stardust.scriptdroid.ui.edit.sidemenu;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
@ -10,14 +10,15 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.DocumentActivity;
|
||||
import com.stardust.scriptdroid.ui.help.DocumentActivity;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.droid.ConsoleActivity;
|
||||
import com.stardust.scriptdroid.droid.assist.BoundsAssistant;
|
||||
import com.stardust.scriptdroid.ui.console.ConsoleActivity;
|
||||
import com.stardust.scriptdroid.bounds_assist.BoundsAssistant;
|
||||
import com.stardust.scriptdroid.external.notification.bounds_assist.BoundsAssistSwitchNotification;
|
||||
import com.stardust.view.ViewBinder;
|
||||
import com.stardust.view.ViewBinding;
|
||||
|
||||
import static com.stardust.scriptdroid.ui.AssistModeSwitchNotification.KEY_ASSIST_MODE_NOTIFICATION;
|
||||
import static com.stardust.scriptdroid.external.notification.bounds_assist.BoundsAssistSwitchNotification.KEY_BOUNDS_ASSIST_SWITCH_NOTIFICATION_ENABLE;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/2/4.
|
||||
@ -72,14 +73,14 @@ public class EditSideMenuFragment extends com.stardust.app.Fragment {
|
||||
|
||||
private void syncSwitchState() {
|
||||
mAssistServiceSwitch.setChecked(BoundsAssistant.isAssistModeEnable());
|
||||
mAssistServiceNotificationSwitch.setChecked(AssistModeSwitchNotification.isEnable());
|
||||
mAssistServiceNotificationSwitch.setChecked(BoundsAssistSwitchNotification.isEnable());
|
||||
}
|
||||
|
||||
private void setUpSwitchCompat() {
|
||||
mAssistServiceSwitch = $(R.id.sw_assist_service);
|
||||
mAssistServiceNotificationSwitch = $(R.id.sw_assist_service_notification);
|
||||
App.getStateObserver().register(BoundsAssistant.KEY_ASSIST_MODE_ENABLE, mAssistServiceSwitch);
|
||||
App.getStateObserver().register(KEY_ASSIST_MODE_NOTIFICATION, mAssistServiceNotificationSwitch);
|
||||
App.getStateObserver().register(BoundsAssistant.KEY_BOUNDS_ASSIST_ENABLE, mAssistServiceSwitch);
|
||||
App.getStateObserver().register(KEY_BOUNDS_ASSIST_SWITCH_NOTIFICATION_ENABLE, mAssistServiceNotificationSwitch);
|
||||
}
|
||||
|
||||
@ViewBinding.Click(R.id.syntax_and_api)
|
||||
@ -104,7 +105,7 @@ public class EditSideMenuFragment extends com.stardust.app.Fragment {
|
||||
|
||||
@ViewBinding.Check(R.id.sw_assist_service_notification)
|
||||
private void setAssistServiceNotificationEnable(boolean enable) {
|
||||
AssistModeSwitchNotification.setEnable(enable);
|
||||
BoundsAssistSwitchNotification.setEnable(enable);
|
||||
}
|
||||
|
||||
@ViewBinding.Click(R.id.assist_service_notification)
|
||||
@ -1,4 +1,4 @@
|
||||
package com.stardust.scriptdroid.ui;
|
||||
package com.stardust.scriptdroid.ui.edit.sidemenu;
|
||||
|
||||
import android.bug.WrapContentLinearLayoutManager;
|
||||
import android.content.Context;
|
||||
@ -13,7 +13,7 @@ import android.widget.TextView;
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.file.FileUtils;
|
||||
import com.stardust.scriptdroid.widget.ExpandableRecyclerView;
|
||||
import com.stardust.widget.ExpandableRecyclerView;
|
||||
|
||||
import java.text.Collator;
|
||||
import java.util.ArrayList;
|
||||
@ -1,4 +1,4 @@
|
||||
package com.stardust.scriptdroid;
|
||||
package com.stardust.scriptdroid.ui.error;
|
||||
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
@ -13,6 +13,8 @@ import android.widget.Toast;
|
||||
|
||||
import com.afollestad.materialdialogs.DialogAction;
|
||||
import com.afollestad.materialdialogs.MaterialDialog;
|
||||
import com.stardust.scriptdroid.ui.BaseActivity;
|
||||
import com.stardust.scriptdroid.R;
|
||||
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
@ -0,0 +1,131 @@
|
||||
package com.stardust.scriptdroid.ui.error;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.design.widget.FloatingActionButton;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.view.View;
|
||||
import android.widget.EditText;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.heinrichreimersoftware.androidissuereporter.IssueReporterActivity;
|
||||
import com.heinrichreimersoftware.androidissuereporter.model.github.GithubTarget;
|
||||
import com.stardust.scriptdroid.R;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/2/13.
|
||||
*/
|
||||
|
||||
public class IssueReportActivity extends IssueReporterActivity {
|
||||
|
||||
|
||||
private boolean mCrash = false;
|
||||
private Method mReportIssue, mValidateInput;
|
||||
private boolean mReportFailed = false;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
handleIntent();
|
||||
setUpToobar();
|
||||
hookSendClick();
|
||||
}
|
||||
|
||||
private void hookSendClick() {
|
||||
FloatingActionButton send = (FloatingActionButton) this.findViewById(com.heinrichreimersoftware.androidissuereporter.R.id.air_buttonSend);
|
||||
send.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
try {
|
||||
reportIssue();
|
||||
} catch (Exception e) {
|
||||
mReportFailed = true;
|
||||
e.printStackTrace();
|
||||
finish();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setUpToobar() {
|
||||
getSupportActionBar().setTitle(R.string.text_issue_report);
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
Toolbar toolbar = (Toolbar) findViewById(R.id.air_toolbar);
|
||||
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
finish();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void handleIntent() {
|
||||
final String errorDetail = getIntent().getStringExtra("error");
|
||||
if (errorDetail != null) {
|
||||
((EditText) findViewById(R.id.air_inputDescription)).setText(errorDetail);
|
||||
((EditText) findViewById(R.id.air_inputTitle)).setText(R.string.text_crash_en);
|
||||
mCrash = true;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean validateInput() {
|
||||
if (mValidateInput == null) {
|
||||
try {
|
||||
mValidateInput = IssueReporterActivity.class.getDeclaredMethod("validateInput");
|
||||
mValidateInput.setAccessible(true);
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
try {
|
||||
return mValidateInput != null && (Boolean) mValidateInput.invoke(this);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void reportIssue() {
|
||||
if (mReportIssue == null) {
|
||||
try {
|
||||
mReportIssue = IssueReporterActivity.class.getDeclaredMethod("reportIssue");
|
||||
mReportIssue.setAccessible(true);
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
try {
|
||||
mReportIssue.invoke(this);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finish() {
|
||||
if (mCrash) {
|
||||
if (!mReportFailed) {
|
||||
Toast.makeText(IssueReportActivity.this, R.string.text_report_succeed, Toast.LENGTH_SHORT).show();
|
||||
} else {
|
||||
Toast.makeText(IssueReportActivity.this, R.string.text_report_fail, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
finishAffinity();
|
||||
|
||||
} else {
|
||||
super.finish();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GithubTarget getTarget() {
|
||||
return new GithubTarget("hyb1996", "NoRootScriptDroid");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getGuestToken() {
|
||||
return "f32d789662645640ff22e240b80f5d76117181a1";
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,11 +1,13 @@
|
||||
package com.stardust.scriptdroid;
|
||||
package com.stardust.scriptdroid.ui.help;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.view.View;
|
||||
|
||||
import com.stardust.scriptdroid.ui.BaseActivity;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.file.FileUtils;
|
||||
import com.stardust.view.MarkdownView;
|
||||
import com.stardust.widget.MarkdownView;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/2/1.
|
||||
@ -1,8 +1,10 @@
|
||||
package com.stardust.scriptdroid;
|
||||
package com.stardust.scriptdroid.ui.main;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
@ -16,32 +18,41 @@ import android.support.v7.widget.Toolbar;
|
||||
import android.text.InputType;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.afollestad.materialdialogs.DialogAction;
|
||||
import com.afollestad.materialdialogs.MaterialDialog;
|
||||
import com.afollestad.materialdialogs.folderselector.FileChooserDialog;
|
||||
import com.stardust.app.NotRemindAgainDialog;
|
||||
import com.stardust.scriptdroid.droid.runtime.action.ActionPerformService;
|
||||
import com.stardust.scriptdroid.BuildConfig;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.droid.runtime.action.ActionPerformAccessibilityDelegate;
|
||||
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.ActionRecordSwitchNotification;
|
||||
import com.stardust.scriptdroid.file.FileUtils;
|
||||
import com.stardust.scriptdroid.file.SampleFileTool;
|
||||
import com.stardust.scriptdroid.file.SampleFileManager;
|
||||
import com.stardust.scriptdroid.service.AccessibilityWatchDogService;
|
||||
import com.stardust.scriptdroid.tool.BackPressedHandler;
|
||||
import com.stardust.scriptdroid.ui.ScriptFileOperation;
|
||||
import com.stardust.scriptdroid.ui.ScriptListRecyclerView;
|
||||
import com.stardust.scriptdroid.ui.SlideMenuFragment;
|
||||
import com.stardust.scriptdroid.ui.SlidingUpPanel;
|
||||
import com.stardust.scriptdroid.ui.BaseActivity;
|
||||
import com.stardust.scriptdroid.ui.main.operation.ScriptFileOperation;
|
||||
import com.stardust.scriptdroid.ui.settings.SettingsActivity;
|
||||
import com.stardust.view.ViewBinder;
|
||||
import com.stardust.view.ViewBinding;
|
||||
import com.stardust.view.accessibility.AccessibilityServiceUtils;
|
||||
import com.stardust.widget.SlidingUpPanel;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
|
||||
public class MainActivity extends BaseActivity implements FileChooserDialog.FileCallback {
|
||||
|
||||
private static final String EXTRA_ACTION = "EXTRA_ACTION";
|
||||
|
||||
public static final String ACTION_NOTIFY_SCRIPT_LIST_CHANGE = "ACTION_NOTIFY_SCRIPT_LIST_CHANGE";
|
||||
private static final String ACTION_ON_ACTION_RECORD_STOPPED = "ACTION_ON_ACTION_RECORD_STOPPED";
|
||||
private static final String ARGUMENT_SCRIPT = "ARGUMENT_SCRIPT";
|
||||
|
||||
private SlidingUpPanel mAddFilePanel;
|
||||
private ScriptListRecyclerView mScriptListRecyclerView;
|
||||
@ -55,6 +66,7 @@ public class MainActivity extends BaseActivity implements FileChooserDialog.File
|
||||
setUpUI();
|
||||
checkPermissions();
|
||||
registerReceivers();
|
||||
handleIntent(getIntent());
|
||||
}
|
||||
|
||||
private void registerReceivers() {
|
||||
@ -68,7 +80,7 @@ public class MainActivity extends BaseActivity implements FileChooserDialog.File
|
||||
}
|
||||
|
||||
private void goToAccessibilityPermissionSettingIfDisabled() {
|
||||
if (!AccessibilityServiceUtils.isAccessibilityServiceEnabled(this, ActionPerformService.class)) {
|
||||
if (!AccessibilityServiceUtils.isAccessibilityServiceEnabled(this, ActionPerformAccessibilityDelegate.class)) {
|
||||
new NotRemindAgainDialog.Builder(this, "goToAccessibilityPermissionSettingIfDisabled")
|
||||
.title(R.string.text_alert)
|
||||
.content(R.string.explain_accessibility_permission)
|
||||
@ -142,19 +154,29 @@ public class MainActivity extends BaseActivity implements FileChooserDialog.File
|
||||
|
||||
@ViewBinding.Click(R.id.create_new_file)
|
||||
private void createScriptFile() {
|
||||
createScriptFileForScript(null);
|
||||
}
|
||||
|
||||
|
||||
private void createScriptFileForScript(final String script) {
|
||||
new MaterialDialog.Builder(this).title(R.string.text_name)
|
||||
.inputType(InputType.TYPE_CLASS_TEXT)
|
||||
.input(getString(R.string.text_please_input_name), "", new MaterialDialog.InputCallback() {
|
||||
@Override
|
||||
public void onInput(@NonNull MaterialDialog dialog, CharSequence input) {
|
||||
String path = ScriptFile.DEFAULT_FOLDER + input + ".js";
|
||||
MainActivity.this.createScriptFile(input.toString(), path);
|
||||
MainActivity.this.createScriptFile(input.toString(), path, script);
|
||||
}
|
||||
}).show();
|
||||
}
|
||||
|
||||
private void createScriptFile(String name, String path) {
|
||||
private void createScriptFile(String name, String path, String script) {
|
||||
if (FileUtils.createFileIfNotExists(path)) {
|
||||
if (script != null) {
|
||||
if (!FileUtils.writeString(path, script)) {
|
||||
Snackbar.make(mDrawerLayout, R.string.text_file_write_fail, Snackbar.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
addScriptFile(name, path);
|
||||
new ScriptFileOperation.Edit().operate(mScriptListRecyclerView, mScriptFileList, mScriptFileList.size() - 1);
|
||||
} else {
|
||||
@ -170,6 +192,16 @@ public class MainActivity extends BaseActivity implements FileChooserDialog.File
|
||||
.show();
|
||||
}
|
||||
|
||||
@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();
|
||||
return;
|
||||
}
|
||||
ActionRecordSwitchNotification.showOrUpdateNotification();
|
||||
Snackbar.make(mDrawerLayout, R.string.hint_start_record, Snackbar.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
@ViewBinding.Click(R.id.setting)
|
||||
private void startSettingActivity() {
|
||||
startActivity(new Intent(this, SettingsActivity.class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
|
||||
@ -184,7 +216,7 @@ public class MainActivity extends BaseActivity implements FileChooserDialog.File
|
||||
public void onRequestPermissionsResult(int requestCode,
|
||||
@NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
if (requestCode == PERMISSION_REQUEST_CODE && grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
SampleFileTool.getInstance().copySampleScriptFileIfNeeded();
|
||||
SampleFileManager.getInstance().copySampleScriptFileIfNeeded();
|
||||
mScriptListRecyclerView.getAdapter().notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
@ -194,6 +226,42 @@ public class MainActivity extends BaseActivity implements FileChooserDialog.File
|
||||
addScriptFile(file.getPath());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNewIntent(Intent intent) {
|
||||
super.onNewIntent(intent);
|
||||
handleIntent(intent);
|
||||
}
|
||||
|
||||
private void handleIntent(Intent intent) {
|
||||
String action = intent.getStringExtra(EXTRA_ACTION);
|
||||
if (action == null)
|
||||
return;
|
||||
switch (action) {
|
||||
case ACTION_ON_ACTION_RECORD_STOPPED:
|
||||
handleRecordedScript(intent.getStringExtra(ARGUMENT_SCRIPT));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void handleRecordedScript(final String script) {
|
||||
new MaterialDialog.Builder(this)
|
||||
.title(R.string.text_recorded)
|
||||
.items(getString(R.string.text_new_file), getString(R.string.text_copy_to_clip))
|
||||
.itemsCallback(new MaterialDialog.ListCallback() {
|
||||
@Override
|
||||
public void onSelection(MaterialDialog dialog, View itemView, int position, CharSequence text) {
|
||||
if (position == 0) {
|
||||
createScriptFileForScript(script);
|
||||
} else {
|
||||
((ClipboardManager) getSystemService(CLIPBOARD_SERVICE))
|
||||
.setPrimaryClip(ClipData.newPlainText("script", script));
|
||||
Toast.makeText(MainActivity.this, R.string.text_already_copy_to_clip, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
})
|
||||
.show();
|
||||
|
||||
}
|
||||
|
||||
private BackPressedHandler mBackPressedHandler = new BackPressedHandler.DoublePressExit(this);
|
||||
|
||||
@ -214,6 +282,14 @@ public class MainActivity extends BaseActivity implements FileChooserDialog.File
|
||||
unregisterReceiver(mReceiver);
|
||||
}
|
||||
|
||||
public static void onActionRecordStopped(Context context, String script) {
|
||||
Intent intent = new Intent(context, MainActivity.class)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
|
||||
.putExtra(EXTRA_ACTION, ACTION_ON_ACTION_RECORD_STOPPED)
|
||||
.putExtra(ARGUMENT_SCRIPT, script);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
private class Receiver extends BroadcastReceiver {
|
||||
|
||||
@Override
|
||||
@ -1,4 +1,4 @@
|
||||
package com.stardust.scriptdroid.ui;
|
||||
package com.stardust.scriptdroid.ui.main;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Environment;
|
||||
@ -16,11 +16,13 @@ import com.afollestad.materialdialogs.MaterialDialog;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.droid.script.file.ScriptFile;
|
||||
import com.stardust.scriptdroid.droid.script.file.ScriptFileList;
|
||||
import com.stardust.scriptdroid.ui.main.operation.ScriptFileOperation;
|
||||
import com.stardust.scriptdroid.ui.main.operation.ScriptFileOperationPopupMenu;
|
||||
import com.stardust.scriptdroid.tool.ClassTool;
|
||||
|
||||
import static com.stardust.scriptdroid.tool.ViewTool.$;
|
||||
|
||||
import static com.stardust.scriptdroid.ui.ScriptFileOperation.*;
|
||||
import static com.stardust.scriptdroid.ui.main.operation.ScriptFileOperation.*;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/1/23.
|
||||
@ -1,4 +1,4 @@
|
||||
package com.stardust.scriptdroid.ui;
|
||||
package com.stardust.scriptdroid.ui.main;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
@ -12,17 +12,18 @@ import android.view.ViewGroup;
|
||||
|
||||
import com.stardust.app.Fragment;
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.DocumentActivity;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.droid.ConsoleActivity;
|
||||
import com.stardust.scriptdroid.bounds_assist.BoundsAssistant;
|
||||
import com.stardust.scriptdroid.droid.Droid;
|
||||
import com.stardust.scriptdroid.droid.assist.BoundsAssistant;
|
||||
import com.stardust.scriptdroid.droid.runtime.action.ActionPerformService;
|
||||
import com.stardust.scriptdroid.external.notification.bounds_assist.BoundsAssistSwitchNotification;
|
||||
import com.stardust.scriptdroid.service.AccessibilityWatchDogService;
|
||||
import com.stardust.scriptdroid.ui.console.ConsoleActivity;
|
||||
import com.stardust.scriptdroid.ui.help.DocumentActivity;
|
||||
import com.stardust.view.ViewBinder;
|
||||
import com.stardust.view.ViewBinding;
|
||||
import com.stardust.view.accessibility.AccessibilityServiceUtils;
|
||||
|
||||
import static com.stardust.scriptdroid.ui.AssistModeSwitchNotification.KEY_ASSIST_MODE_NOTIFICATION;
|
||||
import static com.stardust.scriptdroid.external.notification.bounds_assist.BoundsAssistSwitchNotification.KEY_BOUNDS_ASSIST_SWITCH_NOTIFICATION_ENABLE;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/1/30.
|
||||
@ -59,19 +60,19 @@ public class SlideMenuFragment extends Fragment {
|
||||
mAutoOperateServiceSwitch.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mAutoOperateServiceSwitch.setChecked(ActionPerformService.isEnable());
|
||||
mAutoOperateServiceSwitch.setChecked(AccessibilityWatchDogService.isEnable());
|
||||
}
|
||||
}, 450);
|
||||
mAssistServiceSwitch.setChecked(BoundsAssistant.isAssistModeEnable());
|
||||
mAssistServiceNotificationSwitch.setChecked(AssistModeSwitchNotification.isEnable());
|
||||
mAssistServiceNotificationSwitch.setChecked(BoundsAssistSwitchNotification.isEnable());
|
||||
}
|
||||
|
||||
private void setUpSwitchCompat() {
|
||||
mAutoOperateServiceSwitch = $(R.id.sw_auto_operate_service);
|
||||
mAssistServiceSwitch = $(R.id.sw_assist_service);
|
||||
mAssistServiceNotificationSwitch = $(R.id.sw_assist_service_notification);
|
||||
App.getStateObserver().register(BoundsAssistant.KEY_ASSIST_MODE_ENABLE, mAssistServiceSwitch);
|
||||
App.getStateObserver().register(KEY_ASSIST_MODE_NOTIFICATION, mAssistServiceNotificationSwitch);
|
||||
App.getStateObserver().register(BoundsAssistant.KEY_BOUNDS_ASSIST_ENABLE, mAssistServiceSwitch);
|
||||
App.getStateObserver().register(KEY_BOUNDS_ASSIST_SWITCH_NOTIFICATION_ENABLE, mAssistServiceNotificationSwitch);
|
||||
}
|
||||
|
||||
|
||||
@ -92,10 +93,10 @@ public class SlideMenuFragment extends Fragment {
|
||||
|
||||
@ViewBinding.Check(R.id.sw_auto_operate_service)
|
||||
private void setAutoOperateServiceEnable(boolean enable) {
|
||||
if (enable && !ActionPerformService.isEnable()) {
|
||||
if (enable && !AccessibilityWatchDogService.isEnable()) {
|
||||
AccessibilityServiceUtils.goToAccessibilitySetting(getContext());
|
||||
} else if (!enable && ActionPerformService.isEnable()) {
|
||||
ActionPerformService.disable();
|
||||
} else if (!enable && AccessibilityWatchDogService.isEnable()) {
|
||||
AccessibilityWatchDogService.disable();
|
||||
}
|
||||
}
|
||||
|
||||
@ -111,7 +112,7 @@ public class SlideMenuFragment extends Fragment {
|
||||
|
||||
@ViewBinding.Check(R.id.sw_assist_service_notification)
|
||||
private void setAssistServiceNotificationEnable(boolean enable) {
|
||||
AssistModeSwitchNotification.setEnable(enable);
|
||||
BoundsAssistSwitchNotification.setEnable(enable);
|
||||
}
|
||||
|
||||
@ViewBinding.Click(R.id.assist_service_notification)
|
||||
@ -1,4 +1,4 @@
|
||||
package com.stardust.scriptdroid.ui;
|
||||
package com.stardust.scriptdroid.ui.main.operation;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@ -8,12 +8,13 @@ import android.support.design.widget.Snackbar;
|
||||
|
||||
import com.afollestad.materialdialogs.MaterialDialog;
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.EditActivity;
|
||||
import com.stardust.scriptdroid.ui.edit.EditActivity;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.ShortcutActivity;
|
||||
import com.stardust.scriptdroid.external.shortcut.ShortcutActivity;
|
||||
import com.stardust.scriptdroid.droid.script.file.ScriptFile;
|
||||
import com.stardust.scriptdroid.droid.script.file.ScriptFileList;
|
||||
import com.stardust.scriptdroid.shortcut.Shortcut;
|
||||
import com.stardust.scriptdroid.external.shortcut.Shortcut;
|
||||
import com.stardust.scriptdroid.ui.main.ScriptListRecyclerView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@ -1,4 +1,4 @@
|
||||
package com.stardust.scriptdroid.ui;
|
||||
package com.stardust.scriptdroid.ui.main.operation;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
@ -1,16 +1,21 @@
|
||||
package com.stardust.scriptdroid;
|
||||
package com.stardust.scriptdroid.ui.settings;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.afollestad.materialdialogs.DialogAction;
|
||||
import com.afollestad.materialdialogs.MaterialDialog;
|
||||
import com.stardust.scriptdroid.ui.BaseActivity;
|
||||
import com.stardust.scriptdroid.BuildConfig;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.tool.IntentTool;
|
||||
import com.stardust.view.ViewBinder;
|
||||
import com.stardust.view.ViewBinding;
|
||||
@ -23,6 +28,8 @@ import moe.feng.alipay.zerosdk.AlipayZeroSdk;
|
||||
|
||||
public class AboutActivity extends BaseActivity {
|
||||
|
||||
private int mLolClickCount = 0;
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
@ -61,6 +68,7 @@ public class AboutActivity extends BaseActivity {
|
||||
|
||||
@ViewBinding.Click(R.id.qq)
|
||||
private void openQQToChatWithMe() {
|
||||
Toast.makeText(this, R.string.text_qq_group_id_copied, Toast.LENGTH_SHORT).show();
|
||||
String qq = getString(R.string.qq);
|
||||
IntentTool.goToQQ(this, qq);
|
||||
}
|
||||
@ -99,7 +107,19 @@ public class AboutActivity extends BaseActivity {
|
||||
|
||||
@ViewBinding.Click(R.id.icon)
|
||||
private void lol() {
|
||||
mLolClickCount++;
|
||||
Toast.makeText(this, R.string.text_lll, Toast.LENGTH_LONG).show();
|
||||
if (mLolClickCount >= 5) {
|
||||
new MaterialDialog.Builder(this)
|
||||
.title("Crash Test")
|
||||
.positiveText("Crash")
|
||||
.onPositive(new MaterialDialog.SingleButtonCallback() {
|
||||
@Override
|
||||
public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
|
||||
throw new RuntimeException("Crash Test");
|
||||
}
|
||||
}).show();
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBinding.Click(R.id.developer)
|
||||
@ -1,5 +1,7 @@
|
||||
package com.stardust.scriptdroid;
|
||||
package com.stardust.scriptdroid.ui.settings;
|
||||
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.preference.Preference;
|
||||
@ -9,7 +11,11 @@ import android.support.v7.widget.Toolbar;
|
||||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.stardust.scriptdroid.file.SampleFileTool;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.file.SampleFileManager;
|
||||
import com.stardust.scriptdroid.ui.BaseActivity;
|
||||
import com.stardust.scriptdroid.ui.error.IssueReportActivity;
|
||||
import com.stardust.scriptdroid.ui.main.MainActivity;
|
||||
import com.stardust.util.MapEntries;
|
||||
|
||||
import java.util.Map;
|
||||
@ -66,7 +72,7 @@ public class SettingsActivity extends BaseActivity {
|
||||
.entry(getString(R.string.text_re_import_samples), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
int failCount = SampleFileTool.getInstance().copySampleScriptFile();
|
||||
int failCount = SampleFileManager.getInstance().copySampleScriptFile();
|
||||
if (failCount <= 0) {
|
||||
Toast.makeText(getActivity(), R.string.text_re_import_succeed, Toast.LENGTH_SHORT).show();
|
||||
notifyScriptListChanged();
|
||||
@ -74,6 +80,19 @@ public class SettingsActivity extends BaseActivity {
|
||||
Toast.makeText(getActivity(), R.string.text_fail, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
})
|
||||
.entry(getString(R.string.text_issue_report), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
startActivity(new Intent(getActivity(), IssueReportActivity.class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
|
||||
}
|
||||
})
|
||||
.entry(getString(R.string.text_join_qq_group), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
((ClipboardManager) getActivity().getSystemService(CLIPBOARD_SERVICE)).setPrimaryClip(ClipData.newPlainText("qq", "556928653"));
|
||||
Toast.makeText(getActivity(), R.string.text_qq_group_id_copied, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
})
|
||||
.entry(getString(R.string.text_about), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@ -15,30 +15,18 @@ import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
public class StateObserver {
|
||||
|
||||
public interface OnStateChangedListener<T> {
|
||||
public interface OnStateChangedListener {
|
||||
|
||||
void onStateChanged(T newState);
|
||||
void onStateChanged(boolean newState);
|
||||
|
||||
void initState(T state);
|
||||
void initState(boolean state);
|
||||
}
|
||||
|
||||
|
||||
public static abstract class SimpleOnStateChangedListener<T> implements OnStateChangedListener<T> {
|
||||
public static abstract class SimpleOnStateChangedListener<T> implements OnStateChangedListener {
|
||||
|
||||
@Override
|
||||
public void initState(T state) {
|
||||
onStateChanged(state);
|
||||
}
|
||||
}
|
||||
|
||||
public interface OnBooleanStateChangedListener extends OnStateChangedListener<Boolean> {
|
||||
|
||||
}
|
||||
|
||||
public static abstract class SimpleOnBooleanStateChangedListener implements OnBooleanStateChangedListener {
|
||||
|
||||
@Override
|
||||
public void initState(Boolean state) {
|
||||
public void initState(boolean state) {
|
||||
onStateChanged(state);
|
||||
}
|
||||
}
|
||||
@ -53,9 +41,9 @@ public class StateObserver {
|
||||
|
||||
public void register(final String key, SwitchCompat switchCompat) {
|
||||
final WeakReference<SwitchCompat> switchCompatWeakReference = new WeakReference<>(switchCompat);
|
||||
register(key, new SimpleOnBooleanStateChangedListener() {
|
||||
register(key, new SimpleOnStateChangedListener() {
|
||||
@Override
|
||||
public void onStateChanged(Boolean newState) {
|
||||
public void onStateChanged(boolean newState) {
|
||||
if (switchCompatWeakReference.get() != null) {
|
||||
switchCompatWeakReference.get().setChecked(newState);
|
||||
} else {
|
||||
@ -65,10 +53,8 @@ public class StateObserver {
|
||||
});
|
||||
}
|
||||
|
||||
public <T> void register(String key, OnStateChangedListener<T> listener) {
|
||||
T initialState = readState(key, listener);
|
||||
if (initialState != null)
|
||||
listener.initState(initialState);
|
||||
public void register(String key, OnStateChangedListener listener) {
|
||||
initState(key, listener);
|
||||
synchronized (mKeyStateListenersMap) {
|
||||
List<OnStateChangedListener> listeners = getListenerListOrCreateIfNotExists(key);
|
||||
listeners.add(listener);
|
||||
@ -76,7 +62,7 @@ public class StateObserver {
|
||||
}
|
||||
|
||||
|
||||
private <T> void unregister(String key, OnStateChangedListener<T> stateChangedListener) {
|
||||
private void unregister(String key, OnStateChangedListener stateChangedListener) {
|
||||
synchronized (mKeyStateListenersMap) {
|
||||
List<OnStateChangedListener> listeners = mKeyStateListenersMap.get(key);
|
||||
if (listeners == null) {
|
||||
@ -86,15 +72,13 @@ public class StateObserver {
|
||||
}
|
||||
}
|
||||
|
||||
public <T> void setState(String key, T state) {
|
||||
public void setState(String key, boolean state) {
|
||||
synchronized (mKeyStateListenersMap) {
|
||||
List<OnStateChangedListener> listeners = mKeyStateListenersMap.get(key);
|
||||
if (listeners == null || listeners.isEmpty())
|
||||
return;
|
||||
if (listeners.get(0) instanceof OnBooleanStateChangedListener) {
|
||||
mSharedPreferences.edit().putBoolean(key, (Boolean) state).apply();
|
||||
notifyBooleanStateChanged(listeners, (Boolean) state);
|
||||
}
|
||||
mSharedPreferences.edit().putBoolean(key, state).apply();
|
||||
notifyBooleanStateChanged(listeners, state);
|
||||
}
|
||||
}
|
||||
|
||||
@ -104,12 +88,10 @@ public class StateObserver {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <T> T readState(String key, OnStateChangedListener<T> listener) {
|
||||
if (listener instanceof OnBooleanStateChangedListener) {
|
||||
return mSharedPreferences.contains(key) ? (T) Boolean.valueOf(mSharedPreferences.getBoolean(key, false)) : null;
|
||||
private void initState(String key, OnStateChangedListener listener) {
|
||||
if (mSharedPreferences.contains(key)) {
|
||||
listener.initState(mSharedPreferences.getBoolean(key, false));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private List<OnStateChangedListener> getListenerListOrCreateIfNotExists(String key) {
|
||||
|
||||
@ -1,8 +0,0 @@
|
||||
package com.stardust.util.function;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/1/24.
|
||||
*/
|
||||
|
||||
public class ArrayOptional {
|
||||
}
|
||||
@ -1,8 +0,0 @@
|
||||
package com.stardust.util.function;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/1/26.
|
||||
*/
|
||||
|
||||
public class Domino {
|
||||
}
|
||||
@ -1,15 +0,0 @@
|
||||
package com.stardust.util.function;
|
||||
|
||||
import android.support.annotation.RequiresApi;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/1/24.
|
||||
*/
|
||||
|
||||
public class FunctionTool {
|
||||
|
||||
|
||||
}
|
||||
@ -1,24 +0,0 @@
|
||||
package com.stardust.util.function;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/1/26.
|
||||
*/
|
||||
|
||||
public class ListTool {
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ChildSupplier<T> {
|
||||
T getChild(int i);
|
||||
}
|
||||
|
||||
public static <T> List<T> toList(ChildSupplier<T> supplier, int size) {
|
||||
ArrayList<T> arrayList = new ArrayList<T>(size);
|
||||
for (int i = 0; i < size - 1; i++) {
|
||||
arrayList.add(supplier.getChild(i));
|
||||
}
|
||||
return arrayList;
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
package com.stardust.scriptdroid.widget;
|
||||
package com.stardust.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.Nullable;
|
||||
@ -1,4 +1,4 @@
|
||||
package com.stardust.view;
|
||||
package com.stardust.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
@ -1,4 +1,4 @@
|
||||
package com.stardust.scriptdroid.ui;
|
||||
package com.stardust.widget;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
@ -1,4 +1,4 @@
|
||||
package com.stardust.scriptdroid.widget;
|
||||
package com.stardust.widget;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
11
app/src/main/res/drawable/btn_selector.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item android:state_pressed="true">
|
||||
<color android:color="#cccccc"/>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<color android:color="@android:color/transparent"/>
|
||||
</item>
|
||||
</selector>
|
||||
BIN
app/src/main/res/drawable/ic_pause_gray_48dp.png
Normal file
|
After Width: | Height: | Size: 457 B |
BIN
app/src/main/res/drawable/ic_pause_grey600_48dp.png
Normal file
|
After Width: | Height: | Size: 353 B |
BIN
app/src/main/res/drawable/ic_play_arrow_black_48dp.png
Normal file
|
After Width: | Height: | Size: 208 B |
BIN
app/src/main/res/drawable/ic_play_arrow_gray_48dp.png
Normal file
|
After Width: | Height: | Size: 608 B |
BIN
app/src/main/res/drawable/ic_play_arrow_grey600_48dp.png
Normal file
|
After Width: | Height: | Size: 835 B |
BIN
app/src/main/res/drawable/ic_stop_black_36dp.png
Normal file
|
After Width: | Height: | Size: 117 B |
BIN
app/src/main/res/drawable/ic_stop_grey600_48dp.png
Normal file
|
After Width: | Height: | Size: 244 B |
BIN
app/src/main/res/drawable/ic_stop_white_36pt.png
Normal file
|
After Width: | Height: | Size: 89 B |
BIN
app/src/main/res/drawable/ic_video_record.png
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
@ -22,7 +22,7 @@
|
||||
|
||||
<view
|
||||
android:id="@+id/console"
|
||||
class="com.stardust.scriptdroid.droid.ConsoleActivity$ConsoleView"
|
||||
class="com.stardust.scriptdroid.ui.console.ConsoleActivity$ConsoleView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
|
||||
|
||||
@ -26,7 +26,7 @@
|
||||
</android.support.design.widget.AppBarLayout>
|
||||
</android.support.design.widget.CoordinatorLayout>
|
||||
|
||||
<com.stardust.view.MarkdownView
|
||||
<com.stardust.widget.MarkdownView
|
||||
android:id="@+id/markdown"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
tools:context=".EditActivity">
|
||||
tools:context=".ui.edit.EditActivity">
|
||||
|
||||
<android.support.design.widget.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
@ -27,7 +27,7 @@
|
||||
android:layout_gravity="right"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<com.stardust.scriptdroid.widget.ToolbarMenuItem
|
||||
<com.stardust.widget.ToolbarMenuItem
|
||||
android:id="@+id/run"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="match_parent"
|
||||
@ -35,21 +35,21 @@
|
||||
app:icon_color="@android:color/white"
|
||||
app:text="@string/text_run"/>
|
||||
|
||||
<com.stardust.scriptdroid.widget.ToolbarMenuItem
|
||||
<com.stardust.widget.ToolbarMenuItem
|
||||
android:id="@+id/undo"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="match_parent"
|
||||
app:icon="@drawable/ic_undo_white_48dp"
|
||||
app:text="@string/text_undo"/>
|
||||
|
||||
<com.stardust.scriptdroid.widget.ToolbarMenuItem
|
||||
<com.stardust.widget.ToolbarMenuItem
|
||||
android:id="@+id/redo"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="match_parent"
|
||||
app:icon="@drawable/ic_redo_white_48dp"
|
||||
app:text="@string/text_redo"/>
|
||||
|
||||
<com.stardust.scriptdroid.widget.ToolbarMenuItem
|
||||
<com.stardust.widget.ToolbarMenuItem
|
||||
android:id="@+id/save"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="match_parent"
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
android:id="@+id/drawer_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context="com.stardust.scriptdroid.MainActivity">
|
||||
tools:context=".ui.main.MainActivity">
|
||||
|
||||
|
||||
<android.support.design.widget.CoordinatorLayout
|
||||
@ -41,7 +41,7 @@
|
||||
|
||||
<include layout="@layout/content_main"/>
|
||||
|
||||
<com.stardust.scriptdroid.ui.SlidingUpPanel
|
||||
<com.stardust.widget.SlidingUpPanel
|
||||
android:id="@+id/bottom_menu"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
@ -107,9 +107,35 @@
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/record"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="60dp"
|
||||
android:padding="10dp"
|
||||
android:src="@drawable/ic_video_record"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:text="@string/text_script_record"
|
||||
android:textColor="@color/colorPrimary"
|
||||
android:textSize="16sp"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</com.stardust.scriptdroid.ui.SlidingUpPanel>
|
||||
</com.stardust.widget.SlidingUpPanel>
|
||||
|
||||
</android.support.design.widget.CoordinatorLayout>
|
||||
|
||||
|
||||
@ -7,11 +7,11 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||
tools:context="com.stardust.scriptdroid.MainActivity"
|
||||
tools:context=".ui.main.MainActivity"
|
||||
tools:showIn="@layout/activity_main">
|
||||
|
||||
|
||||
<com.stardust.scriptdroid.ui.ScriptListRecyclerView
|
||||
<com.stardust.scriptdroid.ui.main.ScriptListRecyclerView
|
||||
android:id="@+id/script_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
|
||||
@ -116,12 +116,12 @@
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<com.stardust.scriptdroid.ui.FunctionListRecyclerView
|
||||
<com.stardust.scriptdroid.ui.edit.sidemenu.FunctionListRecyclerView
|
||||
android:id="@+id/function_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
<com.stardust.scriptdroid.ui.AssistClipListRecyclerView
|
||||
<com.stardust.scriptdroid.ui.edit.sidemenu.AssistClipListRecyclerView
|
||||
android:id="@+id/assist_clip_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
68
app/src/main/res/layout/remote_views_record_switch.xml
Normal file
@ -0,0 +1,68 @@
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="64dp"
|
||||
android:background="@android:color/white"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_margin="8dp"
|
||||
android:src="@drawable/ic_android_eat_js"/>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/start_or_pause"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_margin="4dp"
|
||||
android:background="@drawable/btn_selector"
|
||||
android:clickable="true"
|
||||
android:gravity="center_horizontal"
|
||||
android:orientation="vertical"
|
||||
android:padding="4dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/img_start_or_pause"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:src="@drawable/ic_play_arrow_grey600_48dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_start_or_pause"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:text="@string/text_start_record"
|
||||
android:textColor="#777777"
|
||||
android:textSize="12sp"/>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/stop"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_margin="4dp"
|
||||
android:background="@drawable/btn_selector"
|
||||
android:clickable="true"
|
||||
android:gravity="center_horizontal"
|
||||
android:orientation="vertical"
|
||||
android:padding="4dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:src="@drawable/ic_stop_grey600_48dp"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:text="@string/text_stop_record"
|
||||
android:textColor="#777777"
|
||||
android:textSize="12sp"/>
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
<view
|
||||
android:id="@+id/operation_list"
|
||||
class="com.stardust.scriptdroid.ui.ScriptFileOperationPopupMenu$ScriptFileOperationListRecyclerView"
|
||||
class="com.stardust.scriptdroid.ui.main.operation.ScriptFileOperationPopupMenu$ScriptFileOperationListRecyclerView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
</LinearLayout>
|
||||
@ -1,6 +1,6 @@
|
||||
<menu 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"
|
||||
tools:context="com.stardust.scriptdroid.MainActivity">
|
||||
tools:context=".ui.main.MainActivity">
|
||||
|
||||
</menu>
|
||||
|
||||
@ -25,6 +25,18 @@
|
||||
* `notStopped` 若当前脚本处于运行状态时返回`true`, 否则返回`false`。对于某些循环, 例如`while(true)`,请用`while(notStopped())`代替,以免死循环造成的脚本无法正常停止。
|
||||
* `isStoppd` 若当前脚本处于停止状态时返回`true`, 否则返回`false`。
|
||||
* `shell(cmd, root=false)` 执行shell命令cmd, 其中参数root表示是否以root权限执行,默认为false。例如`shell("input keyevent 26", true); //锁屏`。
|
||||
* `getTexts()` 获取屏幕上的文字列表, 返回一个java.util.List<String>。例如:
|
||||
|
||||
```
|
||||
launchApp("微信");
|
||||
while(!click("通讯录"));
|
||||
var texts = getTexts();
|
||||
for(var i = 0; i < texts.size(); i++){
|
||||
log(texts.get(i));
|
||||
}
|
||||
openConsole();
|
||||
```
|
||||
|
||||
###四、全局变量
|
||||
* `context` ApplicationContext,参见安卓[android.content.Context](https://developer.android.com/reference/android/content/Context.html)
|
||||
> 这里的context由于是ApplicationContext,是不可见的,不能用于dialog和其他UI相关。如果要显示弹窗或者视图,请启动UI模式(代码的第一行为`"ui";`既可)并使用activity代替。
|
||||
|
||||
36
app/src/main/res/values-zh/strings.xml
Normal file
@ -0,0 +1,36 @@
|
||||
<resources>
|
||||
<string name="air_title_report_issue">错误报告</string>
|
||||
|
||||
<string name="air_title_issue">问题</string>
|
||||
<string name="air_title_login">登录</string>
|
||||
|
||||
<string name="air_label_issue_title">标题</string>
|
||||
<string name="air_label_issue_description">描述</string>
|
||||
<string name="air_label_device_info">设备信息</string>
|
||||
|
||||
<string name="air_label_use_account">使用Github账号发送</string>
|
||||
<string name="air_label_use_email">使用Email发送</string>
|
||||
<string name="air_label_use_guest">匿名发送</string>
|
||||
<string name="air_label_username">用户名</string>
|
||||
<string name="air_label_password">密码</string>
|
||||
<string name="air_label_email">邮箱</string>
|
||||
<string name="air_label_email_optional">联系邮箱 (选填)</string>
|
||||
|
||||
<string name="air_error_no_title">请输入问题</string>
|
||||
<string name="air_error_no_description">请输入详细描述</string>
|
||||
<string name="air_error_no_username">请输入有效的Github用户名</string>
|
||||
<string name="air_error_no_password">请输入正确的密码</string>
|
||||
<string name="air_error_no_email">请输入邮箱</string>
|
||||
|
||||
<string name="air_dialog_title_loading">正在上传到GitHub…</string>
|
||||
<string name="air_dialog_title_failed">无法发送错误报告</string>
|
||||
<string name="air_dialog_description_failed_wrong_credentials">错误的用户名或密码</string>
|
||||
<string name="air_dialog_description_failed_invalid_token">无效的access token. 请联系软件开发者.</string>
|
||||
<string name="air_dialog_description_failed_issues_not_available">Issues不可用,请联系软件开发者.</string>
|
||||
<string name="air_dialog_description_failed_unknown">未知错误</string>
|
||||
<string name="air_dialog_action_failed">OK</string>
|
||||
<plurals name="air_error_short_description">
|
||||
<item quantity="one">描述至少要 %d 个字.</item>
|
||||
<item quantity="other">描述至少要 %d 个字.</item>
|
||||
</plurals>
|
||||
</resources>
|
||||
@ -99,4 +99,20 @@
|
||||
<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_qq_group_id_copied">已复制群号到剪贴板</string>
|
||||
</resources>
|
||||
|
||||
@ -11,6 +11,12 @@
|
||||
<PreferenceCategory
|
||||
android:title="@string/text_about">
|
||||
|
||||
<Preference
|
||||
android:title="@string/text_issue_report"/>
|
||||
|
||||
<Preference
|
||||
android:title="@string/text_join_qq_group"/>
|
||||
|
||||
<Preference
|
||||
android:title="@string/text_about"/>
|
||||
|
||||
|
||||
@ -2,6 +2,11 @@ package com.stardust.scriptdroid;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
*
|
||||
@ -9,7 +14,70 @@ import org.junit.Test;
|
||||
*/
|
||||
public class ExampleUnitTest {
|
||||
@Test
|
||||
public void testStack() throws Exception {
|
||||
public void testSync() throws Exception {
|
||||
final Sync sync = new Sync();
|
||||
//sync.print(11);
|
||||
add(sync, 11, 123);
|
||||
//Thread.sleep(1);
|
||||
sync.print(11);
|
||||
add(sync, 11, 456);
|
||||
sync.print(11);
|
||||
}
|
||||
|
||||
private void add(final Sync sync, final int key, final int i) {
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
sync.add(key, i);
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
private static class Sync {
|
||||
|
||||
private final Map<Integer, List<Integer>> mMap = new TreeMap<>();
|
||||
|
||||
Sync() {
|
||||
for (int i = 0; i < 10; i++) {
|
||||
List<Integer> list = new ArrayList<>();
|
||||
for (int j = 0; j < 10; j++) {
|
||||
list.add(j * i);
|
||||
}
|
||||
mMap.put(i, list);
|
||||
}
|
||||
}
|
||||
|
||||
public Sync add(int key, int i) {
|
||||
synchronized (mMap) {
|
||||
List<Integer> list = ensureList(key);
|
||||
list.add(i);
|
||||
System.out.println("add:" + key + " " + i);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
private List<Integer> ensureList(int key) {
|
||||
List<Integer> list = mMap.get(key);
|
||||
if (list == null) {
|
||||
list = new ArrayList<>();
|
||||
mMap.put(key, list);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public void print(int key) {
|
||||
synchronized (mMap) {
|
||||
List<Integer> list = mMap.get(key);
|
||||
System.out.print(key + ":");
|
||||
if (list == null) {
|
||||
System.out.print("null");
|
||||
} else {
|
||||
for (Integer i : list) {
|
||||
System.out.print(i + " ");
|
||||
}
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||