From 98cf339cce612b51a7b377c658465f5291ab8b4d Mon Sep 17 00:00:00 2001 From: SuperMonster003 <30370009+SuperMonster003@users.noreply.github.com> Date: Sun, 5 Dec 2021 10:40:13 +0800 Subject: [PATCH] =?UTF-8?q?6.0.1=20-=20Alpha=20-=20=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E5=85=A8=E5=B1=80Polyfill=E5=8F=8A=E6=89=A9=E5=B1=95=E5=AF=B9?= =?UTF-8?q?=E8=B1=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 5 +- README.md | 12 + app/build.gradle | 9 +- app/src/main/assets/doc/CHANGELOG.md | 12 + .../tile/LayoutInspectTileService.java | 3 +- .../autojs/tool/AccessibilityServiceTool.java | 25 +- .../java/org/autojs/autojs/tool/RootTool.java | 16 +- .../autojs/autojs/tool/SafeJsonElement.java | 136 ------ .../autojs/autojs/tool/SafeJsonObject.java | 161 ------- .../java/org/autojs/autojs/tool/WifiTool.java | 36 +- .../autojs/ui/floating/CircularMenu.java | 11 +- .../autojs/ui/main/drawer/DrawerFragment.java | 50 ++- app/src/main/res/values-en/strings.xml | 8 +- app/src/main/res/values/strings.xml | 11 +- app/src/main/strings.xml | 2 +- autojs/build.gradle | 10 +- autojs/src/main/assets/init.js | 88 ++-- autojs/src/main/assets/modules/__globals__.js | 399 ++++++++++++------ .../main/assets/modules/custom-polyfill.js | 29 ++ .../stardust/autojs/core/looper/Loopers.java | 22 +- .../stardust/autojs/core/looper/Timer.java | 23 +- .../autojs/core/looper/TimerThread.java | 8 +- .../inflater/inflaters/BaseViewInflater.java | 255 ++++------- .../inflater/inflaters/ViewGroupInflater.java | 19 +- .../core/ui/inflater/util/Drawables.java | 27 +- .../stardust/autojs/runtime/api/Events.java | 64 +-- .../stardust/autojs/runtime/api/Images.java | 36 +- .../stardust/autojs/runtime/api/Sensors.java | 50 +-- .../com/stardust/autojs/runtime/api/UI.java | 4 +- common/src/main/AndroidManifest.xml | 15 +- .../java/com/stardust/app/DialogUtils.java | 22 +- .../main/java/com/stardust/pio/PFiles.java | 16 +- .../com/stardust/util/ResourceMonitor.java | 18 +- .../com/stardust/auojs/inrt/SplashActivity.kt | 3 +- 34 files changed, 664 insertions(+), 941 deletions(-) delete mode 100644 app/src/main/java/org/autojs/autojs/tool/SafeJsonElement.java delete mode 100644 app/src/main/java/org/autojs/autojs/tool/SafeJsonObject.java create mode 100644 autojs/src/main/assets/modules/custom-polyfill.js diff --git a/.gitignore b/.gitignore index 2774756f..4cd3d5ce 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ *.exe *.iml *.jks +*.log .DS_Store .externalNativeBuild @@ -18,4 +19,6 @@ output-metadata.json /tools/ /local.properties -/sign.properties \ No newline at end of file +/sign.properties + +**/assets/declarations/ \ No newline at end of file diff --git a/README.md b/README.md index b7b01a2a..1ea1a8a4 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/app/build.gradle b/app/build.gradle index cfd3f6d7..8f2b3c2e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -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 diff --git a/app/src/main/assets/doc/CHANGELOG.md b/app/src/main/assets/doc/CHANGELOG.md index aa5a37fc..7a5e0f1e 100644 --- a/app/src/main/assets/doc/CHANGELOG.md +++ b/app/src/main/assets/doc/CHANGELOG.md @@ -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 diff --git a/app/src/main/java/org/autojs/autojs/external/tile/LayoutInspectTileService.java b/app/src/main/java/org/autojs/autojs/external/tile/LayoutInspectTileService.java index 26aa5768..5fcd085e 100644 --- a/app/src/main/java/org/autojs/autojs/external/tile/LayoutInspectTileService.java +++ b/app/src/main/java/org/autojs/autojs/external/tile/LayoutInspectTileService.java @@ -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); diff --git a/app/src/main/java/org/autojs/autojs/tool/AccessibilityServiceTool.java b/app/src/main/java/org/autojs/autojs/tool/AccessibilityServiceTool.java index f5b20420..adce4757 100644 --- a/app/src/main/java/org/autojs/autojs/tool/AccessibilityServiceTool.java +++ b/app/src/main/java/org/autojs/autojs/tool/AccessibilityServiceTool.java @@ -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 accessibilityService) { String serviceName = GlobalAppContext.get().getPackageName() + "/" + accessibilityService.getName(); diff --git a/app/src/main/java/org/autojs/autojs/tool/RootTool.java b/app/src/main/java/org/autojs/autojs/tool/RootTool.java index f3d05a9d..070508af 100644 --- a/app/src/main/java/org/autojs/autojs/tool/RootTool.java +++ b/app/src/main/java/org/autojs/autojs/tool/RootTool.java @@ -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 { diff --git a/app/src/main/java/org/autojs/autojs/tool/SafeJsonElement.java b/app/src/main/java/org/autojs/autojs/tool/SafeJsonElement.java deleted file mode 100644 index 2206aabf..00000000 --- a/app/src/main/java/org/autojs/autojs/tool/SafeJsonElement.java +++ /dev/null @@ -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(); - } -} diff --git a/app/src/main/java/org/autojs/autojs/tool/SafeJsonObject.java b/app/src/main/java/org/autojs/autojs/tool/SafeJsonObject.java deleted file mode 100644 index 90b55f5c..00000000 --- a/app/src/main/java/org/autojs/autojs/tool/SafeJsonObject.java +++ /dev/null @@ -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> entrySet() { - return mJsonObject.entrySet(); - } - - public Set 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(); - } -} diff --git a/app/src/main/java/org/autojs/autojs/tool/WifiTool.java b/app/src/main/java/org/autojs/autojs/tool/WifiTool.java index 1c6a9e5e..b6d6f4c9 100644 --- a/app/src/main/java/org/autojs/autojs/tool/WifiTool.java +++ b/app/src/main/java/org/autojs/autojs/tool/WifiTool.java @@ -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(); } } diff --git a/app/src/main/java/org/autojs/autojs/ui/floating/CircularMenu.java b/app/src/main/java/org/autojs/autojs/ui/floating/CircularMenu.java index 4139e936..f2aca0fe 100644 --- a/app/src/main/java/org/autojs/autojs/ui/floating/CircularMenu.java +++ b/app/src/main/java/org/autojs/autojs/ui/floating/CircularMenu.java @@ -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(); - } } diff --git a/app/src/main/java/org/autojs/autojs/ui/main/drawer/DrawerFragment.java b/app/src/main/java/org/autojs/autojs/ui/main/drawer/DrawerFragment.java index 6c42b2d8..c9af70ea 100644 --- a/app/src/main/java/org/autojs/autojs/ui/main/drawer/DrawerFragment.java +++ b/app/src/main/java/org/autojs/autojs/ui/main/drawer/DrawerFragment.java @@ -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") diff --git a/app/src/main/res/values-en/strings.xml b/app/src/main/res/values-en/strings.xml index 8efcbc36..7173dec9 100644 --- a/app/src/main/res/values-en/strings.xml +++ b/app/src/main/res/values-en/strings.xml @@ -62,7 +62,7 @@ Error Copy debugging log This is a software developer(。・・)ノ - Please choose + Please choose Crash~ o(≧□≦)o (ಥ _ ಥ)Exit or submit a bug report or copy debugging log to the developer(≧∇≦)ノ Clear @@ -182,6 +182,7 @@ Stable mode Foreground service Usage stats access + Provides access to device usage history and statistics which results in currentPackage() a more accurate result Volume down control Task Next @@ -238,6 +239,7 @@ Time Size Type + Icon *.js file Notification access Permission @@ -253,4 +255,8 @@ Failed Color picker Custom + No root access + Auto.js has no root access to record a script. Continue? + Record + Quit diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 62af13f5..1409bab8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -311,9 +311,9 @@ com.example.script%d 不能为空 图标 - 设备没有root - 监测到您的设备没有root, 录制脚本需要root权限, 是否继续? - 仍要录制 + 无root权限 + Auto.js无root权限, 录制脚本需root权限, 是否继续录制 + 录制 无效的登录凭证 密码太短 邮箱已被占用 @@ -393,7 +393,7 @@ 应用更新时 耳机插拔时 每分钟一次 - 某些设置(屏幕方向,地区等)更改时 + 某些设置 (屏幕方向, 地区等) 更改时 正则表达式错误 非法包名 重命名失败 @@ -403,7 +403,7 @@ key_night_mode Auto.js启动时 查看使用情况权限 - 通过\"查看使用情况\"权限可以获取本设备过去使用应用的情况,从而使获取当前应用(currentPackage)时更准确。 + 通过\"查看使用情况\"权限可获取本设备过去使用应用的情况, 从而使\"获取当前应用\" (currentPackage) 结果更准确 打开方式 Root 免Root @@ -421,4 +421,5 @@ 失败 选择颜色 自定义 + 放弃 diff --git a/app/src/main/strings.xml b/app/src/main/strings.xml index b7fd364d..f49f91e0 100644 --- a/app/src/main/strings.xml +++ b/app/src/main/strings.xml @@ -82,7 +82,7 @@ 点击定位剪贴板 Script stopped (不会翻译)\"点击区域辅助服务\"是在要点击的区域不是文本时使用的,参见\"语法与API\"。\"点击区域辅助服务\"只有在\"自动操作服务\"开启时才有效。 - Please choose + 请选择 崩溃了o(≧□≦)o (不会翻译)点击\"退出\"退出程序(ಥ _ ಥ)或者提交错误报告或者复制调试信息反馈给开发者(≧∇≦)ノ 无法在后台显示弹框,脚本已停止运行 diff --git a/autojs/build.gradle b/autojs/build.gradle index 2491f810..51650087 100644 --- a/autojs/build.gradle +++ b/autojs/build.gradle @@ -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' diff --git a/autojs/src/main/assets/init.js b/autojs/src/main/assets/init.js index 693ae0fc..8da5bfd6 100644 --- a/autojs/src/main/assets/init.js +++ b/autojs/src/main/assets/init.js @@ -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; - - -})(); - - +}(); \ No newline at end of file diff --git a/autojs/src/main/assets/modules/__globals__.js b/autojs/src/main/assets/modules/__globals__.js index d285b362..4c7e696b 100644 --- a/autojs/src/main/assets/modules/__globals__.js +++ b/autojs/src/main/assets/modules/__globals__.js @@ -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; - } - - -} \ No newline at end of file + (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); + }, + }); +}; \ No newline at end of file diff --git a/autojs/src/main/assets/modules/custom-polyfill.js b/autojs/src/main/assets/modules/custom-polyfill.js new file mode 100644 index 00000000..72ac79a6 --- /dev/null +++ b/autojs/src/main/assets/modules/custom-polyfill.js @@ -0,0 +1,29 @@ +module.exports = { + fill() { + if (!Object.getOwnPropertyDescriptors) { + /** + * @param {Object} o + * @return {Object.} + */ + 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); + }, + }); + } + }, +}; \ No newline at end of file diff --git a/autojs/src/main/java/com/stardust/autojs/core/looper/Loopers.java b/autojs/src/main/java/com/stardust/autojs/core/looper/Loopers.java index c7cd424f..73a095a6 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/looper/Loopers.java +++ b/autojs/src/main/java/com/stardust/autojs/core/looper/Loopers.java @@ -35,41 +35,39 @@ public class Loopers implements MessageQueue.IdleHandler { private static final Runnable EMPTY_RUNNABLE = () -> { }; - private volatile ThreadLocal waitWhenIdle = new ThreadLocal() { + private final ThreadLocal waitWhenIdle = new ThreadLocal<>() { @Nullable @Override protected Boolean initialValue() { return Looper.myLooper() == Looper.getMainLooper(); } }; - private volatile ThreadLocal> waitIds = new ThreadLocal>() { + private final ThreadLocal> waitIds = new ThreadLocal<>() { @Nullable @Override protected HashSet initialValue() { return new HashSet<>(); } }; - private volatile ThreadLocal maxWaitId = new ThreadLocal() { + private final ThreadLocal maxWaitId = new ThreadLocal<>() { @Nullable @Override protected Integer initialValue() { return 0; } }; - private volatile ThreadLocal> looperQuitHandlers = new ThreadLocal<>(); + private final ThreadLocal> 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(); diff --git a/autojs/src/main/java/com/stardust/autojs/core/looper/Timer.java b/autojs/src/main/java/com/stardust/autojs/core/looper/Timer.java index 03218186..1b386afa 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/looper/Timer.java +++ b/autojs/src/main/java/com/stardust/autojs/core/looper/Timer.java @@ -14,12 +14,10 @@ import com.stardust.concurrent.VolatileBox; public class Timer { - private static final String LOG_TAG = "Timer"; - - private SparseArray mHandlerCallbacks = new SparseArray<>(); + private final SparseArray 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 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); diff --git a/autojs/src/main/java/com/stardust/autojs/core/looper/TimerThread.java b/autojs/src/main/java/com/stardust/autojs/core/looper/TimerThread.java index 61dbc7e7..d7556546 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/looper/TimerThread.java +++ b/autojs/src/main/java/com/stardust/autojs/core/looper/TimerThread.java @@ -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 sTimerMap = new ConcurrentHashMap<>(); + private static final ConcurrentHashMap sTimerMap = new ConcurrentHashMap<>(); private Timer mTimer; private final VolatileBox 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() + "]"; diff --git a/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/BaseViewInflater.java b/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/BaseViewInflater.java index a4a24cdc..b10dc5ec 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/BaseViewInflater.java +++ b/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/BaseViewInflater.java @@ -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 implements ViewInflater { 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 implements ViewInflater { } 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 implements ViewInflater { 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 implements ViewInflater { 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 implements ViewInflater { } 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 implements ViewInflater { 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 implements ViewInflater { 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 implements ViewInflater { 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 implements ViewInflater { 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 implements ViewInflater { 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 implements ViewInflater { } 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 implements ViewInflater { 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 implements ViewInflater { 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 implements ViewInflater { 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 implements ViewInflater { 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"); diff --git a/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/ViewGroupInflater.java b/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/ViewGroupInflater.java index dbec63b1..46eabc3e 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/ViewGroupInflater.java +++ b/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/ViewGroupInflater.java @@ -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 extends BaseViewInflater public boolean setAttr(V view, String attr, String value, ViewGroup parent, Map 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 extends BaseViewInflater 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); diff --git a/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/util/Drawables.java b/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/util/Drawables.java index 3a36d90b..8bbb3ef7 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/util/Drawables.java +++ b/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/util/Drawables.java @@ -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)); } } diff --git a/autojs/src/main/java/com/stardust/autojs/runtime/api/Events.java b/autojs/src/main/java/com/stardust/autojs/runtime/api/Events.java index ff0fbc91..7c43336b 100644 --- a/autojs/src/main/java/com/stardust/autojs/runtime/api/Events.java +++ b/autojs/src/main/java/com/stardust/autojs/runtime/api/Events.java @@ -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 mInterceptedKeys = new HashSet<>(); + private final Set 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)); } diff --git a/autojs/src/main/java/com/stardust/autojs/runtime/api/Images.java b/autojs/src/main/java/com/stardust/autojs/runtime/api/Images.java index 0baede94..54944f0c 100644 --- a/autojs/src/main/java/com/stardust/autojs/runtime/api/Images.java +++ b/autojs/src/main/java/com/stardust/autojs/runtime/api/Images.java @@ -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"); } -} +} \ No newline at end of file diff --git a/autojs/src/main/java/com/stardust/autojs/runtime/api/Sensors.java b/autojs/src/main/java/com/stardust/autojs/runtime/api/Sensors.java index f8075300..e6e201b8 100644 --- a/autojs/src/main/java/com/stardust/autojs/runtime/api/Sensors.java +++ b/autojs/src/main/java/com/stardust/autojs/runtime/api/Sensors.java @@ -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 SENSORS = new MapBuilder() .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 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() { diff --git a/autojs/src/main/java/com/stardust/autojs/runtime/api/UI.java b/autojs/src/main/java/com/stardust/autojs/runtime/api/UI.java index be8f6f01..6b16d438 100644 --- a/autojs/src/main/java/com/stardust/autojs/runtime/api/UI.java +++ b/autojs/src/main/java/com/stardust/autojs/runtime/api/UI.java @@ -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)); } } diff --git a/common/src/main/AndroidManifest.xml b/common/src/main/AndroidManifest.xml index 2dce2c91..9162a6b8 100644 --- a/common/src/main/AndroidManifest.xml +++ b/common/src/main/AndroidManifest.xml @@ -1,13 +1,8 @@ - package="com.stardust" -> - - - - - + diff --git a/common/src/main/java/com/stardust/app/DialogUtils.java b/common/src/main/java/com/stardust/app/DialogUtils.java index aba1bf97..5ceb55f1 100644 --- a/common/src/main/java/com/stardust/app/DialogUtils.java +++ b/common/src/main/java/com/stardust/app/DialogUtils.java @@ -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; } diff --git a/common/src/main/java/com/stardust/pio/PFiles.java b/common/src/main/java/com/stardust/pio/PFiles.java index 90d28c20..1322fa62 100644 --- a/common/src/main/java/com/stardust/pio/PFiles.java +++ b/common/src/main/java/com/stardust/pio/PFiles.java @@ -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) { diff --git a/common/src/main/java/com/stardust/util/ResourceMonitor.java b/common/src/main/java/com/stardust/util/ResourceMonitor.java index 760ee1ec..9340a0f8 100644 --- a/common/src/main/java/com/stardust/util/ResourceMonitor.java +++ b/common/src/main/java/com/stardust/util/ResourceMonitor.java @@ -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; } }); } diff --git a/inrt/src/main/java/com/stardust/auojs/inrt/SplashActivity.kt b/inrt/src/main/java/com/stardust/auojs/inrt/SplashActivity.kt index 0f456270..52367297 100644 --- a/inrt/src/main/java/com/stardust/auojs/inrt/SplashActivity.kt +++ b/inrt/src/main/java/com/stardust/auojs/inrt/SplashActivity.kt @@ -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) } }