Added getTexts and action recorder, fixed github issue report token

This commit is contained in:
hyb1996
2017-02-15 18:10:17 +08:00
parent 04b4303899
commit e2d5efa710
82 changed files with 1392 additions and 518 deletions

View File

@@ -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();
}

View File

@@ -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";
}
}

View File

@@ -1,4 +1,4 @@
package com.stardust.scriptdroid.droid.assist;
package com.stardust.scriptdroid.bounds_assist;
/**
* Created by Stardust on 2017/2/4.

View File

@@ -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);
}
}

View File

@@ -1,4 +1,4 @@
package com.stardust.scriptdroid.droid.assist;
package com.stardust.scriptdroid.bounds_assist;
import android.content.Context;
import android.content.SharedPreferences;

View File

@@ -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() {

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}

View File

@@ -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();
}
}
}
}

View File

@@ -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();

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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());
}
}

View File

@@ -1,4 +1,4 @@
package com.stardust.scriptdroid.shortcut;
package com.stardust.scriptdroid.external.shortcut;
import android.content.Context;
import android.content.Intent;

View File

@@ -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;

View File

@@ -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.

View File

@@ -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();
}
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}

View File

@@ -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();
}
}
}

View File

@@ -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(");");
}
}
}

View File

@@ -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);
}

View File

@@ -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());
}
}
}

View File

@@ -47,4 +47,5 @@ public class IntentTool {
.putExtra(Intent.EXTRA_TEXT, text)
.setType("text/plain"));
}
}

View File

@@ -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;

View File

@@ -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;
/**

View File

@@ -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;

View File

@@ -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() {

View File

@@ -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;

View File

@@ -1,4 +1,4 @@
package com.stardust.scriptdroid.editor920;
package com.stardust.scriptdroid.ui.edit.editor920;
import android.support.annotation.NonNull;

View File

@@ -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.

View File

@@ -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)

View File

@@ -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;

View File

@@ -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;

View File

@@ -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";
}
}

View File

@@ -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.

View File

@@ -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

View File

@@ -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.

View File

@@ -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)

View File

@@ -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;

View File

@@ -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;

View File

@@ -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)

View File

@@ -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() {

View File

@@ -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) {

View File

@@ -1,8 +0,0 @@
package com.stardust.util.function;
/**
* Created by Stardust on 2017/1/24.
*/
public class ArrayOptional {
}

View File

@@ -1,8 +0,0 @@
package com.stardust.util.function;
/**
* Created by Stardust on 2017/1/26.
*/
public class Domino {
}

View File

@@ -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 {
}

View File

@@ -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;
}
}

View File

@@ -1,4 +1,4 @@
package com.stardust.scriptdroid.widget;
package com.stardust.widget;
import android.content.Context;
import android.support.annotation.Nullable;

View File

@@ -1,4 +1,4 @@
package com.stardust.view;
package com.stardust.widget;
import android.content.Context;
import android.os.Build;

View File

@@ -1,4 +1,4 @@
package com.stardust.scriptdroid.ui;
package com.stardust.widget;
import android.annotation.TargetApi;
import android.content.Context;

View File

@@ -1,4 +1,4 @@
package com.stardust.scriptdroid.widget;
package com.stardust.widget;
import android.annotation.TargetApi;
import android.content.Context;