新增 特性continuation
This commit is contained in:
@@ -2,23 +2,22 @@ var global = this;
|
|||||||
|
|
||||||
runtime.init();
|
runtime.init();
|
||||||
|
|
||||||
(function(){
|
(function () {
|
||||||
//重定向importClass使得其支持字符串参数
|
//重定向importClass使得其支持字符串参数
|
||||||
global.importClass =
|
global.importClass =
|
||||||
(function(){
|
(function () {
|
||||||
var __importClass__ = importClass;
|
var __importClass__ = importClass;
|
||||||
return function(pack){
|
return function (pack) {
|
||||||
if(typeof(pack) == "string"){
|
if (typeof (pack) == "string") {
|
||||||
__importClass__(Packages[pack]);
|
__importClass__(Packages[pack]);
|
||||||
}else{
|
} else {
|
||||||
__importClass__(pack);
|
__importClass__(pack);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
})();
|
||||||
})();
|
|
||||||
|
|
||||||
|
|
||||||
//初始化不依赖环境的模块
|
//初始化不依赖环境的模块
|
||||||
global.Promise = require('promise.js');
|
|
||||||
global.JSON = require('__json2__.js');
|
global.JSON = require('__json2__.js');
|
||||||
global.util = require('__util__.js');
|
global.util = require('__util__.js');
|
||||||
global.device = runtime.device;
|
global.device = runtime.device;
|
||||||
@@ -27,26 +26,32 @@ runtime.init();
|
|||||||
runtime.bridges.setBridges(require('__bridges__.js'));
|
runtime.bridges.setBridges(require('__bridges__.js'));
|
||||||
|
|
||||||
//一些内部函数
|
//一些内部函数
|
||||||
global.__asGlobal__ = function(obj, functions){
|
global.__asGlobal__ = function (obj, functions) {
|
||||||
var len = functions.length;
|
var len = functions.length;
|
||||||
for(var i = 0; i < len; i++) {
|
for (var i = 0; i < len; i++) {
|
||||||
var funcName = functions[i];
|
var funcName = functions[i];
|
||||||
if(obj[funcName]){
|
var func = obj[funcName]
|
||||||
global[funcName] = obj[funcName].bind(obj);
|
if (!func) {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
(function (obj, funcName, func) {
|
||||||
|
global[funcName] = function () {
|
||||||
|
return func.apply(obj, arguments);
|
||||||
|
};
|
||||||
|
})(obj, funcName, func);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
global.__exitIfError__ = function(action, defReturnValue){
|
global.__exitIfError__ = function (action, defReturnValue) {
|
||||||
try{
|
try {
|
||||||
return action();
|
return action();
|
||||||
}catch(err){
|
} catch (err) {
|
||||||
if(err instanceof java.lang.Throwable){
|
if (err instanceof java.lang.Throwable) {
|
||||||
exit(err);
|
exit(err);
|
||||||
}else if(err instanceof Error){
|
} else if (err instanceof Error) {
|
||||||
exit(new org.mozilla.javascript.EvaluatorException(err.name + ": " + err.message, err.fileName, err.lineNumber));
|
exit(new org.mozilla.javascript.EvaluatorException(err.name + ": " + err.message, err.fileName, err.lineNumber));
|
||||||
//new java.lang.RuntimeException(err.name + ": " + err.message + "\n" + err.stack));
|
//new java.lang.RuntimeException(err.name + ": " + err.message + "\n" + err.stack));
|
||||||
}else{
|
} else {
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
return defReturnValue;
|
return defReturnValue;
|
||||||
@@ -56,17 +61,22 @@ runtime.init();
|
|||||||
//初始化全局函数
|
//初始化全局函数
|
||||||
require("__globals__")(runtime, global);
|
require("__globals__")(runtime, global);
|
||||||
//初始化一般模块
|
//初始化一般模块
|
||||||
(function(scope){
|
(function (scope) {
|
||||||
var modules = ['app', 'automator', 'console', 'dialogs', 'io', 'selector', 'shell', 'web', 'ui',
|
var modules = ['app', 'automator', 'console', 'dialogs', 'io', 'selector', 'shell', 'web', 'ui',
|
||||||
"images", "timers", "threads", "events", "engines", "RootAutomator", "http", "storages", "floaty",
|
"images", "timers", "threads", "events", "engines", "RootAutomator", "http", "storages", "floaty",
|
||||||
"sensors", "media", "plugins"];
|
"sensors", "media", "plugins", "continuation"];
|
||||||
var len = modules.length;
|
var len = modules.length;
|
||||||
for(var i = 0; i < len; i++) {
|
for (var i = 0; i < len; i++) {
|
||||||
var m = modules[i];
|
var m = modules[i];
|
||||||
scope[m] = require('__' + m + '__')(scope.runtime, scope);
|
scope[m] = require('__' + m + '__')(scope.runtime, scope);
|
||||||
}
|
}
|
||||||
})(global);
|
})(global);
|
||||||
|
|
||||||
|
global.Promise = require('promise.js');
|
||||||
|
global.Promise.prototype.await = function () {
|
||||||
|
return continuation.await(this);
|
||||||
|
}
|
||||||
|
|
||||||
importClass(android.view.KeyEvent);
|
importClass(android.view.KeyEvent);
|
||||||
importClass(com.stardust.autojs.core.util.Shell);
|
importClass(com.stardust.autojs.core.util.Shell);
|
||||||
importClass(android.graphics.Paint);
|
importClass(android.graphics.Paint);
|
||||||
|
|||||||
@@ -1,100 +1,107 @@
|
|||||||
module.exports = function(runtime, scope){
|
module.exports = function (runtime, scope) {
|
||||||
importPackage(Packages["okhttp3"]);
|
importPackage(Packages["okhttp3"]);
|
||||||
importClass(com.stardust.autojs.core.http.MutableOkHttp);
|
importClass(com.stardust.autojs.core.http.MutableOkHttp);
|
||||||
var http = {};
|
var http = {};
|
||||||
|
|
||||||
http.__okhttp__ = new MutableOkHttp();
|
http.__okhttp__ = new MutableOkHttp();
|
||||||
|
|
||||||
http.get = function(url, options, callback){
|
http.get = function (url, options, callback) {
|
||||||
options = options || {};
|
options = options || {};
|
||||||
options.method = "GET";
|
options.method = "GET";
|
||||||
return http.request(url, options, callback);
|
return http.request(url, options, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
http.client = function(){
|
http.client = function () {
|
||||||
return http.__okhttp__.client();
|
return http.__okhttp__.client();
|
||||||
}
|
}
|
||||||
|
|
||||||
http.post = function(url, data, options, callback){
|
http.post = function (url, data, options, callback) {
|
||||||
options = options || {};
|
options = options || {};
|
||||||
options.method = "POST";
|
options.method = "POST";
|
||||||
options.contentType = options.contentType || "application/x-www-form-urlencoded";
|
options.contentType = options.contentType || "application/x-www-form-urlencoded";
|
||||||
if(data){
|
if (data) {
|
||||||
fillPostData(options, data);
|
fillPostData(options, data);
|
||||||
}
|
}
|
||||||
return http.request(url, options, callback);
|
return http.request(url, options, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
http.postJson = function(url, data, options, callback){
|
http.postJson = function (url, data, options, callback) {
|
||||||
options = options || {};
|
options = options || {};
|
||||||
options.contentType = "application/json";
|
options.contentType = "application/json";
|
||||||
return http.post(url, data, options, callback);
|
return http.post(url, data, options, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
http.postMultipart = function(url, files, options, callback){
|
http.postMultipart = function (url, files, options, callback) {
|
||||||
options = options || {};
|
options = options || {};
|
||||||
options.method = "POST";
|
options.method = "POST";
|
||||||
options.contentType = "multipart/form-data";
|
options.contentType = "multipart/form-data";
|
||||||
options.files = files;
|
options.files = files;
|
||||||
return http.request(url, options, callback);
|
return http.request(url, options, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
http.request = function(url, options, callback){
|
http.request = function (url, options, callback) {
|
||||||
if(!callback && ui.isUiThread()){
|
var cont = null;
|
||||||
throw new Error("不能在ui线程执行网络操作,请加上回调函数的参数callback或在子线程执行");
|
if (!callback && ui.isUiThread()) {
|
||||||
|
cont = continuation.create();
|
||||||
}
|
}
|
||||||
var call = http.client().newCall(http.buildRequest(url, options));
|
var call = http.client().newCall(http.buildRequest(url, options));
|
||||||
if(!callback){
|
if (!callback && !cont) {
|
||||||
return wrapResponse(call.execute());
|
return wrapResponse(call.execute());
|
||||||
}
|
}
|
||||||
call.enqueue(new Callback({
|
call.enqueue(new Callback({
|
||||||
onResponse: function(call, res){
|
onResponse: function (call, res) {
|
||||||
callback(wrapResponse(res));
|
res = wrapResponse(res);
|
||||||
|
cont && cont.resume(res);
|
||||||
|
callback && callback(res);
|
||||||
},
|
},
|
||||||
onFailure: function(call, ex){
|
onFailure: function (call, ex) {
|
||||||
callback(null, ex);
|
cont && cont.resumeError(ex);
|
||||||
|
callback && callback(null, ex);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
if(cont) {
|
||||||
|
return cont.await();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
http.buildRequest = function(url, options){
|
http.buildRequest = function (url, options) {
|
||||||
var r = new Request.Builder();
|
var r = new Request.Builder();
|
||||||
if(!url.startsWith("http://") && !url.startsWith("https://")){
|
if (!url.startsWith("http://") && !url.startsWith("https://")) {
|
||||||
url = "http://" + url;
|
url = "http://" + url;
|
||||||
}
|
}
|
||||||
r.url(url);
|
r.url(url);
|
||||||
if(options.headers){
|
if (options.headers) {
|
||||||
setHeaders(r, options.headers);
|
setHeaders(r, options.headers);
|
||||||
}
|
}
|
||||||
if(options.body){
|
if (options.body) {
|
||||||
r.method(options.method, parseBody(options, options.body));
|
r.method(options.method, parseBody(options, options.body));
|
||||||
}else if(options.files){
|
} else if (options.files) {
|
||||||
r.method(options.method, parseMultipart(options.files));
|
r.method(options.method, parseMultipart(options.files));
|
||||||
}else {
|
} else {
|
||||||
r.method(options.method, null);
|
r.method(options.method, null);
|
||||||
}
|
}
|
||||||
return r.build();
|
return r.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseMultipart(files){
|
function parseMultipart(files) {
|
||||||
var builder = new MultipartBody.Builder()
|
var builder = new MultipartBody.Builder()
|
||||||
.setType(MultipartBody.FORM);
|
.setType(MultipartBody.FORM);
|
||||||
for(var key in files){
|
for (var key in files) {
|
||||||
if(!files.hasOwnProperty(key)){
|
if (!files.hasOwnProperty(key)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var value = files[key];
|
var value = files[key];
|
||||||
if(typeof(value) == 'string'){
|
if (typeof (value) == 'string') {
|
||||||
builder.addFormDataPart(key, value);
|
builder.addFormDataPart(key, value);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var path, mimeType, fileName;
|
var path, mimeType, fileName;
|
||||||
if(typeof(value.getPath) == 'function'){
|
if (typeof (value.getPath) == 'function') {
|
||||||
path = value.getPath();
|
path = value.getPath();
|
||||||
}else if(value.length == 2){
|
} else if (value.length == 2) {
|
||||||
fileName = value[0];
|
fileName = value[0];
|
||||||
path = value[1];
|
path = value[1];
|
||||||
}else if(value.length >= 3){
|
} else if (value.length >= 3) {
|
||||||
fileName = value[0];
|
fileName = value[0];
|
||||||
mimeType = value[1]
|
mimeType = value[1]
|
||||||
path = value[2];
|
path = value[2];
|
||||||
@@ -107,77 +114,77 @@ module.exports = function(runtime, scope){
|
|||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseMimeType(ext){
|
function parseMimeType(ext) {
|
||||||
if(ext.length == 0){
|
if (ext.length == 0) {
|
||||||
return "application/octet-stream";
|
return "application/octet-stream";
|
||||||
}
|
}
|
||||||
return android.webkit.MimeTypeMap.getSingleton().getMimeTypeFromExtension(ext)
|
return android.webkit.MimeTypeMap.getSingleton().getMimeTypeFromExtension(ext)
|
||||||
|| "application/octet-stream";
|
|| "application/octet-stream";
|
||||||
}
|
}
|
||||||
|
|
||||||
function fillPostData(options, data){
|
function fillPostData(options, data) {
|
||||||
if(options.contentType == "application/x-www-form-urlencoded"){
|
if (options.contentType == "application/x-www-form-urlencoded") {
|
||||||
var b = new FormBody.Builder();
|
var b = new FormBody.Builder();
|
||||||
for(var key in data){
|
for (var key in data) {
|
||||||
if(data.hasOwnProperty(key)){
|
if (data.hasOwnProperty(key)) {
|
||||||
b.add(key, data[key]);
|
b.add(key, data[key]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
options.body = b.build();
|
options.body = b.build();
|
||||||
}else if(options.contentType == "application/json"){
|
} else if (options.contentType == "application/json") {
|
||||||
options.body = JSON.stringify(data);
|
options.body = JSON.stringify(data);
|
||||||
}else{
|
} else {
|
||||||
options.body = data;
|
options.body = data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function setHeaders(r, headers){
|
function setHeaders(r, headers) {
|
||||||
for(var key in headers){
|
for (var key in headers) {
|
||||||
if(headers.hasOwnProperty(key)){
|
if (headers.hasOwnProperty(key)) {
|
||||||
let value = headers[key];
|
let value = headers[key];
|
||||||
if(Array.isArray(value)){
|
if (Array.isArray(value)) {
|
||||||
value.forEach(v => {
|
value.forEach(v => {
|
||||||
r.header(key, v);
|
r.header(key, v);
|
||||||
});
|
});
|
||||||
}else{
|
} else {
|
||||||
r.header(key, value);
|
r.header(key, value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseBody(options, body){
|
function parseBody(options, body) {
|
||||||
if(typeof(body) == "string"){
|
if (typeof (body) == "string") {
|
||||||
body = RequestBody.create(MediaType.parse(options.contentType), body);
|
body = RequestBody.create(MediaType.parse(options.contentType), body);
|
||||||
}else if(body instanceof RequestBody){
|
} else if (body instanceof RequestBody) {
|
||||||
return body;
|
return body;
|
||||||
}else{
|
} else {
|
||||||
body = new RequestBody({
|
body = new RequestBody({
|
||||||
contentType: function(){
|
contentType: function () {
|
||||||
return MediaType.parse(options.contentType);
|
return MediaType.parse(options.contentType);
|
||||||
},
|
},
|
||||||
writeTo: body
|
writeTo: body
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return body;
|
return body;
|
||||||
}
|
}
|
||||||
|
|
||||||
function wrapResponse(res){
|
function wrapResponse(res) {
|
||||||
var r = {};
|
var r = {};
|
||||||
r.statusCode = res.code();
|
r.statusCode = res.code();
|
||||||
r.statusMessage = res.message();
|
r.statusMessage = res.message();
|
||||||
var headers = res.headers();
|
var headers = res.headers();
|
||||||
r.headers = {};
|
r.headers = {};
|
||||||
for(var i = 0; i < headers.size(); i++){
|
for (var i = 0; i < headers.size(); i++) {
|
||||||
let name = headers.name(i);
|
let name = headers.name(i);
|
||||||
let value = headers.value(i);
|
let value = headers.value(i);
|
||||||
if(r.headers.hasOwnProperty(name)){
|
if (r.headers.hasOwnProperty(name)) {
|
||||||
let origin = r.headers[name];
|
let origin = r.headers[name];
|
||||||
if(!Array.isArray(origin)){
|
if (!Array.isArray(origin)) {
|
||||||
r.headers[name] = [origin];
|
r.headers[name] = [origin];
|
||||||
}
|
}
|
||||||
r.headers[name].push(value);
|
r.headers[name].push(value);
|
||||||
}else{
|
} else {
|
||||||
r.headers[name] = value;
|
r.headers[name] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -185,7 +192,7 @@ module.exports = function(runtime, scope){
|
|||||||
var body = res.body();
|
var body = res.body();
|
||||||
r.body.string = body.string.bind(body);
|
r.body.string = body.string.bind(body);
|
||||||
r.body.bytes = body.bytes.bind(body);
|
r.body.bytes = body.bytes.bind(body);
|
||||||
r.body.json = function(){
|
r.body.json = function () {
|
||||||
return JSON.parse(r.body.string());
|
return JSON.parse(r.body.string());
|
||||||
}
|
}
|
||||||
r.body.contentType = body.contentType();
|
r.body.contentType = body.contentType();
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
|
|
||||||
module.exports = function (runtime, scope) {
|
module.exports = function (runtime, scope) {
|
||||||
|
const ResultAdapter = require("result_adapter");
|
||||||
function images(){
|
function images(){
|
||||||
}
|
}
|
||||||
if(android.os.Build.VERSION.SDK_INT >= 21){
|
if(android.os.Build.VERSION.SDK_INT >= 21){
|
||||||
util.__assignFunctions__(runtime.images, images, ['requestScreenCapture', 'captureScreen', 'read', 'copy', 'load', 'clip', 'pixel'])
|
util.__assignFunctions__(runtime.images, images, ['captureScreen', 'read', 'copy', 'load', 'clip', 'pixel'])
|
||||||
}
|
}
|
||||||
images.opencvImporter = JavaImporter(
|
images.opencvImporter = JavaImporter(
|
||||||
org.opencv.core.Point,
|
org.opencv.core.Point,
|
||||||
@@ -55,6 +56,18 @@ module.exports = function (runtime, scope) {
|
|||||||
|
|
||||||
var colorFinder = javaImages.colorFinder;
|
var colorFinder = javaImages.colorFinder;
|
||||||
|
|
||||||
|
images.requestScreenCapture = function(landscape) {
|
||||||
|
let ScreenCapturer = com.stardust.autojs.core.image.capture.ScreenCapturer;
|
||||||
|
var orientation = ScreenCapturer.ORIENTATION_AUTO;
|
||||||
|
if(landscape === true){
|
||||||
|
orientation = ScreenCapturer.ORIENTATION_LANDSCAPE;
|
||||||
|
}
|
||||||
|
if(landscape === false){
|
||||||
|
orientation = ScreenCapturer.ORIENTATION_PORTRAIT;
|
||||||
|
}
|
||||||
|
return ResultAdapter.promise(javaImages.requestScreenCapture(orientation)).await();
|
||||||
|
}
|
||||||
|
|
||||||
images.save = function (img, path, format, quality) {
|
images.save = function (img, path, format, quality) {
|
||||||
format = format || "png";
|
format = format || "png";
|
||||||
quality = quality == undefined ? 100 : quality;
|
quality = quality == undefined ? 100 : quality;
|
||||||
|
|||||||
@@ -32,7 +32,10 @@ import java.util.concurrent.atomic.AtomicReference;
|
|||||||
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
|
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
|
||||||
public class ScreenCapturer {
|
public class ScreenCapturer {
|
||||||
|
|
||||||
public static final int ORIENTATION_AUTO = -1;
|
public static final int ORIENTATION_AUTO = Configuration.ORIENTATION_UNDEFINED;
|
||||||
|
public static final int ORIENTATION_LANDSCAPE = Configuration.ORIENTATION_LANDSCAPE ;
|
||||||
|
public static final int ORIENTATION_PORTRAIT = Configuration.ORIENTATION_PORTRAIT ;
|
||||||
|
|
||||||
|
|
||||||
private static final String LOG_TAG = "ScreenCapturer";
|
private static final String LOG_TAG = "ScreenCapturer";
|
||||||
private final MediaProjectionManager mProjectionManager;
|
private final MediaProjectionManager mProjectionManager;
|
||||||
|
|||||||
@@ -5,12 +5,15 @@ import android.os.Looper;
|
|||||||
import android.os.MessageQueue;
|
import android.os.MessageQueue;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.stardust.autojs.rhino.AutoJsContext;
|
||||||
import com.stardust.autojs.runtime.ScriptRuntime;
|
import com.stardust.autojs.runtime.ScriptRuntime;
|
||||||
import com.stardust.autojs.runtime.api.Threads;
|
import com.stardust.autojs.runtime.api.Threads;
|
||||||
import com.stardust.autojs.runtime.api.Timers;
|
import com.stardust.autojs.runtime.api.Timers;
|
||||||
import com.stardust.autojs.runtime.exception.ScriptInterruptedException;
|
import com.stardust.autojs.runtime.exception.ScriptInterruptedException;
|
||||||
import com.stardust.lang.ThreadCompat;
|
import com.stardust.lang.ThreadCompat;
|
||||||
|
|
||||||
|
import org.mozilla.javascript.Context;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
|
|
||||||
@@ -81,6 +84,9 @@ public class Loopers implements MessageQueue.IdleHandler {
|
|||||||
if (waitWhenIdle.get() || !waitIds.get().isEmpty()) {
|
if (waitWhenIdle.get() || !waitIds.get().isEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (((AutoJsContext) Context.getCurrentContext()).hasPendingContinuation()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
CopyOnWriteArrayList<LooperQuitHandler> handlers = looperQuitHandlers.get();
|
CopyOnWriteArrayList<LooperQuitHandler> handlers = looperQuitHandlers.get();
|
||||||
if (handlers == null) {
|
if (handlers == null) {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import android.content.Context;
|
|||||||
import android.content.ContextWrapper;
|
import android.content.ContextWrapper;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
@@ -12,7 +13,9 @@ import android.view.WindowManager;
|
|||||||
import com.afollestad.materialdialogs.DialogAction;
|
import com.afollestad.materialdialogs.DialogAction;
|
||||||
import com.afollestad.materialdialogs.MaterialDialog;
|
import com.afollestad.materialdialogs.MaterialDialog;
|
||||||
import com.afollestad.materialdialogs.Theme;
|
import com.afollestad.materialdialogs.Theme;
|
||||||
|
import com.stardust.autojs.rhino.continuation.Continuation;
|
||||||
import com.stardust.autojs.runtime.ScriptBridges;
|
import com.stardust.autojs.runtime.ScriptBridges;
|
||||||
|
import com.stardust.autojs.runtime.ScriptRuntime;
|
||||||
import com.stardust.autojs.runtime.exception.ScriptInterruptedException;
|
import com.stardust.autojs.runtime.exception.ScriptInterruptedException;
|
||||||
import com.stardust.concurrent.VolatileDispose;
|
import com.stardust.concurrent.VolatileDispose;
|
||||||
import com.stardust.util.ArrayUtils;
|
import com.stardust.util.ArrayUtils;
|
||||||
@@ -60,17 +63,22 @@ public class BlockedMaterialDialog extends MaterialDialog {
|
|||||||
private VolatileDispose<Object> mResultBox;
|
private VolatileDispose<Object> mResultBox;
|
||||||
private UiHandler mUiHandler;
|
private UiHandler mUiHandler;
|
||||||
private Object mCallback;
|
private Object mCallback;
|
||||||
|
private Continuation mContinuation;
|
||||||
private ScriptBridges mScriptBridges;
|
private ScriptBridges mScriptBridges;
|
||||||
private boolean mNotified = false;
|
private boolean mNotified = false;
|
||||||
|
|
||||||
public Builder(Context context, UiHandler uiHandler, ScriptBridges scriptBridges, Object callback) {
|
public Builder(Context context, ScriptRuntime runtime, Object callback) {
|
||||||
super(context);
|
super(context);
|
||||||
super.theme(Theme.LIGHT);
|
super.theme(Theme.LIGHT);
|
||||||
mUiHandler = uiHandler;
|
mUiHandler = runtime.uiHandler;
|
||||||
mScriptBridges = scriptBridges;
|
mScriptBridges = runtime.bridges;
|
||||||
mCallback = callback;
|
mCallback = callback;
|
||||||
if (Looper.getMainLooper() != Looper.myLooper()) {
|
if (Looper.getMainLooper() != Looper.myLooper()) {
|
||||||
mResultBox = new VolatileDispose<>();
|
mResultBox = new VolatileDispose<>();
|
||||||
|
} else {
|
||||||
|
if (mCallback == null) {
|
||||||
|
mContinuation = runtime.createContinuation();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,6 +96,9 @@ public class BlockedMaterialDialog extends MaterialDialog {
|
|||||||
if (mCallback != null) {
|
if (mCallback != null) {
|
||||||
mScriptBridges.callFunction(mCallback, null, new Object[]{r});
|
mScriptBridges.callFunction(mCallback, null, new Object[]{r});
|
||||||
}
|
}
|
||||||
|
if (mContinuation != null) {
|
||||||
|
mContinuation.resumeWith(Continuation.Result.Companion.success(r));
|
||||||
|
}
|
||||||
if (mResultBox != null) {
|
if (mResultBox != null) {
|
||||||
mResultBox.setAndNotify(r);
|
mResultBox.setAndNotify(r);
|
||||||
}
|
}
|
||||||
@@ -168,6 +179,9 @@ public class BlockedMaterialDialog extends MaterialDialog {
|
|||||||
} else {
|
} else {
|
||||||
mUiHandler.post(Builder.super::show);
|
mUiHandler.post(Builder.super::show);
|
||||||
}
|
}
|
||||||
|
if (mContinuation != null) {
|
||||||
|
mContinuation.suspend();
|
||||||
|
}
|
||||||
if (mResultBox != null) {
|
if (mResultBox != null) {
|
||||||
return mResultBox.blockedGetOrThrow(ScriptInterruptedException.class);
|
return mResultBox.blockedGetOrThrow(ScriptInterruptedException.class);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package com.stardust.autojs.core.util
|
||||||
|
|
||||||
|
import com.stardust.autojs.core.internal.Functions
|
||||||
|
|
||||||
|
class ScriptPromiseAdapter {
|
||||||
|
|
||||||
|
interface Callback {
|
||||||
|
fun call(arg: Any?)
|
||||||
|
}
|
||||||
|
|
||||||
|
private var mResolveCallback: Callback? = null
|
||||||
|
private var mRejectCallback: Callback? = null
|
||||||
|
private var mResult: Any? = UNSET
|
||||||
|
private var mError: Any? = UNSET
|
||||||
|
|
||||||
|
fun onResolve(callback: Callback): ScriptPromiseAdapter {
|
||||||
|
mResolveCallback = callback
|
||||||
|
mResult.let {
|
||||||
|
if (it !== UNSET) {
|
||||||
|
callback.call(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onReject(callback: Callback): ScriptPromiseAdapter {
|
||||||
|
mRejectCallback = callback
|
||||||
|
mError.let {
|
||||||
|
if (it !== UNSET) {
|
||||||
|
callback.call(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun resolve(result: Any?) {
|
||||||
|
mResult = result
|
||||||
|
mResolveCallback?.call(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun reject(error: Any?) {
|
||||||
|
mError = error
|
||||||
|
mRejectCallback?.call(error)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val UNSET = Object()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,6 +12,8 @@ import com.stardust.autojs.script.JavaScriptSource;
|
|||||||
import com.stardust.autojs.script.ScriptSource;
|
import com.stardust.autojs.script.ScriptSource;
|
||||||
import com.stardust.util.Callback;
|
import com.stardust.util.Callback;
|
||||||
|
|
||||||
|
import org.mozilla.javascript.ContinuationPending;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Stardust on 2017/7/28.
|
* Created by Stardust on 2017/7/28.
|
||||||
*/
|
*/
|
||||||
@@ -44,8 +46,9 @@ public class LoopBasedJavaScriptEngine extends RhinoJavaScriptEngine {
|
|||||||
Object o = LoopBasedJavaScriptEngine.super.execute((JavaScriptSource) source);
|
Object o = LoopBasedJavaScriptEngine.super.execute((JavaScriptSource) source);
|
||||||
if (callback != null)
|
if (callback != null)
|
||||||
callback.onResult(o);
|
callback.onResult(o);
|
||||||
|
} catch (ContinuationPending pending) {
|
||||||
|
pending.printStackTrace();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.d("DDDDD", "execute: " + e.getMessage());
|
|
||||||
if (callback == null) {
|
if (callback == null) {
|
||||||
throw e;
|
throw e;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import com.stardust.pio.PFiles;
|
|||||||
import com.stardust.pio.UncheckedIOException;
|
import com.stardust.pio.UncheckedIOException;
|
||||||
|
|
||||||
import org.mozilla.javascript.Context;
|
import org.mozilla.javascript.Context;
|
||||||
|
import org.mozilla.javascript.Script;
|
||||||
import org.mozilla.javascript.Scriptable;
|
import org.mozilla.javascript.Scriptable;
|
||||||
import org.mozilla.javascript.ScriptableObject;
|
import org.mozilla.javascript.ScriptableObject;
|
||||||
import org.mozilla.javascript.commonjs.module.RequireBuilder;
|
import org.mozilla.javascript.commonjs.module.RequireBuilder;
|
||||||
@@ -23,6 +24,7 @@ import org.mozilla.javascript.commonjs.module.provider.SoftCachingModuleScriptPr
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
@@ -39,7 +41,7 @@ public class RhinoJavaScriptEngine extends JavaScriptEngine {
|
|||||||
private static final String LOG_TAG = "RhinoJavaScriptEngine";
|
private static final String LOG_TAG = "RhinoJavaScriptEngine";
|
||||||
|
|
||||||
private static final String MODULES_PATH = "modules";
|
private static final String MODULES_PATH = "modules";
|
||||||
private static StringScriptSource sInitScript;
|
private static Script sInitScript;
|
||||||
private static final ConcurrentHashMap<Context, RhinoJavaScriptEngine> sContextEngineMap = new ConcurrentHashMap<>();
|
private static final ConcurrentHashMap<Context, RhinoJavaScriptEngine> sContextEngineMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
@@ -69,7 +71,8 @@ public class RhinoJavaScriptEngine extends JavaScriptEngine {
|
|||||||
Reader reader = source.getNonNullScriptReader();
|
Reader reader = source.getNonNullScriptReader();
|
||||||
try {
|
try {
|
||||||
reader = preprocess(reader);
|
reader = preprocess(reader);
|
||||||
return mContext.evaluateReader(mScriptable, reader, source.toString(), 1, null);
|
Script script = mContext.compileReader(reader, source.toString(), 1, null);
|
||||||
|
return mContext.executeScriptWithContinuations(script, mScriptable);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new UncheckedIOException(e);
|
throw new UncheckedIOException(e);
|
||||||
}
|
}
|
||||||
@@ -104,21 +107,19 @@ public class RhinoJavaScriptEngine extends JavaScriptEngine {
|
|||||||
mThread = Thread.currentThread();
|
mThread = Thread.currentThread();
|
||||||
ScriptableObject.putProperty(mScriptable, "__engine__", this);
|
ScriptableObject.putProperty(mScriptable, "__engine__", this);
|
||||||
initRequireBuilder(mContext, mScriptable);
|
initRequireBuilder(mContext, mScriptable);
|
||||||
mContext.evaluateString(mScriptable, getInitScript().getScript(), SOURCE_NAME_INIT, 1, null);
|
mContext.executeScriptWithContinuations(getInitScript(), mScriptable);
|
||||||
}
|
}
|
||||||
|
|
||||||
private JavaScriptSource getInitScript() {
|
private Script getInitScript() {
|
||||||
if (sInitScript == null || BuildConfig.DEBUG)
|
if (sInitScript == null || BuildConfig.DEBUG) {
|
||||||
sInitScript = new StringScriptSource(readInitScript());
|
try {
|
||||||
return sInitScript;
|
Reader reader = new InputStreamReader(mAndroidContext.getAssets().open("init.js"));
|
||||||
}
|
sInitScript = mContext.compileReader(reader, SOURCE_NAME_INIT, 1, null);
|
||||||
|
} catch (IOException e) {
|
||||||
private String readInitScript() {
|
throw new UncheckedIOException(e);
|
||||||
try {
|
}
|
||||||
return PFiles.read(mAndroidContext.getAssets().open("init.js"));
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
}
|
||||||
|
return sInitScript;
|
||||||
}
|
}
|
||||||
|
|
||||||
void initRequireBuilder(Context context, Scriptable scope) {
|
void initRequireBuilder(Context context, Scriptable scope) {
|
||||||
|
|||||||
@@ -4,9 +4,11 @@ import android.app.Activity;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
import androidx.appcompat.widget.Toolbar;
|
import androidx.appcompat.widget.Toolbar;
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
@@ -23,6 +25,8 @@ import com.stardust.autojs.engine.ScriptEngineManager;
|
|||||||
import com.stardust.autojs.runtime.ScriptRuntime;
|
import com.stardust.autojs.runtime.ScriptRuntime;
|
||||||
import com.stardust.autojs.script.ScriptSource;
|
import com.stardust.autojs.script.ScriptSource;
|
||||||
|
|
||||||
|
import org.mozilla.javascript.ContinuationPending;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Stardust on 2017/2/5.
|
* Created by Stardust on 2017/2/5.
|
||||||
*/
|
*/
|
||||||
@@ -84,6 +88,8 @@ public class ScriptExecuteActivity extends AppCompatActivity {
|
|||||||
try {
|
try {
|
||||||
prepare();
|
prepare();
|
||||||
doExecution();
|
doExecution();
|
||||||
|
} catch (ContinuationPending pending) {
|
||||||
|
pending.printStackTrace();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
onException(e);
|
onException(e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package com.stardust.autojs.rhino
|
||||||
|
|
||||||
|
import org.mozilla.javascript.Context
|
||||||
|
import org.mozilla.javascript.ContextFactory
|
||||||
|
import org.mozilla.javascript.ContinuationPending
|
||||||
|
import org.mozilla.javascript.Scriptable
|
||||||
|
|
||||||
|
class AutoJsContext(factory: ContextFactory?) : Context(factory) {
|
||||||
|
|
||||||
|
private val mContinuations = HashSet<Any>()
|
||||||
|
|
||||||
|
override fun captureContinuation(): ContinuationPending {
|
||||||
|
val continuationPending = super.captureContinuation()
|
||||||
|
mContinuations.add(continuationPending.continuation)
|
||||||
|
return continuationPending
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun resumeContinuation(continuation: Any, scope: Scriptable?, functionResult: Any?): Any {
|
||||||
|
mContinuations.remove(continuation)
|
||||||
|
return super.resumeContinuation(continuation, scope, functionResult)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun hasPendingContinuation(): Boolean {
|
||||||
|
return mContinuations.isNotEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val EMPTY_RUNNABLE = Runnable { }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -33,7 +33,7 @@ public class InterruptibleAndroidContextFactory extends AndroidContextFactory {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Context makeContext() {
|
protected Context makeContext() {
|
||||||
Context cx = super.makeContext();
|
Context cx = new AutoJsContext(this);
|
||||||
cx.setInstructionObserverThreshold(10000);
|
cx.setInstructionObserverThreshold(10000);
|
||||||
return cx;
|
return cx;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
package com.stardust.autojs.rhino.continuation
|
||||||
|
|
||||||
|
import com.stardust.autojs.core.looper.Timer
|
||||||
|
import com.stardust.autojs.core.looper.TimerThread
|
||||||
|
import com.stardust.autojs.rhino.AutoJsContext
|
||||||
|
import com.stardust.autojs.runtime.ScriptRuntime
|
||||||
|
|
||||||
|
import org.mozilla.javascript.Context
|
||||||
|
import org.mozilla.javascript.ContinuationPending
|
||||||
|
import org.mozilla.javascript.Scriptable
|
||||||
|
|
||||||
|
class Continuation(val context: AutoJsContext, val scope: Scriptable, private val mTimer: Timer) {
|
||||||
|
var pending: ContinuationPending? = null
|
||||||
|
private set
|
||||||
|
private val mThread: Thread = Thread.currentThread()
|
||||||
|
|
||||||
|
class Result(val result: Any?, val error: Any?) {
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
fun success(result: Any?): Result {
|
||||||
|
return Result(result, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun failure(error: Any?): Result {
|
||||||
|
return Result(null, error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun suspend() {
|
||||||
|
if (pending != null) {
|
||||||
|
throw IllegalStateException("call suspend twice!")
|
||||||
|
}
|
||||||
|
context.captureContinuation().let {
|
||||||
|
pending = it
|
||||||
|
throw it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun resumeWith(result: Result) {
|
||||||
|
val continuation = pending?.continuation
|
||||||
|
?: throw IllegalStateException("call resume() without suspend()!")
|
||||||
|
if (mThread == Thread.currentThread()) {
|
||||||
|
context.resumeContinuation(continuation, scope, result)
|
||||||
|
} else {
|
||||||
|
mTimer.postDelayed({
|
||||||
|
context.resumeContinuation(continuation, scope, result)
|
||||||
|
}, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
fun create(runtime: ScriptRuntime, scope: Scriptable): Continuation {
|
||||||
|
val context = Context.getCurrentContext() as AutoJsContext
|
||||||
|
return Continuation(context, scope, runtime.timers.timerForCurrentThread)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,7 +7,6 @@ package com.stardust.autojs.runtime;
|
|||||||
public class ScriptBridges {
|
public class ScriptBridges {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public interface Bridges {
|
public interface Bridges {
|
||||||
|
|
||||||
Object[] NO_ARGUMENTS = new Object[0];
|
Object[] NO_ARGUMENTS = new Object[0];
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
package com.stardust.autojs.runtime;
|
package com.stardust.autojs.runtime;
|
||||||
|
|
||||||
import android.Manifest;
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
@@ -13,10 +11,10 @@ import com.stardust.autojs.ScriptEngineService;
|
|||||||
import com.stardust.autojs.annotation.ScriptVariable;
|
import com.stardust.autojs.annotation.ScriptVariable;
|
||||||
import com.stardust.autojs.core.accessibility.AccessibilityBridge;
|
import com.stardust.autojs.core.accessibility.AccessibilityBridge;
|
||||||
import com.stardust.autojs.core.image.Colors;
|
import com.stardust.autojs.core.image.Colors;
|
||||||
import com.stardust.autojs.core.permission.PermissionRequestProxyActivity;
|
|
||||||
import com.stardust.autojs.core.permission.Permissions;
|
import com.stardust.autojs.core.permission.Permissions;
|
||||||
import com.stardust.autojs.rhino.AndroidClassLoader;
|
import com.stardust.autojs.rhino.AndroidClassLoader;
|
||||||
import com.stardust.autojs.rhino.TopLevelScope;
|
import com.stardust.autojs.rhino.TopLevelScope;
|
||||||
|
import com.stardust.autojs.rhino.continuation.Continuation;
|
||||||
import com.stardust.autojs.runtime.api.AbstractShell;
|
import com.stardust.autojs.runtime.api.AbstractShell;
|
||||||
import com.stardust.autojs.runtime.api.AppUtils;
|
import com.stardust.autojs.runtime.api.AppUtils;
|
||||||
import com.stardust.autojs.runtime.api.Console;
|
import com.stardust.autojs.runtime.api.Console;
|
||||||
@@ -54,6 +52,7 @@ import com.stardust.view.accessibility.AccessibilityInfoProvider;
|
|||||||
import org.mozilla.javascript.ContextFactory;
|
import org.mozilla.javascript.ContextFactory;
|
||||||
import org.mozilla.javascript.RhinoException;
|
import org.mozilla.javascript.RhinoException;
|
||||||
import org.mozilla.javascript.ScriptStackElement;
|
import org.mozilla.javascript.ScriptStackElement;
|
||||||
|
import org.mozilla.javascript.Scriptable;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -62,13 +61,9 @@ import java.io.PrintWriter;
|
|||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
import static android.content.pm.PackageManager.PERMISSION_DENIED;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Stardust on 2017/1/27.
|
* Created by Stardust on 2017/1/27.
|
||||||
@@ -407,8 +402,8 @@ public class ScriptRuntime {
|
|||||||
ignoresException(floaty::closeAll);
|
ignoresException(floaty::closeAll);
|
||||||
try {
|
try {
|
||||||
events.emit("exit");
|
events.emit("exit");
|
||||||
} catch (Throwable ignored) {
|
} catch (Throwable e) {
|
||||||
console.error("exception on exit: ", ignored);
|
console.error("exception on exit: ", e);
|
||||||
}
|
}
|
||||||
ignoresException(threads::shutDownAll);
|
ignoresException(threads::shutDownAll);
|
||||||
ignoresException(events::recycle);
|
ignoresException(events::recycle);
|
||||||
@@ -451,6 +446,15 @@ public class ScriptRuntime {
|
|||||||
return mProperties.remove(key);
|
return mProperties.remove(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Continuation createContinuation() {
|
||||||
|
return Continuation.Companion.create(this, mTopLevelScope);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Continuation createContinuation(Scriptable scope) {
|
||||||
|
return Continuation.Companion.create(this, scope);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static String getStackTrace(Throwable e, boolean printJavaStackTrace) {
|
public static String getStackTrace(Throwable e, boolean printJavaStackTrace) {
|
||||||
String message = e.getMessage();
|
String message = e.getMessage();
|
||||||
StringBuilder scriptTrace = new StringBuilder(message == null ? "" : message + "\n");
|
StringBuilder scriptTrace = new StringBuilder(message == null ? "" : message + "\n");
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ public class Dialogs {
|
|||||||
if (context == null || ((Activity) context).isFinishing()) {
|
if (context == null || ((Activity) context).isFinishing()) {
|
||||||
context = getContext();
|
context = getContext();
|
||||||
}
|
}
|
||||||
return (BlockedMaterialDialog.Builder) new BlockedMaterialDialog.Builder(context, mRuntime.uiHandler, mRuntime.bridges, callback)
|
return (BlockedMaterialDialog.Builder) new BlockedMaterialDialog.Builder(context, mRuntime, callback)
|
||||||
.theme(Theme.LIGHT);
|
.theme(Theme.LIGHT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package com.stardust.autojs.runtime.api;
|
|||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.Configuration;
|
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.BitmapFactory;
|
import android.graphics.BitmapFactory;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
@@ -12,7 +11,9 @@ import android.media.Image;
|
|||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
|
|
||||||
import androidx.annotation.RequiresApi;
|
import androidx.annotation.RequiresApi;
|
||||||
|
|
||||||
import android.util.Base64;
|
import android.util.Base64;
|
||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
|
|
||||||
@@ -25,8 +26,8 @@ import com.stardust.autojs.core.image.capture.ScreenCapturer;
|
|||||||
import com.stardust.autojs.core.opencv.Mat;
|
import com.stardust.autojs.core.opencv.Mat;
|
||||||
import com.stardust.autojs.core.opencv.OpenCVHelper;
|
import com.stardust.autojs.core.opencv.OpenCVHelper;
|
||||||
import com.stardust.autojs.core.ui.inflater.util.Drawables;
|
import com.stardust.autojs.core.ui.inflater.util.Drawables;
|
||||||
|
import com.stardust.autojs.core.util.ScriptPromiseAdapter;
|
||||||
import com.stardust.autojs.runtime.ScriptRuntime;
|
import com.stardust.autojs.runtime.ScriptRuntime;
|
||||||
import com.stardust.autojs.runtime.exception.ScriptInterruptedException;
|
|
||||||
import com.stardust.concurrent.VolatileDispose;
|
import com.stardust.concurrent.VolatileDispose;
|
||||||
import com.stardust.pio.UncheckedIOException;
|
import com.stardust.pio.UncheckedIOException;
|
||||||
import com.stardust.util.ScreenMetrics;
|
import com.stardust.util.ScreenMetrics;
|
||||||
@@ -70,34 +71,26 @@ public class Images {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||||
public boolean requestScreenCapture(int orientation) {
|
public ScriptPromiseAdapter requestScreenCapture(int orientation) {
|
||||||
ScriptRuntime.requiresApi(21);
|
ScriptRuntime.requiresApi(21);
|
||||||
|
ScriptPromiseAdapter promiseAdapter = new ScriptPromiseAdapter();
|
||||||
if (mScreenCapturer != null) {
|
if (mScreenCapturer != null) {
|
||||||
mScreenCapturer.setOrientation(orientation);
|
mScreenCapturer.setOrientation(orientation);
|
||||||
return true;
|
promiseAdapter.resolve(true);
|
||||||
|
return promiseAdapter;
|
||||||
}
|
}
|
||||||
final VolatileDispose<Boolean> requestResult = new VolatileDispose<>();
|
Looper servantLooper = mScriptRuntime.loopers.getServantLooper();
|
||||||
mScreenCaptureRequester.setOnActivityResultCallback((result, data) -> {
|
mScreenCaptureRequester.setOnActivityResultCallback((result, data) -> {
|
||||||
if (result == Activity.RESULT_OK) {
|
if (result == Activity.RESULT_OK) {
|
||||||
mScreenCapturer = new ScreenCapturer(mContext, data, orientation, ScreenMetrics.getDeviceScreenDensity(),
|
mScreenCapturer = new ScreenCapturer(mContext, data, orientation, ScreenMetrics.getDeviceScreenDensity(),
|
||||||
new Handler(mScriptRuntime.loopers.getServantLooper()));
|
new Handler(servantLooper));
|
||||||
requestResult.setAndNotify(true);
|
promiseAdapter.resolve(true);
|
||||||
} else {
|
} else {
|
||||||
requestResult.setAndNotify(false);
|
promiseAdapter.resolve(false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
mScreenCaptureRequester.request();
|
mScreenCaptureRequester.request();
|
||||||
return requestResult.blockedGetOrThrow(ScriptInterruptedException.class);
|
return promiseAdapter;
|
||||||
}
|
|
||||||
|
|
||||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
|
||||||
public boolean requestScreenCapture(boolean landscape) {
|
|
||||||
return requestScreenCapture(landscape ? Configuration.ORIENTATION_LANDSCAPE : Configuration.ORIENTATION_PORTRAIT);
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
|
||||||
public boolean requestScreenCapture() {
|
|
||||||
return requestScreenCapture(ScreenCapturer.ORIENTATION_AUTO);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||||
|
|||||||
@@ -81,14 +81,14 @@ public class Timers {
|
|||||||
|
|
||||||
public boolean hasPendingCallbacks() {
|
public boolean hasPendingCallbacks() {
|
||||||
//如果是脚本主线程,则检查所有子线程中的定时回调。mFutureCallbackUptimeMillis用来记录所有子线程中定时最久的一个。
|
//如果是脚本主线程,则检查所有子线程中的定时回调。mFutureCallbackUptimeMillis用来记录所有子线程中定时最久的一个。
|
||||||
// if (mThreads.getMainThread() == Thread.currentThread()) {
|
if (mThreads.getMainThread() == Thread.currentThread()) {
|
||||||
// return mMaxCallbackUptimeMillisForAllThreads.get() > SystemClock.uptimeMillis();
|
return mMaxCallbackUptimeMillisForAllThreads.get() > SystemClock.uptimeMillis();
|
||||||
//}
|
}
|
||||||
//否则检查当前线程的定时回调
|
// 否则检查当前线程的定时回调
|
||||||
return getTimerForCurrentThread().hasPendingCallbacks();
|
return getTimerForCurrentThread().hasPendingCallbacks();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void recycle(){
|
public void recycle() {
|
||||||
mMainTimer.removeAllCallbacks();
|
mMainTimer.removeAllCallbacks();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user