fix crash on android5.1 and add console api

This commit is contained in:
hyb1996 2017-02-12 22:43:59 +08:00
parent 6b3a71ef50
commit 564cbb083a
29 changed files with 471 additions and 74 deletions

View File

@ -7,8 +7,8 @@ android {
applicationId "com.stardust.scriptdroid"
minSdkVersion 19
targetSdkVersion 23
versionCode 10
versionName "0.17.02050预览版"
versionCode 20
versionName "1.17.0212"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
@ -46,6 +46,8 @@ dependencies {
compile 'com.furture.react:DuktapeJava:1.1.0'
compile 'com.zzhoujay.markdown:markdown:1.0.2'
compile 'moe.feng:AlipayZeroSdk:1.1'
compile 'com.jraska:console:0.4.3'
compile 'com.jraska:console-timber-tree:0.4.3'
compile files('libs/JSTransformer.jar')
@ -57,5 +59,4 @@ dependencies {
compile(name:'920-file_explorer-release', ext:'aar')
compile(name:'920-app-debug', ext:'aar')
}

Binary file not shown.

View File

@ -75,6 +75,7 @@
<activity android:name=".DocumentActivity"/>
<activity android:name=".AboutActivity"/>
<activity android:name=".SettingsActivity"/>
<activity android:name=".droid.ConsoleActivity"/>
<activity android:name=".ErrorReportActivity"/>
<activity android:name=".droid.script.ScriptExecuteActivity"/>

View File

@ -42,6 +42,8 @@ var longClick = function(a, b, c, d){
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);
@ -49,8 +51,10 @@ var scrollUp = function(a, b, c, d){
var scrollDown = function(a, b, c, d){
if(arguments.length == 0)
return droid.scrollAllDown();
return performAction(function(target){
return droid.scrollAllDown();
if(arguments.length == 1 && typeof a === 'number')
return droid.scrollDown(a);
return performAction(function(target){
return droid.scrollDown(target);
}, arguments);
}
@ -97,3 +101,18 @@ var notStopped = function(){
return !isStopped();
}
var log = function(str){
droid.log(str);
}
var err = function(e){
droid.err(e);
}
var openConsole = function(){
droid.console();
}
var clearConsole = function(){
droid.clearConsole();
}

View File

@ -1,10 +1,14 @@
package com.stardust.scriptdroid;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@ -18,9 +22,13 @@ import static android.content.pm.PackageManager.PERMISSION_GRANTED;
public class BaseActivity extends AppCompatActivity {
protected static final int PERMISSION_REQUEST_CODE = 11186;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@SuppressWarnings("unchecked")
public <T extends View> T $(int resId) {
return (T) findViewById(resId);
@ -49,4 +57,18 @@ public class BaseActivity extends AppCompatActivity {
return list.toArray(new String[list.size()]);
}
public void setToolbarAsBack(String title) {
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.setTitle(title);
setSupportActionBar(toolbar);
if (getSupportActionBar() != null) {
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
}
}

View File

@ -94,6 +94,7 @@ public class MainActivity extends BaseActivity implements FileChooserDialog.File
setUpToolbar();
setUpScriptList();
ViewBinder.bind(this);
}
private void setUpToolbar() {

View File

@ -0,0 +1,74 @@
package com.stardust.scriptdroid.droid;
import android.content.Context;
import android.graphics.Color;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;
import com.jraska.console.Console;
import com.stardust.scriptdroid.BaseActivity;
import com.stardust.scriptdroid.R;
/**
* Created by Stardust on 2017/2/12.
*/
public class ConsoleActivity extends BaseActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setUpUI();
}
private void setUpUI() {
setContentView(R.layout.activity_console);
setToolbarAsBack(getString(R.string.text_console));
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_console, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
Console.clear();
return super.onOptionsItemSelected(item);
}
public static class ConsoleView extends Console {
public ConsoleView(Context context) {
super(context);
init();
}
public ConsoleView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public ConsoleView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public ConsoleView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
private void init() {
findViewById(R.id.console_scroll_view).setBackgroundColor(Color.WHITE);
((TextView) findViewById(R.id.console_text)).setTextIsSelectable(true);
}
}
}

View File

@ -1,9 +1,8 @@
package com.stardust.scriptdroid.droid;
import android.app.Activity;
import android.content.DialogInterface;
import com.afollestad.materialdialogs.MaterialDialog;
import com.jraska.console.timber.ConsoleTree;
import com.stardust.scriptdroid.App;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.droid.runtime.DroidRuntime;
@ -15,12 +14,20 @@ import com.stardust.scriptdroid.file.FileUtils;
import java.io.File;
import java.io.FileNotFoundException;
import timber.log.Timber;
/**
* Created by Stardust on 2017/1/23.
*/
public class Droid {
static {
Timber.plant(new ConsoleTree.Builder()
.infoColor(0xcc000000)
.build());
}
public static final String UI = "\"ui\";";
public interface OnRunFinishedListener {
@ -34,6 +41,7 @@ public class Droid {
public void onRunFinished(Object result, Exception e) {
if (e != null) {
RUNTIME.toast(App.getApp().getString(R.string.text_error) + ": " + e.getMessage());
Timber.e(App.getApp().getString(R.string.text_error), e);
}
}
};

View File

@ -5,12 +5,15 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.graphics.Rect;
import android.os.Handler;
import android.support.annotation.Nullable;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.Toast;
import com.afollestad.materialdialogs.MaterialDialog;
import com.jraska.console.Console;
import com.stardust.scriptdroid.App;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.droid.ConsoleActivity;
import com.stardust.scriptdroid.droid.runtime.action.Action;
import com.stardust.scriptdroid.droid.runtime.action.ActionFactory;
import com.stardust.scriptdroid.droid.runtime.action.ActionPerformService;
@ -19,6 +22,8 @@ import com.stardust.scriptdroid.droid.runtime.api.IDroidRuntime;
import java.util.List;
import timber.log.Timber;
;
/**
@ -30,7 +35,7 @@ public class DroidRuntime implements IDroidRuntime {
private static final String TAG = "DroidRuntime";
private static DroidRuntime runtime = new DroidRuntime();
private final Object mLock = new Object();
private final Object mActionPerformLock = new Object();
private boolean mActionPerformResult;
private Handler mUIHandler;
@ -105,12 +110,22 @@ public class DroidRuntime implements IDroidRuntime {
return performAction(target.createAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD));
}
@Override
public boolean scrollUp(int i) {
return performAction(ActionFactory.createScrollAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD, i));
}
@Override
public boolean scrollDown(int i) {
return performAction(ActionFactory.createScrollAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD, i));
}
public boolean scrollAllUp() {
return performAction(ActionFactory.createScrollAllAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD));
return performAction(ActionFactory.createScrollMaxAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD));
}
public boolean scrollAllDown() {
return performAction(ActionFactory.createScrollAllAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD));
return performAction(ActionFactory.createScrollMaxAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD));
}
@Override
@ -133,6 +148,21 @@ public class DroidRuntime implements IDroidRuntime {
return performAction(target.createAction(AccessibilityNodeInfo.ACTION_PASTE));
}
public void log(@Nullable Object str) {
Timber.i("" + str);
}
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 boolean performAction(Action action) {
if (ActionPerformService.getInstance() == null) {
@ -140,9 +170,9 @@ public class DroidRuntime implements IDroidRuntime {
throw new ScriptStopException(App.getApp().getString(R.string.text_no_accessibility_permission));
}
ActionPerformService.setAction(action);
synchronized (mLock) {
synchronized (mActionPerformLock) {
try {
mLock.wait();
mActionPerformLock.wait();
} catch (InterruptedException e) {
ActionPerformService.setActions(ActionPerformService.NO_ACTION);
throw new ScriptStopException(App.getApp().getString(R.string.text_script_stopped), e);
@ -161,7 +191,6 @@ public class DroidRuntime implements IDroidRuntime {
});
}
@Override
public void sleep(long millis) {
try {
@ -207,8 +236,8 @@ public class DroidRuntime implements IDroidRuntime {
public void notifyActionPerformed(boolean succeed) {
mActionPerformResult = succeed;
synchronized (mLock) {
mLock.notify();
synchronized (mActionPerformLock) {
mActionPerformLock.notify();
}
}

View File

@ -50,7 +50,11 @@ public class ActionFactory {
};
}
public static Action createScrollAllAction(int action) {
return new ScrollAllAction(action);
public static Action createScrollMaxAction(int action) {
return new ScrollMaxAction(action);
}
public static Action createScrollAction(int action, int i){
return new ScrollAction(action, i);
}
}

View File

@ -24,7 +24,7 @@ import java.util.List;
public class ActionPerformService extends AccessibilityService {
private static final String TAG = "ActionPerformService";
private static ActionPerformService instance;
private static volatile ActionPerformService instance;
@SuppressWarnings("unchecked")
public static final List<Action> NO_ACTION = Collections.EMPTY_LIST;
@ -98,17 +98,22 @@ public class ActionPerformService extends AccessibilityService {
@Override
public void onServiceConnected() {
// FIXME: 2017/2/12 有时在无障碍中开启服务后这里不会调用服务也不会运行安卓的BUG???
Log.v(TAG, "onServiceConnected");
}
@Override
public void onCreate() {
super.onCreate();
Log.v(TAG, "onCreate");
instance = this;
}
public static void disable() {
if (instance != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
instance.disableSelf();
} else {
AccessibilityServiceUtils.goToAccessibilitySetting(App.getApp());
}
if (instance != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
instance.disableSelf();
} else {
AccessibilityServiceUtils.goToAccessibilitySetting(App.getApp());
}
}

View File

@ -0,0 +1,57 @@
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();
}
}

View File

@ -1,38 +0,0 @@
package com.stardust.scriptdroid.droid.runtime.action;
import android.view.accessibility.AccessibilityNodeInfo;
/**
* Created by Stardust on 2017/1/27.
*/
public class ScrollAllAction extends Action {
private int mScrollAction;
public ScrollAllAction(int scrollAction) {
mScrollAction = scrollAction;
}
@Override
public boolean perform(AccessibilityNodeInfo rootNodeInfo) {
AccessibilityNodeInfo scrollableNodeInfo = findScrollableNodeInfo(rootNodeInfo);
return scrollableNodeInfo != null && scrollableNodeInfo.performAction(mScrollAction);
}
private AccessibilityNodeInfo findScrollableNodeInfo(AccessibilityNodeInfo nodeInfo) {
if (nodeInfo == null)
return null;
if (nodeInfo.isScrollable()) {
return nodeInfo;
}
for (int i = 0; i < nodeInfo.getChildCount(); i++) {
AccessibilityNodeInfo node = findScrollableNodeInfo(nodeInfo.getChild(i));
if (node != null) {
return node;
}
}
return null;
}
}

View File

@ -0,0 +1,70 @@
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;
}
}

View File

@ -30,6 +30,10 @@ public interface IDroidRuntime {
boolean scrollDown(ActionTarget target);
boolean scrollUp(int i);
boolean scrollDown(int i);
boolean focus(ActionTarget target);
boolean select(ActionTarget target);

View File

@ -26,7 +26,7 @@ public class ScriptExecuteActivity extends Activity {
ScriptExecuteActivity.script = script;
ScriptExecuteActivity.onRunFinishedListener = listener;
ScriptExecuteActivity.runningConfig = config;
App.getApp().startActivity(new Intent(App.getApp(), ScriptExecuteActivity.class));
App.getApp().startActivity(new Intent(App.getApp(), ScriptExecuteActivity.class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
}
@Override

View File

@ -12,6 +12,7 @@ import android.view.ViewGroup;
import com.stardust.scriptdroid.App;
import com.stardust.scriptdroid.DocumentActivity;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.droid.ConsoleActivity;
import com.stardust.scriptdroid.droid.assist.BoundsAssistant;
import com.stardust.view.ViewBinder;
import com.stardust.view.ViewBinding;
@ -86,6 +87,11 @@ public class EditSideMenuFragment extends com.stardust.app.Fragment {
startActivity(new Intent(getContext(), DocumentActivity.class));
}
@ViewBinding.Click(R.id.console)
private void startConsoleActivity() {
startActivity(new Intent(getContext(), ConsoleActivity.class));
}
@ViewBinding.Check(R.id.sw_assist_service)
private void setAssistServiceEnable(boolean enable) {
BoundsAssistant.setAssistModeEnable(enable);

View File

@ -14,6 +14,7 @@ import com.stardust.app.Fragment;
import com.stardust.scriptdroid.App;
import com.stardust.scriptdroid.DocumentActivity;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.droid.ConsoleActivity;
import com.stardust.scriptdroid.droid.Droid;
import com.stardust.scriptdroid.droid.assist.BoundsAssistant;
import com.stardust.scriptdroid.droid.runtime.action.ActionPerformService;
@ -72,6 +73,12 @@ public class SlideMenuFragment extends Fragment {
App.getStateObserver().register(KEY_ASSIST_MODE_NOTIFICATION, mAssistServiceNotificationSwitch);
}
@ViewBinding.Click(R.id.console)
private void startConsoleActivity() {
startActivity(new Intent(getContext(), ConsoleActivity.class));
}
@ViewBinding.Click(R.id.syntax_and_api)
private void startSyntaxHelpActivity() {
startActivity(new Intent(getContext(), DocumentActivity.class));

View File

@ -17,6 +17,8 @@ import java.lang.Thread.UncaughtExceptionHandler;
public class CrashHandler implements UncaughtExceptionHandler {
private static final String TAG = "CrashHandler";
private static int crashCount = 0;
private static long firstCrashMillis = 0;
private final Class<?> mErrorReportClass;
public CrashHandler(Class<?> errorReportClass) {
@ -26,16 +28,40 @@ public class CrashHandler implements UncaughtExceptionHandler {
public void uncaughtException(Thread thread, Throwable ex) {
try {
Log.e(TAG, "Uncaught Exception", ex);
String t = App.getApp().getString(R.string.sorry_for_crash) + ex.toString();
Intent intent = new Intent(App.getApp(), this.mErrorReportClass);
intent.putExtra("message", t);
intent.putExtra("error", throwableToString(ex));
App.getApp().startActivity(intent);
if (crashTooManyTimes())
return;
String msg = App.getApp().getString(R.string.sorry_for_crash) + ex.toString();
startErrorReportActivity(msg, throwableToString(ex));
System.exit(0);
} catch (Throwable var6) {
var6.printStackTrace();
} catch (Throwable throwable) {
throwable.printStackTrace();
}
}
private void startErrorReportActivity(String msg, String detail) {
Intent intent = new Intent(App.getApp(), this.mErrorReportClass);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
intent.putExtra("message", msg);
intent.putExtra("error", detail);
App.getApp().startActivity(intent);
}
private boolean crashTooManyTimes() {
if (crashIntervalTooLong()) {
resetCrashCount();
return false;
}
crashCount++;
return crashCount >= 5;
}
private void resetCrashCount() {
firstCrashMillis = System.currentTimeMillis();
crashCount = 0;
}
private boolean crashIntervalTooLong() {
return System.currentTimeMillis() - firstCrashMillis > 3000;
}
public static String throwableToString(Throwable throwable) {

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 37 KiB

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay"/>
</android.support.design.widget.AppBarLayout>
<view
android:id="@+id/console"
class="com.stardust.scriptdroid.droid.ConsoleActivity$ConsoleView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>

View File

@ -5,6 +5,28 @@
android:orientation="vertical"
android:textSize="16sp">
<LinearLayout
android:id="@+id/console"
android:layout_width="match_parent"
android:layout_height="52dp"
android:background="?selectableItemBackground"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_margin="16dp"
android:src="@drawable/ic_console_green"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:text="@string/text_console"
android:textColor="@android:color/primary_text_light"/>
</LinearLayout>
<LinearLayout
android:id="@+id/syntax_and_api"
android:layout_width="match_parent"
@ -27,6 +49,7 @@
android:textColor="@android:color/primary_text_light"/>
</LinearLayout>
<RelativeLayout
android:id="@+id/assist_service"
android:layout_width="match_parent"

View File

@ -5,6 +5,28 @@
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:id="@+id/console"
android:layout_width="match_parent"
android:layout_height="52dp"
android:background="?selectableItemBackground"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_margin="16dp"
android:src="@drawable/ic_console_green"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:text="@string/text_console"
android:textColor="@android:color/primary_text_light"/>
</LinearLayout>
<LinearLayout
android:id="@+id/syntax_and_api"
android:layout_width="match_parent"

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:orderInCategory="100"
android:title="@string/text_clear"
app:showAsAction="never"/>
</menu>

View File

@ -12,7 +12,7 @@
> 以下的longClick、select、scrollUp、scrollDown的参数均与click类似不再赘述。
* `longClick` 长按
* `select` 选择
* `scrollUp` 上滑。不加参数时会寻找"最大"的可滑动的控件上滑,例如微信消息列表等。
* `scrollUp` 上滑。不加参数时会寻找"最大"的可滑动的控件上滑,例如微信消息列表等; 参数为一个整数i时会找到第i个可滑动控件滑动
* `scrollDown` 下滑。不加参数时与scrollUp类似。
* `input(text)` 把所有输入框的文本都置为text。例如input("测试")。
* `input(i, text)` 把第i个输入框的文本设为text。i从0开始。
@ -28,7 +28,23 @@
* `context` ApplicationContext参见安卓[android.content.Context](https://developer.android.com/reference/android/content/Context.html)
> 这里的context由于是ApplicationContext是不可见的不能用于dialog和其他UI相关。如果要显示弹窗或者视图请启动UI模式代码的第一行为`"ui";`既可并使用activity代替。
* `activity` UI模式下会启动一个Activity来运行脚本并在UI线程下运行。可通过该变量来获取该activity。
###五、在脚本中调用Java
###五、控制台
* `openConsole()` 打开控制台。
* `clearConsole()` 清空控制台。
* `log(text)` 在控制台中输出日志,以例如`log("Hello world");`。
* `err(text)` 在控制台中输出错误信息,以红色字体显示,例如:
```
try{
//do something
}catch(e){
err("错误);
err(e);
openConsole();
}
```
###六、在脚本中调用Java
使用importClass来引入要使用的库例如:
```javascript
importClass("android.view.View.OnClickListener")

View File

@ -1,6 +1,6 @@
<resources>
<string name="app_name">免Root脚本机器人</string>
<string name="version">Version 0.17.0205</string>
<string name="version">Version 1.17.0212</string>
<string name="action_settings">设置</string>
<string name="action_disable_service">关闭服务</string>
<string name="text_accessibility_service_description">使脚本自动操作(点击、长按、滑动等)所需,若关闭则只能执行不涉及自动操作的脚本。</string>
@ -93,4 +93,6 @@
<string name="text_re_import_samples">重新导入示例脚本文件</string>
<string name="text_re_import_succeed">导入成功,重新打开应用生效</string>
<string name="text_fail">失败</string>
<string name="text_clear">清空</string>
<string name="text_console">控制台</string>
</resources>