6.0.1 - Alpha - 增加全局Polyfill及扩展对象

This commit is contained in:
SuperMonster003
2021-12-05 10:40:13 +08:00
parent 99a1d8490f
commit 98cf339cce
34 changed files with 664 additions and 941 deletions

5
.gitignore vendored
View File

@@ -2,6 +2,7 @@
*.exe
*.iml
*.jks
*.log
.DS_Store
.externalNativeBuild
@@ -18,4 +19,6 @@ output-metadata.json
/tools/
/local.properties
/sign.properties
/sign.properties
**/assets/declarations/

View File

@@ -98,6 +98,18 @@
[comment]: <> "Version history only shows last 3 versions"
# v6.0.1 Alpha
###### 2021/12/05
* `新增` polyfill (Object.getOwnPropertyDescriptors)
* `新增` polyfill (Array.prototype.flat)
* `新增` isInteger/isNullish/isPlainObject/isPrimitive/isReference
* `优化` 扩展global.sleep支持随机范围/负数兼容
* `优化` 扩展global.toast支持时长控制/强制覆盖控制/dismiss方法
* `优化` 包名对象全局化 (okhttp3/androidx/de)
* `优化` 升级 Android Material 版本 1.5.0-beta01 -> 1.6.0-alpha01
# v6.0.0
###### 2021/12/01

View File

@@ -115,6 +115,13 @@ android {
buildConfigField "String", "APP_SINCE_DATE", "\"${versions.appSinceDate}\""
}
}
applicationVariants.all { variant ->
variant.mergeAssetsProvider.configure {
doLast {
delete(fileTree(dir: outputDir, includes: ['declarations/**']))
}
}
}
}
repositories {
@@ -138,7 +145,7 @@ dependencies {
// Android supports
implementation "androidx.appcompat:appcompat:1.4.0"
implementation "androidx.cardview:cardview:1.0.0"
implementation "com.google.android.material:material:1.5.0-beta01"
implementation "com.google.android.material:material:1.6.0-alpha01"
implementation "androidx.multidex:multidex:2.0.1"
// Material Dialogs

View File

@@ -4,6 +4,18 @@
******
# v6.0.1 Alpha
###### 2021/12/05
* `新增` polyfill (Object.getOwnPropertyDescriptors)
* `新增` polyfill (Array.prototype.flat)
* `新增` isInteger/isNullish/isPlainObject/isPrimitive/isReference
* `优化` 扩展global.sleep支持随机范围/负数兼容
* `优化` 扩展global.toast支持时长控制/强制覆盖控制/dismiss方法
* `优化` 包名对象全局化 (okhttp3/androidx/de)
* `优化` 升级 Android Material 版本 1.5.0-beta01 -> 1.6.0-alpha01
# v6.0.0
###### 2021/12/01

View File

@@ -49,7 +49,7 @@ public abstract class LayoutInspectTileService extends TileService implements La
public void onClick() {
super.onClick();
Log.d(getClass().getName(), "onClick");
sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
// sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
if (AccessibilityService.Companion.getInstance() == null) {
Toast.makeText(this, R.string.text_no_accessibility_permission_to_capture, Toast.LENGTH_SHORT).show();
AccessibilityServiceTool.goToAccessibilitySetting();
@@ -83,7 +83,6 @@ public abstract class LayoutInspectTileService extends TileService implements La
inactive();
}
});
}
protected abstract FullScreenFloatyWindow onCreateWindow(NodeInfo capture);

View File

@@ -5,6 +5,7 @@ import android.content.Context;
import android.text.TextUtils;
import com.stardust.app.GlobalAppContext;
import org.autojs.autojs.Pref;
import org.autojs.autojs.R;
@@ -35,7 +36,7 @@ public class AccessibilityServiceTool {
public static void goToAccessibilitySetting() {
Context context = GlobalAppContext.get();
if (Pref.isFirstGoToAccessibilitySetting()) {
GlobalAppContext.toast(context.getString(R.string.text_please_choose) + context.getString(R.string.app_name));
GlobalAppContext.toast(context.getString(R.string.text_please_choose) + " " + context.getString(R.string.app_name));
}
try {
AccessibilityServiceUtils.INSTANCE.goToAccessibilitySetting(context);
@@ -44,16 +45,18 @@ public class AccessibilityServiceTool {
}
}
private static final String cmd = "enabled=$(settings get secure enabled_accessibility_services)\n" +
"pkg=%s\n" +
"if [[ $enabled == *$pkg* ]]\n" +
"then\n" +
"echo already_enabled\n" +
"else\n" +
"enabled=$pkg:$enabled\n" +
"settings put secure enabled_accessibility_services $enabled\n" +
"fi\n" +
"settings put secure accessibility_enabled 1";
private static final String cmd = """
enabled=$(settings get secure enabled_accessibility_services)
pkg=%s
if [[ $enabled == *$pkg* ]]
then
echo already_enabled
else
enabled=$pkg:$enabled
settings put secure enabled_accessibility_services $enabled
fi
settings put secure accessibility_enabled 1
""";
public static boolean enableAccessibilityServiceByRoot(Class<? extends android.accessibilityservice.AccessibilityService> accessibilityService) {
String serviceName = GlobalAppContext.get().getPackageName() + "/" + accessibilityService.getName();

View File

@@ -18,13 +18,15 @@ public class RootTool {
}
}
private static final String cmd = "enabled=$(settings get system pointer_location)\n" +
"if [[ $enabled == 1 ]]\n" +
"then\n" +
"settings put system pointer_location 0\n" +
"else\n" +
"settings put system pointer_location 1\n" +
"fi\n";
private static final String cmd = """
enabled=$(settings get system pointer_location)
if [[ $enabled == 1 ]]
then
settings put system pointer_location 0
else
settings put system pointer_location 1
fi
""";
public static void togglePointerLocation() {
try {

View File

@@ -1,136 +0,0 @@
package org.autojs.autojs.tool;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonNull;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import java.math.BigDecimal;
import java.math.BigInteger;
public class SafeJsonElement extends JsonElement {
private final JsonElement mJsonElement;
public SafeJsonElement(JsonElement jsonElement) {
mJsonElement = jsonElement;
}
@Override
public JsonElement deepCopy() {
return null;
}
@Override
public boolean isJsonArray() {
return mJsonElement.isJsonArray();
}
@Override
public boolean isJsonObject() {
return mJsonElement.isJsonObject();
}
@Override
public boolean isJsonPrimitive() {
return mJsonElement.isJsonPrimitive();
}
@Override
public boolean isJsonNull() {
return mJsonElement.isJsonNull();
}
public JsonObject getAsJsonObject() {
return mJsonElement.getAsJsonObject();
}
public SafeJsonObject getAsSafeJsonObject() {
try {
return new SafeJsonObject(mJsonElement.getAsJsonObject());
} catch (Exception e) {
return null;
}
}
@Override
public JsonArray getAsJsonArray() {
return mJsonElement.getAsJsonArray();
}
@Override
public JsonPrimitive getAsJsonPrimitive() {
return mJsonElement.getAsJsonPrimitive();
}
@Override
public JsonNull getAsJsonNull() {
return mJsonElement.getAsJsonNull();
}
@Override
public boolean getAsBoolean() {
return mJsonElement.getAsBoolean();
}
@Override
public Number getAsNumber() {
return mJsonElement.getAsNumber();
}
@Override
public String getAsString() {
return mJsonElement.getAsString();
}
@Override
public double getAsDouble() {
return mJsonElement.getAsDouble();
}
@Override
public float getAsFloat() {
return mJsonElement.getAsFloat();
}
@Override
public long getAsLong() {
return mJsonElement.getAsLong();
}
@Override
public int getAsInt() {
return mJsonElement.getAsInt();
}
@Override
public byte getAsByte() {
return mJsonElement.getAsByte();
}
@Override
public char getAsCharacter() {
return mJsonElement.getAsCharacter();
}
@Override
public BigDecimal getAsBigDecimal() {
return mJsonElement.getAsBigDecimal();
}
@Override
public BigInteger getAsBigInteger() {
return mJsonElement.getAsBigInteger();
}
@Override
public short getAsShort() {
return mJsonElement.getAsShort();
}
@Override
public String toString() {
return mJsonElement.toString();
}
}

View File

@@ -1,161 +0,0 @@
package org.autojs.autojs.tool;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonNull;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Map;
import java.util.Set;
public class SafeJsonObject extends JsonElement {
private final JsonObject mJsonObject;
public SafeJsonObject(JsonObject jsonObject) {
mJsonObject = jsonObject;
}
public JsonObject deepCopy() {
return mJsonObject.deepCopy();
}
public void add(String property, JsonElement value) {
mJsonObject.add(property, value);
}
public JsonElement remove(String property) {
return mJsonObject.remove(property);
}
public void addProperty(String property, String value) {
mJsonObject.addProperty(property, value);
}
public void addProperty(String property, Number value) {
mJsonObject.addProperty(property, value);
}
public void addProperty(String property, Boolean value) {
mJsonObject.addProperty(property, value);
}
public void addProperty(String property, Character value) {
mJsonObject.addProperty(property, value);
}
public Set<Map.Entry<String, JsonElement>> entrySet() {
return mJsonObject.entrySet();
}
public Set<String> keySet() {
return mJsonObject.keySet();
}
public int size() {
return mJsonObject.size();
}
public boolean has(String memberName) {
return mJsonObject.has(memberName);
}
public JsonElement get(String memberName) {
return mJsonObject.get(memberName);
}
public JsonPrimitive getAsJsonPrimitive(String memberName) {
return mJsonObject.getAsJsonPrimitive(memberName);
}
public JsonArray getAsJsonArray(String memberName) {
return mJsonObject.getAsJsonArray(memberName);
}
public JsonObject getAsJsonObject(String memberName) {
return mJsonObject.getAsJsonObject(memberName);
}
public boolean isJsonArray() {
return mJsonObject.isJsonArray();
}
public boolean isJsonObject() {
return mJsonObject.isJsonObject();
}
public boolean isJsonPrimitive() {
return mJsonObject.isJsonPrimitive();
}
public boolean isJsonNull() {
return mJsonObject.isJsonNull();
}
public JsonObject getAsJsonObject() {
return mJsonObject.getAsJsonObject();
}
public JsonArray getAsJsonArray() {
return mJsonObject.getAsJsonArray();
}
public JsonPrimitive getAsJsonPrimitive() {
return mJsonObject.getAsJsonPrimitive();
}
public JsonNull getAsJsonNull() {
return mJsonObject.getAsJsonNull();
}
public boolean getAsBoolean() {
return mJsonObject.getAsBoolean();
}
public Number getAsNumber() {
return mJsonObject.getAsNumber();
}
public String getAsString() {
return mJsonObject.getAsString();
}
public double getAsDouble() {
return mJsonObject.getAsDouble();
}
public float getAsFloat() {
return mJsonObject.getAsFloat();
}
public long getAsLong() {
return mJsonObject.getAsLong();
}
public int getAsInt() {
return mJsonObject.getAsInt();
}
public byte getAsByte() {
return mJsonObject.getAsByte();
}
public char getAsCharacter() {
return mJsonObject.getAsCharacter();
}
public BigDecimal getAsBigDecimal() {
return mJsonObject.getAsBigDecimal();
}
public BigInteger getAsBigInteger() {
return mJsonObject.getAsBigInteger();
}
public short getAsShort() {
return mJsonObject.getAsShort();
}
}

View File

@@ -2,36 +2,36 @@ package org.autojs.autojs.tool;
import android.content.Context;
import android.net.DhcpInfo;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.text.format.Formatter;
import android.util.Log;
import java.math.BigInteger;
import java.net.InetAddress;
import static android.content.Context.WIFI_SERVICE;
import java.net.UnknownHostException;
import java.nio.ByteOrder;
/**
* Created by Stardust on 2017/5/11.
*/
public class WifiTool {
public static String getWifiAddress(Context context) {
WifiManager wifiMgr = (WifiManager) context.getApplicationContext().getSystemService(WIFI_SERVICE);
if(wifiMgr == null){
return null;
public static String getRouterIp(Context context) {
byte[] ipAddressByte = getIpAddressByte(context);
try {
return InetAddress.getByAddress(ipAddressByte).getHostAddress();
} catch (UnknownHostException e) {
Log.e(WifiTool.class.getSimpleName(), "Error getting Hotspot IP address ", e);
return "0.0.0.0";
}
WifiInfo wifiInfo = wifiMgr.getConnectionInfo();
int ip = wifiInfo.getIpAddress();
return Formatter.formatIpAddress(ip);
}
public static String getRouterIp(Context context){
WifiManager wifiService = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
if(wifiService == null){
return null;
private static byte[] getIpAddressByte(Context context) {
WifiManager manager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
DhcpInfo dhcp = manager.getDhcpInfo();
int ipAddress = dhcp.gateway;
if (ByteOrder.nativeOrder().equals(ByteOrder.LITTLE_ENDIAN)) {
ipAddress = Integer.reverseBytes(ipAddress);
}
DhcpInfo dhcpInfo = wifiService.getDhcpInfo();
return Formatter.formatIpAddress(dhcpInfo.gateway);
return BigInteger.valueOf(ipAddress).toByteArray();
}
}

View File

@@ -155,15 +155,14 @@ public class CircularMenu implements Recorder.OnStateChangedListener, LayoutInsp
mWindow.collapse();
if (!RootTool.isRootAvailable()) {
DialogUtils.showDialog(new NotAskAgainDialog.Builder(mContext, "CircularMenu.root")
.title(R.string.text_device_not_rooted)
.content(R.string.prompt_device_not_rooted)
.neutralText(R.string.text_device_rooted)
.positiveText(R.string.ok)
.onNeutral(((dialog, which) -> mRecorder.start()))
.title(R.string.text_no_root_access)
.content(R.string.no_root_access_for_record)
.negativeText(R.string.text_quit)
.positiveText(R.string.text_insist_on_record)
.onPositive(((dialog, which) -> mRecorder.start()))
.build());
} else {
mRecorder.start();
}
}

View File

@@ -155,9 +155,7 @@ public class DrawerFragment extends androidx.fragment.app.Fragment {
if (checked && !isAccessibilityServiceEnabled) {
enableAccessibilityService();
} else if (!checked && isAccessibilityServiceEnabled) {
if (!AccessibilityService.Companion.disable()) {
AccessibilityServiceTool.goToAccessibilitySetting();
}
disableAccessibilityService();
}
}
@@ -177,26 +175,27 @@ public class DrawerFragment extends androidx.fragment.app.Fragment {
}
boolean checked = holder.getSwitchCompat().isChecked();
if (checked && !enabled) {
if (new NotAskAgainDialog.Builder(context, "DrawerFragment.usage_stats")
.title(R.string.text_usage_stats_permission)
.content(R.string.description_usage_stats_permission)
.positiveText(R.string.ok)
.dismissListener(dialog -> {
if (context != null) {
IntentUtil.requestAppUsagePermission(context);
}
})
.show() == null) {
if (context != null) {
IntentUtil.requestAppUsagePermission(context);
}
if (getUsageStatsDialog(context) == null) {
syncSwitchState();
}
}
if (!checked && enabled) {
} else if (!checked && enabled) {
IntentUtil.requestAppUsagePermission(context);
}
}
private MaterialDialog getUsageStatsDialog(Context context) {
return new NotAskAgainDialog.Builder(context, "DrawerFragment.usage_stats")
.title(R.string.text_usage_stats_permission)
.content(R.string.description_usage_stats_permission)
.positiveText(R.string.ok)
.dismissListener(dialog -> {
if (context != null) {
IntentUtil.requestAppUsagePermission(context);
}
})
.show();
}
void showOrDismissFloatingWindow(DrawerMenuItemViewHolder holder) {
boolean isFloatingWindowShowing = FloatyWindowManger.isCircularMenuShowing();
boolean checked = holder.getSwitchCompat().isChecked();
@@ -273,6 +272,7 @@ public class DrawerFragment extends androidx.fragment.app.Fragment {
private boolean hasWriteSecureSettingsAccess() {
Context context = getContext();
if (context != null) {
@SuppressLint("WrongConstant")
int checkVal = context.checkCallingOrSelfPermission(WRITE_SECURE_SETTINGS_PERMISSION);
return checkVal == PackageManager.PERMISSION_GRANTED;
}
@@ -373,7 +373,7 @@ public class DrawerFragment extends androidx.fragment.app.Fragment {
Observable.fromCallable(() -> Pref.shouldEnableAccessibilityServiceByRoot() && !isAccessibilityServiceEnabled())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(needed -> {
if (needed) {
if (needed && RootTool.isRootAvailable()) {
enableAccessibilityServiceByRoot();
}
});
@@ -457,11 +457,17 @@ public class DrawerFragment extends androidx.fragment.app.Fragment {
}
private void enableAccessibilityService() {
if (!Pref.shouldEnableAccessibilityServiceByRoot()) {
if (Pref.shouldEnableAccessibilityServiceByRoot() && RootTool.isRootAvailable()) {
enableAccessibilityServiceByRoot();
} else {
AccessibilityServiceTool.goToAccessibilitySetting();
}
}
private void disableAccessibilityService() {
if (!AccessibilityService.Companion.disable()) {
AccessibilityServiceTool.goToAccessibilitySetting();
return;
}
enableAccessibilityServiceByRoot();
}
@SuppressLint("CheckResult")

View File

@@ -62,7 +62,7 @@
<string name="text_error">Error</string>
<string name="text_copy_debug_info">Copy debugging log</string>
<string name="text_it_is_the_developer_of_app">This is a software developer(。・・)</string>
<string name="text_please_choose">Please choose </string>
<string name="text_please_choose">Please choose</string>
<string name="text_crash">Crash~ o(≧□≦)o</string>
<string name="crash_feedback">(ಥ _ ಥ)Exit or submit a bug report or copy debugging log to the developer(≧∇≦)ノ</string>
<string name="text_clear">Clear</string>
@@ -182,6 +182,7 @@
<string name="text_stable_mode">Stable mode</string>
<string name="text_foreground_service">Foreground service</string>
<string name="text_usage_stats_permission">Usage stats access</string>
<string name="description_usage_stats_permission">Provides access to device usage history and statistics which results in currentPackage() a more accurate result</string>
<string name="text_volume_down_control">Volume down control</string>
<string name="text_task">Task</string>
<string name="text_next_run_time">Next</string>
@@ -238,6 +239,7 @@
<string name="text_time">Time</string>
<string name="text_size">Size</string>
<string name="text_type">Type</string>
<string name="text_icon">Icon</string>
<string name="text_js_file">*.js file</string>
<string name="text_notification_permission">Notification access</string>
<string name="text_permission">Permission</string>
@@ -253,4 +255,8 @@
<string name="text_failed">Failed</string>
<string name="mt_color_picker_title">Color picker</string>
<string name="mt_custom">Custom</string>
<string name="text_no_root_access">No root access</string>
<string name="no_root_access_for_record">Auto.js has no root access to record a script. Continue?</string>
<string name="text_insist_on_record">Record</string>
<string name="text_quit">Quit</string>
</resources>

View File

@@ -311,9 +311,9 @@
<string name="format_default_package_name" formatted="true">com.example.script%d</string>
<string name="text_should_not_be_empty">不能为空</string>
<string name="text_icon">图标</string>
<string name="text_device_not_rooted">设备没有root</string>
<string name="prompt_device_not_rooted">监测到您的设备没有root, 录制脚本需root权限, 是否继续?</string>
<string name="text_device_rooted">仍要录制</string>
<string name="text_no_root_access">root权限</string>
<string name="no_root_access_for_record">Auto.js无root权限, 录制脚本需root权限, 是否继续录制</string>
<string name="text_insist_on_record">录制</string>
<string name="nodebb_error_invalid_login_credentials">无效的登录凭证</string>
<string name="nodebb_error_change_password_error_length">密码太短</string>
<string name="nodebb_error_email_taken">邮箱已被占用</string>
@@ -393,7 +393,7 @@
<string name="text_run_on_package_update">应用更新时</string>
<string name="text_run_on_headset_plug">耳机插拔时</string>
<string name="text_run_on_time_tick">每分钟一次</string>
<string name="text_run_on_config_change">某些设置(屏幕方向,地区等)更改时</string>
<string name="text_run_on_config_change">某些设置 (屏幕方向, 地区等) 更改时</string>
<string name="error_pattern_syntax">正则表达式错误</string>
<string name="text_invalid_package_name">非法包名</string>
<string name="error_cannot_rename">重命名失败</string>
@@ -403,7 +403,7 @@
<string name="key_night_mode">key_night_mode</string>
<string name="text_run_on_startup">Auto.js启动时</string>
<string name="text_usage_stats_permission">查看使用情况权限</string>
<string name="description_usage_stats_permission">通过\"查看使用情况\"权限可获取本设备过去使用应用的情况从而使获取当前应用(currentPackage)更准确</string>
<string name="description_usage_stats_permission">通过\"查看使用情况\"权限可获取本设备过去使用应用的情况, 从而使\"获取当前应用\" (currentPackage) 结果更准确</string>
<string name="text_open_with">打开方式</string>
<string name="text_root">Root</string>
<string name="text_no_root">免Root</string>
@@ -421,4 +421,5 @@
<string name="text_failed">失败</string>
<string name="mt_color_picker_title">选择颜色</string>
<string name="mt_custom">自定义</string>
<string name="text_quit">放弃</string>
</resources>

View File

@@ -82,7 +82,7 @@
<string name="text_assist_clip">点击定位剪贴板</string>
<string name="text_script_stopped">Script stopped</string>
<string name="assist_mode_notice">(不会翻译)\"点击区域辅助服务\"是在要点击的区域不是文本时使用的,参见\"语法与API\"。\"点击区域辅助服务\"只有在\"自动操作服务\"开启时才有效。</string>
<string name="text_please_choose">Please choose</string>
<string name="text_please_choose">请选择</string>
<string name="text_crash">崩溃了o(≧□≦)o</string>
<string name="crash_feedback">(不会翻译)点击\"退出\"退出程序(ಥ _ ಥ)或者提交错误报告或者复制调试信息反馈给开发者(≧∇≦)ノ</string>
<string name="text_cannot_create_dialog_when_app_invisible">无法在后台显示弹框,脚本已停止运行</string>

View File

@@ -1,5 +1,7 @@
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
plugins {
id "com.android.library"
id "kotlin-android"
}
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
kotlinOptions {
@@ -45,8 +47,8 @@ dependencies {
api 'net.lingala.zip4j:zip4j:2.9.1'
api('com.afollestad.material-dialogs:core:0.9.6.0')
api 'com.google.android.material:material:1.5.0-beta01'
api 'com.afollestad.material-dialogs:core:0.9.6.0'
api 'com.google.android.material:material:1.6.0-alpha01'
api 'com.github.hyb1996:EnhancedFloaty:0.31'

View File

@@ -1,37 +1,31 @@
var global = this;
let global = this;
runtime.init();
(function () {
//重定向importClass使其支持字符串参数
global.importClass =
(function () {
var __importClass__ = importClass;
return function (pack) {
if (typeof (pack) == "string") {
__importClass__(Packages[pack]);
} else {
__importClass__(pack);
}
}
})();
!function () {
// 重定向 importClass 使其支持字符串参数
global.importClass = (function () {
let __importClass__ = importClass;
return function (pack) {
__importClass__(typeof pack === 'string' ? Packages[pack] : pack);
};
})();
//内部函数
global.__asGlobal__ = function (obj, functions) {
var len = functions.length;
for (var i = 0; i < len; i++) {
var funcName = functions[i];
var func = obj[funcName]
if (!func) {
continue;
var func = obj[funcName];
if (func) {
(function (obj, funcName, func) {
global[funcName] = function () {
return func.apply(obj, arguments);
};
})(obj, funcName, func);
}
(function (obj, funcName, func) {
global[funcName] = function () {
return func.apply(obj, arguments);
};
})(obj, funcName, func);
}
}
};
global.__exitIfError__ = function (action, defReturnValue) {
try {
@@ -40,7 +34,7 @@ runtime.init();
if (err instanceof java.lang.Throwable) {
exit(err);
} 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));
} else {
exit();
}
@@ -48,25 +42,28 @@ runtime.init();
}
};
// 初始化基础模块
global.timers = require('__timers__.js')(runtime, global);
// 初始化基础模块
global.timers = require('__timers__.js')(runtime, global);
//初始化不依赖环境的模块
global.JSON = require('json2.js');
global.util = require('__util__.js');
global.device = runtime.device;
global.Promise = require('promise.js');
//设置JavaScriptBridges用于与Java层的交互和数据转换
runtime.bridges.setBridges(require('__bridges__.js'));
//初始化不依赖环境的模块
global.JSON = require('json2.js');
global.util = require('__util__.js');
global.device = runtime.device;
global.Promise = require('promise.js');
//设置JavaScriptBridges用于与Java层的交互和数据转换
runtime.bridges.setBridges(require('__bridges__.js'));
//初始化全局函数
require("__globals__")(runtime, global);
require('__globals__')(runtime, global);
require('custom-polyfill').fill();
//初始化一般模块
(function (scope) {
var modules = ['app', 'automator', 'console', 'dialogs', 'io', 'selector', 'shell', 'web', 'ui',
"images", "threads", "events", "engines", "RootAutomator", "http", "storages", "floaty",
"sensors", "media", "plugins", "continuation"];
'images', 'threads', 'events', 'engines', 'RootAutomator', 'http', 'storages', 'floaty',
'sensors', 'media', 'plugins', 'continuation'];
var len = modules.length;
for (var i = 0; i < len; i++) {
var m = modules[i];
@@ -74,17 +71,14 @@ runtime.init();
}
})(global);
importClass(android.view.KeyEvent);
importClass(com.stardust.autojs.core.util.Shell);
importClass(android.graphics.Paint);
KeyEvent = android.view.KeyEvent;
Shell = com.stardust.autojs.core.util.Shell;
Paint = android.graphics.Paint;
Canvas = com.stardust.autojs.core.graphics.ScriptCanvas;
Image = com.stardust.autojs.core.image.ImageWrapper;
//重定向require以便支持相对路径和npm模块
Module = require("jvm-npm.js");
// 重定向require以便支持相对路径和npm模块
Module = require('jvm-npm.js');
require = Module.require;
})();
}();

View File

@@ -1,145 +1,266 @@
let Looper = android.os.Looper;
let Toast = android.widget.Toast;
let Runnable = java.lang.Runnable;
module.exports = function(runtime, global){
global.toast = function(text){
runtime.toast(text);
}
global.toastLog = function(text){
runtime.toast(text);
global.log(text);
}
global.sleep = function(t) {
if(ui.isUiThread()){
throw new Error("不能在ui线程执行阻塞操作请使用setTimeout代替");
}
runtime.sleep(t);
}
global.isStopped = function(){
return runtime.isStopped();
}
global.isShuttingDown = global.isShopped;
global.notStopped = function(){
return !isStopped();
}
global.isRunning = global.notStopped;
global.exit = runtime.exit.bind(runtime);
global.stop = global.exit;
global.setClip = function(text){
runtime.setClip(text);
}
global.getClip = function(text){
return runtime.getClip();
}
global.currentPackage = function(){
global.auto();
return runtime.info.getLatestPackage();
}
global.currentActivity = function(){
global.auto();
return runtime.info.getLatestActivity();
}
global.waitForActivity = function(activity, period){
ensureNonUiThread();
period = period || 200;
while(global.currentActivity() != activity){
sleep(period);
}
}
global.waitForPackage = function(packageName, period){
ensureNonUiThread();
period = period || 200;
while(global.currentPackage() != packageName){
sleep(period);
}
}
function ensureNonUiThread() {
if(ui.isUiThread()){
throw new Error("不能在ui线程执行阻塞操作请在子线程或子脚本执行或者使用setInterval循环检测当前activity和package");
}
}
global.random = function(min, max){
if(arguments.length == 0){
return Math.random();
}
return Math.floor(Math.random() * (max - min + 1)) + min;
}
global.setScreenMetrics = runtime.setScreenMetrics.bind(runtime);
global.requiresApi = runtime.requiresApi.bind(runtime);
global.requiresAutojsVersion = function(version){
if(typeof(version) == 'number'){
if(compare(version, app.autojs.versionCode) > 0){
throw new Error("需要Auto.js版本号" + version + "以上才能运行");
module.exports = function (runtime, global) {
let _ = {
buildTypes: {
release: 100, beta: 50, alpha: 0,
},
ensureNonUiThread() {
if (ui.isUiThread()) {
throw new Error('不能在ui线程执行阻塞操作请在子线程或子脚本执行或者使用setInterval循环检测当前activity和package');
}
}else{
if(compareVersion(version, app.autojs.versionName) > 0){
throw new Error("需要Auto.js版本" + version + "以上才能运行");
},
compareVersion(v1, v2) {
v1 = this.parseVersion(v1);
v2 = this.parseVersion(v2);
if (v1.major !== v2.major) {
return this.compare(v1.major, v2.major);
}
}
}
if (v1.minor !== v2.minor) {
return this.compare(v1.minor, v2.minor);
}
if (v1.revision !== v2.revision) {
return this.compare(v1.revision, v2.revision);
}
if (v1.buildType !== v2.buildType) {
return this.compare(v1.buildType, v2.buildType);
}
return this.compare(v1.build, v2.build);
},
compare(a, b) {
return a > b ? 1 : a < b ? -1 : 0;
},
parseVersion(v) {
const m = /(\d+)\.(\d+)\.(\d+)[ ]?(Alpha|Beta)?(\d*)/.exec(v);
if (!m) {
throw new Error('版本格式不合法: ' + v);
}
return {
major: parseInt(m[1]),
minor: parseInt(m[2]),
revision: parseInt(m[3]),
buildType: _.buildType(m[4]),
build: m[5] ? parseInt(m[5]) : 1,
};
},
buildType(str) {
if (str === 'Alpha') {
return this.buildTypes.alpha;
}
if (str === 'Beta') {
return this.buildTypes.beta;
}
return this.buildTypes.release;
},
};
var buildTypes = {
release: 100,
beta: 50,
alpha: 0
}
Object.assign(global, {
de: Packages.de,
okhttp3: Packages.okhttp3,
androidx: Packages.androidx,
toast(msg, is_long, is_forcible) {
let $ = {
cache: null,
toast(msg, is_long, is_forcible) {
this.init(arguments);
this.post();
},
/** @param {IArguments} args */
init(args) {
let [msg, is_long, is_forcible] = args;
this.message = isNullish(msg) ? '' : msg.toString();
this.is_long = this.parseIsLong(is_long);
this.is_forcible = is_forcible;
},
post() {
ui.post(() => {
new android.os.Handler(Looper.getMainLooper()).post(new Runnable({
run() {
$.is_forcible && $.dismiss();
$.cache = Toast.makeText(context, $.message, $.is_long);
$.show();
},
}));
});
},
parseIsLong(is_long) {
if (typeof is_long === 'number') {
return Number(!!is_long);
}
if (typeof is_long === 'string') {
return Number(/^l(ong)?$/i.test(is_long));
}
if (typeof is_long === 'boolean') {
return Number(is_long);
}
return 0;
},
dismiss() {
if (this.cache instanceof Toast) {
this.cache.cancel();
this.cache = null;
}
},
show() {
this.cache.show();
},
};
function compareVersion(v1, v2){
v1 = parseVersion(v1);
v2 = parseVersion(v2);
log(v1, v2);
return v1.major != v2.major ? compare(v1.major, v2.major) :
v1.minor != v2.minor ? compare(v1.minor, v2.minor) :
v1.revision != v2.revision ? compare(v1.revision, v2.revision) :
v1.buildType != v2.buildType ? compare(v1.buildType, v2.buildType) :
compare(v1.build, v2.build);
}
(function $LazY() {
this.toast = $.toast.bind($);
this.toast.dismiss = () => $.dismiss();
return this.toast;
}).apply(this, arguments);
},
toastLog(msg, is_long, is_forcible) {
this.toast.apply(this, arguments);
this.log(msg);
},
sleep(millis_min, millis_max) {
let $ = {
rex_num: /[+-]?(\d+(\.\d+)?(e\d+)?)/,
set min(v) {
this._min = Number(v);
},
get min() {
return Math.max(this._min, 0);
},
set max(v) {
this._max = Number(v);
},
get max() {
return Math.min(this._max, Number.MAX_SAFE_INTEGER);
},
sleep(min, max) {
if (this.trigger()) {
this.parseArgs(min, max);
runtime.sleep(this.min + this.rand_bound);
}
},
trigger() {
if (ui.isUiThread()) {
throw Error('不能在ui线程执行阻塞操作请使用setTimeout代替');
}
return true;
},
parseArgs(min, max) {
this.parseMin(min);
this.parseMax(max);
this.parseRandBound();
},
parseMin(min) {
if (typeof min !== 'number') {
throw TypeError('Type of millis_min must be a number');
}
this.min = min;
},
parseMax(max) {
if (typeof max === 'number') {
this.max = max;
} else if (typeof max === 'string') {
let matched = max.match(this.rex_num);
if (matched === null) {
throw TypeError('String millis_max must have a number contained');
}
let delta = Number(matched[0]);
this.max = this.min + delta;
this.min = this.min - delta;
} else {
this.max = this.min;
}
},
parseRandBound() {
this.rand_bound = Math.ceil(Math.random() * (this.max - this.min));
},
};
function compare(a, b){
return a > b ? 1 :
a < b ? -1:
0;
}
function parseVersion(v){
var m = /(\d+)\.(\d+)\.(\d+)[ ]?(Alpha|Beta)?(\d*)/.exec(v);
if(!m){
throw new Error("版本格式不合法: " + v);
}
return {
major: parseInt(m[1]),
minor: parseInt(m[2]),
revision: parseInt(m[3]),
buildType: buildType(m[4]),
build: m[5] ? parseInt(m[5]) : 1
};
}
function buildType(str){
if(str == 'Alpha'){
return buildTypes.alpha;
}
if(str == 'Beta'){
return buildTypes.beta;
}
return buildTypes.release;
}
}
(function $LazY() {
return this.sleep = $.sleep.bind($);
}).call(this, millis_min, millis_max);
},
isStopped() {
return runtime.isStopped();
},
notStopped() {
return !this.isStopped();
},
isRunning() {
return this.notStopped();
},
exit() {
return runtime.exit.apply(runtime, arguments);
},
stop() {
this.exit();
},
setClip(text) {
return runtime.setClip(text);
},
getClip() {
return runtime.getClip();
},
currentPackage() {
this.auto();
return runtime.info.getLatestPackage();
},
currentActivity() {
this.auto();
return runtime.info.getLatestActivity();
},
waitForActivity(activity, period) {
_.ensureNonUiThread();
period = period || 200;
while (this.currentActivity() !== activity) {
sleep(period);
}
},
waitForPackage(packageName, period) {
_.ensureNonUiThread();
period = period || 200;
while (this.currentPackage() !== packageName) {
sleep(period);
}
},
random(min, max) {
if (arguments.length === 0) {
return Math.random();
}
return Math.floor(Math.random() * (max - min + 1)) + min;
},
setScreenMetrics() {
return runtime.setScreenMetrics.apply(runtime, arguments);
},
requiresApi() {
return runtime.requiresApi.apply(runtime, arguments);
},
requiresAutojsVersion(version) {
if (typeof version === 'number') {
if (_.compare(version, app.autojs.versionCode) > 0) {
throw new Error('需要Auto.js版本号' + version + '以上才能运行');
}
} else {
if (_.compareVersion(version, app.autojs.versionName) > 0) {
throw new Error('需要Auto.js版本' + version + '以上才能运行');
}
}
},
isPlainObject(o) {
return Object.prototype.toString.call(o).slice(8, -1) === 'Object';
},
isInteger(o) {
return Number.isInteger(o);
},
isNullish(o) {
// nullish coalescing operator: ??
return o === null || o === undefined;
},
isPrimitive(o) {
return o !== Object(o);
},
isReference(o) {
return o === Object(o);
},
});
};

View File

@@ -0,0 +1,29 @@
module.exports = {
fill() {
if (!Object.getOwnPropertyDescriptors) {
/**
* @param {Object} o
* @return {Object.<string,PropertyDescriptor>} <!-- or {PropertyDescriptorMap} -->
*/
Object.getOwnPropertyDescriptors = function (o) {
let _descriptor = {};
Object.getOwnPropertyNames(o).forEach((k) => {
_descriptor[k] = Object.getOwnPropertyDescriptor(o, k);
});
return _descriptor;
};
}
if (!Array.prototype.flat) {
Object.defineProperty(Array.prototype, 'flat', {
value(depth) {
return (function _flat(arr, d) {
return d <= 0 ? arr : arr.reduce((a, b) => {
return a.concat(Array.isArray(b) ? _flat(b, d - 1) : b);
}, []);
})(this.slice(), depth || 1);
},
});
}
},
};

View File

@@ -35,41 +35,39 @@ public class Loopers implements MessageQueue.IdleHandler {
private static final Runnable EMPTY_RUNNABLE = () -> {
};
private volatile ThreadLocal<Boolean> waitWhenIdle = new ThreadLocal<Boolean>() {
private final ThreadLocal<Boolean> waitWhenIdle = new ThreadLocal<>() {
@Nullable
@Override
protected Boolean initialValue() {
return Looper.myLooper() == Looper.getMainLooper();
}
};
private volatile ThreadLocal<HashSet<Integer>> waitIds = new ThreadLocal<HashSet<Integer>>() {
private final ThreadLocal<HashSet<Integer>> waitIds = new ThreadLocal<>() {
@Nullable
@Override
protected HashSet<Integer> initialValue() {
return new HashSet<>();
}
};
private volatile ThreadLocal<Integer> maxWaitId = new ThreadLocal<Integer>() {
private final ThreadLocal<Integer> maxWaitId = new ThreadLocal<>() {
@Nullable
@Override
protected Integer initialValue() {
return 0;
}
};
private volatile ThreadLocal<CopyOnWriteArrayList<LooperQuitHandler>> looperQuitHandlers = new ThreadLocal<>();
private final ThreadLocal<CopyOnWriteArrayList<LooperQuitHandler>> looperQuitHandlers = new ThreadLocal<>();
private volatile Looper mServantLooper;
private Timers mTimers;
private ScriptRuntime mScriptRuntime;
private final Timers mTimers;
private LooperQuitHandler mMainLooperQuitHandler;
private Handler mMainHandler;
private Looper mMainLooper;
private Threads mThreads;
private MessageQueue mMainMessageQueue;
private final Handler mMainHandler;
private final Looper mMainLooper;
private final Threads mThreads;
private final MessageQueue mMainMessageQueue;
public Loopers(ScriptRuntime runtime) {
mTimers = runtime.timers;
mThreads = runtime.threads;
mScriptRuntime = runtime;
prepare();
mMainLooper = Looper.myLooper();
mMainHandler = new Handler();
@@ -122,9 +120,9 @@ public class Loopers implements MessageQueue.IdleHandler {
private void initServantThread() {
final Object lock = Loopers.this;
new ThreadCompat(() -> {
Looper.prepare();
final Object lock = Loopers.this;
mServantLooper = Looper.myLooper();
synchronized (lock) {
lock.notifyAll();

View File

@@ -14,12 +14,10 @@ import com.stardust.concurrent.VolatileBox;
public class Timer {
private static final String LOG_TAG = "Timer";
private SparseArray<Runnable> mHandlerCallbacks = new SparseArray<>();
private final SparseArray<Runnable> mHandlerCallbacks = new SparseArray<>();
private int mCallbackMaxId = 0;
private ScriptRuntime mRuntime;
private Handler mHandler;
private final ScriptRuntime mRuntime;
private final Handler mHandler;
private long mMaxCallbackUptimeMillis = 0;
private final VolatileBox<Long> mMaxCallbackMillisForAllThread;
@@ -39,7 +37,7 @@ public class Timer {
mCallbackMaxId++;
final int id = mCallbackMaxId;
Runnable r = () -> {
callFunction(callback, null, args);
callFunction(callback, args);
mHandlerCallbacks.remove(id);
};
mHandlerCallbacks.put(id, r);
@@ -47,15 +45,15 @@ public class Timer {
return id;
}
private void callFunction(Object callback, Object thiz, Object[] args) {
private void callFunction(Object callback, Object[] args) {
if(Looper.myLooper() == Looper.getMainLooper()){
try {
mRuntime.bridges.callFunction(callback, thiz, args);
mRuntime.bridges.callFunction(callback, null, args);
}catch (Exception e){
mRuntime.exit(e);
}
}else {
mRuntime.bridges.callFunction(callback, thiz, args);
mRuntime.bridges.callFunction(callback, null, args);
}
}
@@ -71,7 +69,7 @@ public class Timer {
public void run() {
if (mHandlerCallbacks.get(id) == null)
return;
callFunction(listener, null, args);
callFunction(listener, args);
postDelayed(this, interval);
}
};
@@ -89,9 +87,6 @@ public class Timer {
}
}
public void post(Runnable r) {
}
public boolean clearInterval(int id) {
return clearCallback(id);
@@ -101,7 +96,7 @@ public class Timer {
mCallbackMaxId++;
final int id = mCallbackMaxId;
Runnable r = () -> {
callFunction(listener, null, args);
callFunction(listener, args);
mHandlerCallbacks.remove(id);
};
mHandlerCallbacks.put(id, r);

View File

@@ -3,6 +3,7 @@ package com.stardust.autojs.core.looper;
import android.os.Handler;
import android.os.Looper;
import androidx.annotation.CallSuper;
import androidx.annotation.NonNull;
import com.stardust.autojs.engine.RhinoJavaScriptEngine;
import com.stardust.autojs.runtime.ScriptRuntime;
@@ -18,12 +19,12 @@ import java.util.concurrent.ConcurrentHashMap;
public class TimerThread extends ThreadCompat {
private static ConcurrentHashMap<Thread, Timer> sTimerMap = new ConcurrentHashMap<>();
private static final ConcurrentHashMap<Thread, Timer> sTimerMap = new ConcurrentHashMap<>();
private Timer mTimer;
private final VolatileBox<Long> mMaxCallbackUptimeMillisForAllThreads;
private final ScriptRuntime mRuntime;
private Runnable mTarget;
private final Runnable mTarget;
private boolean mRunning = false;
private final Object mRunningLock = new Object();
@@ -46,7 +47,7 @@ public class TimerThread extends ThreadCompat {
Looper.loop();
} catch (Throwable e) {
if (!ScriptInterruptedException.causedByInterrupted(e)) {
mRuntime.console.error(Thread.currentThread().toString() + ": ", e);
mRuntime.console.error(Thread.currentThread() + ": ", e);
}
} finally {
onExit();
@@ -121,6 +122,7 @@ public class TimerThread extends ThreadCompat {
}
}
@NonNull
@Override
public String toString() {
return "Thread[" + getName() + "," + getPriority() + "]";

View File

@@ -2,8 +2,9 @@ package com.stardust.autojs.core.ui.inflater.inflaters;
import android.content.res.ColorStateList;
import android.graphics.PorterDuff;
import android.os.Build;
import androidx.annotation.Nullable;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
@@ -135,31 +136,17 @@ public class BaseViewInflater<V extends View> implements ViewInflater<V> {
case "width":
case "layout_width":
switch (value) {
case "wrap_content":
layoutParams.width = ViewGroup.LayoutParams.WRAP_CONTENT;
break;
case "fill_parent":
case "match_parent":
layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
break;
default:
layoutParams.width = Dimensions.parseToPixel(value, view, parent, true);
break;
case "wrap_content" -> layoutParams.width = ViewGroup.LayoutParams.WRAP_CONTENT;
case "fill_parent", "match_parent" -> layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
default -> layoutParams.width = Dimensions.parseToPixel(value, view, parent, true);
}
break;
case "height":
case "layout_height":
switch (value) {
case "wrap_content":
layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
break;
case "fill_parent":
case "match_parent":
layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT;
break;
default:
layoutParams.height = Dimensions.parseToPixel(value, view, parent, false);
break;
case "wrap_content" -> layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
case "fill_parent", "match_parent" -> layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT;
default -> layoutParams.height = Dimensions.parseToPixel(value, view, parent, false);
}
break;
case "layout_gravity":
@@ -168,7 +155,7 @@ public class BaseViewInflater<V extends View> implements ViewInflater<V> {
} else if (parent instanceof FrameLayout) {
((FrameLayout.LayoutParams) layoutParams).gravity = Gravities.parse(value);
} else {
return setLayoutGravity(parent, view, Gravities.parse(value));
return setLayoutGravity(view, Gravities.parse(value));
}
break;
case "layout_weight":
@@ -234,37 +221,30 @@ public class BaseViewInflater<V extends View> implements ViewInflater<V> {
layoutRule = RelativeLayout.CENTER_IN_PARENT;
break;
case "layout_margin":
if (view.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) {
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) view.getLayoutParams();
if (view.getLayoutParams() instanceof ViewGroup.MarginLayoutParams params) {
int margin = Dimensions.parseToIntPixel(value, view);
params.bottomMargin = params.leftMargin = params.topMargin = params.rightMargin = margin;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
params.setMarginStart(margin);
params.setMarginEnd(margin);
}
params.setMarginStart(margin);
params.setMarginEnd(margin);
}
break;
case "layout_marginLeft":
if (view.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) {
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) view.getLayoutParams();
if (view.getLayoutParams() instanceof ViewGroup.MarginLayoutParams params) {
params.leftMargin = Dimensions.parseToIntPixel(value, view);
}
break;
case "layout_marginTop":
if (view.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) {
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) view.getLayoutParams();
if (view.getLayoutParams() instanceof ViewGroup.MarginLayoutParams params) {
params.topMargin = Dimensions.parseToIntPixel(value, view);
}
break;
case "layout_marginRight":
if (view.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) {
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) view.getLayoutParams();
if (view.getLayoutParams() instanceof ViewGroup.MarginLayoutParams params) {
params.rightMargin = Dimensions.parseToIntPixel(value, view);
}
break;
case "layout_marginBottom":
if (view.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) {
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) view.getLayoutParams();
if (view.getLayoutParams() instanceof ViewGroup.MarginLayoutParams params) {
params.bottomMargin = Dimensions.parseToIntPixel(value, view);
}
break;
@@ -293,21 +273,13 @@ public class BaseViewInflater<V extends View> implements ViewInflater<V> {
case "accessibilityTraversalBefore":
Exceptions.unsupports(view, attr, value);
case "alpha":
view.setAlpha(Float.valueOf(value));
break;
case "autofillHints":
case "autofilledHighlight":
Exceptions.unsupports(view, attr, value);
view.setAlpha(Float.parseFloat(value));
break;
case "backgroundTint":
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
view.setBackgroundTintList(ColorStateList.valueOf(Colors.parse(view, value)));
}
view.setBackgroundTintList(ColorStateList.valueOf(Colors.parse(view, value)));
break;
case "backgroundTintMode":
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
view.setBackgroundTintMode(TINT_MODES.get(value));
}
view.setBackgroundTintMode(TINT_MODES.get(value));
break;
case "checked":
if (view instanceof CompoundButton) {
@@ -315,106 +287,73 @@ public class BaseViewInflater<V extends View> implements ViewInflater<V> {
}
break;
case "clickable":
view.setClickable(Boolean.valueOf(value));
view.setClickable(Boolean.parseBoolean(value));
break;
case "contentDescription":
view.setContentDescription(Strings.parse(view, value));
break;
case "contextClickable":
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
view.setContextClickable(Boolean.valueOf(value));
}
break;
case "defaultFocusHighlightEnabled":
Exceptions.unsupports(view, attr, value);
view.setContextClickable(Boolean.parseBoolean(value));
break;
case "drawingCacheQuality":
view.setDrawingCacheQuality(DRAWABLE_CACHE_QUALITIES.get(value));
break;
case "duplicateParentState":
view.setDuplicateParentStateEnabled(Boolean.valueOf(value));
view.setDuplicateParentStateEnabled(Boolean.parseBoolean(value));
break;
case "elevation":
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
view.setElevation(Dimensions.parseToIntPixel(value, view));
}
view.setElevation(Dimensions.parseToIntPixel(value, view));
break;
case "fadeScrollbars":
view.setScrollbarFadingEnabled(Boolean.valueOf(value));
view.setScrollbarFadingEnabled(Boolean.parseBoolean(value));
break;
case "fadingEdgeLength":
view.setFadingEdgeLength(Dimensions.parseToIntPixel(value, view));
break;
case "filterTouchesWhenObscured":
view.setFilterTouchesWhenObscured(Boolean.valueOf(value));
view.setFilterTouchesWhenObscured(Boolean.parseBoolean(value));
break;
case "fitsSystemWindows":
view.setFitsSystemWindows(Boolean.valueOf(value));
view.setFitsSystemWindows(Boolean.parseBoolean(value));
break;
case "focusable":
view.setFocusable(Boolean.valueOf(value));
view.setFocusable(Boolean.parseBoolean(value));
break;
case "focusableInTouchMode":
view.setFocusableInTouchMode(Boolean.valueOf(value));
break;
case "focusedByDefault":
Exceptions.unsupports(view, attr, value);
view.setFocusableInTouchMode(Boolean.parseBoolean(value));
break;
case "forceHasOverlappingRendering":
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
view.forceHasOverlappingRendering(Boolean.valueOf(value));
}
view.forceHasOverlappingRendering(Boolean.parseBoolean(value));
break;
case "foreground":
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
view.setForeground(getDrawables().parse(view, value));
}
view.setForeground(getDrawables().parse(view, value));
break;
case "foregroundGravity":
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
view.setForegroundGravity(Gravities.parse(value));
}
view.setForegroundGravity(Gravities.parse(value));
break;
case "foregroundTint":
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
view.setForegroundTintList(ColorStateList.valueOf(Colors.parse(view, value)));
}
view.setForegroundTintList(ColorStateList.valueOf(Colors.parse(view, value)));
break;
case "foregroundTintMode":
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
view.setForegroundTintMode(TINT_MODES.get(value));
}
view.setForegroundTintMode(TINT_MODES.get(value));
break;
case "hapticFeedbackEnabled":
view.setHapticFeedbackEnabled(Boolean.valueOf(value));
view.setHapticFeedbackEnabled(Boolean.parseBoolean(value));
break;
case "importantForAccessibility":
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
view.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY.get(value));
}
break;
case "importantForAutofill":
Exceptions.unsupports(view, attr, value);
view.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY.get(value));
break;
case "isScrollContainer":
view.setScrollContainer(Boolean.valueOf(value));
view.setScrollContainer(Boolean.parseBoolean(value));
break;
case "keepScreenOn":
view.setKeepScreenOn(Boolean.valueOf(value));
break;
case "keyboardNavigationCluster":
Exceptions.unsupports(view, attr, value);
break;
case "layerType":
Exceptions.unsupports(view, attr, value);
view.setKeepScreenOn(Boolean.parseBoolean(value));
break;
case "layoutDirection":
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
view.setLayoutDirection(LAYOUT_DIRECTIONS.get(value));
}
view.setLayoutDirection(LAYOUT_DIRECTIONS.get(value));
break;
case "longClickable":
view.setLongClickable(Boolean.valueOf(value));
view.setLongClickable(Boolean.parseBoolean(value));
break;
case "minHeight":
view.setMinimumHeight(Dimensions.parseToIntPixel(value, view));
@@ -422,48 +361,13 @@ public class BaseViewInflater<V extends View> implements ViewInflater<V> {
case "minWidth":
view.setMinimumWidth(Dimensions.parseToIntPixel(value, view));
break;
case "nextClusterForward":
Exceptions.unsupports(view, attr, value);
break;
case "nextFocusDown":
Exceptions.unsupports(view, attr, value);
break;
case "nextFocusForward":
Exceptions.unsupports(view, attr, value);
break;
case "nextFocusLeft":
Exceptions.unsupports(view, attr, value);
break;
case "nextFocusRight":
Exceptions.unsupports(view, attr, value);
break;
case "nextFocusUp":
Exceptions.unsupports(view, attr, value);
break;
case "onClick":
Exceptions.unsupports(view, attr, value);
break;
case "paddingEnd":
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
view.setPaddingRelative(view.getPaddingStart(), view.getPaddingTop(),
Dimensions.parseToIntPixel(value, view), view.getPaddingBottom());
} else {
view.setPadding(view.getPaddingLeft(), view.getPaddingTop(),
Dimensions.parseToIntPixel(value, view), view.getPaddingBottom());
}
break;
case "paddingHorizontal":
case "paddingVertical":
Exceptions.unsupports(view, attr, value);
view.setPaddingRelative(view.getPaddingStart(), view.getPaddingTop(),
Dimensions.parseToIntPixel(value, view), view.getPaddingBottom());
break;
case "paddingStart":
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
view.setPaddingRelative(Dimensions.parseToIntPixel(value, view), view.getPaddingTop(),
view.getPaddingEnd(), view.getPaddingBottom());
} else {
view.setPadding(Dimensions.parseToIntPixel(value, view), view.getPaddingTop(),
view.getPaddingRight(), view.getPaddingBottom());
}
view.setPaddingRelative(Dimensions.parseToIntPixel(value, view), view.getPaddingTop(),
view.getPaddingEnd(), view.getPaddingBottom());
break;
case "requiresFadingEdge":
for (String str : value.split("\\|")) {
@@ -484,7 +388,7 @@ public class BaseViewInflater<V extends View> implements ViewInflater<V> {
view.setRotationY(Float.parseFloat(value));
break;
case "saveEnabled":
view.setSaveEnabled(Boolean.valueOf(value));
view.setSaveEnabled(Boolean.parseBoolean(value));
break;
case "scaleX":
view.setScaleX(Float.parseFloat(value));
@@ -493,9 +397,7 @@ public class BaseViewInflater<V extends View> implements ViewInflater<V> {
view.setScaleY(Float.parseFloat(value));
break;
case "scrollIndicators":
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
view.setScrollIndicators(SCROLL_INDICATORS.get(value));
}
view.setScrollIndicators(SCROLL_INDICATORS.get(value));
break;
case "scrollX":
view.setScrollX(Dimensions.parseToIntPixel(value, view));
@@ -503,24 +405,14 @@ public class BaseViewInflater<V extends View> implements ViewInflater<V> {
case "scrollY":
view.setScrollY(Dimensions.parseToIntPixel(value, view));
break;
case "scrollbarAlwaysDrawHorizontalTrack":
case "scrollbarAlwaysDrawVerticalTrack":
Exceptions.unsupports(view, attr, value);
break;
case "scrollbarDefaultDelayBeforeFade":
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
view.setScrollBarDefaultDelayBeforeFade(Integer.valueOf(value));
}
view.setScrollBarDefaultDelayBeforeFade(Integer.parseInt(value));
break;
case "scrollbarFadeDuration":
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
view.setScrollBarFadeDuration(Integer.valueOf(value));
}
view.setScrollBarFadeDuration(Integer.parseInt(value));
break;
case "scrollbarSize":
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
view.setScrollBarSize(Dimensions.parseToIntPixel(value, view));
}
view.setScrollBarSize(Dimensions.parseToIntPixel(value, view));
break;
case "scrollbarStyle":
view.setScrollBarStyle(SCROLLBARS_STYLES.get(value));
@@ -531,7 +423,7 @@ public class BaseViewInflater<V extends View> implements ViewInflater<V> {
case "scrollbarTrackVertical":
Exceptions.unsupports(view, attr, value);
case "scrollbars":
for (String str : value.split("|")) {
for (String str : value.split("\\|")) {
if (str.equals("horizontal")) {
view.setHorizontalScrollBarEnabled(true);
} else if (str.equals("vertical")) {
@@ -540,7 +432,7 @@ public class BaseViewInflater<V extends View> implements ViewInflater<V> {
}
break;
case "soundEffectsEnabled":
view.setSoundEffectsEnabled(Boolean.valueOf(value));
view.setSoundEffectsEnabled(Boolean.parseBoolean(value));
break;
case "stateListAnimator":
Exceptions.unsupports(view, attr, value);
@@ -548,21 +440,10 @@ public class BaseViewInflater<V extends View> implements ViewInflater<V> {
view.setTag(Strings.parse(view, value));
break;
case "textAlignment":
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
view.setTextAlignment(TEXT_ALIGNMENTS.get(value));
}
view.setTextAlignment(TEXT_ALIGNMENTS.get(value));
break;
case "textDirection":
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
view.setTextDirection(TEXT_DIRECTIONS.get(value));
}
break;
case "theme":
//Exceptions.unsupports(view, attr, value);
break;
case "tooltipText":
Exceptions.unsupports(view, attr, value);
view.setTextDirection(TEXT_DIRECTIONS.get(value));
break;
case "transformPivotX":
view.setPivotX(Dimensions.parseToPixel(value, view));
@@ -571,9 +452,7 @@ public class BaseViewInflater<V extends View> implements ViewInflater<V> {
view.setPivotY(Dimensions.parseToPixel(value, view));
break;
case "transitionName":
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
view.setTransitionName(Strings.parse(view, value));
}
view.setTransitionName(Strings.parse(view, value));
break;
case "translationX":
view.setTranslationX(Dimensions.parseToPixel(value, view));
@@ -582,16 +461,34 @@ public class BaseViewInflater<V extends View> implements ViewInflater<V> {
view.setTranslationY(Dimensions.parseToPixel(value, view));
break;
case "translationZ":
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
view.setTranslationZ(Dimensions.parseToPixel(value, view));
}
view.setTranslationZ(Dimensions.parseToPixel(value, view));
break;
case "visibility":
view.setVisibility(VISIBILITY.get(value));
break;
case "autofillHints":
case "autofilledHighlight":
case "tooltipText":
case "defaultFocusHighlightEnabled":
case "focusedByDefault":
case "importantForAutofill":
case "keyboardNavigationCluster":
case "layerType":
case "nextClusterForward":
case "nextFocusDown":
case "nextFocusForward":
case "nextFocusLeft":
case "nextFocusRight":
case "nextFocusUp":
case "onClick":
case "paddingHorizontal":
case "paddingVertical":
case "scrollbarAlwaysDrawHorizontalTrack":
case "scrollbarAlwaysDrawVerticalTrack":
Exceptions.unsupports(view, attr, value);
break;
default:
return false;
}
if (layoutRule != null && parent instanceof RelativeLayout) {
if (layoutTarget) {
@@ -604,7 +501,7 @@ public class BaseViewInflater<V extends View> implements ViewInflater<V> {
return true;
}
public boolean setLayoutGravity(ViewGroup parent, V view, int gravity) {
public boolean setLayoutGravity(V view, int gravity) {
try {
ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
Field field = layoutParams.getClass().getField("gravity");

View File

@@ -1,7 +1,6 @@
package com.stardust.autojs.core.ui.inflater.inflaters;
import android.animation.LayoutTransition;
import android.os.Build;
import android.view.ViewGroup;
import com.stardust.autojs.core.ui.inflater.ResourceParser;
@@ -39,22 +38,16 @@ public class ViewGroupInflater<V extends ViewGroup> extends BaseViewInflater<V>
public boolean setAttr(V view, String attr, String value, ViewGroup parent, Map<String, String> attrs) {
switch (attr) {
case "addStatesFromChildren":
view.setAddStatesFromChildren(Boolean.valueOf(value));
break;
case "alwaysDrawnWithCache":
view.setAlwaysDrawnWithCacheEnabled(Boolean.valueOf(value));
view.setAddStatesFromChildren(Boolean.parseBoolean(value));
break;
case "animateLayoutChanges":
view.setLayoutTransition(new LayoutTransition());
break;
case "animationCache":
view.setAnimationCacheEnabled(Boolean.valueOf(value));
break;
case "clipChildren":
view.setClipChildren(Boolean.valueOf(value));
view.setClipChildren(Boolean.parseBoolean(value));
break;
case "clipToPadding":
view.setClipToPadding(Boolean.valueOf(value));
view.setClipToPadding(Boolean.parseBoolean(value));
break;
case "descendantFocusability":
view.setDescendantFocusability(DESCENDANT_FOCUSABILITY.get(value));
@@ -63,15 +56,13 @@ public class ViewGroupInflater<V extends ViewGroup> extends BaseViewInflater<V>
Exceptions.unsupports(view, attr, value);
break;
case "layoutMode":
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
view.setLayoutMode(LAYOUT_MODES.get(value));
}
view.setLayoutMode(LAYOUT_MODES.get(value));
break;
case "persistentDrawingCache":
view.setPersistentDrawingCache(PERSISTENT_DRAWING_CACHE.get(value));
break;
case "splitMotionEvents":
view.setMotionEventSplittingEnabled(Boolean.valueOf(value));
view.setMotionEventSplittingEnabled(Boolean.parseBoolean(value));
break;
default:
return super.setAttr(view, attr, value, parent, attrs);

View File

@@ -9,11 +9,12 @@ import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
import android.util.Base64;
import android.view.View;
import android.widget.ImageView;
import androidx.appcompat.content.res.AppCompatResources;
import com.stardust.autojs.core.ui.inflater.ImageLoader;
import java.net.URL;
@@ -41,7 +42,6 @@ public class Drawables {
}
public Drawable parse(Context context, String value) {
Resources resources = context.getResources();
if (value.startsWith("@color/") || value.startsWith("@android:color/") || value.startsWith("#")) {
return new ColorDrawable(Colors.parse(context, value));
}
@@ -49,30 +49,29 @@ public class Drawables {
return loadAttrResources(context, value);
}
if (value.startsWith("file://")) {
return decodeImage(value.substring(7));
return decodeImage(context, value.substring(7));
}
return loadDrawableResources(context, value);
}
public Drawable loadDrawableResources(Context context, String value) {
int resId = context.getResources().getIdentifier(value, "drawable",
context.getPackageName());
if (resId == 0)
int resId = context.getResources().getIdentifier(value, "drawable", context.getPackageName());
if (resId == 0) {
throw new Resources.NotFoundException("drawable not found: " + value);
return context.getResources().getDrawable(resId);
}
return AppCompatResources.getDrawable(context, resId);
}
public Drawable loadAttrResources(Context context, String value) {
int[] attr = {context.getResources().getIdentifier(value.substring(1), "attr",
context.getPackageName())};
int[] attr = {context.getResources().getIdentifier(value.substring(1), "attr", context.getPackageName())};
TypedArray ta = context.obtainStyledAttributes(attr);
Drawable drawable = ta.getDrawable(0 /* index */);
ta.recycle();
return drawable;
}
public Drawable decodeImage(String path) {
return new BitmapDrawable(BitmapFactory.decodeFile(path));
public Drawable decodeImage(Context context, String path) {
return new BitmapDrawable(context.getResources(), BitmapFactory.decodeFile(path));
}
public Drawable parse(View view, String name) {
@@ -119,11 +118,7 @@ public class Drawables {
if (value.startsWith("http://") || value.startsWith("https://")) {
loadIntoBackground(view, Uri.parse(value));
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
view.setBackground(parse(view, value));
} else {
view.setBackgroundDrawable(parse(view, value));
}
view.setBackground(parse(view, value));
}
}

View File

@@ -7,24 +7,23 @@ import android.graphics.Point;
import android.os.Build;
import android.os.Handler;
import android.provider.Settings;
import androidx.annotation.RequiresApi;
import android.view.KeyEvent;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import com.stardust.autojs.R;
import com.stardust.autojs.core.accessibility.AccessibilityBridge;
import com.stardust.autojs.core.boardcast.BroadcastEmitter;
import com.stardust.autojs.core.eventloop.EventEmitter;
import com.stardust.autojs.core.looper.Loopers;
import com.stardust.autojs.core.looper.MainThreadProxy;
import com.stardust.autojs.core.looper.Timer;
import com.stardust.autojs.runtime.ScriptRuntime;
import com.stardust.notification.Notification;
import com.stardust.notification.NotificationListenerService;
import com.stardust.autojs.runtime.exception.ScriptException;
import com.stardust.autojs.core.inputevent.InputEventObserver;
import com.stardust.autojs.core.inputevent.TouchObserver;
import com.stardust.autojs.core.looper.Loopers;
import com.stardust.autojs.core.looper.Timer;
import com.stardust.autojs.runtime.ScriptRuntime;
import com.stardust.autojs.runtime.exception.ScriptException;
import com.stardust.notification.Notification;
import com.stardust.notification.NotificationListenerService;
import com.stardust.util.MapBuilder;
import com.stardust.view.accessibility.AccessibilityNotificationObserver;
import com.stardust.view.accessibility.AccessibilityService;
@@ -63,21 +62,20 @@ public class Events extends EventEmitter implements OnKeyListener, TouchObserver
.put(AccessibilityService.GESTURE_SWIPE_DOWN_AND_RIGHT, "down_right")
.build();
private AccessibilityBridge mAccessibilityBridge;
private Context mContext;
private final AccessibilityBridge mAccessibilityBridge;
private final Context mContext;
private TouchObserver mTouchObserver;
private long mLastTouchEventMillis;
private long mTouchEventTimeout = 10;
private boolean mListeningKey = false;
private Loopers mLoopers;
private final Loopers mLoopers;
private Handler mHandler;
private boolean mListeningNotification = false;
private boolean mListeningGesture = false;
private boolean mListeningToast = false;
private ScriptRuntime mScriptRuntime;
private final ScriptRuntime mScriptRuntime;
private volatile boolean mInterceptsAllKey = false;
private KeyInterceptor mKeyInterceptor;
private Set<String> mInterceptedKeys = new HashSet<>();
private final Set<String> mInterceptedKeys = new HashSet<>();
public final BroadcastEmitter broadcast;
@@ -99,9 +97,6 @@ public class Events extends EventEmitter implements OnKeyListener, TouchObserver
return new EventEmitter(mBridges, timer);
}
public EventEmitter emitter(MainThreadProxy mainThreadProxy) {
return new EventEmitter(mBridges, mScriptRuntime.timers.getMainTimer());
}
public void observeKey() {
if (mListeningKey)
@@ -227,9 +222,7 @@ public class Events extends EventEmitter implements OnKeyListener, TouchObserver
ensureHandler();
mLoopers.waitWhenIdle(true);
if (NotificationListenerService.Companion.getInstance() == null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
mContext.startActivity(new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS));
}
throw new ScriptException(mContext.getString(R.string.exception_notification_service_disabled));
}
NotificationListenerService.Companion.getInstance().addListener(this);
@@ -245,20 +238,6 @@ public class Events extends EventEmitter implements OnKeyListener, TouchObserver
mAccessibilityBridge.getNotificationObserver().addToastListener(this);
}
public void observeGesture() {
ScriptRuntime.requiresApi(Build.VERSION_CODES.O);
if (mListeningGesture) {
return;
}
AccessibilityService service = getAccessibilityService();
if ((service.getServiceInfo().flags & AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE) == 0) {
throw new ScriptException(mContext.getString(R.string.text_should_enable_gesture_observing));
}
service.getGestureEventDispatcher().addListener(this);
ensureHandler();
mLoopers.waitWhenIdle(true);
mListeningGesture = true;
}
public Events onNotification(Object listener) {
on("notification", listener);
@@ -286,8 +265,7 @@ public class Events extends EventEmitter implements OnKeyListener, TouchObserver
if (mListeningNotification) {
mAccessibilityBridge.getNotificationObserver().removeNotificationListener(this);
mAccessibilityBridge.getNotificationObserver().removeToastListener(this);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2
&& NotificationListenerService.Companion.getInstance() != null) {
if (NotificationListenerService.Companion.getInstance() != null) {
NotificationListenerService.Companion.getInstance().removeListener(this);
}
}
@@ -298,16 +276,10 @@ public class Events extends EventEmitter implements OnKeyListener, TouchObserver
}
mKeyInterceptor = null;
}
if (mListeningGesture) {
AccessibilityService service = mAccessibilityBridge.getService();
if (service != null) {
service.getGestureEventDispatcher().removeListener(this);
}
}
}
@Override
public void onKeyEvent(final int keyCode, final KeyEvent event) {
public void onKeyEvent(final int keyCode, @NonNull final KeyEvent event) {
mHandler.post(() -> {
String keyName = KeyEvent.keyCodeToString(keyCode).substring(8).toLowerCase();
emit(keyName, event);
@@ -331,13 +303,13 @@ public class Events extends EventEmitter implements OnKeyListener, TouchObserver
mHandler.post(() -> emit("touch", new Point(x, y)));
}
public void onNotification(final Notification notification) {
public void onNotification(@NonNull final Notification notification) {
mHandler.post(() -> emit("notification", notification));
}
@Override
public void onToast(final AccessibilityNotificationObserver.Toast toast) {
public void onToast(@NonNull final AccessibilityNotificationObserver.Toast toast) {
mHandler.post(() -> emit("toast", toast));
}

View File

@@ -55,13 +55,13 @@ public class Images {
private static final String TAG = Images.class.getSimpleName();
private ScriptRuntime mScriptRuntime;
private ScreenCaptureRequester mScreenCaptureRequester;
private final ScriptRuntime mScriptRuntime;
private final ScreenCaptureRequester mScreenCaptureRequester;
private ScreenCapturer mScreenCapturer;
private Context mContext;
private final Context mContext;
private Image mPreCapture;
private ImageWrapper mPreCaptureImage;
private ScreenMetrics mScreenMetrics;
private final ScreenMetrics mScreenMetrics;
private volatile boolean mOpenCvInitialized = false;
@ScriptVariable
@@ -169,11 +169,11 @@ public class Images {
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
if (direction == Gravity.LEFT || direction == Gravity.RIGHT) {
canvas.drawBitmap(img1.getBitmap(), 0, (height - img1.getHeight()) / 2, paint);
canvas.drawBitmap(img2.getBitmap(), img1.getWidth(), (height - img2.getHeight()) / 2, paint);
canvas.drawBitmap(img1.getBitmap(), 0, (float) (height - img1.getHeight()) / 2, paint);
canvas.drawBitmap(img2.getBitmap(), img1.getWidth(), (float) (height - img2.getHeight()) / 2, paint);
} else {
canvas.drawBitmap(img1.getBitmap(), (width - img1.getWidth()) / 2, 0, paint);
canvas.drawBitmap(img2.getBitmap(), (width - img2.getWidth()) / 2, img1.getHeight(), paint);
canvas.drawBitmap(img1.getBitmap(), (float) (width - img1.getWidth()) / 2, 0, paint);
canvas.drawBitmap(img2.getBitmap(), (float) (width - img2.getWidth()) / 2, img1.getHeight(), paint);
}
return ImageWrapper.ofBitmap(bitmap);
}
@@ -217,16 +217,12 @@ public class Images {
}
private Bitmap.CompressFormat parseImageFormat(String format) {
switch (format) {
case "png":
return Bitmap.CompressFormat.PNG;
case "jpeg":
case "jpg":
return Bitmap.CompressFormat.JPEG;
case "webp":
return Bitmap.CompressFormat.WEBP;
}
return null;
return switch (format) {
case "png" -> Bitmap.CompressFormat.PNG;
case "jpeg", "jpg" -> Bitmap.CompressFormat.JPEG;
case "webp" -> Bitmap.CompressFormat.WEBP;
default -> null;
};
}
public ImageWrapper load(String src) {
@@ -265,7 +261,7 @@ public class Images {
}
public void releaseScreenCapturer() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && mScreenCapturer != null) {
if (mScreenCapturer != null) {
mScreenCapturer.release();
}
}
@@ -367,4 +363,4 @@ public class Images {
mOpenCvInitialized = true;
Log.i(TAG, "opencv: initialized");
}
}
}

View File

@@ -5,6 +5,7 @@ import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import androidx.annotation.NonNull;
import com.stardust.autojs.core.eventloop.EventEmitter;
@@ -24,7 +25,6 @@ import java.util.Set;
public class Sensors extends EventEmitter implements Loopers.LooperQuitHandler {
public class SensorEventEmitter extends EventEmitter implements SensorEventListener {
public SensorEventEmitter(ScriptBridges bridges) {
@@ -58,25 +58,22 @@ public class Sensors extends EventEmitter implements Loopers.LooperQuitHandler {
public static final int fastest = SensorManager.SENSOR_DELAY_FASTEST;
}
private static final Map<String, Integer> SENSORS = new MapBuilder<String, Integer>()
.put("ACCELEROMETER", Sensor.TYPE_ACCELEROMETER)
.put("MAGNETIC_FIELD", Sensor.TYPE_MAGNETIC_FIELD)
.put("ORIENTATION", Sensor.TYPE_ORIENTATION)
.put("AMBIENT_TEMPERATURE", Sensor.TYPE_AMBIENT_TEMPERATURE)
.put("GRAVITY", Sensor.TYPE_GRAVITY)
.put("GYROSCOPE", Sensor.TYPE_GYROSCOPE)
.put("LIGHT", Sensor.TYPE_LIGHT)
.put("TEMPERATURE", Sensor.TYPE_TEMPERATURE)
.put("PRESSURE", Sensor.TYPE_PRESSURE)
.put("AMBIENT_TEMPERATURE", Sensor.TYPE_AMBIENT_TEMPERATURE)
.put("PROXIMITY", Sensor.TYPE_PROXIMITY)
.put("GRAVITY", Sensor.TYPE_GRAVITY)
.put("LINEAR_ACCELERATION", Sensor.TYPE_LINEAR_ACCELERATION)
.put("MAGNETIC_FIELD", Sensor.TYPE_MAGNETIC_FIELD)
.put("ORIENTATION", Sensor.TYPE_ORIENTATION)
.put("PRESSURE", Sensor.TYPE_PRESSURE)
.put("PROXIMITY", Sensor.TYPE_PROXIMITY)
.put("RELATIVE_HUMIDITY", Sensor.TYPE_RELATIVE_HUMIDITY)
.put("AMBIENT_TEMPERATURE", Sensor.TYPE_AMBIENT_TEMPERATURE)
.put("TEMPERATURE", Sensor.TYPE_AMBIENT_TEMPERATURE)
.build();
public boolean ignoresUnsupportedSensor = false;
public final Delay delay = new Delay();
private final Set<SensorEventEmitter> mSensorEventEmitters = new HashSet<>();
private final SensorManager mSensorManager;
@@ -84,7 +81,6 @@ public class Sensors extends EventEmitter implements Loopers.LooperQuitHandler {
private final SensorEventEmitter mNoOpSensorEventEmitter;
private final ScriptRuntime mScriptRuntime;
public Sensors(Context context, ScriptRuntime runtime) {
super(runtime.bridges);
mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
@@ -99,8 +95,9 @@ public class Sensors extends EventEmitter implements Loopers.LooperQuitHandler {
}
public SensorEventEmitter register(String sensorName, int delay) {
if (sensorName == null)
if (sensorName == null) {
throw new NullPointerException("sensorName = null");
}
Sensor sensor = getSensor(sensorName);
if (sensor == null) {
if (ignoresUnsupportedSensor) {
@@ -122,26 +119,19 @@ public class Sensors extends EventEmitter implements Loopers.LooperQuitHandler {
return emitter;
}
@Override
public boolean shouldQuit() {
if (mSensorEventEmitters.isEmpty()) {
return true;
}
return false;
return mSensorEventEmitters.isEmpty();
}
public Sensor getSensor(String sensorName) {
Integer type = SENSORS.get(sensorName.toUpperCase());
if (type == null)
type = getSensorTypeByReflect(sensorName);
if (type == null)
return null;
return mSensorManager.getDefaultSensor(type);
sensorName = sensorName.toUpperCase();
Integer type = SENSORS.get(sensorName);
type = type == null ? getSensorTypeByReflect(sensorName) : type;
return type == null ? null : mSensorManager.getDefaultSensor(type);
}
private Integer getSensorTypeByReflect(String sensorName) {
sensorName = sensorName.toUpperCase();
try {
Field field = Sensor.class.getField("TYPE_" + sensorName);
return (Integer) field.get(null);
@@ -151,12 +141,12 @@ public class Sensors extends EventEmitter implements Loopers.LooperQuitHandler {
}
public void unregister(SensorEventEmitter emitter) {
if (emitter == null)
return;
synchronized (mSensorEventEmitters) {
mSensorEventEmitters.remove(emitter);
if (emitter != null) {
synchronized (mSensorEventEmitters) {
mSensorEventEmitters.remove(emitter);
}
mSensorManager.unregisterListener(emitter);
}
mSensorManager.unregisterListener(emitter);
}
public void unregisterAll() {

View File

@@ -110,8 +110,8 @@ public class UI extends ProxyObject {
private class Drawables extends com.stardust.autojs.core.ui.inflater.util.Drawables {
@Override
public Drawable decodeImage(String path) {
return super.decodeImage(mRuntime.files.path(path));
public Drawable decodeImage(Context context, String path) {
return super.decodeImage(context, mRuntime.files.path(path));
}
}

View File

@@ -1,13 +1,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.stardust">
package="com.stardust"
>
<application android:allowBackup="true"
android:label="@string/app_name"
android:supportsRtl="true"
>
</application>
<application
android:allowBackup="true"
android:label="@string/app_name"
android:supportsRtl="true" />
</manifest>

View File

@@ -1,5 +1,6 @@
package com.stardust.app;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
@@ -9,6 +10,8 @@ import android.os.Looper;
import android.view.Window;
import android.view.WindowManager;
import kotlin.Suppress;
/**
* Created by Stardust on 2017/8/4.
*/
@@ -20,24 +23,17 @@ public class DialogUtils {
if (!isActivityContext(context)) {
Window window = dialog.getWindow();
int type;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
} else {
type = WindowManager.LayoutParams.TYPE_PHONE;
}
if (window != null)
int type = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
? WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
: WindowManager.LayoutParams.TYPE_PHONE;
if (window != null) {
window.setType(type);
}
}
if (Looper.getMainLooper() == Looper.myLooper()) {
dialog.show();
} else {
GlobalAppContext.post(new Runnable() {
@Override
public void run() {
dialog.show();
}
});
GlobalAppContext.post(dialog::show);
}
return dialog;
}

View File

@@ -23,21 +23,19 @@ import java.util.Objects;
* Created by Stardust on 2017/4/1.
*/
@SuppressWarnings("ResultOfMethodCallIgnored")
public class PFiles {
static final int DEFAULT_BUFFER_SIZE = 8192;
static final String DEFAULT_ENCODING = Charset.defaultCharset().name();
public static PFileInterface open(String path, String mode, String encoding, int bufferSize) {
switch (mode) {
case "r":
return new PReadableTextFile(path, encoding, bufferSize);
case "w":
return new PWritableTextFile(path, encoding, bufferSize, false);
case "a":
return new PWritableTextFile(path, encoding, bufferSize, true);
}
return null;
return switch (mode) {
case "r" -> new PReadableTextFile(path, encoding, bufferSize);
case "w" -> new PWritableTextFile(path, encoding, bufferSize, false);
case "a" -> new PWritableTextFile(path, encoding, bufferSize, true);
default -> null;
};
}
public static Object open(String path, String mode, String encoding) {

View File

@@ -107,16 +107,14 @@ public final class ResourceMonitor {
if (sHandler == null) {
sHandler = new Handler(Looper.getMainLooper());
}
sHandler.post(new Runnable() {
public final void run() {
UnclosedResourceDetectedException detectedException = new UnclosedResourceDetectedException(exception);
detectedException.fillInStackTrace();
Log.w(LOG_TAG, "UnclosedResourceDetected", detectedException);
if (sUnclosedResourceDetectedHandler != null) {
sUnclosedResourceDetectedHandler.onUnclosedResourceDetected(detectedException);
} else {
throw detectedException;
}
sHandler.post(() -> {
UnclosedResourceDetectedException detectedException = new UnclosedResourceDetectedException(exception);
detectedException.fillInStackTrace();
Log.w(LOG_TAG, "UnclosedResourceDetected", detectedException);
if (sUnclosedResourceDetectedHandler != null) {
sUnclosedResourceDetectedHandler.onUnclosedResourceDetected(detectedException);
} else {
throw detectedException;
}
});
}

View File

@@ -19,6 +19,7 @@ import com.stardust.auojs.inrt.launch.GlobalProjectLauncher
import java.util.ArrayList
import android.content.pm.PackageManager.PERMISSION_DENIED
import android.os.Looper
/**
* Created by Stardust on 2018/2/2.
@@ -34,7 +35,7 @@ class SplashActivity : AppCompatActivity() {
if (!Pref.isFirstUsing) {
main()
} else {
Handler().postDelayed({ this@SplashActivity.main() }, INIT_TIMEOUT)
Handler(Looper.myLooper()!!).postDelayed({ this@SplashActivity.main() }, INIT_TIMEOUT)
}
}