@@ -9,8 +9,8 @@ android {
|
||||
applicationId "com.stardust.scriptdroid"
|
||||
minSdkVersion 17
|
||||
targetSdkVersion 23
|
||||
versionCode 145
|
||||
versionName "2.0.13 Beta3"
|
||||
versionCode 146
|
||||
versionName "2.0.14 Beta"
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
multiDexEnabled true
|
||||
ndk {
|
||||
|
||||
@@ -80,6 +80,11 @@
|
||||
<activity android:name=".ui.help.LocalWebViewActivity"/>
|
||||
<activity android:name=".external.tasker.TaskerScriptEditActivity_"/>
|
||||
<activity android:name=".ui.edit.ViewSampleActivity"/>
|
||||
<activity android:name=".external.widget.ScriptWidgetSettingsActivity_">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name="com.stardust.autojs.runtime.api.image.ScreenCaptureRequestActivity"
|
||||
android:taskAffinity="com.stardust.autojs.runtime.api.image.ScreenCaptureRequestActivity"
|
||||
@@ -241,6 +246,15 @@
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<receiver android:name=".external.widget.ScriptWidget">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.appwidget.provider"
|
||||
android:resource="@xml/script_widget_config"/>
|
||||
</receiver>
|
||||
|
||||
<!-- 声明广告SDK所需要的组件 -->
|
||||
<service
|
||||
android:name="com.qq.e.comm.DownloadService"
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
module.exports = function(){
|
||||
|
||||
}
|
||||
66
app/src/main/assets/sample/QQ与微信/QQ加群成员脚本.js
Normal file
66
app/src/main/assets/sample/QQ与微信/QQ加群成员脚本.js
Normal file
@@ -0,0 +1,66 @@
|
||||
"auto";
|
||||
|
||||
var 好友验证信息 = "AutoJs自动添加群好友";
|
||||
var 延迟 = 500;
|
||||
|
||||
toast("请打开群成员列表");
|
||||
|
||||
var added = {};
|
||||
while(true){
|
||||
var list = className("AbsListView").findOne();
|
||||
list.children().each(function(child){
|
||||
if(child.className() != "android.widget.FrameLayout"){
|
||||
return;
|
||||
}
|
||||
if(!isGroupMember(child)){
|
||||
return;
|
||||
}
|
||||
if(isMyself(child)){
|
||||
return;
|
||||
}
|
||||
child.child(0).click();
|
||||
sleep(500);
|
||||
addAsFriend();
|
||||
sleep(延迟);
|
||||
});
|
||||
className("AbsListView").findOne().scrollForward();
|
||||
}
|
||||
|
||||
|
||||
function isGroupMember(child){
|
||||
if(child.childCount() != 1){
|
||||
return false;
|
||||
}
|
||||
return child.child(0) && child.child(0).className() == "android.widget.FrameLayout";
|
||||
}
|
||||
|
||||
function isMyself(child){
|
||||
var l = child.findByText("我");
|
||||
return l && l.size() > 0;
|
||||
}
|
||||
|
||||
function addAsFriend(){
|
||||
var qq = getQQ();
|
||||
if(added[qq]){
|
||||
while(!click("返回"));
|
||||
return;
|
||||
}
|
||||
added[qq] = true;
|
||||
if(click("加好友")){
|
||||
sleep(800);
|
||||
setText(0, 好友验证信息);
|
||||
while(!click("发送"));
|
||||
sleep(800);
|
||||
if(click("取消")){
|
||||
sleep(400);
|
||||
}
|
||||
back();
|
||||
}else{
|
||||
back();
|
||||
}
|
||||
}
|
||||
|
||||
function getQQ(){
|
||||
var qq = textMatches("\\d{5,12}").findOne().text();
|
||||
return qq;
|
||||
}
|
||||
@@ -5,21 +5,29 @@ function 下滑(){
|
||||
}
|
||||
|
||||
function 赞(){
|
||||
className("ImageView").desc("赞").click();
|
||||
var like = className("ImageView").desc("赞").find();
|
||||
if(like){
|
||||
like.click();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function 显示更多(){
|
||||
for(let i = 0; i < 2;i++){
|
||||
click("显示更多");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
toast("请打开自己的资料页,点击点赞图标");
|
||||
sleep(100);
|
||||
waitForActivity("com.tencent.mobileqq.activity.VisitorsActivity");
|
||||
|
||||
while(notStopped()){
|
||||
for(let i = 0; i < 10; i++){
|
||||
赞();
|
||||
var i = 0;
|
||||
while(i < 10){
|
||||
i += 赞() ? 1 : 0;
|
||||
click("取消");
|
||||
}
|
||||
显示更多();
|
||||
下滑();
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
"auto";
|
||||
|
||||
var 延迟 = 0;
|
||||
|
||||
function 点赞(){
|
||||
className("AbsListView").findOne()
|
||||
.children().each(function(ss){
|
||||
try{
|
||||
var 一行 = 找到图标那一行(ss);
|
||||
if(一行){
|
||||
一行.child(1).click();
|
||||
if(延迟 > 0){
|
||||
sleep(延迟);
|
||||
}
|
||||
}
|
||||
}catch(e){}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function 找到图标那一行(s){
|
||||
for(let i = 0; i < s.getChildCount(); i++){
|
||||
var child = s.child(i);
|
||||
if(child && child.className()
|
||||
.endsWith("RelativeLayout") &&
|
||||
child.getChildCount() >= 4){
|
||||
if(是图片(child.child(1)) &&
|
||||
是图片(child.child(2)) &&
|
||||
是图片(child.child(3))){
|
||||
return child;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function 是图片(item){
|
||||
return item &&
|
||||
item.className().endsWith("ImageView");
|
||||
}
|
||||
|
||||
function 下滑(){
|
||||
className("AbsListView").findOne()
|
||||
.scrollForward();
|
||||
}
|
||||
|
||||
while(true){
|
||||
点赞();
|
||||
下滑();
|
||||
}
|
||||
71
app/src/main/assets/sample/QQ与微信/QQ空间点赞.js
Normal file
71
app/src/main/assets/sample/QQ与微信/QQ空间点赞.js
Normal file
@@ -0,0 +1,71 @@
|
||||
"auto";
|
||||
|
||||
var 延迟 = 0;
|
||||
|
||||
if(!requestScreenCapture()){
|
||||
toast("请求截图失败");
|
||||
stop();
|
||||
}
|
||||
|
||||
var capture;
|
||||
|
||||
function like(){
|
||||
capture = captureScreen();
|
||||
className("AbsListView").findOne()
|
||||
.children().each(function(ss){
|
||||
try{
|
||||
var iconLine = findIconLine(ss);
|
||||
if(iconLine){
|
||||
var likeIcon = iconLine.child(1).child(0);
|
||||
if(notLiked(likeIcon)){
|
||||
likeIcon.click();
|
||||
}
|
||||
if(延迟 > 0){
|
||||
sleep(延迟);
|
||||
}
|
||||
}
|
||||
}catch(e){
|
||||
log(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function findIconLine(s){
|
||||
for(let i = 0; i < s.getChildCount(); i++){
|
||||
var child = s.child(i);
|
||||
if(child && child.className()
|
||||
.endsWith("RelativeLayout") &&
|
||||
child.getChildCount() >= 4){
|
||||
if(isImage(child.child(1)) &&
|
||||
isImage(child.child(2)) &&
|
||||
isImage(child.child(3))){
|
||||
return child;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function isImage(item){
|
||||
if(!item){
|
||||
return false;
|
||||
}
|
||||
if(item.className().endsWith("ImageView")){
|
||||
return true;
|
||||
}
|
||||
if(item.childCount() == 1){
|
||||
return isImage(item.child(0));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function notLiked(likeIcon){
|
||||
var x = likeIcon.bounds().centerX();
|
||||
var y = likeIcon.bounds().centerY();
|
||||
return images.detectsColor(capture, x, y, 0x767886);
|
||||
}
|
||||
|
||||
toast("请打开QQ空间并慢慢下滑");
|
||||
while(true){
|
||||
like();
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
"auto";
|
||||
|
||||
|
||||
//漏赞过多请稍微调大延迟
|
||||
var 延迟 = 200;
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
"auto";
|
||||
|
||||
|
||||
toast("请打开一个聊天窗口");
|
||||
sleep(500);
|
||||
|
||||
while(true){
|
||||
input("我喜欢你");
|
||||
setText("我喜欢你");
|
||||
click("发送");
|
||||
sleep(200);
|
||||
}
|
||||
@@ -3,8 +3,8 @@
|
||||
launchApp("网易云音乐");
|
||||
toast("打开一个歌曲的评论页面");
|
||||
|
||||
//循环直至当前为评论页面
|
||||
waitActivity("com.netease.cloudmusic.activity.ResourceCommentActivity");
|
||||
//等待当前为评论页面
|
||||
waitForActivity("com.netease.cloudmusic.activity.ResourceCommentActivity");
|
||||
|
||||
|
||||
while(true){
|
||||
|
||||
12
app/src/main/assets/sample/图片与图色处理/颜色获取和检测.js
Normal file
12
app/src/main/assets/sample/图片与图色处理/颜色获取和检测.js
Normal file
@@ -0,0 +1,12 @@
|
||||
if(!requestScreenCapture()){
|
||||
toast("请求截图失败");
|
||||
}
|
||||
sleep(2000);
|
||||
var x = 760;
|
||||
var y = 180;
|
||||
//获取在点(x, y)处的颜色
|
||||
var c = images.pixel(captureScreen(), x, y);
|
||||
//显示该颜色
|
||||
toast((c >>> 0).toString(16));
|
||||
//检测在点(x, y)处是否有颜色0x73bdb6 (模糊比较)
|
||||
toast(images.detectsColor(captureScreen(), x, y, 0x73bdb6))
|
||||
@@ -83,10 +83,6 @@ public class App extends MultiDexApplication {
|
||||
}
|
||||
|
||||
|
||||
public static String getResString(int id) {
|
||||
return getApp().getString(id);
|
||||
}
|
||||
|
||||
public VolumeChangeObserver getVolumeChangeObserver() {
|
||||
return mVolumeChangeObserver;
|
||||
}
|
||||
|
||||
@@ -8,15 +8,13 @@ import com.stardust.autojs.runtime.api.AutomatorConfig;
|
||||
import com.stardust.automator.AccessibilityEventCommandHost;
|
||||
import com.stardust.scriptdroid.autojs.AutoJs;
|
||||
|
||||
import org.mozilla.javascript.tools.debugger.Dim;
|
||||
import org.mozilla.javascript.tools.debugger.GuiCallback;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/1/31.
|
||||
*/
|
||||
public class Pref {
|
||||
private static final boolean enableRemoveAdOption = true;
|
||||
|
||||
private static final SharedPreferences DISPOSABLE_BOOLEAN = App.getApp().getSharedPreferences("DISPOSABLE_BOOLEAN", Context.MODE_PRIVATE);
|
||||
private static final String KEY_SERVER_ADDRESS = "Still love you...17.5.14";
|
||||
@@ -99,7 +97,7 @@ public class Pref {
|
||||
}
|
||||
|
||||
private static String getString(int id) {
|
||||
return App.getResString(id);
|
||||
return App.getApp().getString(id);
|
||||
}
|
||||
|
||||
public static int getMaxTextLengthForCodeCompletion() {
|
||||
@@ -147,6 +145,9 @@ public class Pref {
|
||||
def().edit().putLong(KEY_LAST_SHOW_AD_MILLIS, System.currentTimeMillis()).apply();
|
||||
return true;
|
||||
case "Off":
|
||||
if (enableRemoveAdOption) {
|
||||
return false;
|
||||
}
|
||||
lastShowMillis = def().getLong(KEY_LAST_SHOW_AD_MILLIS, 0);
|
||||
if (System.currentTimeMillis() - lastShowMillis < TimeUnit.DAYS.toMillis(2)) {
|
||||
return false;
|
||||
|
||||
@@ -51,15 +51,17 @@ public class RecordNavigatorContent implements NavigatorContent, Recorder.OnStat
|
||||
@BindView(R.id.text_start_or_pause)
|
||||
TextView mStartOrPauseRecordText;
|
||||
|
||||
|
||||
@BindView(R.id.stop_record)
|
||||
View mStopRecord;
|
||||
|
||||
@BindView(R.id.discard_record)
|
||||
View mDiscardRecord;
|
||||
|
||||
|
||||
private Recorder mRecorder;
|
||||
private Context mContext;
|
||||
|
||||
private boolean mDiscard = false;
|
||||
private KeyObserver mKeyObserver;
|
||||
|
||||
private VolumeChangeObserver.OnVolumeChangeListener mOnVolumeChangeListener = new VolumeChangeObserver.OnVolumeChangeListener() {
|
||||
@Override
|
||||
public void onVolumeChange() {
|
||||
@@ -123,6 +125,12 @@ public class RecordNavigatorContent implements NavigatorContent, Recorder.OnStat
|
||||
}
|
||||
}
|
||||
|
||||
@OnClick(R.id.discard_record)
|
||||
void discardRecord() {
|
||||
mDiscard = true;
|
||||
stopRecord();
|
||||
}
|
||||
|
||||
private void resumeRecord() {
|
||||
mRecorder.resume();
|
||||
setState(Recorder.STATE_RECORDING);
|
||||
@@ -135,6 +143,7 @@ public class RecordNavigatorContent implements NavigatorContent, Recorder.OnStat
|
||||
}
|
||||
|
||||
private void startRecord() {
|
||||
mDiscard = false;
|
||||
mRecorder = mRecordedByRootSwitch.isChecked() ? new TouchRecorder(mContext) : AutoJs.getInstance().getAccessibilityActionRecorder();
|
||||
mRecorder.setOnStateChangedListener(this);
|
||||
mRecorder.start();
|
||||
@@ -144,6 +153,7 @@ public class RecordNavigatorContent implements NavigatorContent, Recorder.OnStat
|
||||
|
||||
private void setState(int state) {
|
||||
mStopRecord.setVisibility(state == Recorder.STATE_STOPPED ? View.GONE : View.VISIBLE);
|
||||
mDiscardRecord.setVisibility(state == Recorder.STATE_STOPPED ? View.GONE : View.VISIBLE);
|
||||
mStartOrPauseRecordIcon.setImageResource(state == Recorder.STATE_RECORDING ? R.drawable.ic_pause_white_24dp : R.drawable.ic_play_arrow_white_48dp);
|
||||
//我知道这样写代码会被打 但我懒...
|
||||
mStartOrPauseRecordText.setText(state == Recorder.STATE_RECORDING ? R.string.text_pause_record :
|
||||
@@ -191,7 +201,9 @@ public class RecordNavigatorContent implements NavigatorContent, Recorder.OnStat
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
MainActivity.onRecordStop(mContext, mRecorder.getCode());
|
||||
if (!mDiscard) {
|
||||
MainActivity.onRecordStop(mContext, mRecorder.getCode());
|
||||
}
|
||||
mRecorder = null;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,8 +27,8 @@ public class LayoutInspector {
|
||||
mCapture = null;
|
||||
} else {
|
||||
final AccessibilityNodeInfo root = service.getRootInActiveWindow();
|
||||
Log.d(LOG_TAG, "captureCurrentWindow: root = null");
|
||||
if (root == null) {
|
||||
Log.d(LOG_TAG, "captureCurrentWindow: root = null");
|
||||
mCapture = null;
|
||||
} else {
|
||||
mExecutor.execute(new Runnable() {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.stardust.scriptdroid.external.open;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.TextUtils;
|
||||
@@ -10,6 +11,8 @@ import com.stardust.scriptdroid.ui.BaseActivity;
|
||||
import com.stardust.scriptdroid.ui.main.MainActivity;
|
||||
import com.stardust.scriptdroid.R;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/2/2.
|
||||
*/
|
||||
@@ -30,13 +33,25 @@ public class ImportIntentActivity extends BaseActivity {
|
||||
|
||||
@Override
|
||||
protected void onNewIntent(Intent intent) {
|
||||
handleIntent(intent);
|
||||
try {
|
||||
handleIntent(intent);
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
Toast.makeText(this, R.string.edit_and_run_handle_intent_error, Toast.LENGTH_LONG).show();
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
private void handleIntent(Intent intent) {
|
||||
final String path = intent.getData().getPath();
|
||||
if (!TextUtils.isEmpty(path))
|
||||
MainActivity.importScriptFile(this, path);
|
||||
private void handleIntent(Intent intent) throws FileNotFoundException {
|
||||
Uri uri = intent.getData();
|
||||
if (uri != null && "content".equals(uri.getScheme())) {
|
||||
MainActivity.importScriptFileByInputStream(this, getContentResolver().openInputStream(uri));
|
||||
} else {
|
||||
final String path = intent.getData().getPath();
|
||||
if (!TextUtils.isEmpty(path)) {
|
||||
MainActivity.importScriptFile(this, path);
|
||||
}
|
||||
}
|
||||
finish();
|
||||
}
|
||||
|
||||
|
||||
58
app/src/main/java/com/stardust/scriptdroid/external/widget/ScriptWidget.java
vendored
Normal file
58
app/src/main/java/com/stardust/scriptdroid/external/widget/ScriptWidget.java
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
package com.stardust.scriptdroid.external.widget;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.appwidget.AppWidgetManager;
|
||||
import android.appwidget.AppWidgetProvider;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.widget.RemoteViews;
|
||||
|
||||
import com.stardust.pio.PFile;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.external.CommonUtils;
|
||||
import com.stardust.scriptdroid.external.open.RunIntentActivity;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/7/11.
|
||||
*/
|
||||
|
||||
public class ScriptWidget extends AppWidgetProvider {
|
||||
|
||||
private static final String LOG_TAG = "ScriptWidget";
|
||||
|
||||
@Override
|
||||
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
|
||||
super.onUpdate(context, appWidgetManager, appWidgetIds);
|
||||
Set<Integer> appWidgetIdSet = new HashSet<>();
|
||||
for (int appWidgetId : appWidgetIds) {
|
||||
updateWidget(context, appWidgetId, ScriptWidgets.getPathForAppWidgetId(appWidgetId));
|
||||
appWidgetIdSet.add(appWidgetId);
|
||||
}
|
||||
if (appWidgetIdSet.size() > 1)
|
||||
ScriptWidgets.removeAllNotIn(appWidgetIdSet);
|
||||
}
|
||||
|
||||
static boolean updateWidget(Context context, int widgetId, String path) {
|
||||
if (TextUtils.isEmpty(path) || widgetId == AppWidgetManager.INVALID_APPWIDGET_ID) {
|
||||
return false;
|
||||
}
|
||||
String name = PFile.getNameWithoutExtension(path);
|
||||
int requestCode = ScriptWidgets.getRequestCodeForAppWidgetId(widgetId);
|
||||
Log.d(LOG_TAG, "updateWidget: id = " + widgetId + ", requestCode = " + requestCode + ", path = " + path);
|
||||
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
|
||||
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_script_shortcut);
|
||||
views.setOnClickPendingIntent(R.id.widget, PendingIntent.getActivity(context, requestCode,
|
||||
new Intent(context, RunIntentActivity.class)
|
||||
.putExtra(CommonUtils.EXTRA_KEY_PATH, path)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK), PendingIntent.FLAG_UPDATE_CURRENT));
|
||||
views.setTextViewText(R.id.name, name);
|
||||
appWidgetManager.updateAppWidget(widgetId, views);
|
||||
ScriptWidgets.setPathForAppWidgetId(widgetId, path);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
100
app/src/main/java/com/stardust/scriptdroid/external/widget/ScriptWidgetSettingsActivity.java
vendored
Normal file
100
app/src/main/java/com/stardust/scriptdroid/external/widget/ScriptWidgetSettingsActivity.java
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
package com.stardust.scriptdroid.external.widget;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.appwidget.AppWidgetManager;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.TextUtils;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.widget.RemoteViews;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.external.CommonUtils;
|
||||
import com.stardust.scriptdroid.external.open.RunIntentActivity;
|
||||
import com.stardust.scriptdroid.external.tasker.TaskerScriptEditActivity;
|
||||
import com.stardust.scriptdroid.script.ScriptFile;
|
||||
import com.stardust.scriptdroid.script.StorageScriptProvider;
|
||||
import com.stardust.scriptdroid.ui.BaseActivity;
|
||||
import com.stardust.scriptdroid.ui.main.script_list.ScriptAndFolderListRecyclerView;
|
||||
import com.stardust.scriptdroid.ui.main.script_list.ScriptListWithProgressBarView;
|
||||
|
||||
import org.androidannotations.annotations.AfterViews;
|
||||
import org.androidannotations.annotations.Click;
|
||||
import org.androidannotations.annotations.EActivity;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/7/11.
|
||||
*/
|
||||
@EActivity(R.layout.activity_script_widget_settings)
|
||||
public class ScriptWidgetSettingsActivity extends BaseActivity {
|
||||
|
||||
|
||||
private String mSelectedScriptFilePath;
|
||||
private StorageScriptProvider mStorageScriptProvider;
|
||||
private int mAppWidgetId;
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mAppWidgetId = getIntent().getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
|
||||
}
|
||||
|
||||
@AfterViews
|
||||
void setUpViews() {
|
||||
BaseActivity.setToolbarAsBack(this, R.id.toolbar, getString(R.string.text_please_choose_a_script));
|
||||
initScriptListRecyclerView();
|
||||
}
|
||||
|
||||
|
||||
private void initScriptListRecyclerView() {
|
||||
mStorageScriptProvider = StorageScriptProvider.getExternalStorageProvider();
|
||||
ScriptListWithProgressBarView scriptList = (ScriptListWithProgressBarView) findViewById(R.id.script_list);
|
||||
scriptList.setScriptFileOperationEnabled(false);
|
||||
scriptList.setStorageScriptProvider(mStorageScriptProvider);
|
||||
scriptList.setCurrentDirectory(StorageScriptProvider.DEFAULT_DIRECTORY);
|
||||
scriptList.setOnItemClickListener(new ScriptAndFolderListRecyclerView.OnScriptFileClickListener() {
|
||||
@Override
|
||||
public void onClick(ScriptFile file, int position) {
|
||||
mSelectedScriptFilePath = file.getPath();
|
||||
finish();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (item.getItemId() == R.id.action_refresh) {
|
||||
mStorageScriptProvider.refreshAll();
|
||||
} else if (item.getItemId() == R.id.action_clear_file_selection) {
|
||||
mSelectedScriptFilePath = null;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.script_widget_settings_menu, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finish() {
|
||||
if (ScriptWidget.updateWidget(this, mAppWidgetId, mSelectedScriptFilePath)) {
|
||||
setResult(RESULT_OK, new Intent()
|
||||
.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId));
|
||||
|
||||
} else {
|
||||
setResult(RESULT_CANCELED, new Intent()
|
||||
.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId));
|
||||
}
|
||||
super.finish();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
72
app/src/main/java/com/stardust/scriptdroid/external/widget/ScriptWidgets.java
vendored
Normal file
72
app/src/main/java/com/stardust/scriptdroid/external/widget/ScriptWidgets.java
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
package com.stardust.scriptdroid.external.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.util.Log;
|
||||
|
||||
import com.stardust.scriptdroid.App;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/7/11.
|
||||
*/
|
||||
|
||||
public class ScriptWidgets {
|
||||
|
||||
|
||||
private static final String LOG_TAG = "ScriptWidgets";
|
||||
private static SharedPreferences widgets = App.getApp().getSharedPreferences("ScriptWidgets", Context.MODE_PRIVATE);
|
||||
private static final Pattern ID_PATTERN = Pattern.compile("[a-zA-Z]+_([0-9])+");
|
||||
|
||||
static String getPathForAppWidgetId(int id) {
|
||||
return widgets.getString("path_" + id, null);
|
||||
}
|
||||
|
||||
static void setPathForAppWidgetId(int id, String path) {
|
||||
widgets.edit().putString("path_" + id, path).apply();
|
||||
}
|
||||
|
||||
static int getRequestCodeForAppWidgetId(int id) {
|
||||
int requestCode = widgets.getInt("rc_" + id, -1);
|
||||
if (requestCode == -1) {
|
||||
requestCode = widgets.getInt("max_rc", 0) + 1;
|
||||
widgets.edit()
|
||||
.putInt("rc_" + id, requestCode)
|
||||
.putInt("max_rc", requestCode)
|
||||
.apply();
|
||||
}
|
||||
return requestCode;
|
||||
}
|
||||
|
||||
static void removeAllNotIn(Set<Integer> appWidgetIdSet) {
|
||||
List<String> keysToRemove = new LinkedList<>();
|
||||
for (Map.Entry<String, ?> entry : widgets.getAll().entrySet()) {
|
||||
if (entry.getKey().equals("max_rc")) {
|
||||
continue;
|
||||
}
|
||||
Matcher matcher = ID_PATTERN.matcher(entry.getKey());
|
||||
if (matcher.find()) {
|
||||
int id = Integer.parseInt(matcher.group(1));
|
||||
if (!appWidgetIdSet.contains(id)) {
|
||||
keysToRemove.add(entry.getKey());
|
||||
}
|
||||
} else {
|
||||
Log.w(LOG_TAG, "illegal key: " + entry.getKey());
|
||||
keysToRemove.add(entry.getKey());
|
||||
}
|
||||
}
|
||||
SharedPreferences.Editor editor = widgets.edit();
|
||||
for (String key : keysToRemove) {
|
||||
editor.remove(key);
|
||||
Log.v(LOG_TAG, "remove key: " + key);
|
||||
}
|
||||
editor.apply();
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,8 @@ package com.stardust.scriptdroid.ui;
|
||||
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.CallSuper;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.RequiresApi;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
@@ -26,7 +28,9 @@ import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||
|
||||
public abstract class BaseActivity extends AppCompatActivity {
|
||||
|
||||
|
||||
protected static final int PERMISSION_REQUEST_CODE = 11186;
|
||||
private static boolean isRequestingPermissions = false;
|
||||
private BackPressedHandler.Observer mBackPressObserver = new BackPressedHandler.Observer();
|
||||
|
||||
@Override
|
||||
@@ -62,9 +66,14 @@ public abstract class BaseActivity extends AppCompatActivity {
|
||||
|
||||
protected void checkPermission(String... permissions) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
if (isRequestingPermissions) {
|
||||
return;
|
||||
}
|
||||
String[] requestPermissions = getRequestPermissions(permissions);
|
||||
if (requestPermissions.length > 0)
|
||||
if (requestPermissions.length > 0) {
|
||||
isRequestingPermissions = true;
|
||||
requestPermissions(requestPermissions, PERMISSION_REQUEST_CODE);
|
||||
}
|
||||
} else {
|
||||
int[] grantResults = new int[permissions.length];
|
||||
Arrays.fill(grantResults, PERMISSION_GRANTED);
|
||||
@@ -72,6 +81,7 @@ public abstract class BaseActivity extends AppCompatActivity {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.M)
|
||||
private String[] getRequestPermissions(String[] permissions) {
|
||||
List<String> list = new ArrayList<>();
|
||||
@@ -112,4 +122,11 @@ public abstract class BaseActivity extends AppCompatActivity {
|
||||
activity.getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
isRequestingPermissions = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,10 +36,12 @@ import com.stardust.scriptdroid.Pref;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.autojs.AutoJs;
|
||||
import com.stardust.scriptdroid.external.floatingwindow.HoverMenuManger;
|
||||
import com.stardust.scriptdroid.external.open.ImportIntentActivity;
|
||||
import com.stardust.scriptdroid.script.ScriptFile;
|
||||
import com.stardust.scriptdroid.script.StorageScriptProvider;
|
||||
import com.stardust.scriptdroid.script.sample.Sample;
|
||||
import com.stardust.scriptdroid.ui.main.task.TaskManagerFragment_;
|
||||
import com.stardust.util.IntentExtras;
|
||||
import com.stardust.view.accessibility.AccessibilityService;
|
||||
import com.stardust.scriptdroid.tool.AccessibilityServiceTool;
|
||||
import com.stardust.scriptdroid.tool.DrawableSaver;
|
||||
@@ -66,6 +68,7 @@ import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
@EActivity(R.layout.activity_main)
|
||||
public class MainActivity extends BaseActivity implements OnActivityResultDelegate.DelegateHost {
|
||||
@@ -81,6 +84,7 @@ public class MainActivity extends BaseActivity implements OnActivityResultDelega
|
||||
private static final String ARGUMENT_PATH = "ARGUMENT_PATH";
|
||||
private static final String ACTION_IMPORT_SAMPLE = "I cannot find the way back to you...Eating...17.4.29";
|
||||
private static final String ARGUMENT_SAMPLE = "Take a chance on me...ok...?";
|
||||
private static final String ARGUMENT_INPUT_STREAM = "17.7.12, Hi...could we start all over again...";
|
||||
|
||||
|
||||
@ViewById(R.id.drawer_layout)
|
||||
@@ -306,7 +310,10 @@ public class MainActivity extends BaseActivity implements OnActivityResultDelega
|
||||
return;
|
||||
switch (action) {
|
||||
case ACTION_ON_ACTION_RECORD_STOPPED:
|
||||
handleRecordedScript(intent.getStringExtra(ARGUMENT_SCRIPT));
|
||||
IntentExtras extras = IntentExtras.fromIntent(intent);
|
||||
String script = extras.get(ARGUMENT_SCRIPT);
|
||||
extras.clear();
|
||||
handleRecordedScript(script);
|
||||
break;
|
||||
case ACTION_IMPORT_SCRIPT:
|
||||
handleImportScriptFile(intent);
|
||||
@@ -323,10 +330,17 @@ public class MainActivity extends BaseActivity implements OnActivityResultDelega
|
||||
if (fragment == null) {
|
||||
mIntentToHandle = intent;
|
||||
} else {
|
||||
fragment.importFile(intent.getStringExtra(ARGUMENT_PATH));
|
||||
String path = intent.getStringExtra(ARGUMENT_PATH);
|
||||
if (path != null) {
|
||||
fragment.importFile(intent.getStringExtra(ARGUMENT_PATH));
|
||||
return;
|
||||
}
|
||||
InputStream inputStream = IntentExtras.fromIntent(intent).getAndClear(ARGUMENT_INPUT_STREAM);
|
||||
fragment.importFile("", inputStream);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void handleImportSample(Intent intent) {
|
||||
mViewPager.setCurrentItem(0, true);
|
||||
MyScriptListFragment fragment = getMyScriptListFragment();
|
||||
@@ -388,6 +402,16 @@ public class MainActivity extends BaseActivity implements OnActivityResultDelega
|
||||
.putExtra(ARGUMENT_PATH, path));
|
||||
}
|
||||
|
||||
public static void importScriptFileByInputStream(Context context, InputStream inputStream) {
|
||||
Intent intent = new Intent(context, MainActivity_.class)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP)
|
||||
.putExtra(EXTRA_ACTION, ACTION_IMPORT_SCRIPT);
|
||||
IntentExtras.newExtras()
|
||||
.put(ARGUMENT_INPUT_STREAM, inputStream)
|
||||
.putInIntent(intent);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
public static void importSample(Context context, Sample sample) {
|
||||
context.startActivity(new Intent(context, MainActivity_.class)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP)
|
||||
@@ -442,6 +466,7 @@ public class MainActivity extends BaseActivity implements OnActivityResultDelega
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
StorageScriptProvider.getDefault().notifyStoragePermissionGranted();
|
||||
}
|
||||
|
||||
@@ -456,8 +481,10 @@ public class MainActivity extends BaseActivity implements OnActivityResultDelega
|
||||
public static void onRecordStop(Context context, String script) {
|
||||
Intent intent = new Intent(context, MainActivity_.class)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
.putExtra(EXTRA_ACTION, ACTION_ON_ACTION_RECORD_STOPPED)
|
||||
.putExtra(ARGUMENT_SCRIPT, script);
|
||||
.putExtra(EXTRA_ACTION, ACTION_ON_ACTION_RECORD_STOPPED);
|
||||
IntentExtras.newExtras()
|
||||
.put(ARGUMENT_SCRIPT, script)
|
||||
.putInIntent(intent);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
@@ -466,4 +493,6 @@ public class MainActivity extends BaseActivity implements OnActivityResultDelega
|
||||
public OnActivityResultDelegate.Mediator getOnActivityResultDelegateMediator() {
|
||||
return mActivityResultMediator;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -78,7 +78,6 @@ public class SplashActivity extends BaseActivity {
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
BIN
app/src/main/res/drawable/discard.png
Normal file
BIN
app/src/main/res/drawable/discard.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 901 B |
33
app/src/main/res/layout/activity_script_widget_settings.xml
Normal file
33
app/src/main/res/layout/activity_script_widget_settings.xml
Normal file
@@ -0,0 +1,33 @@
|
||||
<?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:background="@android:color/transparent"
|
||||
android:clipToPadding="false"
|
||||
android:theme="@style/AppTheme.AppBarOverlay">
|
||||
|
||||
|
||||
<com.stardust.theme.widget.ThemeColorToolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
app:popupTheme="@style/AppTheme.PopupOverlay"
|
||||
app:title="@string/_app_name">
|
||||
|
||||
|
||||
</com.stardust.theme.widget.ThemeColorToolbar>
|
||||
</android.support.design.widget.AppBarLayout>
|
||||
|
||||
<com.stardust.scriptdroid.ui.main.script_list.ScriptListWithProgressBarView
|
||||
android:id="@+id/script_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#fafafa"/>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -148,6 +148,37 @@
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="#c4c4c4"/>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/discard_record"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingBottom="16dp"
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingTop="16dp"
|
||||
android:visibility="gone">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:src="@drawable/ic_close_white_24dp"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/text_discard_record"
|
||||
android:textColor="@android:color/primary_text_dark"
|
||||
android:textSize="16sp"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
|
||||
25
app/src/main/res/layout/widget_script_shortcut.xml
Normal file
25
app/src/main/res/layout/widget_script_shortcut.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/widget"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/icon"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:src="@drawable/ic_node_js_black"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:gravity="center"
|
||||
android:maxLines="1"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="12sp"/>
|
||||
|
||||
</LinearLayout>
|
||||
19
app/src/main/res/menu/script_widget_settings_menu.xml
Normal file
19
app/src/main/res/menu/script_widget_settings_menu.xml
Normal file
@@ -0,0 +1,19 @@
|
||||
<?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:id="@+id/action_refresh"
|
||||
android:icon="@drawable/ic_refresh_white_24dp"
|
||||
android:orderInCategory="100"
|
||||
android:title="@string/text_refresh"
|
||||
app:showAsAction="ifRoom"/>
|
||||
|
||||
<item
|
||||
android:id="@+id/action_clear_file_selection"
|
||||
android:orderInCategory="200"
|
||||
android:title="@string/text_clear_file_selection"
|
||||
app:showAsAction="never"/>
|
||||
|
||||
</menu>
|
||||
@@ -206,6 +206,7 @@
|
||||
<string name="hint_loop_delay">延迟多少秒后开始循环</string>
|
||||
<string name="text_number_format_error">格式错误</string>
|
||||
<string name="text_accessibility_settings">打开无障碍服务</string>
|
||||
<string name="text_discard_record">放弃录制</string>
|
||||
|
||||
<string-array name="record_control_keys">
|
||||
<item>无</item>
|
||||
@@ -224,7 +225,7 @@
|
||||
<string-array name="ad_showing_mode_keys">
|
||||
<item>默认</item>
|
||||
<item>每天显示一次</item>
|
||||
<item>两天显示一次</item>
|
||||
<item>关闭广告</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="ad_showing_mode_values">
|
||||
|
||||
8
app/src/main/res/xml/script_widget_config.xml
Normal file
8
app/src/main/res/xml/script_widget_config.xml
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:configure="com.stardust.scriptdroid.external.widget.ScriptWidgetSettingsActivity_"
|
||||
android:initialLayout="@layout/widget_script_shortcut"
|
||||
android:minHeight="40dp"
|
||||
android:minWidth="40dp"
|
||||
android:previewImage="@drawable/ic_node_js_black"
|
||||
android:resizeMode="none"/>
|
||||
@@ -6,6 +6,7 @@
|
||||
<application
|
||||
>
|
||||
<activity android:name=".execution.ScriptExecuteActivity"/>
|
||||
|
||||
<service
|
||||
android:name="com.stardust.view.accessibility.AccessibilityService"
|
||||
android:label="@string/_app_name"
|
||||
@@ -18,6 +19,7 @@
|
||||
android:resource="@xml/accessibility_service_config"/>
|
||||
|
||||
</service>
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
||||
@@ -88,7 +88,7 @@ module.exports = function(__runtime__, scope){
|
||||
}, arguments);
|
||||
}
|
||||
|
||||
automator.input = function(a, b){
|
||||
automator.setText = function(a, b){
|
||||
if(arguments.length == 1){
|
||||
return __runtime__.automator.setText(__runtime__.automator.editable(-1), a);
|
||||
}else{
|
||||
@@ -96,8 +96,16 @@ module.exports = function(__runtime__, scope){
|
||||
}
|
||||
}
|
||||
|
||||
automator.input = function(a, b){
|
||||
if(arguments.length == 1){
|
||||
return __runtime__.automator.appendText(__runtime__.automator.editable(-1), a);
|
||||
}else{
|
||||
return __runtime__.automator.appendText(__runtime__.automator.editable(a), b);
|
||||
}
|
||||
}
|
||||
|
||||
scope.__asGlobal__(__runtime__.automator, ['back', 'home', 'powerDialog', 'notifications', 'quickSettings', 'recents', 'splitScreen']);
|
||||
scope.__asGlobal__(automator, ['click', 'longClick', 'press', 'swipe', 'gesture', 'gestures', 'gestureAsync', 'gesturesAsync', 'scrollDown', 'scrollUp', 'input']);
|
||||
scope.__asGlobal__(automator, ['click', 'longClick', 'press', 'swipe', 'gesture', 'gestures', 'gestureAsync', 'gesturesAsync', 'scrollDown', 'scrollUp', 'input', 'setText']);
|
||||
|
||||
return automator;
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ module.exports = function(__runtime__, scope){
|
||||
return __runtime__.info.getLatestActivity();
|
||||
}
|
||||
|
||||
scope.waitActivity = function(activity, delay){
|
||||
scope.waitForActivity = function(activity, delay){
|
||||
delay = delay || 200;
|
||||
while(scope.currentActivity() != activity){
|
||||
sleep(delay);
|
||||
|
||||
@@ -1,18 +1,23 @@
|
||||
|
||||
module.exports = function(__runtime__, scope){
|
||||
var images = {};
|
||||
if(android.os.Build.VERSION.SDK_INT < 19){
|
||||
return images;
|
||||
}
|
||||
|
||||
var colorFinder = __runtime__.images.colorFinder;
|
||||
var rtImages = __runtime__.getImages();
|
||||
|
||||
images.requestScreenCapture = __runtime__.images.requestScreenCapture.bind(__runtime__.images);
|
||||
var colorFinder = rtImages.colorFinder;
|
||||
|
||||
images.captureScreen = __runtime__.images.captureScreen.bind(__runtime__.images);
|
||||
images.requestScreenCapture = rtImages.requestScreenCapture.bind(rtImages);
|
||||
|
||||
images.saveImage = __runtime__.images.saveImage.bind(__runtime__.images);
|
||||
images.captureScreen = rtImages.captureScreen.bind(rtImages);
|
||||
|
||||
images.pixel = __runtime__.images.pixel;
|
||||
images.saveImage = rtImages.saveImage.bind(rtImages);
|
||||
|
||||
images.detectsColor = __runtime__.images.detectsColor.bind(__runtime__.images);
|
||||
images.pixel = rtImages.pixel;
|
||||
|
||||
images.detectsColor = rtImages.detectsColor.bind(rtImages);
|
||||
|
||||
images.findColor = function(img, color, options){
|
||||
if(typeof(color) == 'string'){
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.stardust.autojs.runtime;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.support.annotation.CallSuper;
|
||||
|
||||
import com.stardust.autojs.engine.ScriptEngine;
|
||||
@@ -40,12 +41,12 @@ public abstract class AbstractScriptRuntime {
|
||||
@ScriptVariable
|
||||
public UI ui;
|
||||
|
||||
@ScriptVariable
|
||||
public Images images;
|
||||
|
||||
@ScriptVariable
|
||||
public Dialogs dialogs;
|
||||
|
||||
private Images images;
|
||||
|
||||
private static WeakReference<Context> applicationContext;
|
||||
|
||||
public AbstractScriptRuntime(UiHandler uiHandler, Console console, AccessibilityBridge bridge, AppUtils appUtils, ScreenCaptureRequester screenCaptureRequester) {
|
||||
@@ -54,7 +55,9 @@ public abstract class AbstractScriptRuntime {
|
||||
this.automator = new SimpleActionAutomator(bridge, this);
|
||||
this.info = bridge.getInfoProvider();
|
||||
this.ui = new UI(uiHandler.getContext());
|
||||
images = new Images(uiHandler.getContext(), this, screenCaptureRequester);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
images = new Images(uiHandler.getContext(), this, screenCaptureRequester);
|
||||
}
|
||||
dialogs = new Dialogs(app, uiHandler);
|
||||
}
|
||||
|
||||
@@ -109,6 +112,12 @@ public abstract class AbstractScriptRuntime {
|
||||
|
||||
@CallSuper
|
||||
public void onStop() {
|
||||
images.releaseScreenCapturer();
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
images.releaseScreenCapturer();
|
||||
}
|
||||
}
|
||||
|
||||
public Object getImages() {
|
||||
return images;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ package com.stardust.autojs.runtime.api.image;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.media.Image;
|
||||
import android.os.Build;
|
||||
import android.support.annotation.RequiresApi;
|
||||
|
||||
import com.stardust.autojs.runtime.ScriptInterruptedException;
|
||||
import com.stardust.concurrent.VolatileBox;
|
||||
@@ -18,6 +20,7 @@ import java.util.concurrent.TimeUnit;
|
||||
* Created by Stardust on 2017/5/18.
|
||||
*/
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
|
||||
public class ColorFinder {
|
||||
|
||||
private static ThreadPoolExecutor sThreadPoolExecutor = new ThreadPoolExecutor(4, 16, 5, TimeUnit.MINUTES, new SynchronousQueue<Runnable>());
|
||||
|
||||
@@ -10,6 +10,7 @@ import android.graphics.Matrix;
|
||||
import android.media.Image;
|
||||
import android.os.Build;
|
||||
import android.support.annotation.RequiresApi;
|
||||
import android.util.Log;
|
||||
|
||||
import com.stardust.autojs.runtime.AbstractScriptRuntime;
|
||||
import com.stardust.autojs.runtime.ScriptInterruptedException;
|
||||
@@ -21,6 +22,7 @@ import com.stardust.util.ScreenMetrics;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/5/20.
|
||||
@@ -103,13 +105,20 @@ public class Images {
|
||||
}
|
||||
|
||||
public static int pixel(Image image, int x, int y) {
|
||||
int originX = x;
|
||||
int originY = y;
|
||||
x = ScreenMetrics.rescaleX(x, image.getWidth());
|
||||
y = ScreenMetrics.rescaleY(y, image.getHeight());
|
||||
Image.Plane plane = image.getPlanes()[0];
|
||||
int offset = y * plane.getRowStride() + x * plane.getPixelStride();
|
||||
int c = plane.getBuffer().getInt(offset);
|
||||
Log.d("Images", String.format(Locale.getDefault(), "(%d, %d)→(%d, %d)", originX, originY, x, y));
|
||||
return (c & 0xff000000) + ((c & 0xff) << 16) + (c & 0x00ff00) + ((c & 0xff0000) >> 16);
|
||||
}
|
||||
|
||||
public static int pixel(Bitmap bitmap, int x, int y) {
|
||||
x = ScreenMetrics.rescaleX(x, bitmap.getWidth());
|
||||
y = ScreenMetrics.rescaleY(y, bitmap.getHeight());
|
||||
return bitmap.getPixel(x, y);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import android.widget.TextView;
|
||||
import com.stardust.enhancedfloaty.FloatyService;
|
||||
import com.stardust.enhancedfloaty.ResizableExpandableFloaty;
|
||||
import com.stardust.enhancedfloaty.ResizableExpandableFloatyWindow;
|
||||
import com.stardust.util.ScreenMetrics;
|
||||
import com.stardust.util.ViewUtil;
|
||||
import com.stardust.autojs.R;
|
||||
|
||||
@@ -30,6 +31,7 @@ public class ConsoleFloaty extends ResizableExpandableFloaty.AbstractResizableEx
|
||||
setShouldRequestFocusWhenExpand(false);
|
||||
setInitialX(100);
|
||||
setInitialY(1000);
|
||||
setCollapsedViewUnpressedAlpha(1.0f);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -58,7 +60,7 @@ public class ConsoleFloaty extends ResizableExpandableFloaty.AbstractResizableEx
|
||||
view.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ViewUtil.setViewMeasure(view, 800, 800);
|
||||
ViewUtil.setViewMeasure(view, ScreenMetrics.getDeviceScreenWidth() * 2 / 3, ScreenMetrics.getDeviceScreenHeight() / 3);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -124,6 +124,12 @@ public class StardustConsole extends AbstractConsole {
|
||||
@Override
|
||||
public void show() {
|
||||
if (!SettingsCompat.canDrawOverlays(mUiHandler.getContext())) {
|
||||
mUiHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
}
|
||||
});
|
||||
SettingsCompat.manageDrawOverlays(mUiHandler.getContext());
|
||||
mUiHandler.toast(R.string.text_no_floating_window_permission);
|
||||
}
|
||||
|
||||
@@ -109,12 +109,20 @@ public class SimpleActionAutomator {
|
||||
return performAction(target.createAction(AccessibilityNodeInfo.ACTION_SELECT));
|
||||
}
|
||||
|
||||
@ScriptInterface
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||
public boolean setText(ActionTarget target, String text) {
|
||||
mScriptRuntime.requiresApi(Build.VERSION_CODES.LOLLIPOP);
|
||||
return performAction(target.createAction(AccessibilityNodeInfo.ACTION_SET_TEXT, text));
|
||||
}
|
||||
|
||||
@ScriptInterface
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||
public boolean appendText(ActionTarget target, String text) {
|
||||
mScriptRuntime.requiresApi(Build.VERSION_CODES.LOLLIPOP);
|
||||
return performAction(target.createAction(UiObject.ACTION_APPEND_TEXT, text));
|
||||
}
|
||||
|
||||
@ScriptInterface
|
||||
public boolean back() {
|
||||
return performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK);
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="46dp"
|
||||
android:layout_height="46dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@android:color/transparent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="46dp"
|
||||
android:layout_height="46dp"
|
||||
android:padding="5dp"
|
||||
android:src="@drawable/ic_debug_console"/>
|
||||
</LinearLayout>
|
||||
@@ -1,10 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:accessibilityEventTypes="typeAllMask"
|
||||
android:accessibilityEventTypes="typeNotificationStateChanged|typeAnnouncement|typeAssistReadingContext|typeContextClicked|typeGestureDetectionEnd|typeGestureDetectionStart|typeTouchExplorationGestureEnd|typeTouchExplorationGestureStart|typeTouchInteractionEnd|typeTouchInteractionStart|typeViewAccessibilityFocusCleared|typeViewAccessibilityFocused|typeViewClicked|typeViewHoverEnter|typeViewHoverExit|typeViewFocused|typeViewLongClicked|typeViewScrolled|typeViewSelected|typeViewTextChanged|typeViewTextSelectionChanged|typeViewTextTraversedAtMovementGranularity|typeWindowContentChanged|typeWindowsChanged|typeWindowStateChanged"
|
||||
android:accessibilityFeedbackType="feedbackGeneric"
|
||||
android:accessibilityFlags="flagRetrieveInteractiveWindows|flagIncludeNotImportantViews|flagReportViewIds|flagRequestEnhancedWebAccessibility"
|
||||
android:accessibilityFlags="flagIncludeNotImportantViews|flagReportViewIds|flagRetrieveInteractiveWindows|flagRequestEnhancedWebAccessibility"
|
||||
android:canPerformGestures="true"
|
||||
android:canRequestEnhancedWebAccessibility="true"
|
||||
android:canRetrieveWindowContent="true"
|
||||
android:description="@string/text_accessibility_service_description"
|
||||
android:notificationTimeout="0"/>
|
||||
android:notificationTimeout="100"/>
|
||||
@@ -36,6 +36,8 @@ import static android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.
|
||||
|
||||
public class UiObject extends AccessibilityNodeInfoCompat {
|
||||
|
||||
public static final int ACTION_APPEND_TEXT = 0x00200001;
|
||||
|
||||
private static final String TAG = "UiObject";
|
||||
private static final boolean DEBUG = false;
|
||||
private static int notRecycledCount = 0;
|
||||
|
||||
@@ -42,14 +42,18 @@ public class ActionFactory {
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||
public static SimpleAction createActionWithEditableFilter(int action, int index, final String text) {
|
||||
public static SimpleAction createActionWithEditableFilter(final int action, int index, final String text) {
|
||||
return new SearchTargetAction(action, new FilterAction.EditableFilter(index)) {
|
||||
|
||||
@Override
|
||||
protected void performAction(UiObject node) {
|
||||
Bundle args = new Bundle();
|
||||
args.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, node.text() + text);
|
||||
node.performAction(getAction(), args);
|
||||
if (action == AccessibilityNodeInfo.ACTION_SET_TEXT) {
|
||||
args.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, text);
|
||||
} else {
|
||||
args.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, node.text() + text);
|
||||
}
|
||||
node.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, args);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
package com.stardust.uiautomator;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.pm.InstrumentationInfo;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/5/9.
|
||||
*/
|
||||
|
||||
public class Test {
|
||||
|
||||
|
||||
private void runTests(Context context) {
|
||||
final String packageName = context.getPackageName();
|
||||
final List<InstrumentationInfo> list =
|
||||
context.getPackageManager().queryInstrumentation(packageName, 0);
|
||||
if (list.isEmpty()) {
|
||||
Toast.makeText(context, "Cannot find instrumentation for " + packageName,
|
||||
Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
final InstrumentationInfo instrumentationInfo = list.get(0);
|
||||
final ComponentName componentName =
|
||||
new ComponentName(instrumentationInfo.packageName,
|
||||
instrumentationInfo.name);
|
||||
if (!context.startInstrumentation(componentName, null, null)) {
|
||||
Toast.makeText(context, "Cannot run instrumentation for " + packageName,
|
||||
Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -59,13 +59,14 @@ public class AccessibilityService extends android.accessibilityservice.Accessibi
|
||||
@Override
|
||||
public void onAccessibilityEvent(final AccessibilityEvent event) {
|
||||
Log.v(TAG, "onAccessibilityEvent: " + event);
|
||||
try {
|
||||
if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
|
||||
|| event.getEventType() == AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
|
||||
|| event.getEventType() == AccessibilityEvent.TYPE_VIEW_HOVER_EXIT) {
|
||||
AccessibilityNodeInfo root = super.getRootInActiveWindow();
|
||||
Log.v(TAG, "getRootInActiveWindow: " + root);
|
||||
if (root != null)
|
||||
if (root != null) {
|
||||
mRootInActiveWindow = root;
|
||||
} catch (Exception ignored) {
|
||||
|
||||
Log.d(TAG, "rootInActiveWindow: " + mRootInActiveWindow);
|
||||
}
|
||||
}
|
||||
if (!containsAllEventTypes && !eventTypes.contains(event.getEventType()))
|
||||
return;
|
||||
@@ -81,6 +82,7 @@ public class AccessibilityService extends android.accessibilityservice.Accessibi
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onInterrupt() {
|
||||
|
||||
|
||||
@@ -27,5 +27,5 @@ dependencies {
|
||||
})
|
||||
testCompile 'junit:junit:4.12'
|
||||
compile 'com.android.support:support-annotations:25.3.1'
|
||||
compile 'com.github.czy1121:settingscompat:1.1.4'
|
||||
compile 'com.github.hyb1996:settingscompat:1.1.5'
|
||||
}
|
||||
|
||||
76
common/src/main/java/com/stardust/util/IntentExtras.java
Normal file
76
common/src/main/java/com/stardust/util/IntentExtras.java
Normal file
@@ -0,0 +1,76 @@
|
||||
package com.stardust.util;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/7/11.
|
||||
*/
|
||||
|
||||
public class IntentExtras implements Serializable {
|
||||
|
||||
private static int mMaxId = -1;
|
||||
private static final String EXTRA_ID = "com.stardust.util.IntentExtras.id";
|
||||
private static SparseArray<Map<String, Object>> extraStore = new SparseArray<>();
|
||||
|
||||
|
||||
public static IntentExtras newExtras() {
|
||||
return new IntentExtras();
|
||||
}
|
||||
|
||||
public static IntentExtras fromIntent(Intent intent) {
|
||||
int id = intent.getIntExtra(EXTRA_ID, -1);
|
||||
if (id < 0) {
|
||||
throw new IllegalArgumentException("");
|
||||
}
|
||||
return new IntentExtras(id);
|
||||
}
|
||||
|
||||
private Map<String, Object> mMap;
|
||||
private int mId;
|
||||
|
||||
private IntentExtras() {
|
||||
mMap = new HashMap<>();
|
||||
mMaxId++;
|
||||
mId = mMaxId;
|
||||
extraStore.put(mId, mMap);
|
||||
}
|
||||
|
||||
|
||||
private IntentExtras(int id) {
|
||||
mMap = extraStore.get(id);
|
||||
mMaxId = id;
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T get(String key) {
|
||||
return (T) mMap.get(key);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T getAndClear(String key) {
|
||||
T value = (T) mMap.get(key);
|
||||
clear();
|
||||
return value;
|
||||
}
|
||||
|
||||
public IntentExtras put(String key, Object value) {
|
||||
mMap.put(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Intent putInIntent(Intent intent) {
|
||||
intent.putExtra(EXTRA_ID, mMaxId);
|
||||
return intent;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
extraStore.remove(mId);
|
||||
mMap = null;
|
||||
}
|
||||
}
|
||||
@@ -49,6 +49,19 @@ public class ScreenMetrics {
|
||||
return y * deviceScreenHeight / height;
|
||||
}
|
||||
|
||||
public static int rescaleX(int x, int width) {
|
||||
if (width == 0 || !initialized)
|
||||
return x;
|
||||
return x * width / deviceScreenWidth;
|
||||
}
|
||||
|
||||
public static int rescaleY(int y, int height) {
|
||||
if (height == 0 || !initialized)
|
||||
return y;
|
||||
return y * height / deviceScreenHeight;
|
||||
}
|
||||
|
||||
|
||||
private int mScreenWidth;
|
||||
private int mScreenHeight;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user