Refactor: split into modules autojs, common, app and automator
This commit is contained in:
@@ -79,7 +79,6 @@
|
||||
<activity
|
||||
android:name=".ui.error.IssueReportActivity"
|
||||
android:theme="@style/IssueReportTheme"/>
|
||||
<activity android:name=".droid.script.ScriptExecuteActivity"/>
|
||||
|
||||
<service android:name=".service.VolumeChangeObverseService"/>
|
||||
<service android:name="com.stardust.view.Floaty$FloatHeadService"/>
|
||||
|
||||
@@ -1,292 +0,0 @@
|
||||
|
||||
if(__engine__ == "rhino"){
|
||||
__importClassOld__ = importClass;
|
||||
var importClass = function(pack){
|
||||
if(typeof(pack) == "string"){
|
||||
__importClassOld__(Packages[pack]);
|
||||
}else{
|
||||
__importClassOld__(pack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var toast = function(text){
|
||||
droid.toast(text);
|
||||
}
|
||||
|
||||
var launchPackage = function(package){
|
||||
droid.launchPackage(package);
|
||||
}
|
||||
|
||||
var launch = function(a, b){
|
||||
if(arguments.length == 2){
|
||||
droid.launch(a, b);
|
||||
}else{
|
||||
droid.launchPackage(a);
|
||||
}
|
||||
}
|
||||
|
||||
var launchApp = function(appName){
|
||||
droid.launchApp(appName);
|
||||
}
|
||||
|
||||
var __this__ = this;
|
||||
|
||||
var back = function(){
|
||||
return droid.back();
|
||||
}
|
||||
|
||||
var home = function(){
|
||||
return droid.home();
|
||||
}
|
||||
|
||||
var powerDialog = function(){
|
||||
return droid.powerDialog();
|
||||
}
|
||||
|
||||
var notifications = function(){
|
||||
return droid.notifications();
|
||||
}
|
||||
|
||||
var quickSettings = function(){
|
||||
return droid.quickSettings();
|
||||
}
|
||||
|
||||
var recents = function(){
|
||||
return droid.recents();
|
||||
}
|
||||
|
||||
var splitScreen = function(){
|
||||
return droid.splitScreen();
|
||||
}
|
||||
|
||||
|
||||
function performAction(action, args){
|
||||
if(args.length == 4){
|
||||
return action(droid.bounds(args[0], args[1], args[2], args[3]));
|
||||
}else if(args.length == 2){
|
||||
return action(droid.text(args[0], args[1]));
|
||||
}else {
|
||||
return action(droid.text(args[0], -1));
|
||||
}
|
||||
}
|
||||
|
||||
var click = function(){
|
||||
return performAction(function(target){
|
||||
return droid.click(target);
|
||||
}, arguments);
|
||||
}
|
||||
|
||||
var longClick = function(a, b, c, d){
|
||||
return performAction(function(target){
|
||||
return droid.longClick(target);
|
||||
}, arguments);
|
||||
}
|
||||
|
||||
|
||||
|
||||
var scrollUp = function(a, b, c, d){
|
||||
if(arguments.length == 0)
|
||||
return droid.scrollAllUp();
|
||||
if(arguments.length == 1 && typeof a === 'number')
|
||||
return droid.scrollUp(a);
|
||||
return performAction(function(target){
|
||||
return droid.scrollUp(target);
|
||||
}, arguments);
|
||||
}
|
||||
|
||||
var scrollDown = function(a, b, c, d){
|
||||
if(arguments.length == 0)
|
||||
return droid.scrollAllDown();
|
||||
if(arguments.length == 1 && typeof a === 'number')
|
||||
return droid.scrollDown(a);
|
||||
return performAction(function(target){
|
||||
return droid.scrollDown(target);
|
||||
}, arguments);
|
||||
}
|
||||
|
||||
var select = function(a, b, c, d){
|
||||
return performAction(function(target){
|
||||
return droid.select(target);
|
||||
}, arguments);
|
||||
}
|
||||
|
||||
var input = function(a, b){
|
||||
if(arguments.length == 1){
|
||||
return droid.setText(droid.editable(-1), a);
|
||||
}else{
|
||||
return droid.setText(droid.editable(a), b);
|
||||
}
|
||||
}
|
||||
|
||||
var sleep = function(millis){
|
||||
droid.sleep(millis);
|
||||
}
|
||||
|
||||
var isStopped = function(){
|
||||
return droid.isStopped();
|
||||
}
|
||||
|
||||
var notStopped = function(){
|
||||
return !isStopped();
|
||||
}
|
||||
|
||||
var log = function(str){
|
||||
droid.log(str);
|
||||
}
|
||||
|
||||
var print = log;
|
||||
|
||||
var err = function(e){
|
||||
droid.err(e);
|
||||
}
|
||||
|
||||
var openConsole = function(){
|
||||
droid.console();
|
||||
}
|
||||
|
||||
var clearConsole = function(){
|
||||
droid.clearConsole();
|
||||
}
|
||||
|
||||
var shell = function(cmd, root){
|
||||
root = root ? 1 : 0;
|
||||
return droid.shell(cmd, root);
|
||||
}
|
||||
|
||||
var currentPackage = function(){
|
||||
return droid.currentPackage();
|
||||
}
|
||||
|
||||
var currentActivity = function(){
|
||||
return droid.currentActivity();
|
||||
}
|
||||
|
||||
var setClip = function(text){
|
||||
droid.setClip(text);
|
||||
}
|
||||
|
||||
var getPackageName = function(appName){
|
||||
return droid.getPackageName(appName);
|
||||
}
|
||||
|
||||
var openAppSetting = function(packageName){
|
||||
return droid.openAppSetting(packageName);
|
||||
}
|
||||
|
||||
var Tap = function(x, y){
|
||||
return shell("input tap " + x + " " + y, true).code == 1;
|
||||
}
|
||||
|
||||
var Swipe = function(x1, y1, x2, y2, duration){
|
||||
if(arguments.length == 5){
|
||||
return shell("input swipe " + x1 + " " + y1 + " " + x2 + " " + y2 + " " + duration, true).code == 1;
|
||||
}
|
||||
return shell("input swipe " + x1 + " " + y1 + " " + x2 + " " + y2, true).code == 1;
|
||||
}
|
||||
|
||||
var KeyCode = function(keyCode){
|
||||
return shell("input keyevent " + keyCode, true).code == 1;
|
||||
}
|
||||
|
||||
var Home = function(){
|
||||
return KeyCode(3);
|
||||
}
|
||||
|
||||
var Back = function(){
|
||||
return KeyCode(4);
|
||||
}
|
||||
|
||||
var Power = function(){
|
||||
return KeyCode(26);
|
||||
}
|
||||
|
||||
var Up = function(){
|
||||
return KeyCode(19);
|
||||
}
|
||||
|
||||
var Down = function(){
|
||||
return KeyCode(20);
|
||||
}
|
||||
|
||||
var Left = function(){
|
||||
return KeyCode(21);
|
||||
}
|
||||
|
||||
var Right = function(){
|
||||
return KeyCode(22);
|
||||
}
|
||||
|
||||
var OK = function(){
|
||||
return KeyCode(23);
|
||||
}
|
||||
|
||||
var VolumeUp = function(){
|
||||
return KeyCode(24);
|
||||
}
|
||||
|
||||
var VolumeDown = function(){
|
||||
return KeyCode(25);
|
||||
}
|
||||
|
||||
var Menu = function(){
|
||||
return KeyCode(1);
|
||||
}
|
||||
|
||||
var Camera = function(){
|
||||
return KeyCode(27);
|
||||
}
|
||||
|
||||
var Text = function(text){
|
||||
return shell("input text " + text, true).code == 1;
|
||||
}
|
||||
|
||||
var __selector__ = droid.selector();
|
||||
var __obj__ = new java.lang.Object();
|
||||
|
||||
for(var x in __selector__){
|
||||
if(!__obj__[x] && !this[x]){
|
||||
this[x] = (function(method) {
|
||||
return function(){
|
||||
var s = droid.selector();
|
||||
//这里不知道怎么写。尴尬。只能写成这样。
|
||||
if(arguments.length == 0){
|
||||
return s[method]();
|
||||
}else if(arguments.length == 1){
|
||||
return s[method](arguments[0]);
|
||||
}else if(arguments.length == 2){
|
||||
return s[method](arguments[0], arguments[1]);
|
||||
}else if(arguments.length == 3){
|
||||
return s[method](arguments[0], arguments[1], arguments[2]);
|
||||
}else if(arguments.length == 4){
|
||||
return s[method](arguments[0], arguments[1], arguments[2], arguments[3]);
|
||||
}else{
|
||||
return s[method].call(s, Array.prototype.slice.call(arguments));
|
||||
}
|
||||
};
|
||||
})(x);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var open = function(path, mode){
|
||||
return com.stardust.pio.PFile.open(path, mode);
|
||||
}
|
||||
|
||||
__importClassOld__(com.stardust.scriptdroid.droid.runtime.api.Shell);
|
||||
|
||||
var newInjectableWebClient = function(){
|
||||
return new com.stardust.scriptdroid.droid.runtime.api.InjectableWebClient(org.mozilla.javascript.Context.getCurrentContext(), __this__);
|
||||
}
|
||||
|
||||
var newInjectableWebView = function(activity){
|
||||
return new com.stardust.scriptdroid.droid.runtime.api.InjectableWebView(activity, org.mozilla.javascript.Context.getCurrentContext(), __this__);
|
||||
}
|
||||
|
||||
/*
|
||||
importClass("com.stardust.scriptdroid.service.AccessibilityDelegate");
|
||||
|
||||
var addAccessibilityDelegate = function(delegate){
|
||||
droid.addAccessibilityDelegate(delegate);
|
||||
}
|
||||
*/
|
||||
@@ -1,46 +0,0 @@
|
||||
var __requireOld__ = require;
|
||||
var __nodejs_modules__ = {
|
||||
'websocket' : com.iwebpp.wspp.WebSocket,
|
||||
'websocketserver': com.iwebpp.wspp.WebSocketServer,
|
||||
'net': com.iwebpp.node.net.TCP,
|
||||
'tcp': com.iwebpp.node.net.TCP,
|
||||
'udt': com.iwebpp.node.net.UDT,
|
||||
'readable': com.iwebpp.node.stream.Readable2,
|
||||
'writable': com.iwebpp.node.stream.Writable2,
|
||||
'duplex': com.iwebpp.node.stream.Duplex,
|
||||
'transform': com.iwebpp.node.stream.Transform,
|
||||
'passthrough': com.iwebpp.node.stream.PassThrough,
|
||||
'dns': com.iwebpp.node.Dns,
|
||||
'url': com.iwebpp.node.Url,
|
||||
}
|
||||
|
||||
var require = function(module){
|
||||
if (module === 'http'){
|
||||
return {
|
||||
get: function(url, listener){
|
||||
return com.iwebpp.node.http.http.get(NodeCurrentContext, url, listener);
|
||||
},
|
||||
request: function(url, listener) {
|
||||
return com.iwebpp.node.http.http.request(NodeCurrentContext, url, listener);
|
||||
},
|
||||
createServer: function(listener) {
|
||||
return com.iwebpp.node.http.http.createServer(NodeCurrentContext, listener);
|
||||
},
|
||||
};
|
||||
}
|
||||
if (module === 'httpp'){
|
||||
return {
|
||||
get: function(url, listener){
|
||||
return com.iwebpp.node.http.httpp.get(NodeCurrentContext, url, listener);
|
||||
},
|
||||
request: function(url, listener) {
|
||||
return com.iwebpp.node.http.httpp.request(NodeCurrentContext, url, listener);
|
||||
},
|
||||
createServer: function(listener) {
|
||||
return com.iwebpp.node.http.httpp.createServer(NodeCurrentContext, listener);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
return __requireOld__(module);
|
||||
};
|
||||
@@ -1,4 +1,4 @@
|
||||
package android.bug;
|
||||
package android.workground;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
@@ -7,7 +7,7 @@ import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.stardust.scriptdroid.tool.ViewTool;
|
||||
import com.stardust.util.ViewUtil;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/1/30.
|
||||
@@ -23,7 +23,7 @@ public abstract class Fragment extends android.support.v4.app.Fragment {
|
||||
}
|
||||
|
||||
public <T extends View> T $(int id) {
|
||||
return ViewTool.$(mView, id);
|
||||
return ViewUtil.$(mView, id);
|
||||
}
|
||||
|
||||
public View findViewById(int id) {
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.stardust.app;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Application;
|
||||
import android.os.Bundle;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/4/2.
|
||||
*/
|
||||
|
||||
public class SimpleActivityLifecycleCallbacks implements Application.ActivityLifecycleCallbacks {
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityStarted(Activity activity) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResumed(Activity activity) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityPaused(Activity activity) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityStopped(Activity activity) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityDestroyed(Activity activity) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,129 +0,0 @@
|
||||
package com.stardust.hover;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.IBinder;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.Log;
|
||||
|
||||
import io.mattcarroll.hover.HoverMenu;
|
||||
import io.mattcarroll.hover.HoverMenuAdapter;
|
||||
import io.mattcarroll.hover.Navigator;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/3/11.
|
||||
*/
|
||||
|
||||
public abstract class HoverMenuService extends Service {
|
||||
|
||||
private static final String TAG = "HoverMenuService";
|
||||
|
||||
private static final String PREF_FILE = "hover_menu";
|
||||
private static final String PREF_HOVER_MENU_VISUAL_STATE = "hover_menu_visual_state";
|
||||
|
||||
|
||||
private HoverMenu mHoverMenu;
|
||||
private boolean mIsRunning;
|
||||
private SharedPreferences mPrefs;
|
||||
private HoverMenu.OnExitListener mWindowHoverMenuMenuExitListener = new HoverMenu.OnExitListener() {
|
||||
@Override
|
||||
public void onExitByUserRequest() {
|
||||
Log.d(TAG, "Menu exit requested.");
|
||||
savePreferredLocation();
|
||||
mHoverMenu.hide();
|
||||
onHoverMenuExitingByUserRequest();
|
||||
stopSelf();
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
Log.d(TAG, "onCreate()");
|
||||
mPrefs = getSharedPreferences(PREF_FILE, Context.MODE_PRIVATE);
|
||||
|
||||
mHoverMenu = new HoverMenuBuilder(getContextForHoverMenu())
|
||||
.displayWithinWindow()
|
||||
.useNavigator(createNavigator())
|
||||
.useAdapter(createHoverMenuAdapter())
|
||||
.restoreVisualState(loadPreferredLocation())
|
||||
.build();
|
||||
mHoverMenu.addOnExitListener(mWindowHoverMenuMenuExitListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
if (!mIsRunning) {
|
||||
Log.d(TAG, "onStartCommand() - showing Hover menu.");
|
||||
mIsRunning = true;
|
||||
mHoverMenu.show();
|
||||
}
|
||||
|
||||
return START_STICKY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
Log.d(TAG, "onDestroy()");
|
||||
mHoverMenu.hide();
|
||||
mIsRunning = false;
|
||||
}
|
||||
|
||||
|
||||
public HoverMenu getHoverMenu() {
|
||||
return mHoverMenu;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook for subclasses to return a custom Context to be used in the creation of the {@code HoverMenu}.
|
||||
* For example, subclasses might choose to provide a ContextThemeWrapper.
|
||||
*
|
||||
* @return context for HoverMenu initialization
|
||||
*/
|
||||
protected Context getContextForHoverMenu() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses can use this hook method to return a customized {@link Navigator} to be used
|
||||
* throughout the entire Hover menu. This {@link Navigator} will be used for every tab in the
|
||||
* Hover menu, so only supply a {@code Navigator} if you truly want every screen to display it.
|
||||
* <p>
|
||||
* If you want only a portion of the screens in the Hover menu to look different, then consider
|
||||
* using composition of {@link NavigatorContent} to achieve the desired effect. For example,
|
||||
* if you want a {@code Toolbar} to appear on one or more screens, consider placing your content
|
||||
* within a {@link ToolbarNavigatorContent}, and then add the {@code ToolbarNavigatorContent}
|
||||
* as the content of the default {@code Navigator}.
|
||||
*
|
||||
* @return Custom Navigator to use on every screen in the Hover menu
|
||||
*/
|
||||
protected Navigator createNavigator() {
|
||||
return null; // Subclasses can override this to provide a custom Navigator.
|
||||
}
|
||||
|
||||
abstract protected HoverMenuAdapter createHoverMenuAdapter();
|
||||
|
||||
/**
|
||||
* Hook method for subclasses to take action when the user exits the HoverMenu. This method runs
|
||||
* just before this {@code HoverMenuService} calls {@code stopSelf()}.
|
||||
*/
|
||||
protected void onHoverMenuExitingByUserRequest() {
|
||||
// Hook for subclasses.
|
||||
}
|
||||
|
||||
private void savePreferredLocation() {
|
||||
String memento = mHoverMenu.getVisualState();
|
||||
mPrefs.edit().putString(PREF_HOVER_MENU_VISUAL_STATE, memento).apply();
|
||||
}
|
||||
|
||||
private String loadPreferredLocation() {
|
||||
return mPrefs.getString(PREF_HOVER_MENU_VISUAL_STATE, null);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,31 +0,0 @@
|
||||
package com.stardust.pio;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/4/1.
|
||||
*/
|
||||
|
||||
public class PFile {
|
||||
|
||||
public static PFile open(String path, String mode) {
|
||||
switch (mode){
|
||||
case "r":
|
||||
return new PReadableFile(path);
|
||||
case "w":
|
||||
return new PWritableFile();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void create(String path){
|
||||
|
||||
}
|
||||
|
||||
public static void createIfNotExists(String path){
|
||||
|
||||
}
|
||||
|
||||
public static void delete(String path){
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,106 +0,0 @@
|
||||
package com.stardust.pio;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/4/1.
|
||||
*/
|
||||
|
||||
public class PReadableFile extends PFile {
|
||||
|
||||
private BufferedReader mBufferedReader;
|
||||
private FileInputStream mFileInputStream;
|
||||
private int mBufferingSize;
|
||||
private String mEncoding;
|
||||
|
||||
public PReadableFile(String path) {
|
||||
this(path, Charset.defaultCharset().name());
|
||||
}
|
||||
|
||||
public PReadableFile(String path, String encoding) {
|
||||
this(path, encoding, -1);
|
||||
}
|
||||
|
||||
public PReadableFile(String path, String encoding, int bufferingSize) {
|
||||
mEncoding = encoding;
|
||||
mBufferingSize = bufferingSize;
|
||||
try {
|
||||
mFileInputStream = new FileInputStream(path);
|
||||
} catch (FileNotFoundException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void ensureBufferReader() {
|
||||
if (mBufferedReader == null) {
|
||||
try {
|
||||
if (mBufferingSize == -1)
|
||||
mBufferedReader = new BufferedReader(new InputStreamReader(mFileInputStream, mEncoding));
|
||||
else
|
||||
mBufferedReader = new BufferedReader(new InputStreamReader(mFileInputStream, mEncoding), mBufferingSize);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public String read() {
|
||||
try {
|
||||
byte[] data = new byte[mFileInputStream.available()];
|
||||
mFileInputStream.read(data);
|
||||
return new String(data, mEncoding);
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public String read(int size) {
|
||||
ensureBufferReader();
|
||||
try {
|
||||
char[] chars = new char[size];
|
||||
int len = mBufferedReader.read(chars);
|
||||
return new String(chars, 0, len);
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public String readline() {
|
||||
ensureBufferReader();
|
||||
try {
|
||||
return mBufferedReader.readLine();
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public String[] readlines() {
|
||||
ensureBufferReader();
|
||||
List<String> lines = new ArrayList<>();
|
||||
try {
|
||||
while (mBufferedReader.ready()) {
|
||||
lines.add(mBufferedReader.readLine());
|
||||
}
|
||||
return lines.toArray(new String[lines.size()]);
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void close() {
|
||||
try {
|
||||
if (mBufferedReader != null) {
|
||||
mBufferedReader.close();
|
||||
} else {
|
||||
mFileInputStream.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package com.stardust.pio;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/4/1.
|
||||
*/
|
||||
|
||||
public class PWritableFile extends PFile {
|
||||
|
||||
public PWritableFile(){
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package com.stardust.pio;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/4/1.
|
||||
*/
|
||||
|
||||
public class UncheckedIOException extends RuntimeException {
|
||||
|
||||
public UncheckedIOException(IOException cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
||||
@@ -2,28 +2,17 @@ package com.stardust.scriptdroid;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Application;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
import com.stardust.automator.AccessibilityEventCommandHost;
|
||||
import com.stardust.scriptdroid.accessibility.AccessibilityInfoProvider;
|
||||
import com.stardust.scriptdroid.droid.runtime.DroidRuntime;
|
||||
import com.stardust.scriptdroid.droid.script.JavaScriptEngine;
|
||||
import com.stardust.scriptdroid.droid.script.NodeJsJavaScriptEngine;
|
||||
import com.stardust.scriptdroid.droid.script.RhinoJavaScriptEngine;
|
||||
import com.stardust.scriptdroid.droid.script.file.ScriptFileList;
|
||||
import com.stardust.scriptdroid.droid.script.file.SharedPrefScriptFileList;
|
||||
import com.stardust.scriptdroid.droid.script.file.StorageScriptFileList;
|
||||
import com.stardust.scriptdroid.layout_inspector.LayoutInspector;
|
||||
import com.stardust.scriptdroid.record.accessibility.AccessibilityActionRecorder;
|
||||
import com.stardust.scriptdroid.service.AccessibilityWatchDogService;
|
||||
import com.squareup.leakcanary.LeakCanary;
|
||||
import com.stardust.scriptdroid.droid.runtime.action.ActionPerformAccessibilityDelegate;
|
||||
import com.stardust.app.SimpleActivityLifecycleCallbacks;
|
||||
import com.stardust.scriptdroid.autojs.AutoJs;
|
||||
import com.stardust.scriptdroid.service.VolumeChangeObverseService;
|
||||
import com.stardust.scriptdroid.tool.CrashHandler;
|
||||
import com.stardust.scriptdroid.ui.error.ErrorReportActivity;
|
||||
import com.stardust.theme.ThemeColor;
|
||||
import com.stardust.theme.ThemeColorManager;
|
||||
import com.stardust.util.CrashHandler;
|
||||
import com.stardust.util.StateObserver;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/1/27.
|
||||
@@ -34,25 +23,18 @@ public class App extends Application {
|
||||
private static final String TAG = "App";
|
||||
|
||||
private static App instance;
|
||||
private static StateObserver stateObserver;
|
||||
private static Activity currentActivity;
|
||||
|
||||
public static App getApp() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public static StateObserver getStateObserver() {
|
||||
return stateObserver;
|
||||
}
|
||||
|
||||
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
instance = this;
|
||||
setUpDebugEnvironment();
|
||||
init();
|
||||
configApp();
|
||||
registerActivityLifecycleCallback();
|
||||
initAccessibilityServiceDelegates();
|
||||
}
|
||||
|
||||
private void setUpDebugEnvironment() {
|
||||
@@ -67,23 +49,16 @@ public class App extends Application {
|
||||
private void init() {
|
||||
ThemeColorManager.setDefaultThemeColor(new ThemeColor(getResources().getColor(R.color.colorPrimary), getResources().getColor(R.color.colorPrimaryDark), getResources().getColor(R.color.colorAccent)));
|
||||
ThemeColorManager.init(this);
|
||||
instance = this;
|
||||
stateObserver = new StateObserver(PreferenceManager.getDefaultSharedPreferences(this));
|
||||
}
|
||||
|
||||
private void configApp() {
|
||||
ScriptFileList.setImpl(SharedPrefScriptFileList.getInstance());
|
||||
JavaScriptEngine.setDefault(new NodeJsJavaScriptEngine(DroidRuntime.getRuntime()));
|
||||
}
|
||||
|
||||
|
||||
private void initAccessibilityServiceDelegates() {
|
||||
AccessibilityWatchDogService.addDelegateIfNeeded(100, ActionPerformAccessibilityDelegate.class);
|
||||
AccessibilityWatchDogService.addDelegateIfNeeded(200, AccessibilityActionRecorder.getInstance());
|
||||
AccessibilityWatchDogService.addDelegateIfNeeded(300, AccessibilityEventCommandHost.getInstance());
|
||||
AccessibilityWatchDogService.addDelegateIfNeeded(400, AccessibilityInfoProvider.getInstance());
|
||||
AccessibilityWatchDogService.addDelegateIfNeeded(500, LayoutInspector.getInstance());
|
||||
|
||||
AutoJs.initInstance(this);
|
||||
VolumeChangeObverseService.addOnVolumeChangeListener(new VolumeChangeObverseService.OnVolumeChangeListener() {
|
||||
@Override
|
||||
public void onVolumeChange() {
|
||||
if (Pref.isRunningVolumeControlEnabled()) {
|
||||
AutoJs.getInstance().getScriptEngineService().stopAllAndToast();
|
||||
}
|
||||
}
|
||||
});
|
||||
startService(new Intent(this, VolumeChangeObverseService.class));
|
||||
}
|
||||
|
||||
private void registerActivityLifecycleCallback() {
|
||||
@@ -93,7 +68,6 @@ public class App extends Application {
|
||||
currentActivity = activity;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onActivityPaused(Activity activity) {
|
||||
currentActivity = null;
|
||||
@@ -120,42 +94,4 @@ public class App extends Application {
|
||||
return getApp().getString(id);
|
||||
}
|
||||
|
||||
|
||||
private static class SimpleActivityLifecycleCallbacks implements ActivityLifecycleCallbacks {
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityStarted(Activity activity) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResumed(Activity activity) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityPaused(Activity activity) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityStopped(Activity activity) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityDestroyed(Activity activity) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
import com.stardust.automator.AccessibilityEventCommandHost;
|
||||
import com.stardust.scriptdroid.autojs.AutoJs;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/1/31.
|
||||
@@ -18,7 +19,7 @@ public class Pref {
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
||||
if (key.equals(App.getResString(R.string.key_run_mode))) {
|
||||
AccessibilityEventCommandHost.getInstance().setRunMode(getRunModeFromValue(sharedPreferences.getString(key, null)));
|
||||
AutoJs.getInstance().getCommandHost().setRunMode(getRunModeFromValue(sharedPreferences.getString(key, null)));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
package com.stardust.scriptdroid.accessibility;
|
||||
|
||||
import android.accessibilityservice.AccessibilityService;
|
||||
import android.content.ComponentName;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.view.accessibility.AccessibilityDelegate;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/3/9.
|
||||
*/
|
||||
|
||||
public class AccessibilityInfoProvider implements AccessibilityDelegate {
|
||||
|
||||
private static AccessibilityInfoProvider instance = new AccessibilityInfoProvider();
|
||||
|
||||
private String mLatestPackage = "";
|
||||
private String mLatestActivity = "";
|
||||
|
||||
public static AccessibilityInfoProvider getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public synchronized String getLatestPackage() {
|
||||
return mLatestPackage;
|
||||
}
|
||||
|
||||
public synchronized String getLatestActivity() {
|
||||
return mLatestActivity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onAccessibilityEvent(AccessibilityService service, AccessibilityEvent event) {
|
||||
setLatestComponent(event.getPackageName(), event.getClassName());
|
||||
return false;
|
||||
}
|
||||
|
||||
private synchronized void setLatestComponent(CharSequence latestPackage, CharSequence latestClass) {
|
||||
if (latestPackage == null)
|
||||
return;
|
||||
mLatestPackage = latestPackage.toString();
|
||||
if (latestClass == null)
|
||||
return;
|
||||
try {
|
||||
ComponentName componentName = new ComponentName(latestPackage.toString(), latestClass.toString());
|
||||
ActivityInfo activityInfo = App.getApp().getPackageManager().getActivityInfo(componentName, 0);
|
||||
mLatestActivity = activityInfo.name;
|
||||
} catch (PackageManager.NameNotFoundException ignored) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
123
app/src/main/java/com/stardust/scriptdroid/autojs/AutoJs.java
Normal file
123
app/src/main/java/com/stardust/scriptdroid/autojs/AutoJs.java
Normal file
@@ -0,0 +1,123 @@
|
||||
package com.stardust.scriptdroid.autojs;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.stardust.autojs.ScriptEngineService;
|
||||
import com.stardust.autojs.ScriptEngineServiceBuilder;
|
||||
import com.stardust.autojs.engine.NodeJsJavaScriptEngine;
|
||||
import com.stardust.autojs.engine.NodeJsJavaScriptEngineManager;
|
||||
import com.stardust.autojs.runtime.*;
|
||||
import com.stardust.autojs.runtime.action.ActionPerformAccessibilityDelegate;
|
||||
import com.stardust.autojs.runtime.api.Console;
|
||||
import com.stardust.automator.AccessibilityEventCommandHost;
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.Pref;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.scripts.StorageScriptProvider;
|
||||
import com.stardust.view.accessibility.AccessibilityInfoProvider;
|
||||
import com.stardust.scriptdroid.layout_inspector.LayoutInspector;
|
||||
import com.stardust.scriptdroid.record.accessibility.AccessibilityActionRecorder;
|
||||
import com.stardust.scriptdroid.service.AccessibilityWatchDogService;
|
||||
import com.stardust.scriptdroid.tool.AccessibilityServiceTool;
|
||||
import com.stardust.scriptdroid.ui.console.TimberConsole;
|
||||
import com.stardust.view.accessibility.AccessibilityServiceUtils;
|
||||
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/4/2.
|
||||
*/
|
||||
|
||||
public class AutoJs implements AccessibilityBridge {
|
||||
|
||||
private static AutoJs instance;
|
||||
|
||||
public static AutoJs getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public static void initInstance(Context context) {
|
||||
instance = new AutoJs(context);
|
||||
}
|
||||
|
||||
private final AccessibilityEventCommandHost mAccessibilityEventCommandHost = new AccessibilityEventCommandHost();
|
||||
private final ActionPerformAccessibilityDelegate mActionPerformAccessibilityDelegate = new ActionPerformAccessibilityDelegate();
|
||||
private final AccessibilityActionRecorder mAccessibilityActionRecorder = new AccessibilityActionRecorder();
|
||||
private final LayoutInspector mLayoutInspector = new LayoutInspector();
|
||||
private final ScriptEngineService mScriptEngineService;
|
||||
private final AccessibilityInfoProvider mAccessibilityInfoProvider;
|
||||
private final ScriptRuntime mRuntime;
|
||||
|
||||
|
||||
private AutoJs(Context context) {
|
||||
mAccessibilityInfoProvider = new AccessibilityInfoProvider(context.getPackageManager());
|
||||
Console console = new TimberConsole();
|
||||
mRuntime = new ScriptRuntime(context, console, this);
|
||||
NodeJsJavaScriptEngineManager manager = new NodeJsJavaScriptEngineManager(context, mRuntime);
|
||||
manager.setRequirePath(StorageScriptProvider.DEFAULT_DIRECTORY_PATH);
|
||||
mScriptEngineService = new ScriptEngineServiceBuilder()
|
||||
.context(context)
|
||||
.engineManger(manager)
|
||||
.console(console)
|
||||
.runtime(mRuntime)
|
||||
.build();
|
||||
ScriptEngineService.setInstance(mScriptEngineService);
|
||||
addAccessibilityServiceDelegates();
|
||||
}
|
||||
|
||||
private void addAccessibilityServiceDelegates() {
|
||||
AccessibilityWatchDogService.addDelegateIfNeeded(100, mActionPerformAccessibilityDelegate);
|
||||
AccessibilityWatchDogService.addDelegateIfNeeded(200, mAccessibilityActionRecorder);
|
||||
AccessibilityWatchDogService.addDelegateIfNeeded(300, mAccessibilityEventCommandHost);
|
||||
AccessibilityWatchDogService.addDelegateIfNeeded(400, mAccessibilityInfoProvider);
|
||||
AccessibilityWatchDogService.addDelegateIfNeeded(500, mLayoutInspector);
|
||||
}
|
||||
|
||||
public AccessibilityActionRecorder getAccessibilityActionRecorder() {
|
||||
return mAccessibilityActionRecorder;
|
||||
}
|
||||
|
||||
public LayoutInspector getLayoutInspector() {
|
||||
return mLayoutInspector;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessibilityEventCommandHost getCommandHost() {
|
||||
return mAccessibilityEventCommandHost;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionPerformAccessibilityDelegate getActionPerformHost() {
|
||||
return mActionPerformAccessibilityDelegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ensureServiceEnabled() {
|
||||
if (AccessibilityWatchDogService.getInstance() == null) {
|
||||
String errorMessage = null;
|
||||
if (AccessibilityServiceUtils.isAccessibilityServiceEnabled(App.getApp(), AccessibilityWatchDogService.class)) {
|
||||
errorMessage = App.getApp().getString(R.string.text_auto_operate_service_enabled_but_not_running);
|
||||
} else {
|
||||
if (Pref.def().getBoolean(App.getApp().getString(R.string.key_enable_accessibility_service_by_root), false)) {
|
||||
if (!AccessibilityServiceTool.enableAccessibilityServiceByRootAndWaitFor(AccessibilityWatchDogService.class, 3000)) {
|
||||
errorMessage = App.getApp().getString(R.string.text_enable_accessibility_service_by_root_timeout);
|
||||
}
|
||||
} else {
|
||||
errorMessage = App.getApp().getString(R.string.text_no_accessibility_permission);
|
||||
}
|
||||
}
|
||||
if (errorMessage != null) {
|
||||
mRuntime.toast(errorMessage);
|
||||
throw new ScriptStopException(errorMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessibilityInfoProvider getInfoProvider() {
|
||||
return mAccessibilityInfoProvider;
|
||||
}
|
||||
|
||||
public ScriptEngineService getScriptEngineService() {
|
||||
return mScriptEngineService;
|
||||
}
|
||||
}
|
||||
@@ -1,172 +0,0 @@
|
||||
package com.stardust.scriptdroid.droid;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.Pref;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.droid.runtime.DroidRuntime;
|
||||
import com.stardust.scriptdroid.droid.script.JavaScriptEngine;
|
||||
import com.stardust.scriptdroid.droid.script.ScriptExecuteActivity;
|
||||
import com.stardust.scriptdroid.service.VolumeChangeObverseService;
|
||||
import com.stardust.scriptdroid.tool.FileUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.text.DateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
import timber.log.Timber;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/1/23.
|
||||
*/
|
||||
|
||||
public class Droid {
|
||||
|
||||
public static final java.lang.String STAY = "\"stay\";";
|
||||
|
||||
public static final String UI = "\"ui\";";
|
||||
|
||||
public static final String AUTO = "\"auto\";";
|
||||
|
||||
public interface OnRunFinishedListener extends Serializable {
|
||||
void onRunFinished(Object result);
|
||||
|
||||
void onException(@NonNull Exception e);
|
||||
}
|
||||
|
||||
public static class SimpleOnRunFinishedListener implements OnRunFinishedListener {
|
||||
|
||||
@Override
|
||||
public void onRunFinished(Object result) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onException(@NonNull Exception e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private static final DroidRuntime RUNTIME = DroidRuntime.getRuntime();
|
||||
public static final JavaScriptEngine JAVA_SCRIPT_ENGINE = JavaScriptEngine.getDefault();
|
||||
private static final OnRunFinishedListener DEFAULT_LISTENER = new SimpleOnRunFinishedListener() {
|
||||
@Override
|
||||
public void onException(@NonNull Exception e) {
|
||||
if (!causedByInterruptedException(e)) {
|
||||
RUNTIME.toast(App.getApp().getString(R.string.text_error) + ": " + e.getMessage());
|
||||
Timber.e(e.getMessage());
|
||||
}
|
||||
}
|
||||
};
|
||||
private static Droid instance = new Droid();
|
||||
private VolumeChangeObverseService.OnVolumeChangeListener mOnVolumeChangeListener = new VolumeChangeObverseService.OnVolumeChangeListener() {
|
||||
@Override
|
||||
public void onVolumeChange() {
|
||||
if (Pref.isRunningVolumeControlEnabled()) {
|
||||
stopAllAndToast();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
private Droid() {
|
||||
VolumeChangeObverseService.addOnVolumeChangeListener(mOnVolumeChangeListener);
|
||||
}
|
||||
|
||||
public static Droid getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public static boolean causedByInterruptedException(Throwable e) {
|
||||
while (e != null) {
|
||||
if (e instanceof InterruptedException) {
|
||||
return true;
|
||||
}
|
||||
e = e.getCause();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void runScriptFile(File file) {
|
||||
runScriptFile(file, null, new RunningConfig());
|
||||
}
|
||||
|
||||
public void runScriptFile(File file, OnRunFinishedListener listener, RunningConfig config) {
|
||||
Timber.v(DateFormat.getTimeInstance().format(new Date()) + " " + App.getResString(R.string.text_start_running) + " " + file);
|
||||
listener = listener == null ? DEFAULT_LISTENER : listener;
|
||||
int errorMsgId = PathChecker.check(file.getPath());
|
||||
if(errorMsgId != PathChecker.CHECK_RESULT_OK){
|
||||
listener.onException(new IOException(App.getResString(errorMsgId)));
|
||||
}
|
||||
runScript(FileUtils.readString(file), listener, config.path(file.getPath()));
|
||||
}
|
||||
|
||||
|
||||
public void runScriptFile(String path) {
|
||||
runScriptFile(new File(path));
|
||||
}
|
||||
|
||||
public void runScript(String script) {
|
||||
runScript(script, null, RunningConfig.getDefault());
|
||||
}
|
||||
|
||||
public void runScript(String script, OnRunFinishedListener listener, RunningConfig config) {
|
||||
App.getApp().startService(new Intent(App.getApp(), VolumeChangeObverseService.class));
|
||||
listener = listener == null ? DEFAULT_LISTENER : listener;
|
||||
if (!TextUtils.isEmpty(config.prepareScript))
|
||||
script = config.prepareScript + "\n" + script;
|
||||
if (config.runInNewThread) {
|
||||
if (script.startsWith(UI)) {
|
||||
ScriptExecuteActivity.runScript(script, listener, config);
|
||||
} else {
|
||||
new Thread(new RunScriptRunnable(script, listener, config)).start();
|
||||
}
|
||||
} else {
|
||||
new RunScriptRunnable(script, listener, config).run();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public int stopAll() {
|
||||
return JAVA_SCRIPT_ENGINE.stopAll();
|
||||
}
|
||||
|
||||
|
||||
public void stopAllAndToast() {
|
||||
int n = stopAll();
|
||||
if (n > 0)
|
||||
RUNTIME.toast(String.format(App.getResString(R.string.text_already_stop_n_scripts), n));
|
||||
else
|
||||
RUNTIME.toast(App.getResString(R.string.text_no_running_script));
|
||||
}
|
||||
|
||||
private static class RunScriptRunnable implements Runnable {
|
||||
|
||||
private final String mScript;
|
||||
private OnRunFinishedListener mOnRunFinishedListener;
|
||||
|
||||
RunScriptRunnable(String script, OnRunFinishedListener listener, RunningConfig config) {
|
||||
mOnRunFinishedListener = listener;
|
||||
mScript = script;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
if (mScript.startsWith(AUTO))
|
||||
DroidRuntime.getRuntime().ensureAccessibilityServiceEnabled();
|
||||
mOnRunFinishedListener.onRunFinished(JAVA_SCRIPT_ENGINE.execute(mScript));
|
||||
} catch (Exception e) {
|
||||
mOnRunFinishedListener.onException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
package com.stardust.scriptdroid.droid;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/2/1.
|
||||
*/
|
||||
public class RunningConfig {
|
||||
|
||||
private static final RunningConfig RUNNING_CONFIG = new RunningConfig();
|
||||
public String path;
|
||||
public String prepareScript = "";
|
||||
|
||||
public static RunningConfig getDefault() {
|
||||
return RUNNING_CONFIG;
|
||||
}
|
||||
|
||||
public boolean runInNewThread = true;
|
||||
|
||||
public RunningConfig runInNewThread(boolean runInNewThread) {
|
||||
this.runInNewThread = runInNewThread;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RunningConfig path(String path) {
|
||||
this.path = path;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RunningConfig prepareScript(String script) {
|
||||
this.prepareScript = script;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -1,436 +0,0 @@
|
||||
package com.stardust.scriptdroid.droid.runtime;
|
||||
|
||||
import android.accessibilityservice.AccessibilityService;
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Environment;
|
||||
import android.os.Handler;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.SpannableString;
|
||||
import android.text.Spanned;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
import android.util.Log;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.afollestad.materialdialogs.MaterialDialog;
|
||||
import com.jraska.console.timber.ConsoleTree;
|
||||
import com.stardust.automator.AccessibilityEventCommandHost;
|
||||
import com.stardust.scriptdroid.Pref;
|
||||
import com.stardust.scriptdroid.accessibility.AccessibilityInfoProvider;
|
||||
import com.stardust.scriptdroid.droid.runtime.action.ActionTarget;
|
||||
import com.stardust.scriptdroid.droid.runtime.api.UiSelector;
|
||||
import com.stardust.scriptdroid.tool.AccessibilityServiceTool;
|
||||
import com.stardust.scriptdroid.service.AccessibilityWatchDogService;
|
||||
import com.stardust.scriptdroid.tool.IntentTool;
|
||||
import com.stardust.theme.dialog.ThemeColorMaterialDialogBuilder;
|
||||
import com.jraska.console.Console;
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.droid.runtime.action.Action;
|
||||
import com.stardust.scriptdroid.droid.runtime.action.ActionFactory;
|
||||
import com.stardust.scriptdroid.droid.runtime.action.ActionPerformAccessibilityDelegate;
|
||||
import com.stardust.scriptdroid.tool.FileUtils;
|
||||
import com.stardust.scriptdroid.tool.Shell;
|
||||
import com.stardust.scriptdroid.ui.console.ConsoleActivity;
|
||||
import com.stardust.view.accessibility.AccessibilityServiceUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
import timber.log.Timber;
|
||||
|
||||
;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/1/27.
|
||||
*/
|
||||
|
||||
public class DroidRuntime {
|
||||
|
||||
static {
|
||||
Timber.plant(new ConsoleTree.Builder()
|
||||
.minPriority(Log.VERBOSE)
|
||||
.verboseColor(0xff909090)
|
||||
.debugColor(0xffc88b48)
|
||||
.infoColor(0xffc9c9c9)
|
||||
.warnColor(0xffa97db6)
|
||||
.errorColor(0xffff534e)
|
||||
.assertColor(0xffff5540)
|
||||
.build());
|
||||
}
|
||||
|
||||
private static class PerformGlobalActionCommand implements AccessibilityEventCommandHost.Command {
|
||||
|
||||
boolean result;
|
||||
private int mGlobalAction;
|
||||
|
||||
PerformGlobalActionCommand(int globalAction) {
|
||||
mGlobalAction = globalAction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(AccessibilityService service, AccessibilityEvent event) {
|
||||
result = service.performGlobalAction(mGlobalAction);
|
||||
}
|
||||
}
|
||||
|
||||
private static final String TAG = "DroidRuntime";
|
||||
private static DroidRuntime runtime = new DroidRuntime();
|
||||
|
||||
private final Object mActionPerformLock = new Object();
|
||||
private Handler mUIHandler;
|
||||
|
||||
public static DroidRuntime getRuntime() {
|
||||
return runtime;
|
||||
}
|
||||
|
||||
protected DroidRuntime() {
|
||||
mUIHandler = new Handler(App.getApp().getMainLooper());
|
||||
}
|
||||
|
||||
public boolean launchPackage(String packageName) {
|
||||
try {
|
||||
PackageManager packageManager = App.getApp().getPackageManager();
|
||||
App.getApp().startActivity(packageManager.getLaunchIntentForPackage(packageName));
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public boolean launchApp(String appName) {
|
||||
return launchPackage(getPackageName(appName));
|
||||
}
|
||||
|
||||
public String getPackageName(String appName) {
|
||||
PackageManager packageManager = App.getApp().getPackageManager();
|
||||
List<ApplicationInfo> installedApplications = packageManager.getInstalledApplications(PackageManager.GET_META_DATA);
|
||||
for (ApplicationInfo applicationInfo : installedApplications) {
|
||||
if (packageManager.getApplicationLabel(applicationInfo).toString().equals(appName)) {
|
||||
return applicationInfo.processName;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public boolean openAppSetting(String packageName) {
|
||||
return IntentTool.goToAppSetting(App.getApp(), packageName);
|
||||
}
|
||||
|
||||
public ActionTarget text(String text, int i) {
|
||||
return new ActionTarget.TextActionTarget(text, i);
|
||||
}
|
||||
|
||||
public ActionTarget bounds(int left, int top, int right, int bottom) {
|
||||
return new ActionTarget.BoundsActionTarget(new Rect(left, top, right, bottom));
|
||||
}
|
||||
|
||||
public ActionTarget editable(int i) {
|
||||
return new ActionTarget.EditableActionTarget(i);
|
||||
}
|
||||
|
||||
public ActionTarget id(String id) {
|
||||
return new ActionTarget.IdActionTarget(id);
|
||||
}
|
||||
|
||||
public boolean click(ActionTarget target) {
|
||||
return performAction(target.createAction(AccessibilityNodeInfo.ACTION_CLICK));
|
||||
}
|
||||
|
||||
public boolean longClick(ActionTarget target) {
|
||||
return performAction(target.createAction(AccessibilityNodeInfo.ACTION_LONG_CLICK));
|
||||
}
|
||||
|
||||
public boolean scrollUp(ActionTarget target) {
|
||||
return performAction(target.createAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD));
|
||||
}
|
||||
|
||||
public boolean scrollDown(ActionTarget target) {
|
||||
return performAction(target.createAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD));
|
||||
}
|
||||
|
||||
public boolean scrollUp(int i) {
|
||||
return performAction(ActionFactory.createScrollAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD, i));
|
||||
}
|
||||
|
||||
public boolean scrollDown(int i) {
|
||||
return performAction(ActionFactory.createScrollAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD, i));
|
||||
}
|
||||
|
||||
public boolean scrollAllUp() {
|
||||
return performAction(ActionFactory.createScrollMaxAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD));
|
||||
}
|
||||
|
||||
public boolean scrollAllDown() {
|
||||
return performAction(ActionFactory.createScrollMaxAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD));
|
||||
}
|
||||
|
||||
public boolean focus(ActionTarget target) {
|
||||
return performAction(target.createAction(AccessibilityNodeInfo.ACTION_FOCUS));
|
||||
}
|
||||
|
||||
public boolean select(ActionTarget target) {
|
||||
return performAction(target.createAction(AccessibilityNodeInfo.ACTION_SELECT));
|
||||
}
|
||||
|
||||
public boolean setText(ActionTarget target, String text) {
|
||||
return performAction(target.createAction(AccessibilityNodeInfo.ACTION_SET_TEXT, text));
|
||||
}
|
||||
|
||||
public void setClip(final String text) {
|
||||
mUIHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
((ClipboardManager) App.getApp().getSystemService(Context.CLIPBOARD_SERVICE)).setPrimaryClip(ClipData.newPlainText(TAG, text));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public boolean back() {
|
||||
return performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK);
|
||||
}
|
||||
|
||||
public boolean home() {
|
||||
return performGlobalAction(AccessibilityService.GLOBAL_ACTION_HOME);
|
||||
}
|
||||
|
||||
public boolean powerDialog() {
|
||||
return performGlobalAction(AccessibilityService.GLOBAL_ACTION_POWER_DIALOG);
|
||||
}
|
||||
|
||||
public boolean notifications() {
|
||||
return performGlobalAction(AccessibilityService.GLOBAL_ACTION_NOTIFICATIONS);
|
||||
}
|
||||
|
||||
public boolean quickSettings() {
|
||||
return performGlobalAction(AccessibilityService.GLOBAL_ACTION_QUICK_SETTINGS);
|
||||
}
|
||||
|
||||
public boolean recents() {
|
||||
return performGlobalAction(AccessibilityService.GLOBAL_ACTION_RECENTS);
|
||||
}
|
||||
|
||||
public boolean splitScreen() {
|
||||
return performGlobalAction(AccessibilityService.GLOBAL_ACTION_TOGGLE_SPLIT_SCREEN);
|
||||
}
|
||||
|
||||
public boolean swipeDown() {
|
||||
return performGlobalAction(AccessibilityService.GESTURE_SWIPE_DOWN);
|
||||
}
|
||||
|
||||
public boolean swipeDownLeft() {
|
||||
return performGlobalAction(AccessibilityService.GESTURE_SWIPE_DOWN_AND_LEFT);
|
||||
}
|
||||
|
||||
public boolean swipeDownRight() {
|
||||
return performGlobalAction(AccessibilityService.GESTURE_SWIPE_DOWN_AND_RIGHT);
|
||||
}
|
||||
|
||||
public boolean swipeDownUp() {
|
||||
return performGlobalAction(AccessibilityService.GESTURE_SWIPE_DOWN_AND_UP);
|
||||
}
|
||||
|
||||
public boolean swipeUp() {
|
||||
return performGlobalAction(AccessibilityService.GESTURE_SWIPE_UP);
|
||||
}
|
||||
|
||||
public boolean swipeUpLeft() {
|
||||
return performGlobalAction(AccessibilityService.GESTURE_SWIPE_UP_AND_LEFT);
|
||||
}
|
||||
|
||||
public boolean swipeUpRight() {
|
||||
return performGlobalAction(AccessibilityService.GESTURE_SWIPE_UP_AND_RIGHT);
|
||||
}
|
||||
|
||||
public boolean swipeUpDown() {
|
||||
return performGlobalAction(AccessibilityService.GESTURE_SWIPE_UP_AND_DOWN);
|
||||
}
|
||||
|
||||
public boolean swipeLeft() {
|
||||
return performGlobalAction(AccessibilityService.GESTURE_SWIPE_LEFT);
|
||||
}
|
||||
|
||||
public boolean swipeLeftRight() {
|
||||
return performGlobalAction(AccessibilityService.GESTURE_SWIPE_LEFT_AND_RIGHT);
|
||||
}
|
||||
|
||||
public boolean swipeLeftUp() {
|
||||
return performGlobalAction(AccessibilityService.GESTURE_SWIPE_LEFT_AND_UP);
|
||||
}
|
||||
|
||||
public boolean swipeLeftDown() {
|
||||
return performGlobalAction(AccessibilityService.GESTURE_SWIPE_LEFT_AND_DOWN);
|
||||
}
|
||||
|
||||
public boolean swipeRight() {
|
||||
return performGlobalAction(AccessibilityService.GESTURE_SWIPE_RIGHT);
|
||||
}
|
||||
|
||||
public boolean swipeRightLeft() {
|
||||
return performGlobalAction(AccessibilityService.GESTURE_SWIPE_RIGHT_AND_LEFT);
|
||||
}
|
||||
|
||||
public boolean swipeRightUp() {
|
||||
return performGlobalAction(AccessibilityService.GESTURE_SWIPE_RIGHT_AND_UP);
|
||||
}
|
||||
|
||||
public boolean swipeRightDown() {
|
||||
return performGlobalAction(AccessibilityService.GESTURE_SWIPE_RIGHT_AND_DOWN);
|
||||
}
|
||||
|
||||
private boolean performGlobalAction(final int action) {
|
||||
ensureAccessibilityServiceEnabled();
|
||||
PerformGlobalActionCommand command = new PerformGlobalActionCommand(action);
|
||||
AccessibilityEventCommandHost.getInstance().executeAndWaitForEvent(command);
|
||||
return command.result;
|
||||
}
|
||||
|
||||
public boolean paste(ActionTarget target) {
|
||||
return performAction(target.createAction(AccessibilityNodeInfo.ACTION_PASTE));
|
||||
}
|
||||
|
||||
public void log(@Nullable Object o) {
|
||||
String str = o + "";
|
||||
SpannableString spannableString = new SpannableString(str);
|
||||
spannableString.setSpan(new ForegroundColorSpan(Color.BLACK), 0, str.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
Console.writeLine(spannableString);
|
||||
}
|
||||
|
||||
public void err(@Nullable Object o) {
|
||||
Timber.e("" + o);
|
||||
}
|
||||
|
||||
public void console() {
|
||||
App.getApp().startActivity(new Intent(App.getApp(), ConsoleActivity.class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
|
||||
}
|
||||
|
||||
public void clearConsole() {
|
||||
Console.clear();
|
||||
}
|
||||
|
||||
private <T> T performAction(Action action) {
|
||||
ensureAccessibilityServiceEnabled();
|
||||
ActionPerformAccessibilityDelegate.setAction(action);
|
||||
synchronized (mActionPerformLock) {
|
||||
try {
|
||||
mActionPerformLock.wait();
|
||||
} catch (InterruptedException e) {
|
||||
ActionPerformAccessibilityDelegate.setAction(ActionPerformAccessibilityDelegate.NO_ACTION);
|
||||
throw new ScriptStopException(App.getApp().getString(R.string.text_script_stopped), e);
|
||||
}
|
||||
}
|
||||
return (T) action.getResult();
|
||||
}
|
||||
|
||||
public void ensureAccessibilityServiceEnabled() {
|
||||
if (AccessibilityWatchDogService.getInstance() == null) {
|
||||
String errorMessage = null;
|
||||
if (AccessibilityServiceUtils.isAccessibilityServiceEnabled(App.getApp(), AccessibilityWatchDogService.class)) {
|
||||
errorMessage = App.getApp().getString(R.string.text_auto_operate_service_enabled_but_not_running);
|
||||
} else {
|
||||
if (Pref.def().getBoolean(App.getApp().getString(R.string.key_enable_accessibility_service_by_root), false)) {
|
||||
if (!AccessibilityServiceTool.enableAccessibilityServiceByRootAndWaitFor(AccessibilityWatchDogService.class, 3000)) {
|
||||
errorMessage = App.getApp().getString(R.string.text_enable_accessibility_service_by_root_timeout);
|
||||
}
|
||||
} else {
|
||||
errorMessage = App.getApp().getString(R.string.text_no_accessibility_permission);
|
||||
}
|
||||
}
|
||||
if (errorMessage != null) {
|
||||
toast(errorMessage);
|
||||
throw new ScriptStopException(errorMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void toast(final String text) {
|
||||
mUIHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Toast.makeText(App.getApp(), text, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void sleep(long millis) {
|
||||
try {
|
||||
Thread.sleep(millis);
|
||||
} catch (InterruptedException e) {
|
||||
throw new ScriptStopException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void addAccessibilityEventListener(final Object delegate) {
|
||||
if (delegate == null)
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
public Shell.CommandResult shell(String cmd, int root) {
|
||||
return Shell.execCommand(cmd, root != 0);
|
||||
}
|
||||
|
||||
public String currentPackage() {
|
||||
ensureAccessibilityServiceEnabled();
|
||||
return AccessibilityInfoProvider.getInstance().getLatestPackage();
|
||||
}
|
||||
|
||||
public String currentActivity() {
|
||||
ensureAccessibilityServiceEnabled();
|
||||
return AccessibilityInfoProvider.getInstance().getLatestActivity();
|
||||
}
|
||||
|
||||
public UiSelector selector() {
|
||||
return new UiSelector();
|
||||
}
|
||||
|
||||
public boolean isStopped() {
|
||||
return Thread.currentThread().isInterrupted();
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
Thread.interrupted();
|
||||
}
|
||||
|
||||
public String readFile(String path) {
|
||||
return FileUtils.readString(new File(Environment.getExternalStorageDirectory() + "/" + path));
|
||||
}
|
||||
|
||||
public ThemeColorMaterialDialogBuilder dialog() {
|
||||
if (App.currentActivity() == null) {
|
||||
throw new ScriptStopException(App.getApp().getString(R.string.text_cannot_create_dialog_when_app_invisible));
|
||||
}
|
||||
return new ThemeColorMaterialDialogBuilder(App.currentActivity()) {
|
||||
|
||||
public MaterialDialog show() {
|
||||
mUIHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
superShow();
|
||||
}
|
||||
});
|
||||
return null;
|
||||
}
|
||||
|
||||
private void superShow() {
|
||||
super.show();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public void notifyActionPerformed() {
|
||||
synchronized (mActionPerformLock) {
|
||||
mActionPerformLock.notify();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package com.stardust.scriptdroid.droid.runtime;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/1/29.
|
||||
*/
|
||||
public class ScriptStopException extends RuntimeException {
|
||||
|
||||
|
||||
public ScriptStopException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public ScriptStopException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public ScriptStopException() {
|
||||
|
||||
}
|
||||
|
||||
public ScriptStopException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
package com.stardust.scriptdroid.droid.runtime.action;
|
||||
|
||||
import android.util.SparseArray;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
|
||||
import com.stardust.util.SparseArrayEntries;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/1/27.
|
||||
*/
|
||||
|
||||
public interface Able {
|
||||
|
||||
SparseArray<Able> ABLE_MAP = new SparseArrayEntries<Able>()
|
||||
.entry(AccessibilityNodeInfo.ACTION_CLICK, new Able() {
|
||||
@Override
|
||||
public boolean isAble(AccessibilityNodeInfo nodeInfo) {
|
||||
return nodeInfo.isClickable();
|
||||
}
|
||||
})
|
||||
.entry(AccessibilityNodeInfo.ACTION_LONG_CLICK, new Able() {
|
||||
@Override
|
||||
public boolean isAble(AccessibilityNodeInfo nodeInfo) {
|
||||
return nodeInfo.isLongClickable();
|
||||
}
|
||||
})
|
||||
.entry(AccessibilityNodeInfo.ACTION_FOCUS, new Able() {
|
||||
@Override
|
||||
public boolean isAble(AccessibilityNodeInfo nodeInfo) {
|
||||
return nodeInfo.isFocusable();
|
||||
}
|
||||
})
|
||||
.entry(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD, new Able() {
|
||||
@Override
|
||||
public boolean isAble(AccessibilityNodeInfo nodeInfo) {
|
||||
return nodeInfo.isScrollable();
|
||||
}
|
||||
})
|
||||
.entry(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD, new Able() {
|
||||
@Override
|
||||
public boolean isAble(AccessibilityNodeInfo nodeInfo) {
|
||||
return nodeInfo.isScrollable();
|
||||
}
|
||||
})
|
||||
.sparseArray();
|
||||
|
||||
boolean isAble(AccessibilityNodeInfo node);
|
||||
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
package com.stardust.scriptdroid.droid.runtime.action;
|
||||
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/1/27.
|
||||
*/
|
||||
|
||||
public abstract class Action {
|
||||
|
||||
private boolean mPerformUtilSucceed = false;
|
||||
private volatile Object mResult = false;
|
||||
|
||||
public Action(boolean performUtilSucceed) {
|
||||
mPerformUtilSucceed = performUtilSucceed;
|
||||
}
|
||||
|
||||
public Action() {
|
||||
this(false);
|
||||
}
|
||||
|
||||
public abstract boolean perform(AccessibilityNodeInfo root);
|
||||
|
||||
public boolean performUtilSucceed() {
|
||||
return mPerformUtilSucceed;
|
||||
}
|
||||
|
||||
public Action setPerformUtilSucceed(boolean performUtilSucceed) {
|
||||
mPerformUtilSucceed = performUtilSucceed;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Object getResult() {
|
||||
return mResult;
|
||||
}
|
||||
|
||||
public void setResult(Object result) {
|
||||
mResult = result;
|
||||
}
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
package com.stardust.scriptdroid.droid.runtime.action;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.os.Bundle;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
|
||||
import com.stardust.util.MapEntries;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/1/27.
|
||||
*/
|
||||
|
||||
public class ActionFactory {
|
||||
|
||||
private static Map<Integer, Object> searchUpAction = new MapEntries<Integer, Object>()
|
||||
.entry(AccessibilityNodeInfo.ACTION_CLICK, null)
|
||||
.entry(AccessibilityNodeInfo.ACTION_LONG_CLICK, null)
|
||||
.entry(AccessibilityNodeInfo.ACTION_SELECT, null)
|
||||
.entry(AccessibilityNodeInfo.ACTION_FOCUS, null)
|
||||
.entry(AccessibilityNodeInfo.ACTION_SELECT, null)
|
||||
.entry(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD, null)
|
||||
.entry(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD, null)
|
||||
.map();
|
||||
|
||||
public static Action createActionWithTextFilter(int action, String text, int index) {
|
||||
if (searchUpAction.containsKey(action))
|
||||
return new SearchUpTargetAction(action, new FilterAction.TextFilter(text, index));
|
||||
else
|
||||
return new DepthFirstSearchTargetAction(action, new FilterAction.TextFilter(text, index));
|
||||
}
|
||||
|
||||
public static Action createActionWithBoundsFilter(int action, Rect rect) {
|
||||
if (searchUpAction.containsKey(action))
|
||||
return new SearchUpTargetAction(action, new FilterAction.BoundsFilter(rect));
|
||||
else
|
||||
return new DepthFirstSearchTargetAction(action, new FilterAction.BoundsFilter(rect));
|
||||
}
|
||||
|
||||
public static Action createActionWithEditableFilter(int action, int index, final String text) {
|
||||
return new SearchTargetAction(action, new FilterAction.EditableFilter(index)) {
|
||||
|
||||
@Override
|
||||
protected void performAction(AccessibilityNodeInfo node) {
|
||||
Bundle args = new Bundle();
|
||||
args.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, text);
|
||||
node.performAction(getAction(), args);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static Action createScrollMaxAction(int action) {
|
||||
return new ScrollMaxAction(action);
|
||||
}
|
||||
|
||||
public static Action createScrollAction(int action, int i) {
|
||||
return new ScrollAction(action, i);
|
||||
}
|
||||
|
||||
public static Action createActionWithIdFilter(int action, String id) {
|
||||
return new FilterAction.SimpleFilterAction(action, new FilterAction.IdFilter(id));
|
||||
}
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
package com.stardust.scriptdroid.droid.runtime.action;
|
||||
|
||||
import android.accessibilityservice.AccessibilityService;
|
||||
import android.content.ComponentName;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.util.Log;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.droid.runtime.DroidRuntime;
|
||||
import com.stardust.view.accessibility.AccessibilityDelegate;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/1/21.
|
||||
*/
|
||||
|
||||
public class ActionPerformAccessibilityDelegate implements AccessibilityDelegate {
|
||||
|
||||
private static final String TAG = "ActionPerformDelegate";
|
||||
|
||||
public static final Action NO_ACTION = null;
|
||||
|
||||
private static final Object ACTION_LOCK = new Object();
|
||||
|
||||
private static Action action;
|
||||
|
||||
//private Executor mExecutor = Executors.newFixedThreadPool(5);
|
||||
|
||||
public static void setAction(Action action) {
|
||||
synchronized (ACTION_LOCK) {
|
||||
ActionPerformAccessibilityDelegate.action = action;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onAccessibilityEvent(AccessibilityService service, AccessibilityEvent event) {
|
||||
synchronized (ACTION_LOCK) {
|
||||
if (action == NO_ACTION)
|
||||
return false;
|
||||
AccessibilityNodeInfo root = service.getRootInActiveWindow();
|
||||
if (root == null) {
|
||||
Log.v(TAG, "root = null");
|
||||
return false;
|
||||
}
|
||||
performAction(root, action);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void performAction(final AccessibilityNodeInfo root, final Action action) {
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Log.i(TAG, "perform action:" + action);
|
||||
if (action.perform(root)) {
|
||||
action.setResult(true);
|
||||
onActionPerformed();
|
||||
} else if (!action.performUtilSucceed()) {
|
||||
action.setResult(false);
|
||||
onActionPerformed();
|
||||
}
|
||||
}
|
||||
}.run();
|
||||
}
|
||||
|
||||
|
||||
private void onActionPerformed() {
|
||||
synchronized (ACTION_LOCK) {
|
||||
action = NO_ACTION;
|
||||
DroidRuntime.getRuntime().notifyActionPerformed();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
package com.stardust.scriptdroid.droid.runtime.action;
|
||||
|
||||
import android.graphics.Rect;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/1/27.
|
||||
*/
|
||||
|
||||
public interface ActionTarget {
|
||||
|
||||
Action createAction(int action, Object... params);
|
||||
|
||||
class TextActionTarget implements ActionTarget {
|
||||
|
||||
String mText;
|
||||
int mIndex;
|
||||
|
||||
public TextActionTarget(String text, int i) {
|
||||
mText = text;
|
||||
mIndex = i;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Action createAction(int action, Object... params) {
|
||||
return ActionFactory.createActionWithTextFilter(action, mText, mIndex);
|
||||
}
|
||||
}
|
||||
|
||||
class BoundsActionTarget implements ActionTarget {
|
||||
|
||||
Rect mBoundsInRect;
|
||||
|
||||
public BoundsActionTarget(Rect rect) {
|
||||
mBoundsInRect = rect;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Action createAction(int action, Object... params) {
|
||||
return ActionFactory.createActionWithBoundsFilter(action, mBoundsInRect);
|
||||
}
|
||||
}
|
||||
|
||||
class EditableActionTarget implements ActionTarget {
|
||||
private int mIndex;
|
||||
|
||||
public EditableActionTarget(int index) {
|
||||
mIndex = index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Action createAction(int action, Object... params) {
|
||||
return ActionFactory.createActionWithEditableFilter(action, mIndex, params[0].toString());
|
||||
}
|
||||
}
|
||||
|
||||
class IdActionTarget implements ActionTarget {
|
||||
private String mId;
|
||||
|
||||
public IdActionTarget(String id) {
|
||||
mId = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Action createAction(int action, Object... params) {
|
||||
return ActionFactory.createActionWithIdFilter(action, mId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
package com.stardust.scriptdroid.droid.runtime.action;
|
||||
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/1/27.
|
||||
*/
|
||||
|
||||
public class DepthFirstSearchTargetAction extends SearchTargetAction {
|
||||
|
||||
|
||||
private Able mAble;
|
||||
|
||||
public DepthFirstSearchTargetAction(int action, Filter filter) {
|
||||
super(action, filter);
|
||||
mAble = Able.ABLE_MAP.get(action);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public AccessibilityNodeInfo searchTarget(AccessibilityNodeInfo n) {
|
||||
if (n == null)
|
||||
return null;
|
||||
if (mAble.isAble(n))
|
||||
return n;
|
||||
for (int i = 0; i < n.getChildCount(); i++) {
|
||||
AccessibilityNodeInfo child = n.getChild(i);
|
||||
if (child == null)
|
||||
continue;
|
||||
AccessibilityNodeInfo node = searchTarget(child);
|
||||
if (node != null)
|
||||
return node;
|
||||
else
|
||||
child.recycle();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,165 +0,0 @@
|
||||
package com.stardust.scriptdroid.droid.runtime.action;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/1/27.
|
||||
*/
|
||||
|
||||
public abstract class FilterAction extends Action {
|
||||
|
||||
|
||||
public interface Filter {
|
||||
|
||||
List<AccessibilityNodeInfo> filter(AccessibilityNodeInfo root);
|
||||
}
|
||||
|
||||
public static class TextFilter implements Filter {
|
||||
|
||||
String mText;
|
||||
int mIndex;
|
||||
|
||||
public TextFilter(String text, int index) {
|
||||
mText = text;
|
||||
mIndex = index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AccessibilityNodeInfo> filter(AccessibilityNodeInfo root) {
|
||||
|
||||
List<AccessibilityNodeInfo> list = root.findAccessibilityNodeInfosByText(mText);
|
||||
if (mIndex == -1)
|
||||
return list;
|
||||
if (mIndex >= list.size())
|
||||
return Collections.EMPTY_LIST;
|
||||
return Collections.singletonList(list.get(mIndex));
|
||||
}
|
||||
}
|
||||
|
||||
public static class BoundsFilter implements Filter {
|
||||
|
||||
Rect mBoundsInScreen;
|
||||
|
||||
public BoundsFilter(Rect boundsInScreen) {
|
||||
mBoundsInScreen = boundsInScreen;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AccessibilityNodeInfo> filter(AccessibilityNodeInfo root) {
|
||||
return Collections.singletonList(findAccessibilityNodeInfosByBounds(root));
|
||||
}
|
||||
|
||||
private AccessibilityNodeInfo findAccessibilityNodeInfosByBounds(AccessibilityNodeInfo root) {
|
||||
if (root == null)
|
||||
return null;
|
||||
Rect rect = new Rect();
|
||||
root.getBoundsInScreen(rect);
|
||||
if (rect.equals(mBoundsInScreen)) {
|
||||
return root;
|
||||
}
|
||||
for (int i = 0; i < root.getChildCount(); i++) {
|
||||
AccessibilityNodeInfo child = root.getChild(i);
|
||||
if (child == null)
|
||||
continue;
|
||||
AccessibilityNodeInfo nodeInfo = findAccessibilityNodeInfosByBounds(child);
|
||||
if (nodeInfo != null)
|
||||
return nodeInfo;
|
||||
else
|
||||
child.recycle();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static class EditableFilter implements Filter {
|
||||
|
||||
private int mIndex;
|
||||
|
||||
public EditableFilter(int index) {
|
||||
mIndex = index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AccessibilityNodeInfo> filter(AccessibilityNodeInfo root) {
|
||||
List<AccessibilityNodeInfo> editableList = findEditable(root);
|
||||
if (mIndex == -1)
|
||||
return editableList;
|
||||
if (mIndex >= editableList.size())
|
||||
return Collections.EMPTY_LIST;
|
||||
return Collections.singletonList(editableList.get(mIndex));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static List<AccessibilityNodeInfo> findEditable(AccessibilityNodeInfo root) {
|
||||
if (root == null) {
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
if (root.isEditable()) {
|
||||
return Collections.singletonList(root);
|
||||
}
|
||||
List<AccessibilityNodeInfo> list = new LinkedList<>();
|
||||
for (int i = 0; i < root.getChildCount(); i++) {
|
||||
list.addAll(findEditable(root.getChild(i)));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
public static class IdFilter implements Filter {
|
||||
|
||||
private final String mId;
|
||||
|
||||
public IdFilter(String id) {
|
||||
this.mId = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AccessibilityNodeInfo> filter(AccessibilityNodeInfo root) {
|
||||
return root.findAccessibilityNodeInfosByViewId(mId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private Filter mFilter;
|
||||
|
||||
public FilterAction(Filter filter) {
|
||||
mFilter = filter;
|
||||
}
|
||||
|
||||
public boolean perform(AccessibilityNodeInfo root) {
|
||||
if (root == null)
|
||||
return false;
|
||||
return perform(mFilter.filter(root));
|
||||
}
|
||||
|
||||
public abstract boolean perform(List<AccessibilityNodeInfo> nodes);
|
||||
|
||||
public static class SimpleFilterAction extends FilterAction {
|
||||
|
||||
private int mAction;
|
||||
|
||||
public SimpleFilterAction(int action, Filter filter) {
|
||||
super(filter);
|
||||
mAction = action;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean perform(List<AccessibilityNodeInfo> nodes) {
|
||||
if(nodes == null || nodes.isEmpty())
|
||||
return false;
|
||||
boolean succeed = true;
|
||||
for(AccessibilityNodeInfo nodeInfo : nodes){
|
||||
if(!nodeInfo.performAction(mAction)){
|
||||
succeed = false;
|
||||
}
|
||||
}
|
||||
return succeed;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
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 {
|
||||
|
||||
|
||||
@Override
|
||||
public boolean perform(AccessibilityNodeInfo root) {
|
||||
List<String> texts = new ArrayList<>();
|
||||
getText(root, texts);
|
||||
super.setResult(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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setResult(Object result) {
|
||||
if (result instanceof List)
|
||||
super.setResult(result);
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
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/12.
|
||||
*/
|
||||
public class ScrollAction extends Action {
|
||||
|
||||
private int mIndex, mAction;
|
||||
|
||||
public ScrollAction(int action, int i) {
|
||||
mAction = action;
|
||||
mIndex = i;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean perform(AccessibilityNodeInfo root) {
|
||||
List<AccessibilityNodeInfo> scrollableNodes = findScrollableNodes(root);
|
||||
boolean result = mIndex < scrollableNodes.size() && scrollableNodes.get(mIndex).performAction(mAction);
|
||||
recycle(scrollableNodes, root);
|
||||
return result;
|
||||
}
|
||||
|
||||
private void recycle(List<AccessibilityNodeInfo> list, AccessibilityNodeInfo root) {
|
||||
for (AccessibilityNodeInfo nodeInfo : list) {
|
||||
if (nodeInfo != root)
|
||||
nodeInfo.recycle();
|
||||
}
|
||||
}
|
||||
|
||||
private List<AccessibilityNodeInfo> findScrollableNodes(AccessibilityNodeInfo root) {
|
||||
List<AccessibilityNodeInfo> list = new ArrayList<>();
|
||||
findScrollableNodes(root, list);
|
||||
return list;
|
||||
}
|
||||
|
||||
private static boolean findScrollableNodes(AccessibilityNodeInfo node, List<AccessibilityNodeInfo> list) {
|
||||
if (node == null) {
|
||||
return false;
|
||||
}
|
||||
if (node.isScrollable()) {
|
||||
list.add(node);
|
||||
}
|
||||
for (int i = 0; i < node.getChildCount(); i++) {
|
||||
AccessibilityNodeInfo child = node.getChild(i);
|
||||
if (child == null)
|
||||
continue;
|
||||
if (!findScrollableNodes(child, list))
|
||||
child.recycle();
|
||||
}
|
||||
return node.isScrollable();
|
||||
}
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
package com.stardust.scriptdroid.droid.runtime.action;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.util.Log;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/1/27.
|
||||
*/
|
||||
|
||||
public class ScrollMaxAction extends Action {
|
||||
|
||||
private static final String TAG = ScrollMaxAction.class.getSimpleName();
|
||||
private int mScrollAction;
|
||||
private AccessibilityNodeInfo mMaxScrollableNode;
|
||||
private AccessibilityNodeInfo mRootNode;
|
||||
|
||||
public ScrollMaxAction(int scrollAction) {
|
||||
mScrollAction = scrollAction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean perform(AccessibilityNodeInfo rootNodeInfo) {
|
||||
reset();
|
||||
mRootNode = rootNodeInfo;
|
||||
findMaxScrollableNodeInfo(rootNodeInfo);
|
||||
boolean result = mMaxScrollableNode != null && mMaxScrollableNode.performAction(mScrollAction);
|
||||
reset();
|
||||
return result;
|
||||
}
|
||||
|
||||
private void reset() {
|
||||
if (mMaxScrollableNode != null && mMaxScrollableNode != mRootNode) {
|
||||
mMaxScrollableNode.recycle();
|
||||
}
|
||||
mMaxScrollableNode = mRootNode = null;
|
||||
}
|
||||
|
||||
private void findMaxScrollableNodeInfo(AccessibilityNodeInfo nodeInfo) {
|
||||
if (nodeInfo == null)
|
||||
return;
|
||||
if (nodeInfo.isScrollable()) {
|
||||
if (mMaxScrollableNode == null) {
|
||||
mMaxScrollableNode = nodeInfo;
|
||||
} else if (getAreaInScreen(mMaxScrollableNode) < getAreaInScreen(nodeInfo)) {
|
||||
if (mMaxScrollableNode != mRootNode)
|
||||
mMaxScrollableNode.recycle();
|
||||
mMaxScrollableNode = nodeInfo;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < nodeInfo.getChildCount(); i++) {
|
||||
AccessibilityNodeInfo child = nodeInfo.getChild(i);
|
||||
if (child != null) {
|
||||
findMaxScrollableNodeInfo(child);
|
||||
if (mMaxScrollableNode != child) {
|
||||
child.recycle();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private long getAreaInScreen(AccessibilityNodeInfo nodeInfo) {
|
||||
Rect rect = new Rect();
|
||||
nodeInfo.getBoundsInScreen(rect);
|
||||
long area = ((long) rect.width()) * rect.height();
|
||||
Log.v(TAG, "area=" + area);
|
||||
return area;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
package com.stardust.scriptdroid.droid.runtime.action;
|
||||
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/1/27.
|
||||
*/
|
||||
|
||||
public abstract class SearchTargetAction extends FilterAction {
|
||||
|
||||
private int mAction;
|
||||
|
||||
public SearchTargetAction(int action, Filter filter) {
|
||||
super(filter);
|
||||
mAction = action;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean perform(List<AccessibilityNodeInfo> nodes) {
|
||||
boolean performed = false;
|
||||
for (AccessibilityNodeInfo node : nodes) {
|
||||
node = searchTarget(node);
|
||||
if (node != null) {
|
||||
performAction(node);
|
||||
performed = true;
|
||||
}
|
||||
}
|
||||
return performed;
|
||||
}
|
||||
|
||||
protected void performAction(AccessibilityNodeInfo node) {
|
||||
node.performAction(mAction);
|
||||
}
|
||||
|
||||
public int getAction(){
|
||||
return mAction;
|
||||
}
|
||||
|
||||
public AccessibilityNodeInfo searchTarget(AccessibilityNodeInfo node) {
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
package com.stardust.scriptdroid.droid.runtime.action;
|
||||
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/1/27.
|
||||
*/
|
||||
|
||||
public class SearchUpTargetAction extends SearchTargetAction {
|
||||
|
||||
private Able mAble;
|
||||
|
||||
public SearchUpTargetAction(int action, Filter filter) {
|
||||
super(action, filter);
|
||||
mAble = Able.ABLE_MAP.get(action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessibilityNodeInfo searchTarget(AccessibilityNodeInfo n) {
|
||||
AccessibilityNodeInfo node = n;
|
||||
while (node != null && !mAble.isAble(node)) {
|
||||
AccessibilityNodeInfo parent = node.getParent();
|
||||
if (node != n) {
|
||||
node.recycle();
|
||||
}
|
||||
node = parent;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
}
|
||||
@@ -1,140 +0,0 @@
|
||||
package com.stardust.scriptdroid.droid.runtime.api;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
import android.webkit.JavascriptInterface;
|
||||
import android.webkit.ValueCallback;
|
||||
import android.webkit.WebSettings;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
|
||||
import com.stardust.scriptdroid.droid.runtime.ScriptStopException;
|
||||
|
||||
import org.mozilla.javascript.Context;
|
||||
import org.mozilla.javascript.Scriptable;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.Queue;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/4/1.
|
||||
*/
|
||||
|
||||
public class InjectableWebClient extends WebViewClient {
|
||||
|
||||
private static final String TAG = "InjectableWebClient";
|
||||
|
||||
private Queue<Pair<String, ValueCallback<String>>> mToInjectJavaScripts = new LinkedList<>();
|
||||
private final ValueCallback<String> defaultCallback = new ValueCallback<String>() {
|
||||
@Override
|
||||
public void onReceiveValue(String value) {
|
||||
Log.i(TAG, "onReceiveValue: " + value);
|
||||
}
|
||||
};
|
||||
private WebView mWebView;
|
||||
private Context mContext;
|
||||
private Scriptable mScriptable;
|
||||
private ScriptBridge mScriptBridge = new ScriptBridge();
|
||||
|
||||
public InjectableWebClient(Context context, Scriptable scriptable) {
|
||||
mContext = context;
|
||||
mScriptable = scriptable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageFinished(WebView view, String url) {
|
||||
mWebView = view;
|
||||
setUpWebView(view);
|
||||
while (!mToInjectJavaScripts.isEmpty()) {
|
||||
Pair<String, ValueCallback<String>> pair = mToInjectJavaScripts.poll();
|
||||
inject(view, pair.first, pair.second);
|
||||
}
|
||||
super.onPageFinished(view, url);
|
||||
}
|
||||
|
||||
@SuppressLint("SetJavaScriptEnabled")
|
||||
private void setUpWebView(WebView view) {
|
||||
view.addJavascriptInterface(mScriptBridge, "rhino");
|
||||
WebSettings webSettings = view.getSettings();
|
||||
webSettings.setJavaScriptEnabled(true);
|
||||
webSettings.setAllowUniversalAccessFromFileURLs(true);
|
||||
}
|
||||
|
||||
private void inject(WebView view, String script, ValueCallback<String> callback) {
|
||||
view.evaluateJavascript(script, callback);
|
||||
}
|
||||
|
||||
public void inject(String script, ValueCallback<String> callback) {
|
||||
if (mWebView != null) {
|
||||
inject(mWebView, script, callback);
|
||||
return;
|
||||
}
|
||||
mToInjectJavaScripts.offer(new Pair<>(script, callback));
|
||||
}
|
||||
|
||||
public void inject(String script) {
|
||||
inject(script, defaultCallback);
|
||||
}
|
||||
|
||||
public String injectAndWait(String script) {
|
||||
InjectReturnCallback callback = new InjectReturnCallback();
|
||||
inject(script, callback);
|
||||
return callback.waitResult();
|
||||
}
|
||||
|
||||
|
||||
private class ScriptBridge {
|
||||
|
||||
private Object result;
|
||||
|
||||
@JavascriptInterface
|
||||
public String eval(final String script) {
|
||||
result = null;
|
||||
mWebView.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Log.v(TAG, "ScriptBridge.eval: " + script);
|
||||
result = mContext.evaluateString(mScriptable, script, "<eval-local>", 1, null);
|
||||
Log.v(TAG, "ScriptBridge.eval = " + result);
|
||||
synchronized (ScriptBridge.this) {
|
||||
ScriptBridge.this.notify();
|
||||
}
|
||||
}
|
||||
});
|
||||
synchronized (ScriptBridge.this) {
|
||||
try {
|
||||
ScriptBridge.this.wait();
|
||||
} catch (InterruptedException e) {
|
||||
throw new ScriptStopException(e);
|
||||
}
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
}
|
||||
|
||||
private static class InjectReturnCallback implements ValueCallback<String> {
|
||||
|
||||
private String result;
|
||||
|
||||
@Override
|
||||
public void onReceiveValue(String value) {
|
||||
result = value;
|
||||
synchronized (this) {
|
||||
this.notify();
|
||||
}
|
||||
}
|
||||
|
||||
String waitResult() {
|
||||
synchronized (this) {
|
||||
try {
|
||||
this.wait();
|
||||
} catch (InterruptedException e) {
|
||||
throw new ScriptStopException(e);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
package com.stardust.scriptdroid.droid.runtime.api;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.support.annotation.RequiresApi;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Pair;
|
||||
import android.webkit.ValueCallback;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
|
||||
import org.mozilla.javascript.Scriptable;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/4/1.
|
||||
*/
|
||||
|
||||
public class InjectableWebView extends WebView {
|
||||
|
||||
private InjectableWebClient mInjectableWebClient;
|
||||
|
||||
public InjectableWebView(Context context, org.mozilla.javascript.Context jsCtx, Scriptable scriptable) {
|
||||
super(context);
|
||||
init(jsCtx, scriptable);
|
||||
}
|
||||
|
||||
private void init(org.mozilla.javascript.Context jsCtx, Scriptable scriptable) {
|
||||
mInjectableWebClient = new InjectableWebClient(jsCtx, scriptable);
|
||||
setWebViewClient(mInjectableWebClient);
|
||||
}
|
||||
|
||||
public void inject(String script, ValueCallback<String> callback) {
|
||||
mInjectableWebClient.inject(script, callback);
|
||||
}
|
||||
|
||||
public void inject(String script) {
|
||||
mInjectableWebClient.inject(script);
|
||||
}
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
package com.stardust.scriptdroid.droid.runtime.api;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/3/7.
|
||||
*/
|
||||
|
||||
public class Shell extends com.stardust.scriptdroid.tool.Shell {
|
||||
|
||||
public Shell(boolean root) {
|
||||
super(root);
|
||||
}
|
||||
|
||||
public void Tap(int x, int y) {
|
||||
execute("input tap " + x + " " + y);
|
||||
}
|
||||
|
||||
public void Swipe(int x1, int y1, int x2, int y2) {
|
||||
execute("input swipe " + x1 + " " + y1 + " " + x2 + " " + y2);
|
||||
}
|
||||
|
||||
public void Swipe(int x1, int y1, int x2, int y2, long duration) {
|
||||
execute("input swipe " + x1 + " " + y1 + " " + x2 + " " + y2 + " " + duration);
|
||||
}
|
||||
|
||||
public void KeyCode(int keyCode) {
|
||||
execute("input keyevent " + keyCode);
|
||||
}
|
||||
|
||||
public void KeyCode(String keyCode) {
|
||||
execute("input keyevent " + keyCode);
|
||||
}
|
||||
|
||||
public void Home() {
|
||||
KeyCode(3);
|
||||
}
|
||||
|
||||
public void Back() {
|
||||
KeyCode(4);
|
||||
}
|
||||
|
||||
public void Power() {
|
||||
KeyCode(26);
|
||||
}
|
||||
|
||||
public void Up() {
|
||||
KeyCode(19);
|
||||
}
|
||||
|
||||
public void Down() {
|
||||
KeyCode(20);
|
||||
}
|
||||
|
||||
public void Left() {
|
||||
KeyCode(21);
|
||||
}
|
||||
|
||||
public void Right() {
|
||||
KeyCode(22);
|
||||
}
|
||||
|
||||
public void OK() {
|
||||
KeyCode(23);
|
||||
}
|
||||
|
||||
public void VolumeUp() {
|
||||
KeyCode(24);
|
||||
}
|
||||
|
||||
public void VolumeDown() {
|
||||
KeyCode(25);
|
||||
}
|
||||
|
||||
public void Menu() {
|
||||
KeyCode(1);
|
||||
}
|
||||
|
||||
public void Camera() {
|
||||
KeyCode(27);
|
||||
}
|
||||
|
||||
public void Text(String text) {
|
||||
execute("input text " + text);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,227 +0,0 @@
|
||||
package com.stardust.scriptdroid.droid.runtime.api;
|
||||
|
||||
import android.accessibilityservice.AccessibilityService;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
|
||||
import com.stardust.automator.AccessibilityEventCommandHost;
|
||||
import com.stardust.automator.ActionArgument;
|
||||
import com.stardust.automator.UiGlobalSelector;
|
||||
import com.stardust.automator.UiObject;
|
||||
import com.stardust.automator.UiObjectCollection;
|
||||
import com.stardust.automator.filter.DfsFilter;
|
||||
import com.stardust.scriptdroid.accessibility.AccessibilityInfoProvider;
|
||||
import com.stardust.scriptdroid.droid.runtime.DroidRuntime;
|
||||
|
||||
import static android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS;
|
||||
import static android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.ACTION_ARGUMENT_COLUMN_INT;
|
||||
import static android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.ACTION_ARGUMENT_PROGRESS_VALUE;
|
||||
import static android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.ACTION_ARGUMENT_ROW_INT;
|
||||
import static android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.ACTION_ARGUMENT_SELECTION_END_INT;
|
||||
import static android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.ACTION_ARGUMENT_SELECTION_START_INT;
|
||||
import static android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE;
|
||||
import static android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.ACTION_CLEAR_ACCESSIBILITY_FOCUS;
|
||||
import static android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.ACTION_CLEAR_FOCUS;
|
||||
import static android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.ACTION_CLICK;
|
||||
import static android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.ACTION_COLLAPSE;
|
||||
import static android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.ACTION_COPY;
|
||||
import static android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.ACTION_CUT;
|
||||
import static android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.ACTION_DISMISS;
|
||||
import static android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.ACTION_EXPAND;
|
||||
import static android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.ACTION_FOCUS;
|
||||
import static android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.ACTION_LONG_CLICK;
|
||||
import static android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.ACTION_PASTE;
|
||||
import static android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.ACTION_SCROLL_BACKWARD;
|
||||
import static android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.ACTION_SCROLL_FORWARD;
|
||||
import static android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.ACTION_SELECT;
|
||||
import static android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.ACTION_SET_SELECTION;
|
||||
import static android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.ACTION_SET_TEXT;
|
||||
import static android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat.ACTION_CONTEXT_CLICK;
|
||||
import static android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat.ACTION_SCROLL_DOWN;
|
||||
import static android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat.ACTION_SCROLL_LEFT;
|
||||
import static android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat.ACTION_SCROLL_RIGHT;
|
||||
import static android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat.ACTION_SCROLL_TO_POSITION;
|
||||
import static android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat.ACTION_SCROLL_UP;
|
||||
import static android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat.ACTION_SET_PROGRESS;
|
||||
import static android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat.ACTION_SHOW_ON_SCREEN;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/3/9.
|
||||
*/
|
||||
|
||||
public class UiSelector extends UiGlobalSelector {
|
||||
|
||||
private class FindCommand implements AccessibilityEventCommandHost.Command {
|
||||
|
||||
UiObjectCollection result;
|
||||
|
||||
@Override
|
||||
public void execute(AccessibilityService service, AccessibilityEvent event) {
|
||||
AccessibilityNodeInfo root = service.getRootInActiveWindow();
|
||||
if (root != null) {
|
||||
result = findOf(root);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final String TAG = "UiSelector";
|
||||
|
||||
public UiObjectCollection find() {
|
||||
ensureAccessibilityServiceEnabled();
|
||||
FindCommand command = new FindCommand();
|
||||
AccessibilityEventCommandHost.getInstance().executeAndWaitForEvent(command);
|
||||
return command.result;
|
||||
}
|
||||
|
||||
private void ensureAccessibilityServiceEnabled(){
|
||||
DroidRuntime.getRuntime().ensureAccessibilityServiceEnabled();
|
||||
}
|
||||
|
||||
|
||||
@NonNull
|
||||
public UiObjectCollection untilFind() {
|
||||
UiObjectCollection uiObjectCollection;
|
||||
do {
|
||||
uiObjectCollection = find();
|
||||
} while (uiObjectCollection == null || uiObjectCollection.size() == 0);
|
||||
return uiObjectCollection;
|
||||
}
|
||||
|
||||
public UiObject findOne() {
|
||||
return untilFindOne();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public UiObject untilFindOne() {
|
||||
UiObjectCollection collection = untilFind();
|
||||
return new UiObject(collection.get(0).getInfo());
|
||||
}
|
||||
|
||||
public UiSelector id(final String id) {
|
||||
if (!id.contains(":")) {
|
||||
addFilter(new DfsFilter() {
|
||||
@Override
|
||||
protected boolean isIncluded(AccessibilityNodeInfo nodeInfo) {
|
||||
String fullId = AccessibilityInfoProvider.getInstance().getLatestPackage() + ":id/" + id;
|
||||
return fullId.equals(nodeInfo.getViewIdResourceName());
|
||||
}
|
||||
});
|
||||
} else {
|
||||
super.id(id);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public boolean performAction(int action, ActionArgument... arguments) {
|
||||
return untilFind().performAction(action, arguments);
|
||||
}
|
||||
|
||||
public boolean click() {
|
||||
return performAction(ACTION_CLICK);
|
||||
}
|
||||
|
||||
public boolean longClick() {
|
||||
return performAction(ACTION_LONG_CLICK);
|
||||
}
|
||||
|
||||
public boolean accessibilityFocus() {
|
||||
return performAction(ACTION_ACCESSIBILITY_FOCUS);
|
||||
}
|
||||
|
||||
public boolean clearAccessibilityFocus() {
|
||||
return performAction(ACTION_CLEAR_ACCESSIBILITY_FOCUS);
|
||||
}
|
||||
|
||||
public boolean focus() {
|
||||
return performAction(ACTION_FOCUS);
|
||||
}
|
||||
|
||||
public boolean clearFocus() {
|
||||
return performAction(ACTION_CLEAR_FOCUS);
|
||||
}
|
||||
|
||||
public boolean copy() {
|
||||
return performAction(ACTION_COPY);
|
||||
}
|
||||
|
||||
public boolean paste() {
|
||||
return performAction(ACTION_PASTE);
|
||||
}
|
||||
|
||||
public boolean select() {
|
||||
return performAction(ACTION_SELECT);
|
||||
}
|
||||
|
||||
public boolean cut() {
|
||||
return performAction(ACTION_CUT);
|
||||
}
|
||||
|
||||
public boolean collapse() {
|
||||
return performAction(ACTION_COLLAPSE);
|
||||
}
|
||||
|
||||
public boolean expand() {
|
||||
return performAction(ACTION_EXPAND);
|
||||
}
|
||||
|
||||
public boolean dismiss() {
|
||||
return performAction(ACTION_DISMISS);
|
||||
}
|
||||
|
||||
public boolean show() {
|
||||
return performAction(ACTION_SHOW_ON_SCREEN.getId());
|
||||
}
|
||||
|
||||
public boolean scrollForward() {
|
||||
return performAction(ACTION_SCROLL_FORWARD);
|
||||
}
|
||||
|
||||
public boolean scrollBackward() {
|
||||
return performAction(ACTION_SCROLL_BACKWARD);
|
||||
}
|
||||
|
||||
public boolean scrollUp() {
|
||||
return performAction(ACTION_SCROLL_UP.getId());
|
||||
}
|
||||
|
||||
public boolean scrollDown() {
|
||||
return performAction(ACTION_SCROLL_DOWN.getId());
|
||||
}
|
||||
|
||||
public boolean scrollLeft() {
|
||||
return performAction(ACTION_SCROLL_LEFT.getId());
|
||||
}
|
||||
|
||||
public boolean scrollRight() {
|
||||
return performAction(ACTION_SCROLL_RIGHT.getId());
|
||||
}
|
||||
|
||||
public boolean contextClick() {
|
||||
return performAction(ACTION_CONTEXT_CLICK.getId());
|
||||
}
|
||||
|
||||
public boolean setSelection(int s, int e) {
|
||||
return performAction(ACTION_SET_SELECTION,
|
||||
new ActionArgument.IntActionArgument(ACTION_ARGUMENT_SELECTION_START_INT, s),
|
||||
new ActionArgument.IntActionArgument(ACTION_ARGUMENT_SELECTION_END_INT, e));
|
||||
}
|
||||
|
||||
public boolean setText(String text) {
|
||||
return performAction(ACTION_SET_TEXT,
|
||||
new ActionArgument.CharSequenceActionArgument(ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, text));
|
||||
}
|
||||
|
||||
public boolean setProgress(float value) {
|
||||
return performAction(ACTION_SET_PROGRESS.getId(),
|
||||
new ActionArgument.FloatActionArgument(ACTION_ARGUMENT_PROGRESS_VALUE, value));
|
||||
}
|
||||
|
||||
public boolean scrollTo(int row, int column) {
|
||||
return performAction(ACTION_SCROLL_TO_POSITION.getId(),
|
||||
new ActionArgument.IntActionArgument(ACTION_ARGUMENT_ROW_INT, row),
|
||||
new ActionArgument.IntActionArgument(ACTION_ARGUMENT_COLUMN_INT, column));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
package com.stardust.scriptdroid.droid.script;
|
||||
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.BuildConfig;
|
||||
import com.stardust.scriptdroid.tool.FileUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/1/27.
|
||||
*/
|
||||
|
||||
public abstract class JavaScriptEngine {
|
||||
|
||||
private static JavaScriptEngine defaultEngine;
|
||||
|
||||
public static JavaScriptEngine getDefault() {
|
||||
return defaultEngine;
|
||||
}
|
||||
|
||||
public static void setDefault(JavaScriptEngine engine) {
|
||||
defaultEngine = engine;
|
||||
}
|
||||
|
||||
Map<String, Object> mVariableMap = new HashMap<>();
|
||||
|
||||
public abstract Object execute(String script);
|
||||
|
||||
public void set(String varName, Object value) {
|
||||
mVariableMap.put(varName, value);
|
||||
}
|
||||
|
||||
public abstract void removeAndDestroy();
|
||||
|
||||
public abstract int stopAll();
|
||||
|
||||
public abstract String[] getGlobalFunctions();
|
||||
|
||||
static class Init {
|
||||
private static final String INIT_SCRIPT = readInitScript();
|
||||
|
||||
private static String readInitScript() {
|
||||
try {
|
||||
return FileUtils.readString(App.getApp().getAssets().open("javasccript_engine_init.js"));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
static String getInitScript() {
|
||||
if (BuildConfig.DEBUG) {
|
||||
// 调试时不缓存INIT_SCRIPT否则修改javasccript_engine_init.js后不会更新
|
||||
return readInitScript();
|
||||
} else {
|
||||
return INIT_SCRIPT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
package com.stardust.scriptdroid.droid.script;
|
||||
|
||||
import com.iwebpp.node.Dns;
|
||||
import com.iwebpp.node.NodeContext;
|
||||
import com.iwebpp.node.Url;
|
||||
import com.iwebpp.node.http.http;
|
||||
import com.iwebpp.node.js.rhino.Host;
|
||||
import com.iwebpp.node.stream.Duplex;
|
||||
import com.iwebpp.node.stream.PassThrough;
|
||||
import com.iwebpp.node.stream.Readable2;
|
||||
import com.iwebpp.node.stream.Transform;
|
||||
import com.iwebpp.node.stream.Writable2;
|
||||
import com.iwebpp.nodeandroid.MainActivity;
|
||||
import com.iwebpp.nodeandroid.Toaster;
|
||||
import com.iwebpp.wspp.WebSocketServer;
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.droid.Droid;
|
||||
import com.stardust.scriptdroid.droid.runtime.DroidRuntime;
|
||||
import com.stardust.scriptdroid.tool.FileUtils;
|
||||
|
||||
import org.mozilla.javascript.Context;
|
||||
import org.mozilla.javascript.Scriptable;
|
||||
import org.mozilla.javascript.ScriptableObject;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/3/25.
|
||||
*/
|
||||
|
||||
public class NodeJsJavaScriptEngine extends RhinoJavaScriptEngine {
|
||||
|
||||
public NodeJsJavaScriptEngine(DroidRuntime runtime) {
|
||||
super(runtime);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object execute(String script) {
|
||||
NodeContext nodectx = new NodeContext();
|
||||
Context context = createContext();
|
||||
Scriptable scope = createScope(context);
|
||||
ScriptableObject.putProperty(scope, "NodeCurrentContext", Context.javaToJS(nodectx, scope));
|
||||
init(context, scope);
|
||||
Object result = context.evaluateString(scope, script, "<script>", 1, null);
|
||||
try {
|
||||
nodectx.execute();
|
||||
} catch (Throwable throwable) {
|
||||
throw new RuntimeException(throwable);
|
||||
}
|
||||
if (!script.startsWith(Droid.UI) && !script.startsWith(Droid.STAY))
|
||||
removeAndDestroy();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init(Context context, Scriptable scope) {
|
||||
super.init(context, scope);
|
||||
try {
|
||||
context.evaluateString(scope, FileUtils.readString(App.getApp().getAssets().open("nodejs_engine_init.js")), "<nodejs_init>", 1, null);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void putProperties(Context context, Scriptable scope) {
|
||||
super.putProperties(context, scope);
|
||||
ScriptableObject.putProperty(scope, "NodeHostEnv", Context.javaToJS(this, scope));
|
||||
}
|
||||
}
|
||||
@@ -1,191 +0,0 @@
|
||||
package com.stardust.scriptdroid.droid.script;
|
||||
|
||||
import com.stardust.scriptdroid.droid.Droid;
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.droid.runtime.DroidRuntime;
|
||||
import com.stardust.scriptdroid.droid.runtime.ScriptStopException;
|
||||
import com.stardust.scriptdroid.droid.script.file.ScriptFile;
|
||||
|
||||
import org.mozilla.javascript.Context;
|
||||
import org.mozilla.javascript.ContextFactory;
|
||||
import org.mozilla.javascript.ImporterTopLevel;
|
||||
import org.mozilla.javascript.Scriptable;
|
||||
import org.mozilla.javascript.ScriptableObject;
|
||||
import org.mozilla.javascript.commonjs.module.RequireBuilder;
|
||||
import org.mozilla.javascript.commonjs.module.provider.ModuleSource;
|
||||
import org.mozilla.javascript.commonjs.module.provider.SoftCachingModuleScriptProvider;
|
||||
import org.mozilla.javascript.commonjs.module.provider.UrlModuleSourceProvider;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/3/1.
|
||||
*/
|
||||
|
||||
public class RhinoJavaScriptEngine extends JavaScriptEngine {
|
||||
|
||||
static {
|
||||
ContextFactory.initGlobal(new InterruptibleContextFactory());
|
||||
}
|
||||
|
||||
private final Set<Thread> mThreads = new HashSet<>();
|
||||
private String[] mFunctions;
|
||||
|
||||
public RhinoJavaScriptEngine(DroidRuntime runtime) {
|
||||
set("droid", runtime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object execute(String script) {
|
||||
Context context = createContext();
|
||||
Scriptable scope = createScope(context);
|
||||
init(context, scope);
|
||||
Object result = context.evaluateString(scope, script, "<script>", 1, null);
|
||||
if (!script.startsWith(Droid.UI) && !script.startsWith(Droid.STAY))
|
||||
removeAndDestroy();
|
||||
return result;
|
||||
}
|
||||
|
||||
protected Scriptable createScope(Context context) {
|
||||
ImporterTopLevel importerTopLevel = new ImporterTopLevel();
|
||||
importerTopLevel.initStandardObjects(context, false);
|
||||
return importerTopLevel;
|
||||
}
|
||||
|
||||
protected Context createContext() {
|
||||
Context context = Context.enter();
|
||||
context.setOptimizationLevel(-1);
|
||||
context.setLanguageVersion(Context.VERSION_1_7);
|
||||
context.setInstructionObserverThreshold(10000);
|
||||
return context;
|
||||
}
|
||||
|
||||
protected void init(Context context, Scriptable scope) {
|
||||
putProperties(context, scope);
|
||||
initRequireBuilder(context, scope);
|
||||
context.evaluateString(scope, Init.getInitScript(), "<init>", 1, null);
|
||||
mThreads.add(Thread.currentThread());
|
||||
}
|
||||
|
||||
protected void putProperties(Context context, Scriptable scope) {
|
||||
ScriptableObject.putProperty(scope, "context", App.getApp());
|
||||
ScriptableObject.putProperty(scope, "__engine__", "rhino");
|
||||
for (Map.Entry<String, Object> variable : mVariableMap.entrySet()) {
|
||||
ScriptableObject.putProperty(scope, variable.getKey(), Context.javaToJS(variable.getValue(), scope));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void initRequireBuilder(Context context, Scriptable scope) {
|
||||
List<URI> list = Collections.singletonList(new File(ScriptFile.DEFAULT_DIRECTORY_PATH).toURI());
|
||||
AssetAndUrlModuleSourceProvider provider = new AssetAndUrlModuleSourceProvider(App.getApp(), list);
|
||||
new RequireBuilder()
|
||||
.setModuleScriptProvider(new SoftCachingModuleScriptProvider(provider))
|
||||
.setSandboxed(true)
|
||||
.createRequire(context, scope)
|
||||
.install(scope);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int stopAll() {
|
||||
int n;
|
||||
synchronized (mThreads) {
|
||||
for (Thread thread : mThreads) {
|
||||
thread.interrupt();
|
||||
}
|
||||
n = mThreads.size();
|
||||
mThreads.clear();
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String[] getGlobalFunctions() {
|
||||
if (mFunctions == null)
|
||||
mFunctions = getGlobalFunctionsInner();
|
||||
return mFunctions;
|
||||
}
|
||||
|
||||
private String[] getGlobalFunctionsInner() {
|
||||
Scriptable scriptable = (Scriptable) execute("this");
|
||||
Object[] ids = scriptable.getIds();
|
||||
String[] functions = new String[ids.length];
|
||||
for (int i = 0; i < ids.length; i++) {
|
||||
functions[i] = ids[i].toString();
|
||||
}
|
||||
return functions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAndDestroy() {
|
||||
synchronized (mThreads) {
|
||||
mThreads.remove(Thread.currentThread());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class InterruptibleContextFactory extends ContextFactory {
|
||||
|
||||
@Override
|
||||
protected void observeInstructionCount(Context cx, int instructionCount) {
|
||||
if (Thread.currentThread().isInterrupted()) {
|
||||
Context.exit();
|
||||
throw new ScriptStopException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Context makeContext() {
|
||||
Context cx = super.makeContext();
|
||||
cx.setInstructionObserverThreshold(10000);
|
||||
return cx;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class AssetAndUrlModuleSourceProvider extends UrlModuleSourceProvider {
|
||||
|
||||
private static final String MODULES_PATH = "modules";
|
||||
private android.content.Context mContext;
|
||||
private List<String> mModules;
|
||||
private final URI mBaseURI = URI.create("file:///android_asset/modules");
|
||||
|
||||
public AssetAndUrlModuleSourceProvider(android.content.Context context, List<URI> list) {
|
||||
super(list, null);
|
||||
mContext = context;
|
||||
try {
|
||||
mModules = Arrays.asList(mContext.getAssets().list(MODULES_PATH));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected ModuleSource loadFromPrivilegedLocations(String moduleId, Object validator) throws IOException, URISyntaxException {
|
||||
String moduleIdWithExtension = moduleId;
|
||||
if (!moduleIdWithExtension.endsWith(".js")) {
|
||||
moduleIdWithExtension += ".js";
|
||||
}
|
||||
if (mModules.contains(moduleIdWithExtension)) {
|
||||
return new ModuleSource(new InputStreamReader(mContext.getAssets().open(MODULES_PATH + "/" + moduleIdWithExtension)), null,
|
||||
URI.create(moduleIdWithExtension), mBaseURI, validator);
|
||||
}
|
||||
return super.loadFromPrivilegedLocations(moduleId, validator);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
package com.stardust.scriptdroid.droid.script;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.droid.Droid;
|
||||
import com.stardust.scriptdroid.droid.RunningConfig;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/2/5.
|
||||
*/
|
||||
|
||||
public class ScriptExecuteActivity extends Activity {
|
||||
|
||||
private static final String EXTRA_SCRIPT = "EXTRA_SCRIPT";
|
||||
private static final String EXTRA_ON_RUN_FINISHED_LISTENER = "EXTRA_ON_RUN_FINISHED_LISTENER";
|
||||
private Object mResult;
|
||||
private String mScript;
|
||||
private Droid.OnRunFinishedListener mOnRunFinishedListener;
|
||||
|
||||
|
||||
public static void runScript(String script, Droid.OnRunFinishedListener listener, RunningConfig config) {
|
||||
App.getApp().startActivity(new Intent(App.getApp(), ScriptExecuteActivity.class)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
.putExtra(EXTRA_SCRIPT, script)
|
||||
.putExtra(EXTRA_ON_RUN_FINISHED_LISTENER, listener));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
handleIntent(getIntent());
|
||||
runScript();
|
||||
}
|
||||
|
||||
private void handleIntent(Intent intent) {
|
||||
mScript = intent.getStringExtra(EXTRA_SCRIPT);
|
||||
mOnRunFinishedListener = (Droid.OnRunFinishedListener) intent.getSerializableExtra(EXTRA_ON_RUN_FINISHED_LISTENER);
|
||||
}
|
||||
|
||||
private void runScript() {
|
||||
Droid.JAVA_SCRIPT_ENGINE.set("activity", this);
|
||||
try {
|
||||
mResult = Droid.JAVA_SCRIPT_ENGINE.execute(mScript);
|
||||
} catch (Exception e) {
|
||||
mOnRunFinishedListener.onException(e);
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finish() {
|
||||
mOnRunFinishedListener.onRunFinished(mResult);
|
||||
super.finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
Droid.JAVA_SCRIPT_ENGINE.set("activity", null);
|
||||
Droid.JAVA_SCRIPT_ENGINE.removeAndDestroy();
|
||||
}
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
package com.stardust.scriptdroid.droid.script.file;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/3/27.
|
||||
*/
|
||||
|
||||
public class StorageScriptFileList extends ScriptFileList {
|
||||
|
||||
private List<ScriptFile> mFiles;
|
||||
private ScriptFile mFolder;
|
||||
|
||||
public StorageScriptFileList() {
|
||||
this(ScriptFile.DEFAULT_DIRECTORY_PATH);
|
||||
}
|
||||
|
||||
|
||||
public ScriptFile getFolder() {
|
||||
return mFolder;
|
||||
}
|
||||
|
||||
public StorageScriptFileList(ScriptFile folder) {
|
||||
if (!folder.isDirectory()) {
|
||||
throw new IllegalArgumentException("file is not folder:" + folder);
|
||||
}
|
||||
mFolder = folder;
|
||||
mFiles = Arrays.asList(folder.listFiles(new FileFilter() {
|
||||
@Override
|
||||
public boolean accept(File file) {
|
||||
return file.isDirectory() || (file.getName().endsWith(".js") && !file.getName().startsWith("."));
|
||||
}
|
||||
}));
|
||||
Collections.sort(mFiles, new Comparator<ScriptFile>() {
|
||||
@Override
|
||||
public int compare(ScriptFile o1, ScriptFile o2) {
|
||||
if (o1.isDirectory() != o2.isDirectory()) {
|
||||
return o1.isDirectory() ? -1 : 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public StorageScriptFileList(String path) {
|
||||
this(new ScriptFile(path));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void add(ScriptFile scriptFile) {
|
||||
try {
|
||||
scriptFile.createNewFile();
|
||||
mFiles.add(scriptFile);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScriptFile get(int i) {
|
||||
return mFiles.get(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(int i) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rename(int position, String newName, boolean renameFile) {
|
||||
if (!renameFile)
|
||||
throw new UnsupportedOperationException();
|
||||
mFiles.get(position).renameTo(newName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return mFiles.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsPath(String path) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -4,14 +4,9 @@ import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.provider.Settings;
|
||||
import android.view.View;
|
||||
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.layout_inspector.view.LayoutInspectView;
|
||||
import com.stardust.scriptdroid.tool.IntentTool;
|
||||
import com.stardust.view.Floaty;
|
||||
import com.stardust.view.ResizableFloaty;
|
||||
import com.stardust.util.IntentUtil;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/3/10.
|
||||
@@ -37,10 +32,10 @@ public class FloatingWindowManger {
|
||||
Uri.parse("package:" + packageName))
|
||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
|
||||
} catch (Exception e) {
|
||||
IntentTool.goToAppSetting(App.getApp());
|
||||
IntentUtil.goToAppDetailSettings(App.getApp());
|
||||
}
|
||||
} else {
|
||||
IntentTool.goToAppSetting(App.getApp());
|
||||
IntentUtil.goToAppDetailSettings(App.getApp());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,9 +15,8 @@ import android.widget.Toast;
|
||||
import com.stardust.hover.HoverMenuBuilder;
|
||||
import com.stardust.hover.SimpleHoverMenuTransitionListener;
|
||||
import com.stardust.hover.WindowHoverMenu;
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.droid.runtime.DroidRuntime;
|
||||
import com.stardust.scriptdroid.autojs.AutoJs;
|
||||
import com.stardust.scriptdroid.external.floating_window.view.FloatingLayoutBoundsView;
|
||||
import com.stardust.scriptdroid.external.floating_window.view.FloatingLayoutHierarchyView;
|
||||
import com.stardust.scriptdroid.layout_inspector.LayoutInspector;
|
||||
@@ -29,8 +28,6 @@ import com.stardust.util.MessageEvent;
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
import io.mattcarroll.hover.HoverMenu;
|
||||
import io.mattcarroll.hover.defaulthovermenu.window.WindowViewController;
|
||||
|
||||
@@ -150,14 +147,14 @@ public class HoverMenuService extends Service {
|
||||
|
||||
@Override
|
||||
public void onCollapsing() {
|
||||
LayoutInspector.getInstance().clearCapture();
|
||||
AutoJs.getInstance().getLayoutInspector().clearCapture();
|
||||
EventBus.getDefault().post(new MessageEvent(MESSAGE_MENU_COLLAPSING));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void captureCurrentWindow() {
|
||||
NodeInfo nodeInfo = LayoutInspector.getInstance().captureCurrentWindow();
|
||||
NodeInfo nodeInfo = AutoJs.getInstance().getLayoutInspector().captureCurrentWindow();
|
||||
if (nodeInfo == null)
|
||||
return;
|
||||
mFloatingLayoutHierarchyView.setRootNode(nodeInfo);
|
||||
|
||||
@@ -4,36 +4,26 @@ import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.accessibility.AccessibilityInfoProvider;
|
||||
import com.stardust.scriptdroid.droid.Droid;
|
||||
import com.stardust.scriptdroid.autojs.AutoJs;
|
||||
import com.stardust.view.accessibility.AccessibilityInfoProvider;
|
||||
import com.stardust.scriptdroid.external.floating_window.HoverMenuService;
|
||||
import com.stardust.scriptdroid.layout_inspector.LayoutInspector;
|
||||
import com.stardust.scriptdroid.tool.ClipboardTool;
|
||||
import com.stardust.util.ClipboardUtil;
|
||||
import com.stardust.scriptdroid.ui.main.MainActivity;
|
||||
import com.stardust.util.MessageEvent;
|
||||
import com.stardust.view.ViewBinder;
|
||||
import com.stardust.view.ViewBinding;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import io.mattcarroll.hover.Navigator;
|
||||
import io.mattcarroll.hover.NavigatorContent;
|
||||
import io.mattcarroll.hover.defaulthovermenu.menus.Menu;
|
||||
import io.mattcarroll.hover.defaulthovermenu.menus.MenuAction;
|
||||
import io.mattcarroll.hover.defaulthovermenu.menus.MenuItem;
|
||||
import io.mattcarroll.hover.defaulthovermenu.menus.MenuListNavigatorContent;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/3/12.
|
||||
@@ -59,7 +49,7 @@ public class MainMenuNavigatorContent implements NavigatorContent {
|
||||
|
||||
@ViewBinding.Click(R.id.layout_hierarchy)
|
||||
private void showLayoutHierarchy() {
|
||||
if (LayoutInspector.getInstance().getCapture() == null) {
|
||||
if (AutoJs.getInstance().getLayoutInspector().getCapture() == null) {
|
||||
Toast.makeText(mView.getContext(), R.string.text_no_accessibility_permission_to_capture, Toast.LENGTH_SHORT).show();
|
||||
} else {
|
||||
HoverMenuService.postEvent(new MessageEvent(HoverMenuService.MESSAGE_SHOW_LAYOUT_HIERARCHY));
|
||||
@@ -68,7 +58,7 @@ public class MainMenuNavigatorContent implements NavigatorContent {
|
||||
|
||||
@ViewBinding.Click(R.id.layout_bounds)
|
||||
private void showLayoutBounds() {
|
||||
if (LayoutInspector.getInstance().getCapture() == null) {
|
||||
if (AutoJs.getInstance().getLayoutInspector().getCapture() == null) {
|
||||
Toast.makeText(mView.getContext(), R.string.text_no_accessibility_permission_to_capture, Toast.LENGTH_SHORT).show();
|
||||
} else {
|
||||
HoverMenuService.postEvent(new MessageEvent(HoverMenuService.MESSAGE_SHOW_LAYOUT_BOUNDS));
|
||||
@@ -77,7 +67,7 @@ public class MainMenuNavigatorContent implements NavigatorContent {
|
||||
|
||||
@ViewBinding.Click(R.id.stop_all_running_scripts)
|
||||
private void stopAllRunningScripts() {
|
||||
Droid.getInstance().stopAllAndToast();
|
||||
AutoJs.getInstance().getScriptEngineService().stopAllAndToast();
|
||||
}
|
||||
|
||||
@ViewBinding.Click(R.id.open_launcher)
|
||||
@@ -100,21 +90,21 @@ public class MainMenuNavigatorContent implements NavigatorContent {
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
private void syncCurrentInfo() {
|
||||
mCurrentPackage = AccessibilityInfoProvider.getInstance().getLatestPackage();
|
||||
mCurrentActivity = AccessibilityInfoProvider.getInstance().getLatestActivity();
|
||||
mCurrentPackage = AutoJs.getInstance().getInfoProvider().getLatestPackage();
|
||||
mCurrentActivity = AutoJs.getInstance().getInfoProvider().getLatestActivity();
|
||||
mCurrentActivityTextView.setText(mContext.getString(R.string.text_current_activity) + mCurrentActivity);
|
||||
mCurrentPackageTextView.setText(mContext.getString(R.string.text_current_package) + mCurrentPackage);
|
||||
}
|
||||
|
||||
@ViewBinding.Click(R.id.current_activity)
|
||||
private void copyCurrentActivity() {
|
||||
ClipboardTool.setClip(mCurrentActivity);
|
||||
ClipboardUtil.setClip(mContext, mCurrentActivity);
|
||||
Toast.makeText(mContext, R.string.text_copied, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
@ViewBinding.Click(R.id.current_package)
|
||||
private void copyCurrentPackage() {
|
||||
ClipboardTool.setClip(mCurrentPackage);
|
||||
ClipboardUtil.setClip(mContext, mCurrentPackage);
|
||||
Toast.makeText(mContext, R.string.text_copied, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.Pref;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.accessibility.AccessibilityEventHelper;
|
||||
import com.stardust.scriptdroid.autojs.AutoJs;
|
||||
import com.stardust.scriptdroid.external.floating_window.HoverMenuService;
|
||||
import com.stardust.scriptdroid.record.Recorder;
|
||||
import com.stardust.scriptdroid.record.accessibility.AccessibilityActionRecorder;
|
||||
@@ -128,7 +129,7 @@ public class RecordNavigatorContent implements NavigatorContent, Recorder.OnStat
|
||||
}
|
||||
|
||||
private void startRecord() {
|
||||
mRecorder = mRecordedByRootSwitch.isChecked() ? new TouchRecorder() : AccessibilityActionRecorder.getInstance();
|
||||
mRecorder = mRecordedByRootSwitch.isChecked() ? new TouchRecorder() : AutoJs.getInstance().getAccessibilityActionRecorder();
|
||||
mRecorder.setOnStateChangedListener(this);
|
||||
mRecorder.start();
|
||||
setState(Recorder.STATE_RECORDING);
|
||||
|
||||
@@ -5,9 +5,8 @@ import android.support.annotation.NonNull;
|
||||
import android.view.ContextThemeWrapper;
|
||||
import android.view.View;
|
||||
|
||||
import com.stardust.scriptdroid.scripts.ScriptFileList;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.droid.script.file.ScriptFileList;
|
||||
import com.stardust.scriptdroid.droid.script.file.SharedPrefScriptFileList;
|
||||
import com.stardust.scriptdroid.external.floating_window.view.FloatingScriptFileListView;
|
||||
|
||||
import io.mattcarroll.hover.Navigator;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.stardust.scriptdroid.external.floating_window.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Environment;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v7.widget.DividerItemDecoration;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
@@ -14,12 +13,12 @@ import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.afollestad.materialdialogs.MaterialDialog;
|
||||
import com.stardust.scriptdroid.scripts.ScriptFile;
|
||||
import com.stardust.scriptdroid.scripts.ScriptFileList;
|
||||
import com.stardust.scriptdroid.App;
|
||||
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.external.floating_window.HoverMenuService;
|
||||
import com.stardust.scriptdroid.tool.ViewTool;
|
||||
import com.stardust.util.ViewUtil;
|
||||
import com.stardust.scriptdroid.ui.main.operation.ScriptFileOperation;
|
||||
import com.stardust.scriptdroid.ui.main.operation.ScriptFileOperationPopupMenu;
|
||||
import com.stardust.theme.dialog.ThemeColorMaterialDialogBuilder;
|
||||
@@ -198,8 +197,8 @@ public class FloatingScriptFileListView extends RecyclerView {
|
||||
super(itemView);
|
||||
name = (TextView) itemView.findViewById(R.id.name);
|
||||
path = (TextView) itemView.findViewById(R.id.path);
|
||||
ViewTool.$(itemView, R.id.edit).setOnClickListener(mOnEditIconClickListener);
|
||||
ViewTool.$(itemView, R.id.more).setOnClickListener(mOnMoreIconClickListener);
|
||||
ViewUtil.$(itemView, R.id.edit).setOnClickListener(mOnEditIconClickListener);
|
||||
ViewUtil.$(itemView, R.id.more).setOnClickListener(mOnMoreIconClickListener);
|
||||
itemView.setOnClickListener(mOnItemClickListener);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,23 +2,14 @@ package com.stardust.scriptdroid.external.open;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.TextUtils;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.afollestad.materialdialogs.MaterialDialog;
|
||||
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.tool.FileUtils;
|
||||
import com.stardust.scriptdroid.ui.BaseActivity;
|
||||
import com.stardust.scriptdroid.ui.main.MainActivity;
|
||||
import com.stardust.theme.dialog.ThemeColorMaterialDialogBuilder;
|
||||
import com.stardust.scriptdroid.R;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/2/2.
|
||||
*/
|
||||
|
||||
@@ -6,14 +6,16 @@ import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.stardust.scriptdroid.droid.Droid;
|
||||
import com.stardust.scriptdroid.droid.PathChecker;
|
||||
import com.stardust.scriptdroid.droid.RunningConfig;
|
||||
import com.stardust.scriptdroid.autojs.AutoJs;
|
||||
import com.stardust.scriptdroid.scripts.PathChecker;
|
||||
import com.stardust.autojs.script.FileScriptSource;
|
||||
import com.stardust.autojs.script.MultiScriptSource;
|
||||
import com.stardust.autojs.script.ScriptSource;
|
||||
import com.stardust.autojs.script.StringScriptSource;
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.external.CommonUtils;
|
||||
import com.stardust.scriptdroid.R;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/2/22.
|
||||
*/
|
||||
@@ -24,7 +26,7 @@ public class RunIntentActivity extends Activity {
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
try {
|
||||
handleIntent();
|
||||
handleIntent(getIntent());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Toast.makeText(this, R.string.edit_and_run_handle_intent_error, Toast.LENGTH_LONG).show();
|
||||
@@ -32,16 +34,17 @@ public class RunIntentActivity extends Activity {
|
||||
finish();
|
||||
}
|
||||
|
||||
private void handleIntent() {
|
||||
Intent intent = getIntent();
|
||||
private void handleIntent(Intent intent) {
|
||||
String path = getPath(intent);
|
||||
String script = intent.getStringExtra(CommonUtils.EXTRA_KEY_PREPARE_SCRIPT);
|
||||
ScriptSource source = null;
|
||||
if (path == null && script != null) {
|
||||
Droid.getInstance().runScript(script);
|
||||
} else {
|
||||
if (new PathChecker(this).checkAndToastError(path)) {
|
||||
Droid.getInstance().runScriptFile(new File(path), null, new RunningConfig().prepareScript(script));
|
||||
}
|
||||
source = new StringScriptSource(script);
|
||||
} else if (path != null && new PathChecker(this).checkAndToastError(path)) {
|
||||
source = new MultiScriptSource(new StringScriptSource(script), new FileScriptSource(path));
|
||||
}
|
||||
if (source != null) {
|
||||
AutoJs.getInstance().getScriptEngineService().execute(source);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,8 +4,10 @@ import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.stardust.scriptdroid.droid.Droid;
|
||||
import com.stardust.scriptdroid.droid.PathChecker;
|
||||
import com.stardust.scriptdroid.autojs.AutoJs;
|
||||
import com.stardust.scriptdroid.scripts.PathChecker;
|
||||
import com.stardust.autojs.script.FileScriptSource;
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.external.CommonUtils;
|
||||
|
||||
/**
|
||||
@@ -17,7 +19,7 @@ public class ShortcutActivity extends Activity {
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
final String path = getIntent().getStringExtra(CommonUtils.EXTRA_KEY_PATH);
|
||||
if(new PathChecker(this).checkAndToastError(path)){
|
||||
if (new PathChecker(this).checkAndToastError(path)) {
|
||||
runScriptFile(path);
|
||||
}
|
||||
}
|
||||
@@ -29,7 +31,7 @@ public class ShortcutActivity extends Activity {
|
||||
|
||||
private void runScriptFile(String path) {
|
||||
try {
|
||||
Droid.getInstance().runScriptFile(path);
|
||||
AutoJs.getInstance().getScriptEngineService().execute(new FileScriptSource(path));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Toast.makeText(this, e.getMessage(), Toast.LENGTH_SHORT).show();
|
||||
|
||||
@@ -6,9 +6,8 @@ import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.Log;
|
||||
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.scripts.ScriptFile;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.droid.script.file.ScriptFile;
|
||||
import com.stardust.scriptdroid.external.CommonUtils;
|
||||
import com.stardust.scriptdroid.ui.main.my_script_list.ScriptAndFolderListRecyclerView;
|
||||
import com.twofortyfouram.locale.sdk.client.ui.activity.AbstractPluginActivity;
|
||||
|
||||
@@ -12,13 +12,6 @@ import com.stardust.view.accessibility.AccessibilityDelegate;
|
||||
|
||||
public class LayoutInspector implements AccessibilityDelegate {
|
||||
|
||||
|
||||
private static LayoutInspector instance = new LayoutInspector();
|
||||
|
||||
public static LayoutInspector getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
private AccessibilityNodeInfo mRootInActiveWindow;
|
||||
private NodeInfo mCapture;
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
|
||||
import com.stardust.scriptdroid.layout_inspector.NodeInfo;
|
||||
import com.stardust.scriptdroid.tool.ViewTool;
|
||||
import com.stardust.util.ViewUtil;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/3/10.
|
||||
@@ -63,7 +63,7 @@ public class LayoutBoundsView extends View {
|
||||
mPaint = new Paint();
|
||||
mPaint.setColor(Color.GREEN);
|
||||
mPaint.setStyle(Paint.Style.STROKE);
|
||||
mStatusBarHeight = ViewTool.getStatusBarHeight(getContext());
|
||||
mStatusBarHeight = ViewUtil.getStatusBarHeight(getContext());
|
||||
setWillNotDraw(false);
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ import android.widget.TextView;
|
||||
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.layout_inspector.NodeInfo;
|
||||
import com.stardust.scriptdroid.tool.ViewTool;
|
||||
import com.stardust.util.ViewUtil;
|
||||
import com.stardust.widget.LevelBeamView;
|
||||
|
||||
import java.util.Collections;
|
||||
@@ -120,7 +120,7 @@ public class LayoutHierarchyView extends MultiLevelListView {
|
||||
mPaint.setStyle(Paint.Style.STROKE);
|
||||
mPaint.setAntiAlias(true);
|
||||
mPaint.setStrokeWidth(3);
|
||||
mStatusBarHeight = ViewTool.getStatusBarHeight(getContext());
|
||||
mStatusBarHeight = ViewUtil.getStatusBarHeight(getContext());
|
||||
}
|
||||
|
||||
public Paint getBoundsPaint() {
|
||||
|
||||
@@ -13,6 +13,7 @@ import android.widget.FrameLayout;
|
||||
import android.widget.ViewSwitcher;
|
||||
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.autojs.AutoJs;
|
||||
import com.stardust.scriptdroid.layout_inspector.LayoutInspector;
|
||||
import com.stardust.scriptdroid.layout_inspector.NodeInfo;
|
||||
|
||||
@@ -71,7 +72,7 @@ public class LayoutInspectView extends FrameLayout {
|
||||
}
|
||||
|
||||
public void showLayoutBoundsView() {
|
||||
mLayoutBoundsView.setRootNode(LayoutInspector.getInstance().captureCurrentWindow());
|
||||
mLayoutBoundsView.setRootNode(AutoJs.getInstance().getLayoutInspector().captureCurrentWindow());
|
||||
backToLayoutBoundsView();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
package com.stardust.scriptdroid.layout_inspector.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
@@ -13,7 +11,7 @@ import android.widget.Toast;
|
||||
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.layout_inspector.NodeInfo;
|
||||
import com.stardust.scriptdroid.tool.ClipboardTool;
|
||||
import com.stardust.util.ClipboardUtil;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
@@ -21,7 +19,6 @@ import de.codecrafters.tableview.TableDataAdapter;
|
||||
import de.codecrafters.tableview.TableView;
|
||||
import de.codecrafters.tableview.model.TableColumnWeightModel;
|
||||
import de.codecrafters.tableview.toolkit.SimpleTableDataAdapter;
|
||||
import de.codecrafters.tableview.toolkit.SimpleTableHeaderAdapter;
|
||||
import de.codecrafters.tableview.toolkit.TableDataRowBackgroundProviders;
|
||||
|
||||
/**
|
||||
@@ -81,7 +78,7 @@ public class NodeInfoView extends TableView {
|
||||
textView.setOnLongClickListener(new OnLongClickListener() {
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
ClipboardTool.setClip(textView.getText());
|
||||
ClipboardUtil.setClip(getContext(), textView.getText());
|
||||
Toast.makeText(getContext(), R.string.text_already_copy_to_clip, Toast.LENGTH_SHORT).show();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import android.util.SparseArray;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
|
||||
import com.stardust.scriptdroid.droid.runtime.action.FilterAction;
|
||||
import com.stardust.autojs.runtime.action.FilterAction;
|
||||
import com.stardust.scriptdroid.layout_inspector.NodeInfo;
|
||||
import com.stardust.util.SparseArrayEntries;
|
||||
import com.stardust.view.accessibility.AccessibilityNodeInfoHelper;
|
||||
|
||||
@@ -28,22 +28,13 @@ public class AccessibilityActionRecorder extends Recorder.DefaultIMPL implements
|
||||
|
||||
private static final long RECORD_TIME_OUT = 10 * 60 * 1000;
|
||||
|
||||
private static AccessibilityActionRecorder instance;
|
||||
private boolean mRecordMessageEnabled;
|
||||
|
||||
private boolean mShouldIgnoreFirstAction = false;
|
||||
|
||||
public static AccessibilityActionRecorder getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new AccessibilityActionRecorder();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
private AccessibilityActionConverter mConverter;
|
||||
private long mRecordStartMillis;
|
||||
|
||||
public AccessibilityActionRecorder(){
|
||||
public AccessibilityActionRecorder() {
|
||||
super(true);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,6 @@ package com.stardust.scriptdroid.record.inputevent;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.droid.runtime.DroidRuntime;
|
||||
import com.stardust.scriptdroid.ui.main.MainActivity;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
package com.stardust.scriptdroid.droid;
|
||||
package com.stardust.scriptdroid.scripts;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Build;
|
||||
import android.text.TextUtils;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.stardust.scriptdroid.R;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
|
||||
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||
@@ -30,9 +26,9 @@ public class PathChecker {
|
||||
|
||||
public static int check(final String path) {
|
||||
if (TextUtils.isEmpty(path))
|
||||
return R.string.text_path_is_empty;
|
||||
return com.stardust.autojs.R.string.text_path_is_empty;
|
||||
if (!new File(path).exists())
|
||||
return R.string.text_file_not_exists;
|
||||
return com.stardust.autojs.R.string.text_file_not_exists;
|
||||
return CHECK_RESULT_OK;
|
||||
}
|
||||
|
||||
@@ -47,7 +43,7 @@ public class PathChecker {
|
||||
|
||||
private int checkWithStoragePermission(String path) {
|
||||
if (!hasStorageReadPermission(mActivity)) {
|
||||
return R.string.text_no_file_rw_permission;
|
||||
return com.stardust.autojs.R.string.text_no_file_rw_permission;
|
||||
}
|
||||
return check(path);
|
||||
}
|
||||
@@ -1,12 +1,8 @@
|
||||
package com.stardust.scriptdroid.droid.script.file;
|
||||
package com.stardust.scriptdroid.scripts;
|
||||
|
||||
import android.os.Environment;
|
||||
|
||||
import com.stardust.scriptdroid.droid.Droid;
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.tool.FileUtils;
|
||||
|
||||
import com.stardust.pio.PFile;
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.io.FilenameFilter;
|
||||
@@ -18,9 +14,6 @@ import java.util.ArrayList;
|
||||
|
||||
public class ScriptFile extends File {
|
||||
|
||||
public static final String DEFAULT_DIRECTORY_PATH = Environment.getExternalStorageDirectory() + App.getApp().getString(R.string.folder_name);
|
||||
public static final ScriptFile DEFAULT_DIRECTORY = new ScriptFile(DEFAULT_DIRECTORY_PATH);
|
||||
|
||||
private String mSimplifyPath;
|
||||
private String mSimplifiedName;
|
||||
|
||||
@@ -30,7 +23,7 @@ public class ScriptFile extends File {
|
||||
}
|
||||
|
||||
private void init() {
|
||||
mSimplifiedName = FileUtils.getNameWithoutExtension(getPath());
|
||||
mSimplifiedName = PFile.getNameWithoutExtension(getPath());
|
||||
mSimplifyPath = getPath();
|
||||
if (mSimplifyPath.startsWith(Environment.getExternalStorageDirectory().getPath())) {
|
||||
mSimplifyPath = mSimplifyPath.substring(Environment.getExternalStorageDirectory().getPath().length());
|
||||
@@ -42,10 +35,6 @@ public class ScriptFile extends File {
|
||||
init();
|
||||
}
|
||||
|
||||
public void run() {
|
||||
Droid.getInstance().runScriptFile(this);
|
||||
}
|
||||
|
||||
public boolean renameTo(String newName) {
|
||||
return renameTo(new File(getParent(), newName));
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.stardust.scriptdroid.droid.script.file;
|
||||
package com.stardust.scriptdroid.scripts;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package com.stardust.scriptdroid.droid.script.file;
|
||||
package com.stardust.scriptdroid.scripts;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.stardust.pio.PFile;
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.tool.FileUtils;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
@@ -78,7 +78,7 @@ public class SharedPrefScriptFileList extends ScriptFileList {
|
||||
public void rename(int position, String newName, boolean renameFile) {
|
||||
mScriptName.set(position, newName);
|
||||
if (renameFile) {
|
||||
String newPath = FileUtils.renameWithoutExtension(mScriptPath.get(position), newName);
|
||||
String newPath = PFile.renameWithoutExtension(mScriptPath.get(position), newName);
|
||||
mScriptPath.set(position, newPath);
|
||||
}
|
||||
syncWithSharedPref();
|
||||
@@ -1,15 +1,13 @@
|
||||
package com.stardust.scriptdroid.scripts;
|
||||
|
||||
import com.stardust.scriptdroid.droid.script.file.ScriptFile;
|
||||
import android.os.Environment;
|
||||
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.util.FileSorter;
|
||||
import com.stardust.util.LimitedHashMap;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/3/31.
|
||||
@@ -27,20 +25,39 @@ public class StorageScriptProvider {
|
||||
}
|
||||
}
|
||||
|
||||
public static final String DEFAULT_DIRECTORY_PATH = Environment.getExternalStorageDirectory() + App.getApp().getString(R.string.folder_name);
|
||||
public static final ScriptFile DEFAULT_DIRECTORY = new ScriptFile(DEFAULT_DIRECTORY_PATH);
|
||||
|
||||
|
||||
|
||||
private static StorageScriptProvider instance = new StorageScriptProvider();
|
||||
|
||||
public static StorageScriptProvider getInstance() {
|
||||
public static StorageScriptProvider getDefault() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
private EventBus mDirectoryEventBus = new EventBus();
|
||||
private LimitedHashMap<String, ScriptFile[]> mScriptFileCache = new LimitedHashMap<>(10);
|
||||
private LimitedHashMap<String, ScriptFile[]> mScriptFileCache;
|
||||
private ScriptFile mInitialDirectory;
|
||||
private ScriptFile[] mInitialDirectoryScriptFiles;
|
||||
|
||||
private ScriptFile[] mInitialDirectoryScriptFiles = listAndSortFiles(ScriptFile.DEFAULT_DIRECTORY);
|
||||
public StorageScriptProvider(String path, int cacheSize) {
|
||||
this(new ScriptFile(path), cacheSize);
|
||||
}
|
||||
|
||||
public StorageScriptProvider(ScriptFile initialDirectory, int cacheSize) {
|
||||
mInitialDirectory = initialDirectory;
|
||||
mInitialDirectoryScriptFiles = getInitialDirectoryScriptFilesInner();
|
||||
mScriptFileCache = new LimitedHashMap<>(cacheSize);
|
||||
}
|
||||
|
||||
public StorageScriptProvider() {
|
||||
this(DEFAULT_DIRECTORY, 10);
|
||||
}
|
||||
|
||||
public void notifyDirectoryChanged(ScriptFile directory) {
|
||||
if (directory.equals(ScriptFile.DEFAULT_DIRECTORY)) {
|
||||
mInitialDirectoryScriptFiles = listAndSortFiles(ScriptFile.DEFAULT_DIRECTORY);
|
||||
if (directory.equals(mInitialDirectory)) {
|
||||
mInitialDirectoryScriptFiles = getInitialDirectoryScriptFilesInner();
|
||||
} else {
|
||||
clearCache(directory);
|
||||
}
|
||||
@@ -49,16 +66,24 @@ public class StorageScriptProvider {
|
||||
|
||||
public void notifyStoragePermissionGranted() {
|
||||
mScriptFileCache.clear();
|
||||
mInitialDirectoryScriptFiles = listAndSortFiles(ScriptFile.DEFAULT_DIRECTORY);
|
||||
mDirectoryEventBus.post(new DirectoryChangeEvent(ScriptFile.DEFAULT_DIRECTORY));
|
||||
mInitialDirectoryScriptFiles = getInitialDirectoryScriptFilesInner();
|
||||
mDirectoryEventBus.post(new DirectoryChangeEvent(mInitialDirectory));
|
||||
}
|
||||
|
||||
public ScriptFile getInitialDirectory() {
|
||||
return mInitialDirectory;
|
||||
}
|
||||
|
||||
public ScriptFile[] getInitialDirectoryScriptFiles() {
|
||||
return mInitialDirectoryScriptFiles;
|
||||
}
|
||||
|
||||
private ScriptFile[] getInitialDirectoryScriptFilesInner() {
|
||||
return listAndSortFiles(mInitialDirectory);
|
||||
}
|
||||
|
||||
public ScriptFile[] getDirectoryScriptFiles(ScriptFile directory) {
|
||||
if (directory.equals(ScriptFile.DEFAULT_DIRECTORY)) {
|
||||
if (directory.equals(mInitialDirectory)) {
|
||||
return mInitialDirectoryScriptFiles;
|
||||
}
|
||||
ScriptFile[] scriptFiles = getScriptFilesFromCache(directory);
|
||||
@@ -74,7 +99,7 @@ public class StorageScriptProvider {
|
||||
|
||||
|
||||
private ScriptFile[] getScriptFiles(ScriptFile directory) {
|
||||
ScriptFile[] scriptFiles =listAndSortFiles(directory);
|
||||
ScriptFile[] scriptFiles = listAndSortFiles(directory);
|
||||
mScriptFileCache.put(directory.getPath(), scriptFiles);
|
||||
return scriptFiles;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package com.stardust.scriptdroid.scripts.sample;
|
||||
import android.content.Context;
|
||||
import android.content.res.AssetManager;
|
||||
|
||||
import com.stardust.scriptdroid.tool.FileUtils;
|
||||
import com.stardust.pio.PFile;
|
||||
import com.stardust.scriptdroid.App;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -43,7 +43,7 @@ public class SampleFileManager {
|
||||
try {
|
||||
String[] samples = assets.list(path);
|
||||
for (String sample : samples) {
|
||||
group.add(new Sample(FileUtils.getNameWithoutExtension(sample), path + "/" + sample));
|
||||
group.add(new Sample(PFile.getNameWithoutExtension(sample), path + "/" + sample));
|
||||
}
|
||||
return group;
|
||||
} catch (IOException e) {
|
||||
|
||||
@@ -8,6 +8,7 @@ import com.stardust.scriptdroid.Pref;
|
||||
import com.stardust.scriptdroid.service.AccessibilityWatchDogService;
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.util.Shell;
|
||||
import com.stardust.view.accessibility.AccessibilityServiceUtils;
|
||||
|
||||
import static com.stardust.view.accessibility.AccessibilityServiceUtils.isAccessibilityServiceEnabled;
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
package com.stardust.scriptdroid.tool;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.support.v4.widget.DrawerLayout;
|
||||
import android.view.Gravity;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.stardust.scriptdroid.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/2/3.
|
||||
*/
|
||||
public interface BackPressedHandler {
|
||||
|
||||
boolean onBackPressed(Activity activity);
|
||||
|
||||
class Observer implements BackPressedHandler {
|
||||
|
||||
private List<BackPressedHandler> mBackPressedHandlers = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public boolean onBackPressed(Activity activity) {
|
||||
for (BackPressedHandler handler : mBackPressedHandlers) {
|
||||
if (handler.onBackPressed(activity)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void registerHandler(BackPressedHandler handler) {
|
||||
mBackPressedHandlers.add(handler);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class DoublePressExit implements BackPressedHandler {
|
||||
|
||||
private final Activity mActivity;
|
||||
private long mLastPressedMillis;
|
||||
private long mDoublePressInterval = 1000;
|
||||
|
||||
public DoublePressExit(Activity activity) {
|
||||
mActivity = activity;
|
||||
}
|
||||
|
||||
public DoublePressExit doublePressInterval(long doublePressInterval) {
|
||||
mDoublePressInterval = doublePressInterval;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onBackPressed(Activity activity) {
|
||||
if (System.currentTimeMillis() - mLastPressedMillis < mDoublePressInterval) {
|
||||
mActivity.finish();
|
||||
} else {
|
||||
mLastPressedMillis = System.currentTimeMillis();
|
||||
Toast.makeText(mActivity, R.string.text_press_again_to_exit, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class DrawerAutoClose implements BackPressedHandler {
|
||||
|
||||
private DrawerLayout mDrawerLayout;
|
||||
private int mGravity;
|
||||
|
||||
public DrawerAutoClose(DrawerLayout drawerLayout, int gravity){
|
||||
mDrawerLayout = drawerLayout;
|
||||
mGravity = gravity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onBackPressed(Activity activity) {
|
||||
if (mDrawerLayout.isDrawerOpen(mGravity)) {
|
||||
mDrawerLayout.closeDrawer(mGravity);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package com.stardust.scriptdroid.tool;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/1/23.
|
||||
*/
|
||||
|
||||
public class ClassTool {
|
||||
|
||||
public static void loadClass(Class c) {
|
||||
try {
|
||||
Class.forName(c.getName());
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void loadClasses(Class... classes) {
|
||||
for (Class c : classes) {
|
||||
loadClass(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
package com.stardust.scriptdroid.tool;
|
||||
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
|
||||
import com.stardust.scriptdroid.App;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/3/10.
|
||||
*/
|
||||
|
||||
public class ClipboardTool {
|
||||
|
||||
|
||||
public static void setClip(CharSequence text) {
|
||||
((ClipboardManager) App.getApp().getSystemService(Context.CLIPBOARD_SERVICE)).setPrimaryClip(ClipData.newPlainText("", text));
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.stardust.util;
|
||||
package com.stardust.scriptdroid.tool;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/2/2.
|
||||
@@ -71,4 +71,4 @@ public class CrashHandler implements UncaughtExceptionHandler {
|
||||
throwable.printStackTrace(pw);
|
||||
return sw.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,263 +0,0 @@
|
||||
package com.stardust.scriptdroid.tool;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.droid.script.file.ScriptFile;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.lang.reflect.Field;
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/1/23.
|
||||
*/
|
||||
|
||||
public class FileUtils {
|
||||
|
||||
private static final int BUFFER_SIZE = 1024 * 100;
|
||||
|
||||
public static String getPath(Context context, Uri uri) throws URISyntaxException {
|
||||
if ("content".equalsIgnoreCase(uri.getScheme())) {
|
||||
String[] projection = {"_data"};
|
||||
Cursor cursor = null;
|
||||
|
||||
try {
|
||||
cursor = context.getContentResolver().query(uri, projection, null, null, null);
|
||||
int column_index = cursor.getColumnIndexOrThrow("_data");
|
||||
if (cursor.moveToFirst()) {
|
||||
return cursor.getString(column_index);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Eat it
|
||||
}
|
||||
} else if ("file".equalsIgnoreCase(uri.getScheme())) {
|
||||
return uri.getPath();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String getPath(InputStream inputStream) {
|
||||
if (inputStream instanceof FileInputStream) {
|
||||
FileInputStream fis = (FileInputStream) inputStream;
|
||||
try {
|
||||
Field field = fis.getClass().getDeclaredField("path");
|
||||
field.setAccessible(true);
|
||||
return (String) field.get(fis);
|
||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean createFileIfNotExists(String path) {
|
||||
ensureFolder(path);
|
||||
File file = new File(path);
|
||||
if (!file.exists()) {
|
||||
try {
|
||||
return file.createNewFile();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean ensureFolder(String path) {
|
||||
int i = path.lastIndexOf("\\");
|
||||
if (i < 0)
|
||||
i = path.lastIndexOf("/");
|
||||
if (i >= 0) {
|
||||
String folder = path.substring(0, i);
|
||||
File file = new File(folder);
|
||||
if (file.exists())
|
||||
return true;
|
||||
return file.mkdirs();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static String readString(File file, String encoding) {
|
||||
try {
|
||||
return readString(new FileInputStream(file), encoding);
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static String readString(File file) {
|
||||
return readString(file, "utf-8");
|
||||
}
|
||||
|
||||
public static String readString(InputStream is, String encoding) {
|
||||
try {
|
||||
byte[] bytes = new byte[is.available()];
|
||||
is.read(bytes);
|
||||
return new String(bytes, encoding);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static String readString(InputStream inputStream) {
|
||||
return readString(inputStream, "utf-8");
|
||||
}
|
||||
|
||||
public static boolean copy(int rawId, String path) {
|
||||
InputStream is = App.getApp().getResources().openRawResource(rawId);
|
||||
return copy(is, path);
|
||||
}
|
||||
|
||||
public static boolean copy(InputStream is, String path) {
|
||||
if (!ensureFolder(path))
|
||||
return false;
|
||||
File file = new File(path);
|
||||
try {
|
||||
if (!file.exists())
|
||||
if (!file.createNewFile())
|
||||
return false;
|
||||
FileOutputStream fos = new FileOutputStream(file);
|
||||
return copy(is, fos);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean copy(InputStream is, OutputStream os) {
|
||||
byte[] buffer = new byte[BUFFER_SIZE];
|
||||
try {
|
||||
while (is.available() > 0) {
|
||||
int n = is.read(buffer);
|
||||
os.write(buffer, 0, n);
|
||||
}
|
||||
is.close();
|
||||
os.close();
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static boolean copy(String pathFrom, String pathTo) {
|
||||
try {
|
||||
return copy(new FileInputStream(pathFrom), pathTo);
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean copyAsset(String assetFile, String path) {
|
||||
try {
|
||||
return copy(App.getApp().getAssets().open(assetFile), path);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static String renameWithoutExtension(String path, String newName) {
|
||||
File file = new File(path);
|
||||
File newFile = new File(file.getParent(), newName + "." + getExtension(file.getName()));
|
||||
file.renameTo(newFile);
|
||||
return newFile.getAbsolutePath();
|
||||
}
|
||||
|
||||
public static String getExtension(String fileName) {
|
||||
int i = fileName.lastIndexOf('.');
|
||||
if (i < 0)
|
||||
return "";
|
||||
return fileName.substring(i + 1);
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
public static String generateNotExistingPath(String path, String extension) {
|
||||
if (!new File(path + extension).exists())
|
||||
return path + extension;
|
||||
int i = 0;
|
||||
while (true) {
|
||||
String pathI = path + "(" + i + ")" + extension;
|
||||
if (!new File(pathI).exists())
|
||||
return pathI;
|
||||
i++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static String getNameWithoutExtension(String fileName) {
|
||||
int a = fileName.lastIndexOf('/');
|
||||
if (a < 0)
|
||||
a = fileName.lastIndexOf('\\');
|
||||
int b = fileName.lastIndexOf('.');
|
||||
if (a < 0)
|
||||
a = -1;
|
||||
if (b < 0)
|
||||
b = fileName.length();
|
||||
fileName = fileName.substring(a + 1, b);
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public static File copyAssetToTmpFile(Context context, String path) {
|
||||
String extension = getExtension(path);
|
||||
String name = getNameWithoutExtension(path);
|
||||
if (name.length() < 5) {
|
||||
name += name.hashCode();
|
||||
}
|
||||
try {
|
||||
File tmpFile = File.createTempFile(name, "." + extension, context.getCacheDir());
|
||||
copyAsset(path, tmpFile.getPath());
|
||||
return tmpFile;
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean deleteAll(File file) {
|
||||
if (file.isFile())
|
||||
return file.delete();
|
||||
for (File child : file.listFiles()) {
|
||||
if (!deleteAll(child))
|
||||
return false;
|
||||
}
|
||||
return file.delete();
|
||||
}
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
package com.stardust.scriptdroid.tool;
|
||||
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.R;
|
||||
|
||||
/**
|
||||
* Intent工具,用于Activity之间的跳转,调起其他应用程序等
|
||||
*/
|
||||
public class IntentTool {
|
||||
|
||||
public static boolean goToQQ(Context context, String qq) {
|
||||
try {
|
||||
String url = "mqqwpa://im/chat?chat_type=wpa&uin=" + qq;
|
||||
context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
|
||||
return true;
|
||||
} catch (Exception exception) {
|
||||
exception.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/****************
|
||||
* 发起添加群流程。群号:免Root脚本精灵交流群(556928653) 的 key 为: vjHXzZlpGcXNe-YEWzQ85mm_z8y-curC
|
||||
* 调用 joinQQGroup(vjHXzZlpGcXNe-YEWzQ85mm_z8y-curC) 即可发起手Q客户端申请加群 免Root脚本精灵交流群(556928653)
|
||||
*
|
||||
* @param key 由官网生成的key
|
||||
* @return 返回true表示呼起手Q成功,返回false表示呼起失败
|
||||
******************/
|
||||
public static boolean joinQQGroup(Context context, String key) {
|
||||
Intent intent = new Intent().addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent.setData(Uri.parse("mqqopensdkapi://bizAgent/qm/qr?url=http%3A%2F%2Fqm.qq.com%2Fcgi-bin%2Fqm%2Fqr%3Ffrom%3Dapp%26p%3Dandroid%26k%3D" + key));
|
||||
// 此Flag可根据具体产品需要自定义,如设置,则在加群界面按返回,返回手Q主界面,不设置,按返回会返回到呼起产品界面 //intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
try {
|
||||
context.startActivity(intent);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void goToMail(Context context, String sendTo, @Nullable String title, @Nullable String content) {
|
||||
Uri uri = Uri.parse("mailto:" + sendTo);
|
||||
String[] email = {sendTo};
|
||||
Intent intent = new Intent(Intent.ACTION_SENDTO, uri).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent.putExtra(Intent.EXTRA_CC, email);
|
||||
if (title != null)
|
||||
intent.putExtra(Intent.EXTRA_SUBJECT, title);
|
||||
if (content != null)
|
||||
intent.putExtra(Intent.EXTRA_TEXT, content);
|
||||
context.startActivity(Intent.createChooser(intent, context.getString(R.string.text_choose_email_app)));
|
||||
}
|
||||
|
||||
public static void goToMail(Context context, String sendTo) {
|
||||
goToMail(context, sendTo, null, null);
|
||||
}
|
||||
|
||||
public static boolean goToLink(Context context, String link) {
|
||||
try {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(link)).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
context.startActivity(intent);
|
||||
return true;
|
||||
} catch (ActivityNotFoundException ignored) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void shareText(Context context, String text) {
|
||||
context.startActivity(new Intent(Intent.ACTION_SEND)
|
||||
.putExtra(Intent.EXTRA_TEXT, text)
|
||||
.setType("text/plain"));
|
||||
}
|
||||
|
||||
public static boolean goToAppSetting(Context context, String packageName) {
|
||||
try {
|
||||
Intent i = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
|
||||
i.addCategory(Intent.CATEGORY_DEFAULT);
|
||||
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
i.setData(Uri.parse("package:" + packageName));
|
||||
context.startActivity(i);
|
||||
return true;
|
||||
} catch (ActivityNotFoundException ignored) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean goToAppSetting(Context context) {
|
||||
return goToAppSetting(context, context.getPackageName());
|
||||
}
|
||||
}
|
||||
@@ -1,266 +0,0 @@
|
||||
package com.stardust.scriptdroid.tool;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.Log;
|
||||
|
||||
import com.stardust.scriptdroid.App;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
import jackpal.androidterm.ShellTermSession;
|
||||
import jackpal.androidterm.util.TermSettings;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/1/20.
|
||||
* <p>
|
||||
* 来自网络~~
|
||||
*/
|
||||
|
||||
public class Shell {
|
||||
|
||||
|
||||
private static final String TAG = "Shell";
|
||||
|
||||
private final static String COMMAND_SU = "su";
|
||||
private final static String COMMAND_SH = "sh";
|
||||
private final static String COMMAND_EXIT = "exit\n";
|
||||
private final static String COMMAND_LINE_END = "\n";
|
||||
|
||||
private Process mProcess;
|
||||
private DataOutputStream mCommandOutputStream;
|
||||
private BufferedReader mSucceedReader;
|
||||
private BufferedReader mErrorReader;
|
||||
|
||||
private StringBuilder mSucceedOutput = new StringBuilder();
|
||||
private StringBuilder mErrorOutput = new StringBuilder();
|
||||
|
||||
public Shell() {
|
||||
this(false);
|
||||
}
|
||||
|
||||
public Shell(boolean root) {
|
||||
try {
|
||||
mProcess = new ProcessBuilder(root ? COMMAND_SU : COMMAND_SH).redirectErrorStream(true).start();
|
||||
mCommandOutputStream = new DataOutputStream(mProcess.getOutputStream());
|
||||
mSucceedReader = new BufferedReader(new InputStreamReader(mProcess.getInputStream()));
|
||||
mErrorReader = new BufferedReader(new InputStreamReader(mProcess.getErrorStream()));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public Shell execute(String command) {
|
||||
try {
|
||||
mCommandOutputStream.writeBytes(command);
|
||||
if (!command.endsWith(COMMAND_LINE_END)) {
|
||||
mCommandOutputStream.writeBytes(COMMAND_LINE_END);
|
||||
}
|
||||
mCommandOutputStream.flush();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Shell exitAndWaitFor() {
|
||||
exit();
|
||||
try {
|
||||
mProcess.waitFor();
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Shell readAll() {
|
||||
return readSucceedOutput().readErrorOutput();
|
||||
}
|
||||
|
||||
public Shell readSucceedOutput() {
|
||||
try {
|
||||
while (mSucceedReader.ready()) {
|
||||
String line = mSucceedReader.readLine();
|
||||
mSucceedOutput.append(line).append("\n");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Shell readErrorOutput() {
|
||||
String line;
|
||||
try {
|
||||
while ((line = mErrorReader.readLine()) != null) {
|
||||
mErrorOutput.append(line).append("\n");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public StringBuilder getSucceedOutput() {
|
||||
return mSucceedOutput;
|
||||
}
|
||||
|
||||
public StringBuilder getErrorOutput() {
|
||||
return mErrorOutput;
|
||||
}
|
||||
|
||||
public Shell exit() {
|
||||
execute(COMMAND_EXIT);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Shell destroy() {
|
||||
mProcess.destroy();
|
||||
return this;
|
||||
}
|
||||
|
||||
public Process getProcess() {
|
||||
return mProcess;
|
||||
}
|
||||
|
||||
public BufferedReader getSucceedReader() {
|
||||
return mSucceedReader;
|
||||
}
|
||||
|
||||
public BufferedReader getErrorReader() {
|
||||
return mErrorReader;
|
||||
}
|
||||
|
||||
public int waitFor() {
|
||||
try {
|
||||
return mProcess.waitFor();
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Command执行结果
|
||||
*
|
||||
* @author Mountain
|
||||
*/
|
||||
public static class CommandResult {
|
||||
public int code = -1;
|
||||
public String error;
|
||||
public String result;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ShellResult{" +
|
||||
"code=" + code +
|
||||
", error='" + error + '\'' +
|
||||
", result='" + result + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行命令—单条
|
||||
*
|
||||
* @param command
|
||||
* @param isRoot
|
||||
* @return
|
||||
*/
|
||||
public static CommandResult execCommand(String command, boolean isRoot) {
|
||||
String[] commands = command.split("\n");
|
||||
return execCommand(commands, isRoot);
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行命令-多条
|
||||
*
|
||||
* @param commands
|
||||
* @param isRoot
|
||||
* @return
|
||||
*/
|
||||
public static CommandResult execCommand(String[] commands, boolean isRoot) {
|
||||
CommandResult commandResult = new CommandResult();
|
||||
if (commands == null || commands.length == 0) return commandResult;
|
||||
Process process = null;
|
||||
DataOutputStream os = null;
|
||||
BufferedReader successResult = null;
|
||||
BufferedReader errorResult = null;
|
||||
StringBuilder successMsg = null;
|
||||
StringBuilder errorMsg = null;
|
||||
try {
|
||||
process = Runtime.getRuntime().exec(isRoot ? COMMAND_SU : COMMAND_SH);
|
||||
os = new DataOutputStream(process.getOutputStream());
|
||||
for (String command : commands) {
|
||||
if (command != null) {
|
||||
os.write(command.getBytes());
|
||||
os.writeBytes(COMMAND_LINE_END);
|
||||
os.flush();
|
||||
}
|
||||
}
|
||||
os.writeBytes(COMMAND_EXIT);
|
||||
os.flush();
|
||||
commandResult.code = process.waitFor();
|
||||
//获取错误信息
|
||||
successMsg = new StringBuilder();
|
||||
errorMsg = new StringBuilder();
|
||||
successResult = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
||||
errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream()));
|
||||
String s;
|
||||
while ((s = successResult.readLine()) != null) successMsg.append(s);
|
||||
while ((s = errorResult.readLine()) != null) errorMsg.append(s);
|
||||
commandResult.result = successMsg.toString();
|
||||
commandResult.error = errorMsg.toString();
|
||||
Log.i(TAG, commandResult.toString());
|
||||
} catch (Exception e) {
|
||||
String errmsg = e.getMessage();
|
||||
if (errmsg != null) {
|
||||
Log.e(TAG, errmsg);
|
||||
} else {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} finally {
|
||||
try {
|
||||
if (os != null) os.close();
|
||||
if (successResult != null) successResult.close();
|
||||
if (errorResult != null) errorResult.close();
|
||||
} catch (IOException e) {
|
||||
String errmsg = e.getMessage();
|
||||
if (errmsg != null) {
|
||||
Log.e(TAG, errmsg);
|
||||
} else {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (process != null) process.destroy();
|
||||
}
|
||||
return commandResult;
|
||||
}
|
||||
|
||||
public static Process exec(String[] commands, boolean isRoot) {
|
||||
try {
|
||||
Process process = Runtime.getRuntime().exec(isRoot ? COMMAND_SU : COMMAND_SH);
|
||||
DataOutputStream os = new DataOutputStream(process.getOutputStream());
|
||||
for (String command : commands) {
|
||||
if (command != null) {
|
||||
os.write(command.getBytes());
|
||||
os.writeBytes(COMMAND_LINE_END);
|
||||
os.flush();
|
||||
}
|
||||
}
|
||||
os.writeBytes(COMMAND_EXIT);
|
||||
os.flush();
|
||||
os.close();
|
||||
return process;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Process exec(String command, boolean isRoot) {
|
||||
return exec(command.split("\n"), isRoot);
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
package com.stardust.scriptdroid.tool;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.support.annotation.IdRes;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/1/24.
|
||||
*/
|
||||
|
||||
public class ViewTool {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <V extends View> V $(View view, @IdRes int resId) {
|
||||
return (V) view.findViewById(resId);
|
||||
}
|
||||
|
||||
public static int getStatusBarHeight(Context context) {
|
||||
int result = 0;
|
||||
int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
|
||||
if (resourceId > 0) {
|
||||
result = context.getResources().getDimensionPixelSize(resourceId);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -10,9 +10,8 @@ import android.view.View;
|
||||
|
||||
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.tool.BackPressedHandler;
|
||||
import com.stardust.theme.ThemeColorManager;
|
||||
import com.stardust.theme.app.ThemeColorAppCompatActivity;
|
||||
import com.stardust.util.BackPressedHandler;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
package com.stardust.scriptdroid.ui.console;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.graphics.Color;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.SpannableString;
|
||||
import android.text.Spanned;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
import android.util.Log;
|
||||
|
||||
import com.jraska.console.timber.ConsoleTree;
|
||||
import com.stardust.autojs.runtime.api.Console;
|
||||
import com.stardust.scriptdroid.App;
|
||||
|
||||
|
||||
import timber.log.Timber;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/4/2.
|
||||
*/
|
||||
|
||||
public class TimberConsole implements Console {
|
||||
|
||||
static {
|
||||
Timber.plant(new ConsoleTree.Builder()
|
||||
.minPriority(Log.VERBOSE)
|
||||
.verboseColor(0xff909090)
|
||||
.debugColor(0xffc88b48)
|
||||
.infoColor(0xffc9c9c9)
|
||||
.warnColor(0xffa97db6)
|
||||
.errorColor(0xffff534e)
|
||||
.assertColor(0xffff5540)
|
||||
.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void i(@Nullable Object o) {
|
||||
i(o + "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void i(String str) {
|
||||
Timber.i(str);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void e(@Nullable String message) {
|
||||
Timber.e(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void e(@Nullable Object o) {
|
||||
e(o + "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void v(@Nullable String v) {
|
||||
Timber.v(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void v(@Nullable Object o) {
|
||||
v(o + "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(@Nullable Object o) {
|
||||
log(o + "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(String str) {
|
||||
SpannableString spannableString = new SpannableString(str);
|
||||
spannableString.setSpan(new ForegroundColorSpan(Color.BLACK), 0, str.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
com.jraska.console.Console.writeLine(spannableString);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show() {
|
||||
App.getApp().startActivity(new Intent(App.getApp(), ConsoleActivity.class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
com.jraska.console.Console.clear();
|
||||
}
|
||||
}
|
||||
@@ -15,10 +15,13 @@ import android.view.View;
|
||||
|
||||
import com.afollestad.materialdialogs.DialogAction;
|
||||
import com.afollestad.materialdialogs.MaterialDialog;
|
||||
import com.stardust.autojs.engine.JavaScriptEngine;
|
||||
import com.stardust.autojs.engine.ScriptExecutionListener;
|
||||
import com.stardust.autojs.script.FileScriptSource;
|
||||
import com.stardust.autojs.script.ScriptSource;
|
||||
import com.stardust.pio.PFile;
|
||||
import com.stardust.scriptdroid.Pref;
|
||||
import com.stardust.scriptdroid.droid.Droid;
|
||||
import com.stardust.scriptdroid.droid.RunningConfig;
|
||||
import com.stardust.scriptdroid.tool.FileUtils;
|
||||
import com.stardust.scriptdroid.autojs.AutoJs;
|
||||
import com.stardust.scriptdroid.ui.edit.editor920.Editor920Activity;
|
||||
import com.stardust.scriptdroid.ui.edit.sidemenu.EditSideMenuFragment;
|
||||
import com.stardust.scriptdroid.ui.edit.sidemenu.FunctionListRecyclerView;
|
||||
@@ -39,7 +42,8 @@ import com.stardust.theme.ThemeColorManager;
|
||||
import com.stardust.view.ViewBinder;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Timer;
|
||||
import java.text.DateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
import timber.log.Timber;
|
||||
|
||||
@@ -54,19 +58,25 @@ public class EditActivity extends Editor920Activity {
|
||||
private static final String ACTION_ON_RUN_FINISHED = "ACTION_ON_RUN_FINISHED";
|
||||
private static final String EXTRA_EXCEPTION_MESSAGE = "EXTRA_EXCEPTION_MESSAGE";
|
||||
|
||||
private static final Droid.OnRunFinishedListener ON_RUN_FINISHED_LISTENER = new Droid.OnRunFinishedListener() {
|
||||
private static final ScriptExecutionListener SCRIPT_EXECUTION_LISTENER = new ScriptExecutionListener() {
|
||||
|
||||
@Override
|
||||
public void onRunFinished(Object result) {
|
||||
public void onStart(JavaScriptEngine engine, ScriptSource source) {
|
||||
AutoJs.getInstance().getScriptEngineService().getDefaultListener().onStart(engine, source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(JavaScriptEngine engine, ScriptSource source, Object result) {
|
||||
App.getApp().sendBroadcast(new Intent(ACTION_ON_RUN_FINISHED));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onException(@NonNull Exception e) {
|
||||
public void onException(JavaScriptEngine engine, ScriptSource source, Exception e) {
|
||||
App.getApp().sendBroadcast(new Intent(ACTION_ON_RUN_FINISHED)
|
||||
.putExtra(EXTRA_EXCEPTION_MESSAGE, e.getMessage()));
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
public static void editFile(Context context, String path) {
|
||||
@@ -145,7 +155,7 @@ public class EditActivity extends Editor920Activity {
|
||||
if (getIntent().getBooleanExtra("fromAssets", false)) {
|
||||
mReadOnly = true;
|
||||
//TODO 优化
|
||||
mFile = FileUtils.copyAssetToTmpFile(this, path);
|
||||
mFile = PFile.copyAssetToTmpFile(this, path);
|
||||
} else {
|
||||
mFile = new File(path);
|
||||
}
|
||||
@@ -254,7 +264,7 @@ public class EditActivity extends Editor920Activity {
|
||||
private void run() {
|
||||
Snackbar.make(mView, R.string.text_start_running, Snackbar.LENGTH_SHORT).show();
|
||||
setMenuStatus(R.id.run, MenuDef.STATUS_DISABLED);
|
||||
Droid.getInstance().runScriptFile(mFile, ON_RUN_FINISHED_LISTENER, RunningConfig.getDefault());
|
||||
AutoJs.getInstance().getScriptEngineService().execute(new FileScriptSource(mFile), SCRIPT_EXECUTION_LISTENER);
|
||||
}
|
||||
|
||||
@ViewBinding.Click(R.id.undo)
|
||||
@@ -337,9 +347,9 @@ public class EditActivity extends Editor920Activity {
|
||||
|
||||
@Override
|
||||
protected void onRestoreInstanceState(Bundle savedInstanceState) {
|
||||
try{
|
||||
try {
|
||||
super.onRestoreInstanceState(savedInstanceState);
|
||||
}catch (RuntimeException e){
|
||||
} catch (RuntimeException e) {
|
||||
// FIXME: 2017/3/20
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
@@ -13,8 +13,9 @@ import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.droid.script.JavaScriptEngine;
|
||||
import com.stardust.scriptdroid.autojs.AutoJs;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
@@ -77,7 +78,7 @@ public class InputMethodEnhanceBar extends RecyclerView implements CodeCompletio
|
||||
private void init() {
|
||||
setAdapter(new CodeCompletionAdapter());
|
||||
setLayoutManager(new LinearLayoutManager(getContext(), HORIZONTAL, false));
|
||||
mCodeCompletion.setFunctions(JavaScriptEngine.getDefault().getGlobalFunctions());
|
||||
mCodeCompletion.setFunctions(AutoJs.getInstance().getScriptEngineService().getJavaScriptEngineManager().getGlobalFunctions());
|
||||
}
|
||||
|
||||
public void setEditTextBridge(EditTextBridge editTextBridge) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.stardust.scriptdroid.ui.edit.sidemenu;
|
||||
|
||||
import android.bug.WrapContentLinearLayoutManager;
|
||||
import android.workground.WrapContentLinearLayoutManager;
|
||||
import android.content.Context;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
@@ -10,9 +10,9 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.stardust.pio.PFile;
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.tool.FileUtils;
|
||||
import com.stardust.widget.ExpandableRecyclerView;
|
||||
|
||||
import java.text.Collator;
|
||||
@@ -134,7 +134,7 @@ public class FunctionListRecyclerView extends ExpandableRecyclerView {
|
||||
}
|
||||
|
||||
private static void initFunctionList() {
|
||||
String[] functions = FileUtils.readString(App.getApp().getResources().openRawResource(R.raw.edit_side_menu_functions)).split("\n");
|
||||
String[] functions = PFile.read(App.getApp().getResources().openRawResource(R.raw.edit_side_menu_functions)).split("\n");
|
||||
for (String f : functions) {
|
||||
String[] str = f.split(" ");
|
||||
FUNCTION_LIST.add(new Function(str[0], str[1]));
|
||||
|
||||
@@ -4,16 +4,12 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.stardust.pio.PFile;
|
||||
import com.stardust.scriptdroid.ui.BaseActivity;
|
||||
import com.stardust.widget.CommonMarkdownView;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.tool.FileUtils;
|
||||
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/2/1.
|
||||
@@ -54,12 +50,12 @@ public class DocumentationActivity extends BaseActivity {
|
||||
int rawId = intent.getIntExtra("resId", 0);
|
||||
if (path != null) {
|
||||
try {
|
||||
mDocumentation = FileUtils.readString(getAssets().open("help/" + path));
|
||||
mDocumentation = PFile.read(getAssets().open("help/" + path));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else if (rawId != 0) {
|
||||
mDocumentation = FileUtils.readString(getResources().openRawResource(rawId));
|
||||
mDocumentation = PFile.read(getResources().openRawResource(rawId));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,17 +12,16 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.stardust.pio.PFile;
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.ui.BaseActivity;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.tool.FileUtils;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -166,7 +165,7 @@ public class HelpCatalogueActivity extends BaseActivity {
|
||||
static {
|
||||
Map<String, List<Item>> fromJson;
|
||||
try {
|
||||
String json = FileUtils.readString(App.getApp().getAssets().open("help/catalogue.json"));
|
||||
String json = PFile.read(App.getApp().getAssets().open("help/catalogue.json"));
|
||||
Gson gson = new Gson();
|
||||
Type type = new TypeToken<Map<String, List<Item>>>() {
|
||||
}.getType();
|
||||
|
||||
@@ -6,8 +6,8 @@ import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.webkit.WebView;
|
||||
|
||||
import com.stardust.pio.PFile;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.tool.FileUtils;
|
||||
import com.stardust.scriptdroid.ui.BaseActivity;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -43,7 +43,7 @@ public class LocalWebViewActivity extends BaseActivity {
|
||||
String path = intent.getStringExtra("path");
|
||||
if (path != null)
|
||||
try {
|
||||
mHtml = FileUtils.readString(getAssets().open("help/" + path));
|
||||
mHtml = PFile.read(getAssets().open("help/" + path));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
mHtml = getString(R.string.text_load_failed);
|
||||
|
||||
@@ -17,7 +17,6 @@ import android.support.v4.view.ViewPager;
|
||||
import android.support.v4.widget.DrawerLayout;
|
||||
import android.support.v7.app.ActionBarDrawerToggle;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.text.InputType;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
@@ -31,9 +30,6 @@ import com.stardust.app.FragmentPagerAdapterBuilder;
|
||||
import com.stardust.app.NotAskAgainDialog;
|
||||
import com.stardust.app.OnActivityResultDelegate;
|
||||
import com.stardust.scriptdroid.Pref;
|
||||
import com.stardust.scriptdroid.droid.script.file.ScriptFile;
|
||||
import com.stardust.scriptdroid.droid.script.file.ScriptFileList;
|
||||
import com.stardust.scriptdroid.external.open.ImportIntentActivity;
|
||||
import com.stardust.scriptdroid.scripts.StorageScriptProvider;
|
||||
import com.stardust.scriptdroid.service.AccessibilityWatchDogService;
|
||||
import com.stardust.scriptdroid.tool.AccessibilityServiceTool;
|
||||
@@ -44,18 +40,14 @@ import com.stardust.scriptdroid.ui.main.sample_list.SampleScriptListFragment;
|
||||
import com.stardust.scriptdroid.ui.main.task.TaskManagerFragment;
|
||||
import com.stardust.scriptdroid.ui.settings.SettingsActivity;
|
||||
import com.stardust.theme.dialog.ThemeColorMaterialDialogBuilder;
|
||||
import com.stardust.util.MessageEvent;
|
||||
import com.stardust.util.BackPressedHandler;
|
||||
import com.stardust.view.ViewBinding;
|
||||
import com.stardust.widget.SlidingUpPanel;
|
||||
import com.stardust.scriptdroid.BuildConfig;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.tool.FileUtils;
|
||||
import com.stardust.scriptdroid.tool.BackPressedHandler;
|
||||
import com.stardust.view.ViewBinder;
|
||||
import com.stardust.view.accessibility.AccessibilityServiceUtils;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
|
||||
@@ -96,7 +88,7 @@ public class MainActivity extends BaseActivity implements FileChooserDialog.File
|
||||
}
|
||||
});
|
||||
registerBackPressedHandler(new BackPressedHandler.DrawerAutoClose(mDrawerLayout, Gravity.START));
|
||||
registerBackPressedHandler(new BackPressedHandler.DoublePressExit(this));
|
||||
registerBackPressedHandler(new BackPressedHandler.DoublePressExit(this, R.string.text_press_again_to_exit));
|
||||
}
|
||||
|
||||
private void checkPermissions() {
|
||||
@@ -302,7 +294,7 @@ public class MainActivity extends BaseActivity implements FileChooserDialog.File
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
StorageScriptProvider.getInstance().notifyStoragePermissionGranted();
|
||||
StorageScriptProvider.getDefault().notifyStoragePermissionGranted();
|
||||
}
|
||||
|
||||
@ViewBinding.Click(R.id.toolbar)
|
||||
|
||||
@@ -5,15 +5,15 @@ import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.SwitchCompat;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.stardust.app.Fragment;
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.droid.Droid;
|
||||
import com.stardust.scriptdroid.autojs.AutoJs;
|
||||
import com.stardust.scriptdroid.external.floating_window.FloatingWindowManger;
|
||||
import com.stardust.scriptdroid.external.floating_window.HoverMenuService;
|
||||
import com.stardust.scriptdroid.service.AccessibilityWatchDogService;
|
||||
@@ -124,7 +124,7 @@ public class SlideMenuFragment extends Fragment {
|
||||
|
||||
@ViewBinding.Click(R.id.stop_all_running_scripts)
|
||||
private void stopAllRunningScripts() {
|
||||
int n = Droid.getInstance().stopAll();
|
||||
int n = AutoJs.getInstance().getScriptEngineService().stopAll();
|
||||
if (n > 0)
|
||||
Snackbar.make(getView(), String.format(getString(R.string.text_already_stop_n_scripts), n), Snackbar.LENGTH_SHORT).show();
|
||||
else
|
||||
|
||||
@@ -13,10 +13,10 @@ import android.widget.EditText;
|
||||
import com.afollestad.materialdialogs.DialogAction;
|
||||
import com.afollestad.materialdialogs.MaterialDialog;
|
||||
import com.stardust.app.Fragment;
|
||||
import com.stardust.scriptdroid.scripts.ScriptFile;
|
||||
import com.stardust.pio.PFile;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.droid.script.file.ScriptFile;
|
||||
import com.stardust.scriptdroid.scripts.StorageScriptProvider;
|
||||
import com.stardust.scriptdroid.tool.FileUtils;
|
||||
import com.stardust.scriptdroid.ui.main.operation.ScriptFileOperation;
|
||||
import com.stardust.theme.dialog.ThemeColorMaterialDialogBuilder;
|
||||
import com.stardust.view.ViewBinder;
|
||||
@@ -25,8 +25,6 @@ import com.stardust.widget.SimpleAdapterDataObserver;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import me.zhanghai.android.materialprogressbar.MaterialProgressBar;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/3/13.
|
||||
*/
|
||||
@@ -125,9 +123,9 @@ public class MyScriptListFragment extends Fragment {
|
||||
}
|
||||
|
||||
public void createScriptFile(String path, String script) {
|
||||
if (FileUtils.createFileIfNotExists(path)) {
|
||||
if (PFile.createIfNotExists(path)) {
|
||||
if (script != null) {
|
||||
if (!FileUtils.writeString(path, script)) {
|
||||
if (!PFile.write(path, script)) {
|
||||
Snackbar.make(getView(), R.string.text_file_write_fail, Snackbar.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
@@ -143,14 +141,14 @@ public class MyScriptListFragment extends Fragment {
|
||||
}
|
||||
|
||||
public void importFile(final String pathFrom) {
|
||||
showFileNameInputDialog(FileUtils.getNameWithoutExtension(pathFrom), new MaterialDialog.InputCallback() {
|
||||
showFileNameInputDialog(PFile.getNameWithoutExtension(pathFrom), new MaterialDialog.InputCallback() {
|
||||
@Override
|
||||
public void onInput(@NonNull MaterialDialog dialog, CharSequence input) {
|
||||
final String pathTo = getCurrentDirectoryPath() + input + ".js";
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (FileUtils.copy(pathFrom, pathTo)) {
|
||||
if (PFile.copy(pathFrom, pathTo)) {
|
||||
showMessage(R.string.text_import_succeed);
|
||||
} else {
|
||||
showMessage(R.string.text_import_fail);
|
||||
@@ -204,7 +202,7 @@ public class MyScriptListFragment extends Fragment {
|
||||
getActivity().runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
StorageScriptProvider.getInstance().notifyDirectoryChanged(getCurrentDirectory());
|
||||
StorageScriptProvider.getDefault().notifyDirectoryChanged(getCurrentDirectory());
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -282,7 +280,7 @@ public class MyScriptListFragment extends Fragment {
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (FileUtils.deleteAll(mSelectedScriptFile)) {
|
||||
if (PFile.deleteRecursively(mSelectedScriptFile)) {
|
||||
showMessage(R.string.text_already_delete);
|
||||
notifyScriptFileChanged();
|
||||
} else {
|
||||
|
||||
@@ -14,8 +14,11 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.stardust.autojs.script.FileScriptSource;
|
||||
import com.stardust.scriptdroid.autojs.AutoJs;
|
||||
import com.stardust.scriptdroid.scripts.ScriptFile;
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.droid.script.file.ScriptFile;
|
||||
import com.stardust.scriptdroid.scripts.StorageScriptProvider;
|
||||
import com.stardust.scriptdroid.ui.main.operation.ScriptFileOperation;
|
||||
|
||||
@@ -71,7 +74,8 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
int position = getChildViewHolder((View) v.getParent()).getAdapterPosition();
|
||||
mScriptFileList[getActualPosition(position)].run();
|
||||
ScriptFile file = mScriptFileList[getActualPosition(position)];
|
||||
AutoJs.getInstance().getScriptEngineService().execute(new FileScriptSource(file));
|
||||
}
|
||||
};
|
||||
private OnClickListener mOnEditClickListener = new OnClickListener() {
|
||||
@@ -88,6 +92,7 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView {
|
||||
private ScriptFile mRootFolder;
|
||||
private Adapter mAdapter;
|
||||
private boolean mCanGoBack;
|
||||
private StorageScriptProvider mStorageScriptProvider = StorageScriptProvider.getDefault();
|
||||
|
||||
public ScriptAndFolderListRecyclerView(Context context) {
|
||||
super(context);
|
||||
@@ -106,16 +111,20 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView {
|
||||
|
||||
private void setCurrentFolder(ScriptFile folder, boolean canGoBack) {
|
||||
mCurrentFolder = folder;
|
||||
mScriptFileList = StorageScriptProvider.getInstance().getDirectoryScriptFiles(folder);
|
||||
mScriptFileList = mStorageScriptProvider.getDirectoryScriptFiles(folder);
|
||||
mCanGoBack = canGoBack;
|
||||
mAdapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public void setRootFolder(ScriptFile folder) {
|
||||
private void setRootFolder(ScriptFile folder) {
|
||||
mRootFolder = folder;
|
||||
setCurrentFolder(mRootFolder, false);
|
||||
}
|
||||
|
||||
public void setStorageScriptProvider(StorageScriptProvider storageScriptProvider) {
|
||||
mStorageScriptProvider = storageScriptProvider;
|
||||
}
|
||||
|
||||
public void setOnItemClickListener(OnScriptFileClickListener onItemClickListener) {
|
||||
mOnItemClickListener = onItemClickListener;
|
||||
}
|
||||
@@ -138,7 +147,7 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView {
|
||||
addItemDecoration(new DividerItemDecoration(getContext(), VERTICAL));
|
||||
mAdapter = new Adapter();
|
||||
setAdapter(mAdapter);
|
||||
setRootFolder(ScriptFile.DEFAULT_DIRECTORY);
|
||||
setRootFolder(mStorageScriptProvider.getInitialDirectory());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -162,13 +171,13 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView {
|
||||
@Override
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
StorageScriptProvider.getInstance().registerDirectoryChangeListener(this);
|
||||
mStorageScriptProvider.registerDirectoryChangeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow();
|
||||
StorageScriptProvider.getInstance().unregisterDirectoryChangeListener(this);
|
||||
mStorageScriptProvider.unregisterDirectoryChangeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.stardust.scriptdroid.ui.main.my_script_list;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Environment;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v7.widget.DividerItemDecoration;
|
||||
@@ -12,21 +11,16 @@ import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.stardust.scriptdroid.droid.script.file.ScriptFile;
|
||||
import com.stardust.scriptdroid.droid.script.file.ScriptFileList;
|
||||
import com.stardust.scriptdroid.tool.ViewTool;
|
||||
import com.stardust.scriptdroid.scripts.ScriptFile;
|
||||
import com.stardust.scriptdroid.scripts.ScriptFileList;
|
||||
import com.stardust.util.ViewUtil;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.ui.main.operation.ScriptFileOperation;
|
||||
import com.stardust.scriptdroid.ui.main.operation.ScriptFileOperationPopupMenu;
|
||||
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/1/23.
|
||||
*/
|
||||
@@ -147,8 +141,8 @@ public class ScriptListRecyclerView extends ThemeColorRecyclerView {
|
||||
super(itemView);
|
||||
name = (TextView) itemView.findViewById(R.id.name);
|
||||
path = (TextView) itemView.findViewById(R.id.path);
|
||||
ViewTool.$(itemView, R.id.edit).setOnClickListener(mOnEditIconClickListener);
|
||||
ViewTool.$(itemView, R.id.run).setOnClickListener(mOnRunIconClickListener);
|
||||
ViewUtil.$(itemView, R.id.edit).setOnClickListener(mOnEditIconClickListener);
|
||||
ViewUtil.$(itemView, R.id.run).setOnClickListener(mOnRunIconClickListener);
|
||||
itemView.setOnClickListener(mOnItemClickListenerProxy);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
package com.stardust.scriptdroid.ui.main.operation;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
|
||||
import com.afollestad.materialdialogs.MaterialDialog;
|
||||
import com.stardust.scriptdroid.droid.script.file.ScriptFile;
|
||||
import com.stardust.scriptdroid.droid.script.file.ScriptFileList;
|
||||
import com.stardust.autojs.script.FileScriptSource;
|
||||
import com.stardust.scriptdroid.autojs.AutoJs;
|
||||
import com.stardust.scriptdroid.scripts.ScriptFile;
|
||||
import com.stardust.scriptdroid.scripts.ScriptFileList;
|
||||
import com.stardust.scriptdroid.external.CommonUtils;
|
||||
import com.stardust.scriptdroid.external.shortcut.Shortcut;
|
||||
import com.stardust.scriptdroid.external.shortcut.ShortcutActivity;
|
||||
@@ -39,7 +40,7 @@ public abstract class ScriptFileOperation {
|
||||
App.getApp().startActivity(new Intent(Intent.ACTION_VIEW).setDataAndType(uri, "text/plain").addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
|
||||
}
|
||||
|
||||
public static void createShortcut(ScriptFile scriptFile){
|
||||
public static void createShortcut(ScriptFile scriptFile) {
|
||||
new Shortcut(App.getApp()).name(scriptFile.getSimplifiedName())
|
||||
.targetClass(ShortcutActivity.class)
|
||||
.icon(R.drawable.ic_robot_green)
|
||||
@@ -82,7 +83,7 @@ public abstract class ScriptFileOperation {
|
||||
public void operate(RecyclerView recyclerView, ScriptFileList scriptFileList, int position) {
|
||||
EventBus.getDefault().post(new ShowMessageEvent(R.string.text_start_running));
|
||||
ScriptFile scriptFile = scriptFileList.get(position);
|
||||
scriptFile.run();
|
||||
AutoJs.getInstance().getScriptEngineService().execute(new FileScriptSource(scriptFile));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.stardust.scriptdroid.ui.main.operation;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.support.annotation.Nullable;
|
||||
@@ -18,7 +17,7 @@ import android.widget.ImageView;
|
||||
import android.widget.PopupWindow;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.stardust.scriptdroid.tool.ViewTool;
|
||||
import com.stardust.util.ViewUtil;
|
||||
import com.stardust.scriptdroid.R;
|
||||
|
||||
import java.util.List;
|
||||
@@ -99,7 +98,7 @@ public class ScriptFileOperationPopupMenu extends PopupWindow {
|
||||
private void initContentView() {
|
||||
View contentView = View.inflate(mContext, R.layout.script_file_operation_popup_menu_content, null);
|
||||
setContentView(contentView);
|
||||
mOperationListRecyclerView = ViewTool.$(contentView, R.id.operation_list);
|
||||
mOperationListRecyclerView = ViewUtil.$(contentView, R.id.operation_list);
|
||||
mOperationListRecyclerView.setOnItemClickListener(mOnItemClickRealListener);
|
||||
mOperationListRecyclerView.setScriptFileOperationList(mScriptFileOperationList);
|
||||
}
|
||||
@@ -165,8 +164,8 @@ public class ScriptFileOperationPopupMenu extends PopupWindow {
|
||||
ViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
itemView.setOnClickListener(mOnItemClickListener);
|
||||
operationName = ViewTool.$(itemView, R.id.name);
|
||||
icon = ViewTool.$(itemView, R.id.icon);
|
||||
operationName = ViewUtil.$(itemView, R.id.name);
|
||||
icon = ViewUtil.$(itemView, R.id.icon);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,12 +9,13 @@ import android.view.ViewGroup;
|
||||
|
||||
import com.afollestad.materialdialogs.MaterialDialog;
|
||||
import com.stardust.app.Fragment;
|
||||
import com.stardust.scriptdroid.scripts.ScriptFile;
|
||||
import com.stardust.scriptdroid.scripts.ScriptFileList;
|
||||
import com.stardust.pio.PFile;
|
||||
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.scripts.StorageScriptProvider;
|
||||
import com.stardust.scriptdroid.scripts.sample.Sample;
|
||||
import com.stardust.scriptdroid.scripts.sample.SampleFileManager;
|
||||
import com.stardust.scriptdroid.tool.FileUtils;
|
||||
import com.stardust.scriptdroid.ui.edit.EditActivity;
|
||||
import com.stardust.scriptdroid.ui.main.my_script_list.MyScriptListFragment;
|
||||
import com.stardust.util.MessageEvent;
|
||||
@@ -69,8 +70,8 @@ public class SampleScriptListFragment extends Fragment {
|
||||
}
|
||||
|
||||
private void copySampleToMyScripts(Sample sample) {
|
||||
String path = ScriptFile.DEFAULT_DIRECTORY_PATH + sample.name + ".js";
|
||||
if (!ScriptFileList.getImpl().containsPath(path) && FileUtils.copyAsset(sample.path, path)) {
|
||||
String path = StorageScriptProvider.DEFAULT_DIRECTORY_PATH + sample.name + ".js";
|
||||
if (!ScriptFileList.getImpl().containsPath(path) && PFile.copyAsset(getActivity(), sample.path, path)) {
|
||||
ScriptFileList.getImpl().add(new ScriptFile(path));
|
||||
EventBus.getDefault().post(new MessageEvent(MyScriptListFragment.MESSAGE_SCRIPT_FILE_ADDED));
|
||||
Snackbar.make(mSampleScriptListRecyclerView, R.string.text_import_succeed, Snackbar.LENGTH_SHORT).show();
|
||||
|
||||
@@ -12,9 +12,9 @@ import android.widget.Toast;
|
||||
|
||||
import com.afollestad.materialdialogs.DialogAction;
|
||||
import com.afollestad.materialdialogs.MaterialDialog;
|
||||
import com.stardust.scriptdroid.tool.IntentTool;
|
||||
import com.stardust.scriptdroid.ui.BaseActivity;
|
||||
import com.stardust.theme.dialog.ThemeColorMaterialDialogBuilder;
|
||||
import com.stardust.util.IntentUtil;
|
||||
import com.stardust.view.ViewBinding;
|
||||
import com.stardust.scriptdroid.BuildConfig;
|
||||
import com.stardust.scriptdroid.R;
|
||||
@@ -51,7 +51,7 @@ public class AboutActivity extends BaseActivity {
|
||||
|
||||
@ViewBinding.Click(R.id.github)
|
||||
private void openGitHub() {
|
||||
if (!IntentTool.goToLink(this, getString(R.string.my_github))) {
|
||||
if (!IntentUtil.browse(this, getString(R.string.my_github))) {
|
||||
Toast.makeText(this, R.string.text_no_brower, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
@@ -59,7 +59,7 @@ public class AboutActivity extends BaseActivity {
|
||||
@ViewBinding.Click(R.id.qq)
|
||||
private void openQQToChatWithMe() {
|
||||
String qq = getString(R.string.qq);
|
||||
if (!IntentTool.goToQQ(this, qq)) {
|
||||
if (!IntentUtil.chatWithQQ(this, qq)) {
|
||||
Toast.makeText(this, R.string.text_mobile_qq_not_installed, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
@@ -67,7 +67,7 @@ public class AboutActivity extends BaseActivity {
|
||||
@ViewBinding.Click(R.id.email)
|
||||
private void openEmailToSendMe() {
|
||||
String email = getString(R.string.email);
|
||||
IntentTool.goToMail(this, email);
|
||||
IntentUtil.sendMailTo(this, email);
|
||||
}
|
||||
|
||||
|
||||
@@ -93,7 +93,7 @@ public class AboutActivity extends BaseActivity {
|
||||
|
||||
@ViewBinding.Click(R.id.share)
|
||||
private void share() {
|
||||
IntentTool.shareText(this, getString(R.string.share_app));
|
||||
IntentUtil.shareText(this, getString(R.string.share_app));
|
||||
}
|
||||
|
||||
@ViewBinding.Click(R.id.icon)
|
||||
|
||||
@@ -11,9 +11,9 @@ import android.view.View;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.stardust.scriptdroid.Pref;
|
||||
import com.stardust.scriptdroid.tool.IntentTool;
|
||||
import com.stardust.scriptdroid.ui.BaseActivity;
|
||||
import com.stardust.scriptdroid.ui.error.IssueReportActivity;
|
||||
import com.stardust.util.IntentUtil;
|
||||
import com.stardust.util.MapEntries;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.theme.app.ColorSelectActivity;
|
||||
@@ -122,7 +122,7 @@ public class SettingsActivity extends BaseActivity {
|
||||
.entry(getString(R.string.text_join_qq_group), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!IntentTool.joinQQGroup(getActivity(), "vjHXzZlpGcXNe-YEWzQ85mm_z8y-curC")) {
|
||||
if (!IntentUtil.joinQQGroup(getActivity(), "vjHXzZlpGcXNe-YEWzQ85mm_z8y-curC")) {
|
||||
Toast.makeText(getActivity(), R.string.text_mobile_qq_not_installed, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
package com.stardust.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.AssetManager;
|
||||
|
||||
import com.stardust.scriptdroid.tool.FileUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/3/14.
|
||||
*/
|
||||
|
||||
public class AssetsCache {
|
||||
|
||||
private Map<String, String> mCache = new HashMap<>();
|
||||
|
||||
|
||||
public String read(AssetManager manager, String path) throws IOException {
|
||||
String str = mCache.get(path);
|
||||
if (str == null) {
|
||||
str = FileUtils.readString(manager.open(path));
|
||||
mCache.put(path, str);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
package com.stardust.util;
|
||||
|
||||
import com.stardust.scriptdroid.scripts.StorageScriptProvider;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/3/31.
|
||||
*/
|
||||
|
||||
public class FileSorter {
|
||||
|
||||
public static void sort(File[] files) {
|
||||
Arrays.sort(files, new Comparator<File>() {
|
||||
@Override
|
||||
public int compare(File o1, File o2) {
|
||||
if (o1.isDirectory() != o2.isDirectory())
|
||||
return o1.isDirectory() ? Integer.MIN_VALUE : Integer.MAX_VALUE;
|
||||
return o1.getName().compareTo(o2.getName());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static class TestSuite {
|
||||
|
||||
@Test
|
||||
public void testEngFileSort() {
|
||||
File file1 = new File("d:/a.txt");
|
||||
File file2 = new File("e:/b.txt");
|
||||
File file3 = new File("c:/c.txt");
|
||||
File[] files = {file2, file3, file1};
|
||||
sort(files);
|
||||
Assert.assertArrayEquals(new File[]{file1, file2, file3}, files);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEngFileSortWithDirectory() {
|
||||
File dir1 = new File("d:/");
|
||||
File dir2 = new File("e:/");
|
||||
File file1 = new File("e:/a.txt");
|
||||
File file2 = new File("e:/b.txt");
|
||||
File file3 = new File("d:/c.txt");
|
||||
Assert.assertTrue(dir1.isDirectory());
|
||||
Assert.assertTrue(dir2.isDirectory());
|
||||
File[] files = {file2, file3, dir1, file1, dir2};
|
||||
sort(files);
|
||||
Assert.assertArrayEquals(new File[]{dir1, dir2, file1, file2, file3}, files);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCnFileSort() {
|
||||
File file1 = new File("a.txt");
|
||||
File file2 = new File("b.txt");
|
||||
File file3 = new File("啊.txt");
|
||||
File file4 = new File("啊啊.txt");
|
||||
File[] files = {file2, file4, file3, file1};
|
||||
sort(files);
|
||||
Assert.assertArrayEquals(new File[]{file1, file2, file3, file4}, files);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCnFileSortWithDirectory() {
|
||||
File dir1 = new File("d:/整理/");
|
||||
File dir2 = new File("d:/迅雷下载/");
|
||||
File file1 = new File("d:/整理/a.txt");
|
||||
File file2 = new File("啊.txt");
|
||||
File file3 = new File("啊啊.txt");
|
||||
Assert.assertTrue(dir1.isDirectory());
|
||||
Assert.assertTrue(dir2.isDirectory());
|
||||
File[] files = {file2, file3, dir1, file1, dir2};
|
||||
sort(files);
|
||||
Assert.assertArrayEquals(new File[]{dir1, dir2, file1, file2, file3}, files);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
package com.stardust.util;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.Uri;
|
||||
import android.widget.Toast;
|
||||
|
||||
import static com.stardust.scriptdroid.tool.IntentTool.goToAppSetting;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/3/10.
|
||||
*/
|
||||
|
||||
public class FloatingWindowUtils {
|
||||
|
||||
public static boolean checkFloatingWindowPermission(Context context, int messageResId) {
|
||||
if (!isFloatingWindowPermitted(context)) {
|
||||
Toast.makeText(context, messageResId, Toast.LENGTH_SHORT).show();
|
||||
goToAppSetting(context, context.getPackageName());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean isFloatingWindowPermitted(Context context) {
|
||||
PackageManager pm = context.getPackageManager();
|
||||
return pm.checkPermission(Manifest.permission.SYSTEM_ALERT_WINDOW, context.getPackageName())
|
||||
== PackageManager.PERMISSION_GRANTED;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
package com.stardust.util;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/3/31.
|
||||
*/
|
||||
|
||||
public class LimitedHashMap<K, V> extends LinkedHashMap<K, V> {
|
||||
|
||||
private int mMaxSize;
|
||||
|
||||
public LimitedHashMap(int maxSize) {
|
||||
super(4, 0.75f, true);
|
||||
mMaxSize = maxSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean removeEldestEntry(Entry<K, V> eldest) {
|
||||
return size() > mMaxSize;
|
||||
}
|
||||
|
||||
|
||||
public static class TestSuite {
|
||||
|
||||
@Test
|
||||
public void testAutoRemove() {
|
||||
LimitedHashMap<String, Integer> hashMap = new LimitedHashMap<>(5);
|
||||
hashMap.put("a", 1);
|
||||
hashMap.put("b", 2);
|
||||
hashMap.put("c", 3);
|
||||
hashMap.put("d", 4);
|
||||
hashMap.put("e", 5);
|
||||
hashMap.put("f", 6);
|
||||
assertFalse(hashMap.containsKey("a"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAutoReorder() {
|
||||
LimitedHashMap<String, Integer> hashMap = new LimitedHashMap<>(5);
|
||||
hashMap.put("a", 1);
|
||||
hashMap.put("b", 2);
|
||||
hashMap.put("c", 3);
|
||||
hashMap.put("d", 4);
|
||||
hashMap.put("e", 5);
|
||||
hashMap.get("a");
|
||||
hashMap.put("f", 6);
|
||||
assertTrue(hashMap.containsKey("a"));
|
||||
assertFalse(hashMap.containsKey("b"));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package com.stardust.util;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/1/26.
|
||||
*/
|
||||
|
||||
public class MapEntries<K, V> {
|
||||
|
||||
private Map<K, V> mMap;
|
||||
|
||||
public MapEntries() {
|
||||
this(new TreeMap<K, V>());
|
||||
}
|
||||
|
||||
public MapEntries(Map<K, V> map) {
|
||||
mMap = map;
|
||||
}
|
||||
|
||||
public MapEntries<K, V> entry(K key, V value) {
|
||||
mMap.put(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Map<K, V> map() {
|
||||
return mMap;
|
||||
}
|
||||
|
||||
public Map<K, V> putIn(Map<K, V> map) {
|
||||
map.putAll(mMap);
|
||||
return map;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package com.stardust.util;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/3/12.
|
||||
*/
|
||||
|
||||
public class MessageEvent {
|
||||
|
||||
public String message;
|
||||
public Object param;
|
||||
|
||||
public MessageEvent(String message, Object param) {
|
||||
this.message = message;
|
||||
this.param = param;
|
||||
}
|
||||
|
||||
|
||||
public MessageEvent(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
package com.stardust.util;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.support.v7.widget.SwitchCompat;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/2/3.
|
||||
*/
|
||||
|
||||
public class StateObserver {
|
||||
|
||||
public interface OnStateChangedListener {
|
||||
|
||||
void onStateChanged(boolean newState);
|
||||
|
||||
void initState(boolean state);
|
||||
}
|
||||
|
||||
|
||||
public static abstract class SimpleOnStateChangedListener<T> implements OnStateChangedListener {
|
||||
|
||||
@Override
|
||||
public void initState(boolean state) {
|
||||
onStateChanged(state);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private final Map<String, List<OnStateChangedListener>> mKeyStateListenersMap = new HashMap<>();
|
||||
private SharedPreferences mSharedPreferences;
|
||||
|
||||
public StateObserver(SharedPreferences sharedPreferences) {
|
||||
mSharedPreferences = sharedPreferences;
|
||||
}
|
||||
|
||||
public void register(final String key, SwitchCompat switchCompat) {
|
||||
final WeakReference<SwitchCompat> switchCompatWeakReference = new WeakReference<>(switchCompat);
|
||||
register(key, new SimpleOnStateChangedListener() {
|
||||
@Override
|
||||
public void onStateChanged(boolean newState) {
|
||||
if (switchCompatWeakReference.get() != null) {
|
||||
switchCompatWeakReference.get().setChecked(newState);
|
||||
} else {
|
||||
unregister(key, this);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void register(String key, OnStateChangedListener listener) {
|
||||
initState(key, listener);
|
||||
synchronized (mKeyStateListenersMap) {
|
||||
List<OnStateChangedListener> listeners = getListenerListOrCreateIfNotExists(key);
|
||||
listeners.add(listener);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void unregister(String key, OnStateChangedListener stateChangedListener) {
|
||||
synchronized (mKeyStateListenersMap) {
|
||||
List<OnStateChangedListener> listeners = mKeyStateListenersMap.get(key);
|
||||
if (listeners == null) {
|
||||
return;
|
||||
}
|
||||
listeners.remove(stateChangedListener);
|
||||
}
|
||||
}
|
||||
|
||||
public void setState(String key, boolean state) {
|
||||
synchronized (mKeyStateListenersMap) {
|
||||
List<OnStateChangedListener> listeners = mKeyStateListenersMap.get(key);
|
||||
if (listeners == null || listeners.isEmpty())
|
||||
return;
|
||||
mSharedPreferences.edit().putBoolean(key, state).apply();
|
||||
notifyBooleanStateChanged(listeners, state);
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyBooleanStateChanged(List<OnStateChangedListener> listeners, boolean state) {
|
||||
for (OnStateChangedListener listener : listeners) {
|
||||
listener.onStateChanged(state);
|
||||
}
|
||||
}
|
||||
|
||||
private void initState(String key, OnStateChangedListener listener) {
|
||||
if (mSharedPreferences.contains(key)) {
|
||||
listener.initState(mSharedPreferences.getBoolean(key, false));
|
||||
}
|
||||
}
|
||||
|
||||
private List<OnStateChangedListener> getListenerListOrCreateIfNotExists(String key) {
|
||||
List<OnStateChangedListener> listeners = mKeyStateListenersMap.get(key);
|
||||
if (listeners == null) {
|
||||
listeners = new CopyOnWriteArrayList<>();
|
||||
mKeyStateListenersMap.put(key, listeners);
|
||||
}
|
||||
return listeners;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -150,7 +150,7 @@ public class Floaty {
|
||||
*/
|
||||
public static synchronized Floaty getInstance() {
|
||||
if (floaty == null) {
|
||||
throw new NullPointerException("Floaty not initialized! First call createInstance method, then to access Floaty in any other class call getInstance()");
|
||||
throw new NullPointerException("Floaty not initialized! First call createInstance method, then to access Floaty in any other class call getDefault()");
|
||||
}
|
||||
return floaty;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user