2 Commits

787 changed files with 17858 additions and 15382 deletions

11
.gitignore vendored
View File

@@ -8,10 +8,12 @@
.externalNativeBuild
output.json
output-metadata.json
desktop.ini
.git/
.gradle/
.idea/
/.git/
/.gradle/
/.idea/
/build/
/libs/**/build/
/captures/
@@ -21,4 +23,5 @@ output-metadata.json
/local.properties
/sign.properties
**/assets/declarations/
**/assets/declarations/
**/assets/sample/.declarations/

127
README.md
View File

@@ -2,7 +2,7 @@
<div align="center">
<p>
<img alt="AF_Banner" src="https://github.com/SuperMonster002/Hello-Sockpuppet/raw/master/auto.js-banner_800×224_transparent.png"/>
<img alt="AF_Banner" src="https://raw.githubusercontent.com/SuperMonster002/Hello-Sockpuppet/master/auto.js-banner_800%C3%97224_transparent.png"/>
</p>
<p>Android 平台支持无障碍服务的 JavaScript 自动化工具</p>
@@ -10,13 +10,14 @@
<p>
<a href="https://github.com/SuperMonster003/AutoJs6/releases/latest"><img alt="GitHub release (latest by date)" src="https://img.shields.io/github/v/release/SuperMonster003/AutoJs6"/></a>
<a href="https://github.com/SuperMonster003/AutoJs6/issues"><img alt="GitHub closed issues" src="https://img.shields.io/github/issues/SuperMonster003/AutoJs6?color=009688"/></a>
<a href="https://github.com/mozilla/rhino"><img alt="Rhino" src="https://img.shields.io/badge/engine-rhino%201.7.14-ff69b4"/></a>
<a href="https://www.codefactor.io/repository/github/SuperMonster003/AutoJs6"><img alt="CodeFactor Grade" src="https://www.codefactor.io/repository/github/SuperMonster003/AutoJs6/badge"/></a>
<a href="https://lgtm.com/projects/g/SuperMonster003/AutoJs6/?mode=list"><img alt="LGTM Grade" src="https://img.shields.io/lgtm/grade/javascript/github/SuperMonster003/AutoJs6?label=lgtm"/></a>
<br>
<a href="https://github.com/SuperMonster003/AutoJs6/commit/ce88d3acb797b180c3f1f15bf77dbba5e934393c"><img alt="Created" src="https://img.shields.io/date/1636632233?color=2e7d32&label=created"/></a>
<a href="https://github.com/mozilla/rhino"><img alt="Rhino" src="https://img.shields.io/badge/rhino-1.7.15--snapshot-F06292"/></a>
<a href="https://developer.android.com/studio/archive"><img alt="Android Studio" src="https://img.shields.io/badge/android%20studio-bumblebee%202021.1.1-B64FC8"/></a>
<br>
<a href="https://github.com/SuperMonster003/AutoJs6/commit/99a1d8490fac5b6d55f6f183db59ad833a2064ed"><img alt="Created" src="https://img.shields.io/date/1636632233?color=2e7d32&label=created"/></a>
<a href="https://github.com/SuperMonster003/AutoJs6/find/master"><img alt="GitHub Code Size" src="https://img.shields.io/github/languages/code-size/SuperMonster003/AutoJs6?color=795548"/></a>
<a href="https://github.com/SuperMonster003/AutoJs6/find/master"><img alt="GitHub Code Lines" src="https://img.shields.io/tokei/lines/github/SuperMonster003/AutoJs6?color=37474F"/></a>
<a href="https://github.com/SuperMonster003/AutoJs6/blob/master/LICENSE"><img alt="GitHub License" src="https://img.shields.io/github/license/SuperMonster003/AutoJs6?color=534BAE"/></a>
</p>
</div>
@@ -26,7 +27,7 @@
### 简介
* Android 平台支持无障碍服务的 JavaScript 自动化工具
* 需要 [Android 7.0](https://zh.wikipedia.org/wiki/Android_Nougat) (`API 24`) 及以上
* 需要 [Android 7.0](https://zh.wikipedia.org/wiki/Android_Nougat) ([API](https://developer.android.com/guide/topics/manifest/uses-sdk-element#ApiLevels) [24](https://developer.android.com/reference/android/os/Build.VERSION_CODES#N)) 及以上
* 复刻 (Fork) 自 [hyb1996/Auto.js](https://github.com/hyb1996/Auto.js)
******
@@ -35,7 +36,7 @@
******
* [项目文档](http://docs.autojs.org)
* [项目文档](https://hyb1996.github.io/AutoJs-Docs) (临时参考文档)
******
@@ -65,7 +66,7 @@
* VSCode 插件支持客户端 (LAN) 及服务端 (LAN/ADB) 连接方式
* Rhino 引擎由 [v1.7.7.2](https://github.com/mozilla/rhino/releases/tag/Rhino1_7_7_2_Release) 升级至 [v1.7.14](https://github.com/mozilla/rhino/)
* [Rhino](https://github.com/mozilla/rhino/) 引擎由 [v1.7.7.2](https://github.com/mozilla/rhino/releases/tag/Rhino1_7_7_2_Release) 升级至 [v1.7.15-SNAPSHOT](https://github.com/SuperMonster003/Rhino-For-AutoJs6/commits/master)
* 支持 [Object.values()](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/values)
@@ -103,12 +104,73 @@
[comment]: <> "Version history only shows last 3 versions"
# v6.1.1
###### 2022/05/31
* `新增` 检查更新/下载更新/更新提示功能 (参阅 设置页面) (暂不支持安卓 7.x 系统)
* `修复` 应用在安卓 10 系统无法读写外部存储的问题 _[`issue #17`](https://github.com/SuperMonster003/AutoJs6/issues/17)_
* `修复` 编辑器页面长按时可能导致应用崩溃的问题 _[`issue #18`](https://github.com/SuperMonster003/AutoJs6/issues/18)_
* `修复` 编辑器页面长按菜单 "删除行" 和 "复制行" 功能无效的问题
* `修复` 编辑器页面选项菜单中 "粘贴" 功能缺失的问题
* `优化` 部分异常消息字符串资源化 (en / zh)
* `优化` 调整内容未保存对话框的按钮布局并增加颜色区分
* `优化` 部分依赖或本地库版本调整 _[`CHANGELOG.md`](https://github.com/SuperMonster003/AutoJs6/blob/master/app/src/main/assets/doc/CHANGELOG.md#v611)_
# v6.1.0
###### 2022/05/26 - 包名变更 谨慎升级
* `提示` 修改应用包名为 org.autojs.autojs6 避免与开源 Auto.js 应用包名冲突
* `新增` 首页抽屉增加 "投影媒体权限" 开关 (Root / ADB 方式) (开关状态检测为实验性)
* `新增` 文件浏览器支持显示隐藏文件和文件夹 (参阅 设置页面)
* `新增` 强制 Root 检查功能 (参阅 设置页面 及 示例代码)
* `新增` 内置 autojs 模块 (参阅 示例代码 > AutoJs6)
* `新增` 内置 tasks 模块 (参阅 示例代码 > 任务)
* `新增` console.launch() 方法启动日志活动页面
* `新增` util.morseCode 工具 (参阅 示例代码 > 工具 > 摩斯电码)
* `新增` util.versionCodes 工具 (参阅 示例代码 > 工具 > 安卓版本信息查询)
* `新增` util.getClass() 等方法 (参阅 示例代码 > 工具 > 获取类与类名)
* `新增` timers.setIntervalExt() 方法 (参阅 示例代码 > 定时器 > 条件周期执行)
* `新增` colors.toInt() / rgba() 等方法 (参阅 示例代码 > 图像与颜色 > 基本颜色转换)
* `新增` automator.isServiceEnabled() / ensureService() 方法
* `新增` automator.lockScreen() 等方法 (参阅 示例代码 > 无障碍服务 > 安卓 9 新增)
* `新增` automator.headsethook() 等方法 (参阅 示例代码 > 无障碍服务 > 安卓 11 新增)
* `新增` automator.captureScreen() 方法 (参阅 示例代码 > 无障碍服务 > 获取屏幕截图)
* `新增` dialogs.build() 选项参数属性 animation, linkify 等 (参阅 示例代码 > 对话框 > 个性化对话框)
* `修复` dialogs.build() 选项参数属性 inputHint, itemsSelectedIndex 等功能异常
* `修复` JsDialog#on('multi_choice') 回调参数功能异常
* `修复` UiObject#parent().indexInParent() 总是返回 -1 的问题 _[`issue #16`](https://github.com/SuperMonster003/AutoJs6/issues/16)_
* `修复` Promise.resolve() 返回的 Thenable 在临近脚本结束时可能不被调用的问题
* `修复` 包名或类名中可能的拼写失误 (boardcast -> broadcast / auojs -> autojs)
* `修复` images.requestScreenCapture() 在高版本安卓系统可能导致应用崩溃的问题 (API >= 31)
* `修复` images.requestScreenCapture() 多个脚本实例同时申请可能导致应用崩溃的问题
* `修复` 调用 new RootAutomator() 可能出现的假死问题
* `优化` RootAutomator 在无 Root 权限时将无法实例化
* `优化` 重新设计 "关于应用与开发者" 页面
* `优化` 重构全部内置 JavaScript 模块
* `优化` 重构全部 Gradle 构建脚本并增加公共配置脚本 (config.gradle)
* `优化` Gradle 构建工具支持版本号自动管理及构建文件自动命名
* `优化` Gradle 构建工具增加 task 支持附加 CRC32 摘要到构建文件 (appendDigestToReleasedFiles)
* `优化` shell() 调用时将异常写入返回结果而非直接将异常抛出 (无需 try/catch)
* `优化` 使用 Rhino 内置的 JSON 替代原 json2 模块
* `优化` auto.waitFor() 支持超时参数
* `优化` threads.start() 支持箭头函数参数
* `优化` console.trace() 支持按日志等级参数 (参阅 示例代码 > 控制台 > 打印调用栈)
* `优化` device.vibrate() 支持模式震动及摩斯电码震动 (参阅 示例代码 > 设备 > 模式震动 / 摩斯电码震动)
* `优化` 外部存储读写权限适配高版本安卓系统 (API >= 30)
* `优化` 控制台字体采用 Material Color 增强普通及夜间主题下的字体可读性
* `优化` 保存 ImageWrapper 所有实例弱引用并在脚本结束时自动回收 (实验性)
* `优化` 附加 CircleImageView 版本 3.1.0
* `优化` 升级 Rhino 引擎版本 1.7.14 -> 1.7.15-snapshot
* `优化` 部分依赖或本地库版本调整 _[`CHANGELOG.md`](https://github.com/SuperMonster003/AutoJs6/blob/master/app/src/main/assets/doc/CHANGELOG.md#v610)_
# v6.0.3
###### 2022/03/19
* `新增` 多语言切换功能 (尚不完善)
* `新增` recorder 模块 (参阅 示例代码 > 计时器 > *.js × 4)
* `新增` 内置 recorder 模块 (参阅 示例代码 > 计时器)
* `新增` 使用 "修改安全设置权限" 自动启用无障碍服务及开关设置
* `修复` 点击 "快速设置" 中相关图标后面板未自动收起的问题 (试修) _[`issue #7`](https://github.com/SuperMonster003/AutoJs6/issues/7)_
* `修复` toast 使用强制显示参数时可能导致 AutoJs6 崩溃的问题
@@ -120,58 +182,13 @@
* `优化` 主页抽屉增加前台服务状态开关的同步
* `优化` 主页抽屉展开时立即按需同步开关状态
* `优化` 显示指针位置增加状态检测及结果提示
* `优化` 支持 64 位操作系统 (Ref to TonyJiangWJ)
* `优化` 支持 64 位操作系统 (Ref to [TonyJiangWJ](https://github.com/TonyJiangWJ))
* `优化` 悬浮窗初始化时同时应用透明度设置 (无需点击后再应用透明度)
* `优化` 重置文件内容时增加是否为示例代码文件的检测并增加结果提示
* `优化` 转移打包插件下载地址 GitHub -> JsDelivr
* `优化` 附加 Zeugma Solutions LocaleHelper 版本 1.5.1
* `优化` 降级 Android Material 版本 1.6.0-alpha02 -> 1.5.0
* `优化` 升级 Kotlinx Coroutines 版本 1.6.0-native-mt -> 1.6.0
* `优化` 升级 OpenCV 版本 3.4.3 -> 4.5.4 -> 4.5.5 (Ref to TonyJiangWJ)
* `优化` 升级 Okhttp3 版本 3.10.0 -> 5.0.0-alpha.4 -> 5.0.0-alpha.6
* `优化` 升级 Android Gradle 插件版本 7.2.0-beta01 -> 7.3.0-alpha06
* `优化` 升级 Auto.js-ApkBuilder 版本 1.0.1 -> 1.0.3
* `优化` 升级 Glide Compiler 版本 4.12.0 -> 4.13.1
* `优化` 升级 Gradle 发行版本 7.4-rc-2 -> 7.4.1
* `优化` 升级 Gradle Compile 版本 31 -> 32
* `优化` 升级 Gson 版本 2.8.9 -> 2.9.0
# v6.0.2
###### 2022/02/05
* `新增` images.bilateralFilter() 双边滤波图像处理方法
* `修复` 多次调用 toast 只生效最后一次调用的问题
* `修复` toast.dismiss() 可能无效的问题
* `修复` 客户端模式及服务端模式开关可能无法正常工作的问题
* `修复` 客户端模式及服务端模式开关状态不能正常刷新的问题
* `修复` Android 7 解析 UI 模式 text 元素异常 (Ref to TonyJiangWJ) _[`issue #4`](https://github.com/SuperMonster003/AutoJs6/issues/4)_ _[`#9`](https://github.com/SuperMonster003/AutoJs6/issues/9)_
* `优化` 忽略 sleep() 的 ScriptInterruptedException 异常
* `优化` 附加 Androidx AppCompat (Legacy) 版本 1.0.2
* `优化` 升级 Androidx AppCompat 版本 1.4.0 -> 1.4.1
* `优化` 升级 Androidx Preference 版本 1.1.1 -> 1.2.0
* `优化` 升级 Okhttp3 版本 3.10.0 -> 5.0.0-alpha.3 -> 5.0.0-alpha.4
* `优化` 升级 Android Material 版本 1.6.0-alpha01 -> 1.6.0-alpha02
* `优化` 升级 Android Gradle 插件版本 7.2.0-alpha06 -> 7.2.0-beta01
* `优化` 升级 Gradle 发行版本 7.3.3 -> 7.4-rc-2
# v6.0.1
###### 2022/01/01
* `新增` 连接 VSCode 插件支持客户端 (LAN) 及服务端 (LAN/ADB) 方式 (Ref to Auto.js Pro)
* `新增` 增加 $base64 全局对象 (Ref to Auto.js Pro)
* `新增` 增加 isInteger/isNullish/isPlainObject/isPrimitive/isReference 全局方法
* `新增` 增加 polyfill (Object.getOwnPropertyDescriptors)
* `新增` 增加 polyfill (Array.prototype.flat)
* `优化` 扩展 global.sleep 支持 随机范围/负数兼容
* `优化` 扩展 global.toast 支持 时长控制/强制覆盖控制/dismiss
* `优化` 包名对象全局化 (okhttp3/androidx/de)
* `优化` 升级 Android Material 版本 1.5.0-beta01 -> 1.6.0-alpha01
* `优化` 升级 Android Gradle 插件版本 7.2.0-alpha04 -> 7.2.0-alpha06
* `优化` 升级 Kotlinx Coroutines 版本 1.5.2-native-mt -> 1.6.0-native-mt
* `优化` 升级 Kotlin Gradle 插件版本 1.6.0 -> 1.6.10
* `优化` 升级 Gradle 发行版本 7.3 -> 7.3.3
* `优化` 部分依赖或本地库版本调整 _[`CHANGELOG.md`](https://github.com/SuperMonster003/AutoJs6/blob/master/app/src/main/assets/doc/CHANGELOG.md#v603)_
##### 更多版本历史可参阅

View File

@@ -1,155 +1,27 @@
plugins {
id 'com.android.application'
id 'com.jakewharton.butterknife'
id 'kotlin-android'
id 'kotlin-kapt'
ext {
applicationId = 'org.autojs.autojs6'
namespace = applicationId
}
def properties = new Properties()
def propFile = new File('sign.properties')
def isPropFileExists = propFile.exists()
isPropFileExists && properties.load(new FileInputStream(propFile))
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
kotlinOptions {
jvmTarget = JavaVersion.VERSION_16
}
}
// tasks.withType(JavaCompile) {
// options.compilerArgs << '-Xlint:deprecation' << '-Xlint:unchecked'
// }
android {
signingConfigs {
isPropFileExists && release {
storeFile file(properties['storeFile'])
keyPassword properties['keyPassword']
keyAlias properties['keyAlias']
storePassword properties['storePassword']
}
}
compileSdkVersion versions.project.compile
defaultConfig {
applicationId 'org.autojs.autojs'
minSdkVersion versions.project.mini
targetSdkVersion versions.project.target
versionCode versions.project.appVersionCode
versionName versions.project.appVersionName
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
multiDexEnabled true
javaCompileOptions {
annotationProcessorOptions {
arguments = [
'resourcePackageName': applicationId,
'androidManifestFile': "$projectDir/src/main/AndroidManifest.xml".toString()
]
}
}
}
buildTypes {
debug {
shrinkResources false
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
if (isPropFileExists) {
signingConfig signingConfigs.release
}
// Disable Crashlytics reports.
ext.enableCrashlytics = false
// Disables PNG crunching for the release build type.
crunchPngs false
}
release {
shrinkResources false
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
if (isPropFileExists) {
signingConfig signingConfigs.release
}
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_16
targetCompatibility JavaVersion.VERSION_16
encoding = 'utf-8'
}
lintOptions {
abortOnError false
disable 'MissingTranslation'
disable 'ExtraTranslation'
}
configurations.all {
resolutionStrategy.force 'com.google.code.findbugs:jsr305:3.0.1'
}
flavorDimensions 'channel'
splits {
// Configures multiple APKs based on ABI.
abi {
// Enables building multiple APKs per ABI.
enable true
// By default all ABIs are included, so use reset() and include to specify that we only
// want APKs for x86 and x86_64.
// Resets the list of ABIs that Gradle should create APKs for to none.
reset()
// Specifies a list of ABIs that Gradle should create APKs for.
include 'x86', 'armeabi-v7a', 'arm64-v8a', 'x86_64'
// Specifies that we do not want to also generate a universal APK that includes all ABIs.
universalApk true
}
}
productFlavors {
common {
buildConfigField 'String', 'CHANNEL', '"common"'
buildConfigField 'String', 'APP_SINCE_DATE', "\"${versions.project.appSinceDate}\""
}
}
applicationVariants.all { variant ->
variant.outputs.all { output ->
def aj = "AutoJs6"
def ver = versionName.replaceAll(/\s/, "-")
// FIXME by SuperMonster003 as of Mar 19, 2022.
// ! Interface com.android.build.OutputFile is deprecated.
// ! Another way of getting ABI is needed.
def abi = getFilter(com.android.build.OutputFile.ABI)
output.outputFileName = "${aj}-v${ver}-${abi ? "${abi}" : "universal"}.apk".toLowerCase()
}
variant.mergeAssetsProvider.configure {
doLast {
delete(fileTree(dir: outputDir, includes: ['declarations/**']))
}
}
}
}
repositories {
google()
apply {
from rootProject.file('config.gradle')
plugin 'kotlin-kapt'
}
dependencies {
// JUnit
testImplementation "junit:junit:${versions.junit}"
// LeakCanary
debugImplementation "com.squareup.leakcanary:leakcanary-android:${versions.leakcanary}"
debugImplementation "com.squareup.leakcanary:leakcanary-android:2.9.1"
// Kotlin
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.0'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.1-native-mt'
// Android Annotations
kapt "org.androidannotations:androidannotations:${versions.annotations}"
implementation "org.androidannotations:androidannotations-api:${versions.annotations}"
kapt "org.androidannotations:androidannotations:4.8.0"
implementation "org.androidannotations:androidannotations-api:4.8.0"
// ButterKnife
kapt "com.jakewharton:butterknife-compiler:${versions.butterKnife}"
implementation "com.jakewharton:butterknife:${versions.butterKnife}"
kapt "com.jakewharton:butterknife-compiler:10.2.3"
implementation "com.jakewharton:butterknife:10.2.3"
// Android supports
implementation 'androidx.cardview:cardview:1.0.0'
@@ -190,23 +62,23 @@ dependencies {
// Retrofit
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.9.0'
implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2'
// Glide
kapt "com.github.bumptech.glide:compiler:${versions.glide}"
kapt "com.github.bumptech.glide:compiler:4.13.2"
// Joda Time
implementation 'joda-time:joda-time:2.10.13'
implementation 'joda-time:joda-time:2.10.14'
// Tasker Plugin
implementation 'com.twofortyfouram:android-plugin-client-sdk-for-locale:4.0.3'
// Flurry
implementation 'com.flurry.android:analytics:13.1.0'
implementation 'com.flurry.android:analytics:13.3.0'
// Android Job
implementation 'com.evernote:android-job:1.4.2'
implementation 'com.evernote:android-job:1.4.3'
// Extracted from com.github.hyb1996:MutableTheme:1.0.0
implementation 'com.jrummyapps:colorpicker:2.1.7'
@@ -214,14 +86,8 @@ dependencies {
implementation 'com.github.ozodrukh:CircularReveal:2.0.1'
// Bugly
implementation project(':libs:com.tencent.bugly.crashreport-2.6.6')
implementation project(':libs:com.tencent.bugly.crashreport-4.0.4')
implementation project(':automator')
implementation project(':common')
// Indirect: automator, common
implementation project(':autojs')
}
java {
sourceCompatibility = JavaVersion.VERSION_16
targetCompatibility = JavaVersion.VERSION_16
}

View File

@@ -7,7 +7,6 @@ import org.mozilla.javascript.Scriptable;
/**
* Created by Stardust on 2017/5/13.
*/
public class RhinoE4XTest {
@Test

View File

@@ -2,33 +2,52 @@
xmlns:tools="http://schemas.android.com/tools"
package="org.autojs.autojs">
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.BROADCAST_CLOSE_SYSTEM_DIALOGS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!--
@Hint by SuperMonster003 on May 27, 2022.
! WRT: android.permission.WRITE_EXTERNAL_STORAGE
! MSV<API>: android:maxSdkVersion="API"
! LGC: android:requestLegacyExternalStorage="true" (since API 29)
! MAN: android.permission.MANAGE_EXTERNAL_STORAGE (since API 30)
!
! Storage permission requirement on different API targets.
! [ XXX ] means optional but recommended.
!
! Target API == 28: WRT
! Target API == 29: WRT + [ MSV<29> ] / WRT + [ MSV<28> ] + LGC
! Target API >= 30: WRT + [ MSV<29> ] + LGC + MAN
-->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="29" />
<uses-permission
android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
<uses-permission android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission
android:name="android.permission.QUERY_ALL_PACKAGES"
tools:ignore="QueryAllPackagesPermission" />
<uses-permission
android:name="android.permission.PACKAGE_USAGE_STATS"
tools:ignore="ProtectedPermissions" />
<uses-permission
android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />
android:name="android.permission.BROADCAST_CLOSE_SYSTEM_DIALOGS"
tools:ignore="ProtectedPermissions" />
<!-- 非Auto.js运行必需不会主动申请某些脚本可以自行申请-->
<!-- 非Auto.js运行必需不会主动申请某些脚本可以自行申请 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<!-- Ad SDK Permissions -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<application
android:name="org.autojs.autojs.App"
android:allowBackup="false"
@@ -38,7 +57,9 @@
android:supportsRtl="true"
android:theme="@style/AppTheme"
android:usesCleartextTraffic="true"
tools:replace="android:label, android:allowBackup">
android:requestLegacyExternalStorage="true"
tools:replace="android:label, android:allowBackup"
tools:ignore="DataExtractionRules">
<meta-data
android:name="android.max_aspect"
@@ -74,7 +95,7 @@
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="org.autojs.autojs.fileprovider"
android:authorities="org.autojs.autojs6.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
@@ -126,7 +147,7 @@
android:theme="@style/IssueReporterTheme" />
<service android:name="org.autojs.autojs.external.foreground.ForegroundService" />
<service android:name="org.autojs.autojs.external.foreground.MainActivityForegroundService" />
<service android:name="org.autojs.autojs.external.ScriptExecutionIntentService" />
<activity android:name="org.autojs.autojs.external.tasker.TaskPrefEditActivity_" />
@@ -165,7 +186,7 @@
android:exported="true"
android:icon="@drawable/ic_android_eat_js"
android:label="@string/app_name"
android:targetActivity=".external.tasker.TaskPrefEditActivity_"
android:targetActivity="org.autojs.autojs.external.tasker.TaskPrefEditActivity_"
tools:ignore="ExportedActivity">
<intent-filter>
<action android:name="com.twofortyfouram.locale.intent.action.EDIT_SETTING" />

View File

@@ -4,12 +4,87 @@
******
# v6.1.1
###### 2022/05/31
* `新增` 检查更新/下载更新/更新提示功能 (参阅 设置页面) (暂不支持安卓 7.x 系统)
* `修复` 应用在安卓 10 系统无法读写外部存储的问题 _[`issue #17`](https://github.com/SuperMonster003/AutoJs6/issues/17)_
* `修复` 编辑器页面长按时可能导致应用崩溃的问题 _[`issue #18`](https://github.com/SuperMonster003/AutoJs6/issues/18)_
* `修复` 编辑器页面长按菜单 "删除行" 和 "复制行" 功能无效的问题
* `修复` 编辑器页面选项菜单中 "粘贴" 功能缺失的问题
* `优化` 部分异常消息字符串资源化 (en / zh)
* `优化` 调整内容未保存对话框的按钮布局并增加颜色区分
* `优化` 附加 github-api 版本 1.306
* `优化` 替换 retrofit2-rxjava2-adapter 版本 1.0.0 为 adapter-rxjava2 版本 2.9.0
# v6.1.0
###### 2022/05/26 - 包名变更 谨慎升级
* `提示` 修改应用包名为 org.autojs.autojs6 避免与开源 Auto.js 应用包名冲突
* `新增` 首页抽屉增加 "投影媒体权限" 开关 (Root / ADB 方式) (开关状态检测为实验性)
* `新增` 文件浏览器支持显示隐藏文件和文件夹 (参阅 设置页面)
* `新增` 强制 Root 检查功能 (参阅 设置页面 及 示例代码)
* `新增` 内置 autojs 模块 (参阅 示例代码 > AutoJs6)
* `新增` 内置 tasks 模块 (参阅 示例代码 > 任务)
* `新增` console.launch() 方法启动日志活动页面
* `新增` util.morseCode 工具 (参阅 示例代码 > 工具 > 摩斯电码)
* `新增` util.versionCodes 工具 (参阅 示例代码 > 工具 > 安卓版本信息查询)
* `新增` util.getClass() 等方法 (参阅 示例代码 > 工具 > 获取类与类名)
* `新增` timers.setIntervalExt() 方法 (参阅 示例代码 > 定时器 > 条件周期执行)
* `新增` colors.toInt() / rgba() 等方法 (参阅 示例代码 > 图像与颜色 > 基本颜色转换)
* `新增` automator.isServiceEnabled() / ensureService() 方法
* `新增` automator.lockScreen() 等方法 (参阅 示例代码 > 无障碍服务 > 安卓 9 新增)
* `新增` automator.headsethook() 等方法 (参阅 示例代码 > 无障碍服务 > 安卓 11 新增)
* `新增` automator.captureScreen() 方法 (参阅 示例代码 > 无障碍服务 > 获取屏幕截图)
* `新增` dialogs.build() 选项参数属性 animation, linkify 等 (参阅 示例代码 > 对话框 > 个性化对话框)
* `修复` dialogs.build() 选项参数属性 inputHint, itemsSelectedIndex 等功能异常
* `修复` JsDialog#on('multi_choice') 回调参数功能异常
* `修复` UiObject#parent().indexInParent() 总是返回 -1 的问题 _[`issue #16`](https://github.com/SuperMonster003/AutoJs6/issues/16)_
* `修复` Promise.resolve() 返回的 Thenable 在临近脚本结束时可能不被调用的问题
* `修复` 包名或类名中可能的拼写失误 (boardcast -> broadcast / auojs -> autojs)
* `修复` images.requestScreenCapture() 在高版本安卓系统可能导致应用崩溃的问题 (API >= 31)
* `修复` images.requestScreenCapture() 多个脚本实例同时申请可能导致应用崩溃的问题
* `修复` 调用 new RootAutomator() 可能出现的假死问题
* `优化` RootAutomator 在无 Root 权限时将无法实例化
* `优化` 重新设计 "关于应用与开发者" 页面
* `优化` 重构全部内置 JavaScript 模块
* `优化` 重构全部 Gradle 构建脚本并增加公共配置脚本 (config.gradle)
* `优化` Gradle 构建工具支持版本号自动管理及构建文件自动命名
* `优化` Gradle 构建工具增加 task 支持附加 CRC32 摘要到构建文件 (appendDigestToReleasedFiles)
* `优化` shell() 调用时将异常写入返回结果而非直接将异常抛出 (无需 try/catch)
* `优化` 使用 Rhino 内置的 JSON 替代原 json2 模块
* `优化` auto.waitFor() 支持超时参数
* `优化` threads.start() 支持箭头函数参数
* `优化` console.trace() 支持按日志等级参数 (参阅 示例代码 > 控制台 > 打印调用栈)
* `优化` device.vibrate() 支持模式震动及摩斯电码震动 (参阅 示例代码 > 设备 > 模式震动 / 摩斯电码震动)
* `优化` 外部存储读写权限适配高版本安卓系统 (API >= 30)
* `优化` 控制台字体采用 Material Color 增强普通及夜间主题下的字体可读性
* `优化` 保存 ImageWrapper 所有实例弱引用并在脚本结束时自动回收 (实验性)
* `优化` 附加 CircleImageView 版本 3.1.0
* `优化` 升级 Android Analytics 版本 13.1.0 -> 13.3.0
* `优化` 升级 Android Gradle 插件版本 7.3.0-alpha06 -> 7.4.0-alpha02
* `优化` 升级 Android Job 版本 1.4.2 -> 1.4.3
* `优化` 升级 Android Material 版本 1.5.0 -> 1.6.0
* `优化` 升级 CrashReport 版本 2.6.6 -> 4.0.4
* `优化` 升级 Glide 版本 4.13.1 -> 4.13.2
* `优化` 升级 Joda Time 版本 2.10.13 -> 2.10.14
* `优化` 升级 Kotlin Gradle 插件版本 1.6.10 -> 1.6.21
* `优化` 升级 Kotlinx Coroutines 版本 1.6.0 -> 1.6.1-native-mt
* `优化` 升级 Leakcanary 版本 2.8.1 -> 2.9.1
* `优化` 升级 Okhttp3 版本 5.0.0-alpha.6 -> 5.0.0-alpha.7
* `优化` 升级 Rhino 引擎版本 1.7.14 -> 1.7.15-snapshot
* `优化` 升级 Zip4j 版本 2.9.1 -> 2.10.0
* `优化` 移除 Groovy JSON 版本 3.0.8
* `优化` 移除 Kotlin Stdlib JDK7 版本 1.6.21
# v6.0.3
###### 2022/03/19
* `新增` 多语言切换功能 (尚不完善)
* `新增` recorder 模块 (参阅 示例代码 > 计时器 > *.js × 4)
* `新增` 内置 recorder 模块 (参阅 示例代码 > 计时器)
* `新增` 使用 "修改安全设置权限" 自动启用无障碍服务及开关设置
* `修复` 点击 "快速设置" 中相关图标后面板未自动收起的问题 (试修) _[`issue #7`](https://github.com/SuperMonster003/AutoJs6/issues/7)_
* `修复` toast 使用强制显示参数时可能导致 AutoJs6 崩溃的问题
@@ -21,14 +96,14 @@
* `优化` 主页抽屉增加前台服务状态开关的同步
* `优化` 主页抽屉展开时立即按需同步开关状态
* `优化` 显示指针位置增加状态检测及结果提示
* `优化` 支持 64 位操作系统 (Ref to TonyJiangWJ)
* `优化` 支持 64 位操作系统 (Ref to [TonyJiangWJ](https://github.com/TonyJiangWJ))
* `优化` 悬浮窗初始化时同时应用透明度设置 (无需点击后再应用透明度)
* `优化` 重置文件内容时增加是否为示例代码文件的检测并增加结果提示
* `优化` 转移打包插件下载地址 GitHub -> JsDelivr
* `优化` 附加 Zeugma Solutions LocaleHelper 版本 1.5.1
* `优化` 降级 Android Material 版本 1.6.0-alpha02 -> 1.5.0
* `优化` 升级 Kotlinx Coroutines 版本 1.6.0-native-mt -> 1.6.0
* `优化` 升级 OpenCV 版本 3.4.3 -> 4.5.4 -> 4.5.5 (Ref to TonyJiangWJ)
* `优化` 升级 OpenCV 版本 3.4.3 -> 4.5.4 -> 4.5.5 (Ref to [TonyJiangWJ](https://github.com/TonyJiangWJ))
* `优化` 升级 Okhttp3 版本 3.10.0 -> 5.0.0-alpha.4 -> 5.0.0-alpha.6
* `优化` 升级 Android Gradle 插件版本 7.2.0-beta01 -> 7.3.0-alpha06
* `优化` 升级 Auto.js-ApkBuilder 版本 1.0.1 -> 1.0.3
@@ -46,11 +121,12 @@
* `修复` toast.dismiss() 可能无效的问题
* `修复` 客户端模式及服务端模式开关可能无法正常工作的问题
* `修复` 客户端模式及服务端模式开关状态不能正常刷新的问题
* `修复` Android 7 解析 UI 模式 text 元素异常 (Ref to TonyJiangWJ) _[`issue #4`](https://github.com/SuperMonster003/AutoJs6/issues/4)_ _[`#9`](https://github.com/SuperMonster003/AutoJs6/issues/9)_
* `修复` Android 7 解析 UI 模式 text 元素异常 (Ref to [TonyJiangWJ](https://github.com/TonyJiangWJ)) _[`issue #4`](https://github.com/SuperMonster003/AutoJs6/issues/4)_ _[`#9`](https://github.com/SuperMonster003/AutoJs6/issues/9)_
* `优化` 忽略 sleep() 的 ScriptInterruptedException 异常
* `优化` 附加 Androidx AppCompat (Legacy) 版本 1.0.2
* `优化` 升级 Androidx AppCompat 版本 1.4.0 -> 1.4.1
* `优化` 升级 Androidx Preference 版本 1.1.1 -> 1.2.0
* `优化` 升级 Rhino 引擎版本 1.7.14-snapshot -> 1.7.14
* `优化` 升级 Okhttp3 版本 3.10.0 -> 5.0.0-alpha.3 -> 5.0.0-alpha.4
* `优化` 升级 Android Material 版本 1.6.0-alpha01 -> 1.6.0-alpha02
* `优化` 升级 Android Gradle 插件版本 7.2.0-alpha06 -> 7.2.0-beta01
@@ -60,8 +136,8 @@
###### 2022/01/01
* `新增` 连接 VSCode 插件支持客户端 (LAN) 及服务端 (LAN/ADB) 方式 (Ref to Auto.js Pro)
* `新增` 增加 $base64 "工具类" (Ref to Auto.js Pro)
* `新增` 连接 VSCode 插件支持客户端 (LAN) 及服务端 (LAN/ADB) 方式 (Ref to [Auto.js Pro](https://g.pro.autojs.org/))
* `新增` 内置 base64 模块 (Ref to [Auto.js Pro](https://g.pro.autojs.org/))
* `新增` 增加 isInteger/isNullish/isPlainObject/isPrimitive/isReference 全局方法
* `新增` 增加 polyfill (Object.getOwnPropertyDescriptors)
* `新增` 增加 polyfill (Array.prototype.flat)
@@ -97,7 +173,7 @@
* `优化` 升级 JSON 模块至 2017-06-12 版本并整合 cycle.js
* `优化` 移除 Activity 前置时的自动检查更新功能并移除检查更新相关按钮
* `优化` AppOpsKt#isOpPermissionGranted 内部代码逻辑
* `优化` ResourceMonitor 使用 ReentrantLock 增强安全性 (Ref to TonyJiangWJ)
* `优化` ResourceMonitor 使用 ReentrantLock 增强安全性 (Ref to [TonyJiangWJ](https://github.com/TonyJiangWJ))
* `优化` 使用 Maven Central 等仓库替换 JCenter 仓库
* `优化` 抽离并移除重复的本地库文件
* `优化` 本地化 CrashReport 版本 2.6.6

View File

@@ -174,4 +174,41 @@
pad = o => o.padEnd(2, '_');
`${pad(h)}:${pad(m)}:${pad(s)}`; // '9_:30:7_'
```
* [Object.hasOwn](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwn)
```javascript
let o = {a: 1};
Object.defineProperty(o, 'b', {value: 2});
Object.hasOwn(o, 'a'); // true
o.hasOwnProperty('a'); // true
'a' in o; // true
Object.hasOwn(o, 'b'); // true
o.hasOwnProperty('b'); // true
'b' in o; // true
Object.hasOwn(o, 'toString'); // false
o.hasOwnProperty('toString'); // false
'toString' in o; // true
let p = Object.create(null);
Object.defineProperties(p, {
a: {value: 1, enumerable: true},
b: {value: 2, enumerable: false},
});
Object.hasOwn(p, 'a'); // true
// p.hasOwnProperty('a'); // TypeError
'a' in p; // true
Object.hasOwn(p, 'b'); // true
// p.hasOwnProperty('b'); // TypeError
'b' in p; // true
Object.hasOwn(p, 'toString'); // false
// p.hasOwnProperty('toString'); // TypeError
'toString' in p; // false
```

View File

@@ -529,7 +529,7 @@ function highlight(prefix, suffix, tag) {
sh_highlightElement(element, sh_languages[language]);
highlighted = true;
}
else if (typeof(prefix) === 'string' && typeof(suffix) === 'string') {
else if (typeof prefix === 'string' && typeof suffix === 'string') {
sh_load(language, element, prefix, suffix);
}
else {
@@ -538,7 +538,7 @@ function highlight(prefix, suffix, tag) {
break;
}
}
if (highlighted === false && donthighlight == false) {
if (highlighted === false && donthighlight === false) {
sh_highlightElement(element, sh_languages["javascript"]);
}
}

View File

@@ -0,0 +1,399 @@
{
"AXR": "Arrow function returns without (X) the Return keyword",
"a11y": "accessibility",
"acc": "account",
"accu": "accumulated",
"act": [
"action",
"activity"
],
"addn": [
"addition",
"additional"
],
"af": "ant forest",
"ahd": "ahead",
"amt": "amount",
"anm": "animation",
"app": "application",
"args": "arguments",
"argv": "argument values",
"asg": [
"assign",
"assignment"
],
"async": "asynchronous",
"avail": "available",
"avt": "avatar",
"b": [
"bottom",
"bounds",
"backup",
"blue",
"bomb"
],
"bak": "backup",
"blist": "blacklist",
"blt": "bilateral",
"bnd": [
"bound",
"bounds"
],
"bo": "bitmap options",
"btm": "bottom",
"btn": "button",
"buf": "buffer",
"c": [
"checked",
"click",
"clickable",
"color",
"compass"
],
"cbk": "callback",
"cf": "comparison (latin: conferatur)",
"cfg": "configuration",
"cfm": "confirm",
"chk": "check",
"cmd": "command",
"cmps": "compass",
"cnsl": "console",
"cnt": "count",
"col": "color",
"cond": "condition",
"constr": "constructor",
"cont": "content",
"coord": "coordination",
"ctd": "countdown",
"ctr": "counter",
"ctx": "context",
"cur": "current",
"cvr": "cover",
"cwd": "current working directory",
"cwp": "current working path",
"cxn": "connection",
"d": "dialog",
"dat": "data",
"dbg": "debug",
"dc": "decrease",
"dec": [
"decode",
"decrypt"
],
"def": "default",
"del": [
"delete",
"deletion"
],
"desc": "description",
"dev": [
"device",
"development"
],
"diag": "dialog",
"dic": "dictionary",
"diff": "difference",
"dis": "dismiss",
"disp": "display",
"dist": [
"distance",
"disturb",
"disturbance"
],
"dn": "down",
"dnt": "donation",
"dny": "dynamic",
"drxn": "direction",
"ds": "data source",
"dsk": "data source key",
"du": "duration",
"dupe": [
"duplicate",
"duplicated",
"duplication"
],
"dys": "dysfunctional",
"e": [
"error",
"engine",
"event"
],
"eball": "energy ball",
"eballs": "energy balls",
"ele": "element",
"emount": "energy amount",
"enabl": [
"enable",
"enabled"
],
"enc": [
"encode",
"encrypt"
],
"ens": "ensure",
"ent": "entrance",
"eq": "equal",
"eql": "equal",
"et": "elapsed time",
"ev": "event",
"evt": "event",
"ex": "exception",
"exc": "exclude",
"excl": "exclusive",
"excpt": "exception",
"exec": "execution",
"exp": "expected",
"ext": "extension",
"f": "function",
"fg": [
"foreground",
"flag"
],
"flg": "flag",
"flo": "floaty",
"fltr": "filter",
"forc": [
"force",
"forcible",
"forcibly"
],
"frac": "fraction",
"fri": "friend",
"frst": "forest",
"ft": "fault tolerance",
"fx": [
"function",
"special effects"
],
"fxo": "function object (an object with some functions)",
"fxs": "functions",
"g": "green",
"glob": "global",
"grn": "green",
"gt": "greater than",
"h": [
"height",
"head",
"heads"
],
"his": "history",
"horiz": "horizontal",
"i": [
"intent",
"increment"
],
"ic": "increase",
"ident": "identification",
"idt": "identification",
"idx": "index",
"ifn": "if needed",
"IIFE": "Immediately-Invoked Function Expression",
"inc": "increment",
"inf": "information",
"info": "information",
"inp": "input",
"ins": "insurance",
"inst": "instant",
"intrp": "interrupt",
"invt": "invitation",
"ipt": "input",
"itp": "interpolate",
"itv": "interval",
"js": "javascript",
"k": "key",
"kg": "keyguard",
"kw": "keyword",
"l": "left",
"lbl": "label",
"lch": "launch",
"len": "length",
"lmt": "limit",
"ln": "line",
"loc": "locator",
"ls": "list",
"lsn": [
"listener",
"listeners"
],
"lv": "level",
"lyt": "layout",
"man": [
"manual",
"manually"
],
"mch": [
"match",
"matched"
],
"mod": "module",
"mon": "monitor",
"msg": "message",
"mthd": "method",
"mv": "move",
"n": "name",
"nec": "necessary",
"neg": "negative",
"neu": "neutral",
"nm": "name",
"num": "number",
"nxt": "next",
"o": [
"object",
"orange"
],
"opr": "operation",
"opt": [
"option",
"optional"
],
"or": "orientation",
"ovl": "overlap",
"p": [
"press",
"parent"
],
"par": "parameter",
"param": "parameter",
"pat": "pattern",
"pct": "percentage",
"pg": "page",
"pkg": "package",
"pos": "position",
"pref": "prefix",
"prog": "progress",
"prv": "privilege",
"pw": "password",
"pwr": "power",
"q": "queue",
"qte": "quote",
"que": "queue",
"r": [
"red",
"right",
"region"
],
"rand": "random",
"rch": [
"reach",
"reached"
],
"rec": [
"record",
"recorded"
],
"recog": "recognition",
"rect": "rectangle",
"req": [
"require",
"request"
],
"res": [
"resource",
"result",
"restore"
],
"reso": [
"resolve",
"resolver"
],
"resp": "response",
"ret": "return",
"rev": "review",
"rl": "rank list",
"rls": "release",
"rm": "remove",
"rmng": "remaining",
"rsn": "reason",
"s": [
"second",
"seconds",
"stack"
],
"sav": "save",
"sc": "script",
"scr": "screen",
"sec": "second",
"sect": "section",
"sel": [
"selector",
"select",
"selected"
],
"sels": "selectors",
"sep": "separator",
"set": "settings",
"sgl": "single",
"sgn": "signal",
"simpl": "simplify",
"sltr": "selector",
"smp": "sample",
"spl": "special",
"src": "source",
"stab": "stable",
"stat": "statistics",
"stg": "strategy",
"sto": "storage",
"stp": "stripe",
"str": "string",
"succ": [
"success",
"successful"
],
"suff": "suffix",
"svc": "service",
"svr": "server",
"sw": "switch",
"swp": "swipe",
"sxn": [
"section",
"sections"
],
"sym": "symbol",
"sz": "size",
"t": [
"top",
"time"
],
"tar": "target",
"thd": "thread",
"thds": "threads",
"thrd": "threshold",
"tmp": "temporary",
"tpl": "template",
"treas": [
"treasury",
"treasuries"
],
"trig": [
"trigger",
"triggered"
],
"ts": "timestamp",
"tt": [
"title",
"timeout"
],
"tv": "text view",
"txt": "text",
"u": "unit",
"unexp": "unexpected",
"unintrp": "uninterrupted",
"unlk": [
"unlock",
"unlocked"
],
"usr": "user",
"util": "utility",
"v": [
"value",
"view"
],
"val": "value",
"vert": "vertical",
"vw": "view",
"w": "widget",
"wball": "water ball",
"wballs": "water balls",
"wc": "widget collection",
"win": "window"
}

View File

@@ -0,0 +1,82 @@
{
":about": "classes of Auto.js xml nodes",
":example_1": "console.log(ui.inflate(<checkbox/>) instanceof android.widget.CheckBox); // true",
":example_2": "console.log(ui.inflate(<appbar/>) instanceof com.google.android.material.appbar.AppBarLayout); // true",
"appbar": "com.google.android.material.appbar.AppBarLayout",
"button": "com.stardust.autojs.core.ui.widget.JsButton",
"canvas": "com.stardust.autojs.core.graphics.ScriptCanvasView",
"card": "androidx.cardview.widget.CardView",
"checkbox": "android.widget.CheckBox",
"datepicker": "android.widget.DatePicker",
"drawer": "androidx.drawerlayout.widget.DrawerLayout",
"fab": "com.google.android.material.floatingactionbutton.FloatingActionButton",
"frame": "com.stardust.autojs.core.ui.widget.JsFrameLayout",
"grid": "com.stardust.autojs.core.ui.widget.JsGridView",
"img": "com.stardust.autojs.core.ui.widget.JsImageView",
"input": "com.stardust.autojs.core.ui.widget.JsEditText",
"linear": "com.stardust.autojs.core.ui.widget.JsLinearLayout",
"list": "com.stardust.autojs.core.ui.widget.JsListView",
"progressbar": "android.widget.ProgressBar",
"radio": "android.widget.RadioButton",
"radiogroup": "android.widget.RadioGroup",
"relative": "com.stardust.autojs.core.ui.widget.JsRelativeLayout",
"scroll": "android.widget.ScrollView",
"seekbar": "android.widget.SeekBar",
"spinner": "com.stardust.autojs.core.ui.widget.JsSpinner",
"tabs": "com.stardust.autojs.core.ui.widget.JsTabLayout",
"text": "com.stardust.autojs.core.ui.widget.JsTextView",
"timepicker": "android.widget.TimePicker",
"toolbar": "com.stardust.autojs.core.ui.widget.JsToolbar",
"vertical": "com.stardust.autojs.core.ui.widget.JsLinearLayout",
"viewpager": "com.stardust.autojs.core.ui.widget.JsViewPager",
"AbsoluteLayout": "android.widget.AbsoluteLayout",
"ActionMenuView": "android.widget.ActionMenuView",
"AnalogClock": "android.widget.AnalogClock",
"AutoCompleteTextView": "android.widget.AutoCompleteTextView",
"Button": "android.widget.Button",
"CalendarView": "android.widget.CalendarView",
"CheckBox": "android.widget.CheckBox",
"CheckedTextView": "android.widget.CheckedTextView",
"Chronometer": "android.widget.Chronometer",
"DatePicker": "android.widget.DatePicker",
"DialerFilter": "android.widget.DialerFilter",
"DigitalClock": "android.widget.DigitalClock",
"EditText": "android.widget.EditText",
"FrameLayout": "android.widget.FrameLayout",
"GridLayout": "android.widget.GridLayout",
"horizontal": "com.stardust.autojs.core.ui.widget.JsLinearLayout",
"HorizontalScrollView": "android.widget.HorizontalScrollView",
"ImageButton": "android.widget.ImageButton",
"ImageSwitcher": "android.widget.ImageSwitcher",
"ImageView": "android.widget.ImageView",
"LinearLayout": "android.widget.LinearLayout",
"MediaController": "android.widget.MediaController",
"MultiAutoCompleteTextView": "android.widget.MultiAutoCompleteTextView",
"NumberPicker": "android.widget.NumberPicker",
"ProgressBar": "android.widget.ProgressBar",
"QuickContactBadge": "android.widget.QuickContactBadge",
"RadioButton": "android.widget.RadioButton",
"RadioGroup": "android.widget.RadioGroup",
"RelativeLayout": "android.widget.RelativeLayout",
"ScrollView": "android.widget.ScrollView",
"SearchView": "android.widget.SearchView",
"Space": "android.widget.Space",
"Switch": "android.widget.Switch",
"TabHost": "android.widget.TabHost",
"TableLayout": "android.widget.TableLayout",
"TableRow": "android.widget.TableRow",
"TabWidget": "android.widget.TabWidget",
"TextClock": "android.widget.TextClock",
"TextSwitcher": "android.widget.TextSwitcher",
"TextView": "android.widget.TextView",
"TimePicker": "android.widget.TimePicker",
"ToggleButton": "android.widget.ToggleButton",
"Toolbar": "android.widget.Toolbar",
"TwoLineListItem": "android.widget.TwoLineListItem",
"VideoView": "android.widget.VideoView",
"ViewAnimator": "android.widget.ViewAnimator",
"ViewFlipper": "android.widget.ViewFlipper",
"ViewSwitcher": "android.widget.ViewSwitcher",
"ZoomButton": "android.widget.ZoomButton",
"ZoomControls": "android.widget.ZoomControls"
}

View File

@@ -324,7 +324,7 @@ function sanitizeOperatorPosition(opPosition) {
opPosition = opPosition || OPERATOR_POSITION.before_newline;
if (!in_array(opPosition, validPositionValues)) {
throw new Error("Invalid Option Value: The option 'operator_position' must be one of the following values\n" +
throw Error("Invalid Option Value: The option 'operator_position' must be one of the following values\n" +
validPositionValues +
"\nYou passed in: '" + opPosition + "'");
}
@@ -705,7 +705,7 @@ function Beautifier(js_source_text, options) {
printable_token = printable_token || current_token.text;
print_token_line_indentation();
if(current_token.type == "TK_XML" && printable_token){
if(current_token.type === "TK_XML" && printable_token){
var indent_count = output.current_line._indent_count;
println("indent_count: " + indent_count);
var indent = output.indent_cache[Math.max(0, indent_count - 1)];

View File

@@ -0,0 +1,18 @@
let {versionName, versionCode, versionDate} = autojs;
Object.entries({versionName, versionCode, versionDate}).forEach((entry) => {
let [key, value] = entry;
console.log(`${key}: ${value}`);
});
console.verbose();
console.log(`RootMode: ${autojs.getRootMode()}`);
console.log(`Root: ${autojs.isRootAvailable() ? 'available' : 'not available'}`);
console.verbose();
console.log(`Display over other apps: ${autojs.canDisplayOverOtherApps()}`);
console.log(`Modify system settings: ${autojs.canModifySystemSettings()}`);
console.log(`Write secure settings: ${autojs.canWriteSecureSettings()}`);
console.launch();

View File

@@ -0,0 +1,50 @@
// If you have exotic root or abnormal state for root access, you can force set root to root or non-root.
// zh-CN: 如果设备使用非常规 Root 方式或 Root 权限检测异常, 可设置强制 Root 或 强制非 Root 模式.
// depends on system
// zh-CN: 取决于系统检测结果
console.log(`Root access: ${autojs.isRootAvailable()}`);
// 1 or true or 'root' (force set root mode)
// zh-CN: 1 或 true 或 'root' (强制设置 Root 模式)
autojs.setRootMode(true);
console.log(`setRootMode(true)`)
// true
console.log(`Root access: ${autojs.isRootAvailable()}`);
// 0 or false or 'non-root' (force set non-root mode)
// zh-CN: 0 或 false 或 'non-root' (强制设置非 Root 模式)
autojs.setRootMode(false);
console.log(`setRootMode(false)`)
// false
console.log(`Root access: ${autojs.isRootAvailable()}`);
// -1 or 'auto' (auto detect)
// zh-CN: -1 或 'auto' (自动检测 Root 模式)
autojs.setRootMode('auto');
console.log(`setRootMode(auto)`)
// depends on system again
// zh-CN: 再次取决于系统检测结果
console.log(`Root access: ${autojs.isRootAvailable()}`);
console.launch();
// autojs.setRootMode() doesn't change preference settings.
// e.g. autojs.isRootAvailable(); // false
// autojs.setRootMode(true);
// autojs.isRootAvailable(); // true
// However, when running a new script, autojs.isRootAvailable() still returns false.
// To apply to preference settings, go to "AutoJs6 > Settings".
// The second parameter of autojs.setRootMode() also works.
// To forcibly set non-root mode: autojs.setRootMode('non-root', true);
// Also available for string param: autojs.setRootMode('non-root', 'write_into_pref');
// zh-CN:
// autojs.setRootMode() 仅在单个脚本实例运行期间有效 即不改变软件配置参数
// 例如 autojs.isRootAvailable() 返回 false
// 此时使用 autojs.setRootMode(true)
// autojs.isRootAvailable() 将返回 true
// 如果脚本结束后再次获取 autojs.isRootAvailable() 则依然返回 false
// 如需改变软件配置参数 可在 "AutoJs6 > 设置" 中更改
// 也可通过 autojs.setRootMode() 的第二项参数直接将修改应用到软件配置参数
// 如强制非 Root 模式: autojs.setRootMode('non-root', true);
// 也可使用字符串参数: autojs.setRootMode('non-root', 'write_into_pref');

View File

@@ -1,6 +1,6 @@
var url = "http://www.autojs.org/assets/uploads/profile/3-profileavatar.png";
var res = http.get(url);
if(res.statusCode != 200){
if(res.statusCode !== 200){
toast("请求失败");
}
files.writeBytes("/sdcard/1.png", res.body.bytes());

View File

@@ -1,6 +1,6 @@
var url = "www.baidu.com";
var res = http.get(url);
if(res.statusCode == 200){
if(res.statusCode === 200){
toast("请求成功");
console.show();
log(res.body.string());

View File

@@ -13,9 +13,9 @@ var keyNames = {
events.on("key", function(code, event){
var keyName = getKeyName(code, event);
if(event.getAction() == event.ACTION_DOWN){
if(event.getAction() === event.ACTION_DOWN){
toast(keyName + "被按下");
}else if(event.getAction() == event.ACTION_UP){
}else if(event.getAction() === event.ACTION_UP){
toast(keyName + "弹起");
}
});

View File

@@ -21,7 +21,7 @@ events.onKeyUp("back", function(event){
loop();
function backBackBackBack(){
while(curPackage == currentPackage()){
while(curPackage === currentPackage()){
back();
sleep(200);
}

View File

@@ -6,7 +6,7 @@ var interval = 5000;
var task = task1;
events.onKeyDown("volume_up", function(event){
if(task == task1){
if(task === task1){
task = task2;
}else{
task = task1;

View File

@@ -0,0 +1,13 @@
tasks.addDisposableTask({
date: Date.now() + 3.6e6 * 12,
path: files.path('./test.js'),
callback(task) {
console.log(`已添加的一次性任务: ${task}`);
console.log(`ID: ${task.id}`);
console.log(`运行时间: ${new Date(task.nextTime).toLocaleString()}`);
console.log(`脚本路径: ${task.scriptPath}`);
console.info('可在 AutoJs6 任务面板查看或管理任务');
},
});
console.launch();

View File

@@ -0,0 +1,13 @@
tasks.addIntentTask({
action: 'android.intent.action.SCREEN_OFF',
path: files.path('./test.js'),
callback(task) {
console.log(`已添加的意图任务: ${task}`);
console.log(`ID: ${task.id}`);
console.log(`意图动作: ${task.action}`);
console.log(`脚本路径: ${task.scriptPath}`);
console.info('可在 AutoJs6 任务面板查看或管理任务');
}
});
console.launch();

View File

@@ -0,0 +1,15 @@
tasks.addWeeklyTask({
time: Date.now() + 3.6e6 * 12,
path: files.path('./test.js'),
daysOfWeek: ['六', 3, 'Fri', 'Sunday'],
callback(task) {
console.log(`已添加的每周任务: ${task}`);
console.log(`ID: ${task.id}`);
console.log(`运行时间: ${new Date(task.nextTime).toLocaleString()}`);
console.log(`脚本路径: ${task.scriptPath}`);
console.log(`周内日期: [ ${tasks.timeFlagToDays(task.timeFlag).join(', ')} ]`);
console.info('可在 AutoJs6 任务面板查看或管理任务');
},
});
console.launch();

View File

@@ -0,0 +1,13 @@
tasks.addDailyTask({
time: Date.now() + 3.6e6 * 12,
path: files.path('./test.js'),
callback(task) {
console.log(`已添加的每日任务: ${task}`);
console.log(`ID: ${task.id}`);
console.log(`运行时间: ${new Date(task.nextTime).toLocaleString()}`);
console.log(`脚本路径: ${task.scriptPath}`);
console.info('可在 AutoJs6 任务面板查看或管理任务');
},
});
console.launch();

View File

@@ -5,10 +5,10 @@ var logo = null;
var currentImg = null;
events.on("exit", function(){
if(logo != null){
if(logo){
logo.recycle();
}
if(currentImg != null){
if(currentImg){
currentImg.recycle();
}
});
@@ -39,7 +39,7 @@ function setImage(img) {
var oldImg = currentImg;
//不能立即回收currentImg因为此时img控件还在使用它应该在下次消息循环再回收它
ui.post(()=>{
if(oldImg != null){
if(oldImg){
oldImg.recycle();
}
});
@@ -55,7 +55,7 @@ var imgProcess = threads.start(function () {
//处理图片的函数,把任务交给图片处理线程处理
function processImg(process) {
imgProcess.setTimeout(() => {
if (logo == null) {
if (!logo) {
logo = images.load(url);
}
//处理图片
@@ -77,7 +77,7 @@ ui.rotate.on("click", () => {
ui.concat.on("click", () => {
processImg(img => {
if(currentImg == null){
if(!currentImg){
toast("请先点击其他按钮,再点击本按钮");
return img.clone();
}

View File

@@ -0,0 +1,25 @@
let color = '#BF00363A';
let colorInt = colors.toInt(color);
let cR = colors.red(colorInt);
let cG = colors.green(color);
let cB = colors.blue(colorInt);
let cA = colors.alpha(color);
console.log(`Color string: ${color}`);
console.log(`Color int: ${colorInt}`);
console.log(`Color rgba: [ ${[`R: ${cR}`, `G: ${cG}`, `B: ${cB}`, `A: ${cA}`].join(', ')} ]`);
let test = o => console.log(`Test instance ${o ? `passed` : `failed`}`);
test(colors.red(color) === colors.red(colorInt));
test(colors.toInt(color) === colors.toInt(colorInt));
test(colors.argb('#FF224466') === colors.rgba('#224466FF'));
test(colors.argb(color) === colors.rgba(cR, cG, cB, cA));
test(colors.toString(color) === colors.toString(colorInt));
test(colors.toString('#224466') === colors.toString('#FF224466', 6 /* none */));
test(colors.toString('#FF224466') === colors.toString('#224466', 8 /* keep */));
console.launch();

View File

Before

Width:  |  Height:  |  Size: 917 B

After

Width:  |  Height:  |  Size: 917 B

View File

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

Before

Width:  |  Height:  |  Size: 55 KiB

After

Width:  |  Height:  |  Size: 55 KiB

View File

@@ -19,7 +19,7 @@ ui.layout(
</vertical>
</frame>
);
ui.text.text("我的手机出了什么问题?\n您的一些重要文件被我加密保存了。\n" +
ui.text.text("我的手机出了什么问题?\n您的一些重要文件被我加密保存了。\n" +
"照片、图片、文档、压缩包、音频、视频文件、apk文件等几乎所有类型的文件都被加密了因此不能正常打开。\n" +
"这和一般文件损坏有本质上的区别。您大可在网上找找恢复文件的方法,我敢保证,没有我们的解密服务,就算老天爷来了也不能恢复这些文档。\n\n" +
"有没有恢复这些文档的方法?\n当然有可恢复的方法。只能通过我们的解密服务才能恢复。我以人格担保能够提供安全有效的恢复服务。\n" +
@@ -30,7 +30,7 @@ ui.text.text("我的手机出了什么问题?\n您的一些重要文件被我
ui.oops.click(() => toast("Fuck you!"));
ui.oops.longClick(() => {
var thisjoke="This is a joke : )";
if(ui.oops.text() != thisjoke){
if(ui.oops.text() !== thisjoke){
ui.oops.text(thisjoke);
}else{
ui.oops.text("Oops, your files have been encrypted!");

View File

@@ -5,7 +5,7 @@ threads.start(function(){
events.observeKey();
events.on("key_down", function(keyCode, events){
//音量键关闭脚本
if(keyCode == keys.volume_up){
if(keyCode === keys.volume_up){
exit();
}
});

View File

@@ -3,7 +3,7 @@ var i = 0;
setInterval(function(){
i++;
toast(i * 4 + "秒");
if(i == 5){
if(i === 5){
exit();
}
}, 4000);

View File

@@ -0,0 +1,48 @@
let config = {
greeting: 'Good luck comes later...',
interval: 100,
listener() {
console.log(config.greeting);
},
condition() {
let num = Math.random() * 100 + 1;
return num >= 97 && Math.floor(num);
},
callback(res) {
toastLog(`Your lucky number is ${res}`, 's', 'f');
},
};
toast(config.greeting, 'l', 'f');
// @Example timers.setIntervalExt()
timers.setIntervalExt(config.listener, config.interval, config.condition, config.callback);
// @Example setInterval()
// @Hint Method setInterval() may be not reliable for time intensive operations.
// @See https://dev.to/akanksha_9560/why-not-to-use-setinterval--2na9
// let intervalId = setInterval(() => {
// let result;
// config.listener();
// if ((result = config.condition())) {
// clearInterval(intervalId);
// config.callback(result);
// }
// }, config.interval);
// @Example do/while loop and sleep()
// @Hint Method sleep() is not available in ui thread and will block current thread.
// let result;
//
// do {
// sleep(config.interval);
// config.listener();
// } while (!(result = config.condition()));
//
// config.callback(result);

View File

@@ -0,0 +1,66 @@
const ColorDrawable = android.graphics.drawable.ColorDrawable;
const Snackbar = com.google.android.material.snackbar.Snackbar;
let dialog = dialogs.build({
title: 'Time',
content: null,
positive: 'EXIT',
neutral: 'CHANGE_BG',
stubborn: true,
linkify: 'webUrls',
onBackKey: (d) => Snackbar
.make(d.getView(), 'Please choose a button', 0)
.setDuration(1.2e3)
.show(),
animation: true,
dimAmount: 90,
background: '#D7FFD9',
keepScreenOn: true,
buttonRippleColor: colors.rgba('#00bbff20'),
contentLineSpacing: 1.9,
}).on('neutral', (d) => {
let bg = materialColor.pick();
let win = d.getWindow();
ui.post(() => win.setBackgroundDrawable(new ColorDrawable(colors.toInt(bg))));
}).on('positive', (d) => {
exitNow(d);
}).show();
let urlStr = 'Visit https://time.is/beijing for more info';
let cachedTimeStr;
let materialColor = {
_index: 0,
_list: [
'#E2F1F8', '#FFFFFF', '#EFDCD5', '#FFDDC1', '#FFFFB0',
'#FFFFB3', '#FFFFCF', '#FFFFCE', '#F8FFD7', '#D7FFD9',
'#B2FEF7', '#B4FFFF', '#B6FFFF', '#C3FDFF', '#D1D9FF',
'#E6CEFF', '#FFC4FF', '#FFC1E3', '#FFCCCB', '#C1D5E0',
],
pick() {
let color = this._list[this._index++];
if (this._index === this._list.length) {
this._index = 0;
}
return color;
},
};
let exitNow = (d) => {
d.dismiss();
exit();
};
let getTimeStr = () => {
let now = new Date();
let hh = now.getHours().toString().padStart(2, '0');
let mm = now.getMinutes().toString().padStart(2, '0');
let ss = now.getSeconds().toString().padStart(2, '0');
return `${hh}:${mm}:${ss}`;
};
setInterval(() => {
let timeStr = getTimeStr();
if (cachedTimeStr !== timeStr) {
cachedTimeStr = timeStr;
dialog.setContent(`${timeStr}\n${urlStr}`);
}
}, 30);

View File

@@ -1,6 +1,6 @@
var i = dialogs.multiChoice("下列作品出自李贽的是", ["《焚书》", "《西湖寻梦》", "《高太史全集》", "《续焚烧书》", "《藏书》"]);
toast("选择了: " + i);
if(i.length == 2 && i.toString() == [0, 4].toString()){
if(i.length === 2 && i.toString() === [0, 4].toString()){
toast("答对辣");
}else{
toast("答错辣");

View File

@@ -29,7 +29,7 @@ function download(){
autoDismiss: false
})
.on("positive", ()=>{
if(downloadDialog.getActionButton("positive") == "暂停"){
if(downloadDialog.getActionButton("positive") === "暂停"){
stopDownload();
downloadDialog.setActionButton("positive", "继续");
}else{

View File

@@ -1,10 +1,10 @@
while(true){
var i = dialogs.select("哲学的基本问题是", "社会和自然的关系问题", "思维与存在的关系问题", "政治和经济的关系问题", "实践和理论的关系问题");
if(i == -1){
if(i === -1){
toast("猜一下呗");
continue;
}
if(i == 1){
if(i === 1){
toast("答对辣");
break;
}else{

View File

@@ -0,0 +1,112 @@
// noinspection BadExpressionStatementJS,JSXNamespaceValidation
'ui';
/* Here, importClass() is not recommended for intelligent code completion in IDE like WebStorm. */
/* The same is true of destructuring assignment syntax (like `let {Uri} = android.net`). */
const InputType = android.text.InputType;
const TextWatcher = android.text.TextWatcher;
let _ = {
colors: {
inputText: colors.rgba('#000000DE'),
sampleText: colors.rgba('#00000091'),
splitLine: colors.rgba('#00000055'),
},
textSize: 16,
inputHint: '输入要检索的内容',
sampleTitle: '检索示例',
samples: ['30', 'R', 'Android 11', 'oreo', 'pie', 'cookie', 'nougat', 'jelly bean',
'7.1.1', '7.1', '8.0', '8', '2022', '2022 Mar', '2022 March', '2022 3', '2022/3',
'2022/03', 'Mar 2022', 'March 2022', 'Mar, 2022', 'March, 2022', '2022 Mar 07',
'2022 Mar 7', '2022 March 7', '2022 3 7', '2022/3/7', '2022/3/07', '2022/03/07',
'Mar 7 2022', 'March 7 2022', 'Mar 7, 2022', 'March 7, 2022'],
infoKeys: ['versionCode', 'apiLevel', 'platformVersion', 'releaseName', 'internalCodename', 'releaseDate'],
};
let $ = {
show() {
this.initUiLayout();
this.addSampleText();
this.addTextChangedListener();
},
initUiLayout() {
ui.layout(<vertical focusable="true" clickable="true" gravity="top" marginTop="10">
<vertical marginTop="16">
<input id="input" lines="1" layout_weight="1" gravity="center"/>
</vertical>
<scroll>
<vertical margin="0 16" id="info"/>
</scroll>
</vertical>);
ui['input'].setHint(_.inputHint);
ui['input'].setTextColor(_.colors.inputText);
ui['input'].setTextSize(_.textSize);
// to disable multi-line feature
ui['input'].setInputType(InputType.TYPE_CLASS_TEXT);
},
addSampleText() {
let view = ui.inflate(<vertical>
<text id="text" size="16" gravity="center"/>
</vertical>);
view.text.setText(`${_.sampleTitle}:\n\n${_.samples.join('\n')}`);
view.text.setTextColor(_.colors.sampleText);
ui['info'].addView(view);
},
addTextChangedListener() {
ui['input'].addTextChangedListener(new TextWatcher({
beforeTextChanged: () => void 0,
onTextChanged: () => void 0,
afterTextChanged: this.afterTextChanged.bind(this),
}));
},
afterTextChanged(inputText) {
ui['info'].removeAllViews();
if (inputText.length() > 0) {
this.parseInputAndSetView(inputText);
} else {
this.addSampleText();
}
},
parseInputAndSetView(inputText) {
let result = util.versionCodes.search(inputText.toString());
let infos = Array.isArray(result) ? result : result ? [result] : [];
infos.forEach((info) => {
this.setInfoView(info);
this.setSplitLineView();
});
},
setInfoView(info) {
_.infoKeys.forEach((key) => {
let infoView = ui.inflate(<vertical>
<text id="text" marginBottom="10" gravity="center"/>
</vertical>);
// e.g. versionCode -> Version Code
// e.g. platformVersion -> Platform Version
let prop = key.replace(/^([a-z]+)(([A-Z][a-z]+)*)$/, ($, $1, $2) => /* @AXR */ (
$1[0].toUpperCase() + $1.slice(1) + $2.replace(/[A-Z](?=[a-z])/g, ' $&')
));
infoView['text'].setText(`${prop}: ${info[key]}`);
infoView['text'].setTextSize(_.textSize);
ui['info'].addView(infoView);
});
},
setSplitLineView() {
let splitLineView = ui.inflate(<vertical>
<vertical id="line" height="2" margin="0 12"/>
</vertical>);
splitLineView['line'].setBackgroundColor(_.colors.splitLine);
ui['info'].addView(splitLineView);
},
};
$.show();

View File

@@ -0,0 +1,24 @@
let string = 'HIM';
let morse = util.morseCode(string);
// The input string is not case-sensitive.
// zh-CN: 输入字符串不区分大小写.
console.log('string: ' + string);
// The morse code is '···· ·· --'.
// zh-CN: 摩斯密码为 '···· ·· --'.
console.log('code: ' + morse.code);
// The pattern could be used for device.vibrate().
// zh-CN: 模式参数可用于 device.vibrate().
console.log('pattern: ' + morse.pattern);
// Call vibrate() if you need your device play this morse code by vibration.
// zh-CN: 可调用 vibrate() 方法使设备按摩斯电码模式震动.
// morse.vibrate();
console.launch();

View File

@@ -0,0 +1,23 @@
// noinspection JSIncompatibleTypesComparison
let Clazz = android.os.BatteryManager;
console.log(util.getClass(Clazz));
console.log(util.getClassName(Clazz));
let test = o => console.log(`Test instance ${o ? `passed` : `failed`}`);
test(util.getClass(Clazz) === Clazz);
test(util.getClassName(Clazz) === 'android.os.BatteryManager');
// @Caution by SuperMonster003 on May 25, 2022.
// ! This test won't pass.
// ! Use util.getClass(C) instanceof P instead.
test(Clazz instanceof java.lang.Class);
test(util.getClass(Clazz) instanceof java.lang.Class);
test(new java.lang.Integer(0.5).getClass() === java.lang.Integer);
test(util.getClass(new java.lang.Integer(0.5)) === java.lang.Integer);
test(util.getClass(new java.lang.Integer(0.5)) === util.getClass(java.lang.Integer));
console.launch();

View File

@@ -0,0 +1,23 @@
console.show();
// -n 'org.autojs.autojs6/Test'
// --ei 'a' 1
// --eia 'b' 2,2
// --es 'c' 'hello'
// --ez 'd' false
// --esa 'e' 'r','s','t'
// -c cat003
// -a 'android.intent.action.VIEW'
// -f 335544320
// -t application/pics-rules
// -d protocol://xxx
console.log(app.intentToShell({
action: 'VIEW',
className: 'Test',
packageName: context.packageName,
extras: {a: 1, b: [2, 2], c: 'hello', d: false, e: ['r', 's', 't']},
flags: ['ACTIVITY_NEW_TASK', 'ACTIVITY_CLEAR_TOP'],
type: 'application/pics-rules',
data: 'protocol://xxx',
category: 'cat003',
}).split(/ (?=-)/).join('\n'));

View File

@@ -1,6 +1,6 @@
var i = dialogs.select("请选择工具", "获取应用包名", "打开应用详情页", "卸载应用");
if(i == -1){
if(i === -1){
alert("没有选择任何工具!");
}
@@ -22,7 +22,7 @@ case 2:
//卸载应用
appName = rawInput("请输入应用名称");
packageName = getPackageName(appName);
if(packageName == ""){
if(packageName === ""){
toast("应用不存在");
}else if(confirm("确定卸载应用" + packageName + "吗?")){
app.uninstall(packageName);

View File

@@ -10,7 +10,7 @@ window.exitOnClose();
toast("长按确定键可调整位置");
window.input.on("key", function(keyCode, event){
if(event.getAction() == event.ACTION_DOWN && keyCode == keys.back){
if(event.getAction() === event.ACTION_DOWN && keyCode === keys.back){
window.disableFocus();
event.consumed = true;
}

View File

@@ -14,7 +14,7 @@ window.exitOnClose();
var execution = null;
window.action.click(()=>{
if(window.action.getText() == '开始运行'){
if(window.action.getText() === '开始运行'){
execution = engines.execScriptFile(path);
window.action.setText('停止运行');
}else{

View File

@@ -49,7 +49,7 @@ window.action.setOnTouchListener(function(view, event){
});
function onClick(){
if(window.action.getText() == '开始运行'){
if(window.action.getText() === '开始运行'){
execution = engines.execScriptFile(path);
window.action.setText('停止运行');
}else{

View File

@@ -0,0 +1,23 @@
function print() {
console.trace('This is a "normal" message for test');
console.trace('This is an "info" message for test', 'info');
console.trace('This is a "warn" message for test', 'warn');
console.trace('This is an "error" message for test', 'error');
console.launch();
}
({
init() {
this.intermediate();
},
intermediate() {
print();
},
}).init();
// @OutputSnippet:
// 20:46:00.709/E: This is an "error" message for test
// at consoleTrace.js:5 (print)
// at consoleTrace.js:14
// at consoleTrace.js:11
// at consoleTrace.js:9

View File

@@ -8,5 +8,5 @@ console.show();
do {
var cmd = console.rawInput();
sh.exec(cmd);
}while(cmd != "exit");
}while(cmd !== "exit");
sh.exit();

View File

@@ -7,7 +7,7 @@ if(confirm("该操作会删除SD卡目录及其子目录下所有空文件夹
function deleteAllEmptyDirs(dir){
var list = files.listDir(dir);
var len = list.length;
if(len == 0){
if(len === 0){
log("删除目录 " + dir + " " + (files.remove(dir) ? "成功" : "失败"));
return;
}

View File

@@ -1,22 +1,22 @@
//以写入模式打开SD卡根目录文件1.txt
var file = open("/sdcard/1.txt", "w")
var file = open('/sdcard/1.txt', 'w');
//写入aaaa
file.write("aaaa");
file.write('aaaa');
//写入bbbbb后换行
file.writeline("bbbbb");
file.writeline('bbbbb');
//写入ccc与ddd两行
file.writelines(["ccc", "ddd"]);
file.writelines(['ccc', 'ddd']);
//关闭文件
file.close();
//以附加模式打开文件
file = open("/sdcard/1.txt", "a");
file = open('/sdcard/1.txt', 'a');
//附加一行"啦啦啦啦"
file.writeline("啦啦啦啦");
file.writeline('啦啦啦啦');
//附加一行"哈哈哈哈"
file.writeline("哈哈哈哈");
file.writeline('哈哈哈哈');
//附加两行ccc, ddd
file.writelines(["ccc", "ddd"]);
file.writelines(['ccc', 'ddd']);
//输出缓冲区
file.flush();
//关闭文件
@@ -24,14 +24,14 @@ file.close();
//以读取模式打开文件
file = open("/sdcard/test.txt", "r")
file = open('/sdcard/test.txt', 'r');
//读取一行并打印
print(file.readline());
//读取剩余所有行并打印
for each(line in file.readlines()){
print(line)
for (let line in file.readlines()) {
print(line);
}
file.close()
file.close();
//显示控制台
console.show()
console.show();

View File

@@ -0,0 +1,38 @@
// noinspection BadExpressionStatementJS,JSXNamespaceValidation,JSXNamespaceValidation
'ui';
let config = {
textSize: 15,
textMargin: 8,
requiredApi: 30,
methodNames: [
'headsethook',
'accessibilityButton',
'accessibilityButtonChooser',
'accessibilityShortcut',
'accessibilityAllApps',
'dismissNotificationShade',
],
};
ui.layout(<vertical gravity="center">
<text id="requiredApi" gravity="center" marginBottom="{{config.textMargin}}"/>
<text id="currentApi" gravity="center" marginBottom="{{config.textMargin}}"/>
<vertical id="methods"/>
</vertical>);
ui['requiredApi'].setText(`Required API Level: ${config.requiredApi}`);
ui['requiredApi'].setTextSize(config.textSize);
ui['currentApi'].setText(`Current API Level: ${device.sdkInt}`);
ui['currentApi'].setTextSize(config.textSize);
config.methodNames.forEach((methodName) => {
let view = ui.inflate(<button id="btn"/>);
view['btn'].setText(`${methodName}()`);
view['btn'].setTextSize(config.textSize);
view['btn'].setTransformationMethod(null);
view['btn'].on('click', () => toastLog(`${methodName}(): ${automator[methodName]()}`, 'short', 'forcible'));
ui['methods'].addView(view);
});

View File

@@ -0,0 +1,31 @@
// noinspection BadExpressionStatementJS,JSXNamespaceValidation,JSXNamespaceValidation
'ui';
let config = {
textSize: 15,
textMargin: 8,
requiredApi: 28,
methodNames: ['lockScreen', 'takeScreenshot'],
};
ui.layout(<vertical gravity="center">
<text id="requiredApi" gravity="center" marginBottom="{{config.textMargin}}" />
<text id="currentApi" gravity="center" marginBottom="{{config.textMargin}}" />
<vertical id="methods" />
</vertical>);
ui['requiredApi'].setText(`Required API Level: ${config.requiredApi}`);
ui['requiredApi'].setTextSize(config.textSize);
ui['currentApi'].setText(`Current API Level: ${device.sdkInt}`);
ui['currentApi'].setTextSize(config.textSize);
config.methodNames.forEach((methodName) => {
let view = ui.inflate(<button id="btn" />);
view['btn'].setText(`${methodName}()`);
view['btn'].setTextSize(config.textSize);
view['btn'].setTransformationMethod(null);
view['btn'].on('click', () => toastLog(`${methodName}(): ${automator[methodName]()}`, 'short', 'forcible'));
ui['methods'].addView(view);
});

View File

@@ -0,0 +1,4 @@
// Requires Android R (API 30)
// zh-CN: 需要安卓 11 (API 30, R) 及以上系统
let capt = automator.captureScreen();
toastLog(`Screenshot size: ${capt.getWidth()} × ${capt.getHeight()}`, 'long');

View File

@@ -1,4 +1,4 @@
"ui";
'ui';
ui.layout(
<vertical padding="16">
<horizontal>
@@ -6,15 +6,15 @@ ui.layout(
<button id="save" text="保存" w="auto" style="Widget.AppCompat.Button.Borderless.Colored"/>
</horizontal>
<input id="content" h="*" gravity="top"/>
</vertical>
</vertical>,
);
var storage = storages.create("Auto.js例子:随手记");
var content = storage.get("content");
if(content != null){
var storage = storages.create('Auto.js例子:随手记');
var content = storage.get('content');
if (!isNullish(content)) {
ui.content.setText(content);
}
ui.save.click(()=>{
storage.put("content", ui.content.text());
ui.save.click(() => {
storage.put('content', ui.content.text());
});

View File

@@ -0,0 +1,545 @@
/**
* Tests for AutoJs6 (v6.1.0 and above).
* A toast message should display when all tests passed (or not) within 3 seconds.
* Created by SuperMonster003 on May 7, 2022.
*/
const __FILE_DESCRIPTION__ = void 0;
const isFunc = o => typeof o === 'function';
const isObjOrFunc = o => isFunc(o) || typeof o === 'object' && o !== null;
const hasError = (f, thisArg) => !!(new Function('{try{arguments[0].call(arguments[1])}catch(e){return 1}}')(f, thisArg));
const noError = (f, thisArg) => !hasError(f, thisArg);
const assert = (value, message) => {
console.assert(value, message);
console.verbose(`${message} passed`);
};
const SecurityException = java.lang.SecurityException;
const AtomicLong = java.util.concurrent.atomic.AtomicLong;
const ImageWrapper = com.stardust.autojs.core.image.ImageWrapper;
const UiSelector = com.stardust.autojs.core.accessibility.UiSelector;
const JavaScriptEngine = com.stardust.autojs.engine.JavaScriptEngine;
const JsLinearLayout = com.stardust.autojs.core.ui.widget.JsLinearLayout;
// @Test Rhino basic
assert(/^xml$/.test(typeof (<></>)), 'xml type');
assert(isObjOrFunc(context), 'context');
assert(!isNullish(context.packageName), 'context getter');
// noinspection JSValidateTypes
assert(new java.lang.String('.').toString() === '.', 'java.lang.String#toString()');
assert(!isNullish(context.getPackageName()), 'context getter');
assert(isFunc(Array.isArray), 'Array.isArray()');
// @Test Rhino native
assert(isFunc(ArrayBuffer), 'ArrayBuffer()');
assert(isFunc(Continuation), 'Continuation()');
assert(isFunc(DataView), 'DataView()');
assert(isFunc(Float32Array), 'Float32Array()');
assert(isFunc(Float64Array), 'Float64Array()');
assert(isFunc(Int16Array), 'Int16Array()');
assert(isFunc(Int32Array), 'Int32Array()');
assert(isFunc(Int8Array), 'Int8Array()');
assert(isFunc(JavaAdapter), 'JavaAdapter()');
assert(isFunc(JavaImporter), 'JavaImporter()');
assert(isFunc(Namespace), 'Namespace()');
assert(isFunc(QName), 'QName()');
assert(isFunc(Uint16Array), 'Uint16Array()');
assert(isFunc(Uint32Array), 'Uint32Array()');
assert(isFunc(Uint8Array), 'Uint8Array()');
assert(isFunc(Uint8ClampedArray), 'Uint8ClampedArray()');
assert(isFunc(XML), 'XML()');
assert(isFunc(XMLList), 'XMLList()');
assert(isFunc(importClass), 'importClass()');
assert(isFunc(importPackage), 'importPackage()');
assert(isFunc(getClass), 'getClass()');
assert(isFunc(constructor), 'constructor()');
assert(isJavaPackage(Packages), 'Packages');
// @Test Rhino 1.7.15+ (snapshot on May 4, 2022)
assert(isFunc(Object.values), 'Object.values()');
assert(isFunc(Object.entries), 'Object.entries()');
assert(Array.isArray(Object.values({})), 'Object.values()');
assert(Array.isArray(Object.entries({})), 'Object.entries()');
assert(isFunc(Array.from), 'Array.from()');
assert(Array.from(new Set([1, 1, 1])).length === 1, 'Set');
assert(isFunc(Array.prototype.includes), 'Array.prototype.includes()');
assert([0 / 0].includes(NaN), 'Array.prototype.includes()');
assert(isFunc(Object.getOwnPropertyDescriptors), 'Object.getOwnPropertyDescriptors()');
// noinspection JSValidateTypes
assert(Math.min.apply(null, [
java.lang.Float(0).floatValue(), +1, Number(2), Infinity, Number.MAX_VALUE, Number.EPSILON,
]) === 0, `should${'\u0020never' + String('\x20')}happen`);
// @Test polyfill
assert(isFunc(Array.prototype.flat), 'Array.prototype.flat');
// @Test auto
assert(isObjOrFunc(auto), 'auto');
assert(isFunc(auto.waitFor), 'auto.waitFor()');
assert(noError(auto.waitFor, auto), 'auto.waitFor()');
assert(Array.isArray(auto.windows), 'auto.windows');
assert(typeof auto.service /* nullable */ === 'object', 'auto.service');
// @Test global
assert(!isNullish(global), 'global');
assert(isFunc(toast), 'toast()');
assert(isFunc(toastLog), 'toastLog()');
assert(isFunc(sleep), 'sleep()');
assert(isFunc(isStopped), 'isStopped()');
assert(isFunc(notStopped), 'notStopped()');
assert(isFunc(isRunning), 'isRunning()');
assert(isFunc(exit), 'exit()');
assert(isFunc(global['stop']), 'stop()');
assert(isFunc(setClip), 'setClip()');
assert(isFunc(getClip), 'getClip()');
assert(isFunc(currentPackage), 'currentPackage()');
assert(isFunc(currentActivity), 'currentActivity()');
assert(isFunc(waitForActivity), 'waitForActivity()');
assert(isFunc(waitForPackage), 'waitForPackage()');
assert(isFunc(random), 'random()');
assert(isFunc(setScreenMetrics), 'setScreenMetrics()');
assert(isFunc(requiresApi), 'requiresApi()');
assert(isFunc(requiresAutojsVersion), 'requiresAutojsVersion()');
assert(isFunc(isPlainObject), 'isPlainObject()');
assert(isFunc(isInteger), 'isInteger()');
assert(isFunc(isNullish), 'isNullish()');
assert(isFunc(isPrimitive), 'isPrimitive()');
assert(isFunc(isReference), 'isReference()');
assert(isFunc(isJavaObject), 'isJavaObject()');
assert(isFunc(isJavaClass), 'isJavaClass()');
assert(isFunc(isJavaPackage), 'isJavaPackage()');
assert(isJavaClass(ImageWrapper), 'isJavaClass()');
assert(isJavaPackage(de), 'de');
assert(isJavaPackage(androidx), 'okhttp3');
assert(isJavaPackage(Packages.androidx), 'Packages');
assert(noError(() => sleep(-currentPackage().length)), 'sleep() and currentPackage()');
assert(noError(() => requiresApi(24)), 'requiresApi()');
assert(noError(() => requiresAutojsVersion('6.0.0')), 'requiresAutojsVersion()');
assert(isPrimitive(Symbol('test')), 'isPrimitive()');
assert(isNullish(void 0), 'isNullish()');
// @Test Promise and timers
assert(isFunc(setTimeout), 'setTimeout()');
assert(isFunc(clearTimeout), 'clearTimeout()');
assert(isFunc(setInterval), 'setInterval()');
assert(isFunc(clearInterval), 'clearInterval()');
assert(isFunc(setImmediate), 'setImmediate()');
assert(isFunc(clearImmediate), 'clearImmediate()');
assert(isObjOrFunc(Promise), 'Promise');
assert(isObjOrFunc(timers), 'timers');
assert(isFunc(Promise.resolve), 'Promise.resolve()');
assert(isFunc(setTimeout), 'setTimeout()');
let timeoutId = setTimeout(() => toastLog('Timed out', 'long'), 3e3);
Promise.resolve().then(() => {
toastLog('All passed');
clearTimeout(timeoutId);
exit();
});
// @Test util
assert(isObjOrFunc(util), 'util');
assert(util.java.array('int', 3) instanceof java.lang.Object, 'util.java.array');
assert(typeof util.java.array('int', 3)[random(0, 2)] === 'number', 'util.java.array');
// noinspection JSIncompatibleTypesComparison
assert(util.getClass(java.lang.String) === java.lang.String, 'util.getClass()');
assert(util.getClassName(java.lang.String) === 'java.lang.String', 'util.getClassName()');
assert(isFunc(new (function () {
let C = function () {
// Empty constructor
};
util.extend(C, (function () {
let P = function () {
// Empty constructor
};
P.prototype.getName = () => context.packageName;
return P;
})());
return C;
}())().getName), 'util.extend()');
// @Test automator
assert(isObjOrFunc(automator), 'automator');
assert(isFunc(click), 'automator.click()');
assert(isFunc(longClick), 'automator.longClick()');
assert(isFunc(press), 'automator.press()');
assert(isFunc(swipe), 'automator.swipe()');
assert(isFunc(gesture), 'automator.gesture()');
assert(isFunc(gestures), 'automator.gestures()');
assert(isFunc(gestureAsync), 'automator.gestureAsync()');
assert(isFunc(gesturesAsync), 'automator.gesturesAsync()');
assert(isFunc(scrollDown), 'automator.scrollDown()');
assert(isFunc(scrollUp), 'automator.scrollUp()');
assert(isFunc(input), 'automator.input()');
assert(isFunc(setText), 'automator.setText()');
assert(isFunc(back), 'runtime.automator.back()');
assert(isFunc(home), 'runtime.automator.home()');
assert(isFunc(powerDialog), 'runtime.automator.powerDialog()');
assert(isFunc(notifications), 'runtime.automator.notifications()');
assert(isFunc(quickSettings), 'runtime.automator.quickSettings()');
assert(isFunc(recents), 'runtime.automator.recents()');
assert(isFunc(splitScreen), 'runtime.automator.splitScreen()');
// @Test images
assert(isObjOrFunc(images), 'images');
assert(isFunc(requestScreenCapture), 'global.requestScreenCapture()');
assert(isFunc(captureScreen), 'global.captureScreen()');
assert(isFunc(findImage), 'global.findImage()');
assert(isFunc(findImageInRegion), 'global.findImageInRegion()');
assert(isFunc(findColor), 'global.findColor()');
assert(isFunc(findColorInRegion), 'global.findColorInRegion()');
assert(isFunc(findColorEquals), 'global.findColorEquals()');
assert(isFunc(findMultiColors), 'global.findMultiColors()');
assert(noError(images.requestScreenCapture, images), 'images.requestScreenCapture()');
try {
assert(images.captureScreen() instanceof ImageWrapper);
// captureScreen() for the second time instantly
let capt = images.captureScreen();
assert(typeof capt.getHeight() === 'number');
assert(images.matchTemplate(capt, capt) !== undefined);
assert(images.findAllPointsForColor(capt, '#bfbfbf') !== undefined);
capt.recycle();
} catch (e) {
assert(e.javaException instanceof SecurityException, 'images.captureScreen()');
}
// @Test colors
assert(isObjOrFunc(colors), 'colors');
assert(typeof colors.parseColor('#ffffff') === 'number', 'colors.parseColor()');
assert(typeof colors.toInt(colors.toString(-1)) === 'number', 'colors.toInt() and colors.toString()');
assert(colors.rgba('#005B4F91') === colors.argb('#91005B4F'), 'colors.rgba() and colors.argb()');
assert(colors.rgba(0x00, 0x5B, 0x4F, 0x91) === colors.argb(0x91, 0x00, 0x5B, 0x4F), 'colors.rgba() and colors.argb()');
// @Test dialogs
assert(isObjOrFunc(dialogs), 'dialogs');
assert(isFunc(rawInput), 'global.rawInput()');
assert(isFunc(alert), 'global.alert()');
assert(isFunc(confirm), 'global.confirm()');
assert(isFunc(prompt), 'global.prompt()');
assert(noError(() => dialogs.build({customView: '<vertical><vertical/></vertical>'}).show().dismiss()), 'dialogs.build()');
assert(noError(() => dialogs.build({title: '', content: '', positive: '', positiveColor: -1}).show().dismiss()), 'dialogs.build()');
// @Test storages
assert(isObjOrFunc(storages), 'storages');
assert(noError(() => {
let sto = storages.create('\ufffeee');
sto.put('key', 'value');
assert(sto.get('null', 'def') === 'def');
assert(sto.get('key') === 'value');
storages.remove('\ufffeee');
}));
// @Test threads
assert(isObjOrFunc(threads), 'threads');
assert(isFunc(sync), 'global.sync()');
assert(noError(() => threads.start(() => null)), 'threads.start()');
assert(noError(() => threads.start(() => sleep(9e3)).interrupt()), 'threads.interrupt()');
assert(noError(() => threads.start(() => sleep(9e3)).join(-1)), 'threads.join()');
assert(threads.atomic(0) instanceof AtomicLong, 'threads.atomic()');
assert(noError(threads.shutDownAll, threads), 'threads.shutDownAll()');
// @Test device
assert(isObjOrFunc(device), 'device');
assert(device.height * device.width > 0, 'device.height and device.width');
assert(typeof device.brand === 'string' && device.brand.length > 0, 'device.brand');
assert(noError(() => device.vibrate([0, 1])), 'device.vibrate()');
assert(noError(device.cancelVibration, device), 'device.cancelVibration()');
assert(noError(device.cancelKeepingAwake, device), 'device.cancelKeepingAwake()');
// @Test files
assert(isObjOrFunc(files), 'files');
assert(isFunc(open), 'global.open()');
assert(files.join('', '', '', '') === '/', 'files.join()');
assert(files.join('a', 'b', 'c', 'd') === 'a/b/c/d', 'files.join()');
assert(files.exists('') === true, 'files.exists()');
assert(files.isDir(files.getSdcardPath()), 'files.isDir()');
assert(noError(() => files.listDir(files.cwd(), () => true)), 'files.listDir() and files.cwd()');
// @Test console
assert(isObjOrFunc(console), 'console');
assert(isFunc(print), 'global.print()');
assert(isFunc(log), 'global.log()');
assert(isFunc(err), 'global.err()');
assert(isFunc(openConsole), 'global.openConsole()');
assert(isFunc(clearConsole), 'global.clearConsole()');
assert(isFunc(console.setGlobalLogConfig), 'console.setGlobalLogConfig()');
assert(isFunc(console.verbose), 'console.verbose()');
// @Test app
assert(isObjOrFunc(app), 'app');
assert(isFunc(launchPackage), 'global.launchPackage()');
assert(isFunc(launch), 'global.launch()');
assert(isFunc(launchApp), 'global.launchApp()');
assert(isFunc(getPackageName), 'global.getPackageName()');
assert(isFunc(getAppName), 'global.getAppName()');
assert(isFunc(openAppSetting), 'global.openAppSetting()');
assert(new RegExp('-n \'[.\\w]+\\/Test\'' +
' --ei \'a\' 1' +
' --eia \'b\' 2,2' +
' --es \'c\' \'hello\'' +
' --ez \'d\' false' +
' --esa \'e\' \'r\',\'s\',\'t\'' +
' -c cat003' +
' -a \'android.intent.action.VIEW\'' +
' -f 335544320' +
' -t application\\/pics-rules' +
' -d protocol:\\/\\/xxx',
).test(app.intentToShell({
action: 'VIEW',
className: 'Test',
packageName: context.packageName,
extras: {a: 1, b: [2, 2], c: 'hello', d: false, e: ['r', 's', 't']},
flags: ['ACTIVITY_NEW_TASK', 'ACTIVITY_CLEAR_TOP'],
type: 'application/pics-rules',
data: 'protocol://xxx',
category: 'cat003',
})), 'app.intentToShell()');
assert(!isNullish(app.getAppName(context.packageName)), 'app.getAppName()');
assert(typeof app.autojs.versionName === 'string', 'app.autojs.versionName');
assert(typeof app.autojs.versionCode === 'number', 'app.autojs.versionCode');
assert(typeof app.autojs.versionDate === 'string', 'app.autojs.versionDate');
// @Test selector
assert(isObjOrFunc(selector), 'selector');
assert(selector() instanceof UiSelector, 'selector()');
assert(isFunc(select), 'global.select()');
assert(isFunc(clickable), 'global.clickable()');
assert(isFunc(focus), 'global.focus()');
assert(isFunc(scrollBackward), 'global.scrollBackward()');
assert(isFunc(password), 'global.password()');
assert(isFunc(descMatches), 'global.descMatches()');
assert(isFunc(findOneOf), 'global.findOneOf()');
assert(isFunc(id), 'global.id()');
assert(isFunc(text), 'global.text()');
assert(isFunc(contextClick), 'global.contextClick()');
assert(isFunc(algorithm), 'global.algorithm()');
assert(isFunc(accessibilityFocus), 'global.accessibilityFocus()');
assert(isFunc(dismiss), 'global.dismiss()');
assert(isFunc(focusable), 'global.focusable()');
assert(isFunc(click), 'global.click()');
assert(isFunc(classNameStartsWith), 'global.classNameStartsWith()');
assert(isFunc(scrollTo), 'global.scrollTo()');
assert(isFunc(scrollRight), 'global.scrollRight()');
assert(isFunc(findAndReturnList), 'global.findAndReturnList()');
assert(isFunc(setSelection), 'global.setSelection()');
assert(isFunc(selection), 'global.selection()');
assert(isFunc(bounds), 'global.bounds()');
assert(isFunc(addFilter), 'global.addFilter()');
assert(isFunc(columnSpan), 'global.columnSpan()');
assert(isFunc(cut), 'global.cut()');
assert(isFunc(visibleToUser), 'global.visibleToUser()');
assert(isFunc(setProgress), 'global.setProgress()');
assert(isFunc(textMatches), 'global.textMatches()');
assert(isFunc(className), 'global.className()');
assert(isFunc(boundsInside), 'global.boundsInside()');
assert(isFunc(enabled), 'global.enabled()');
assert(isFunc(scrollUp), 'global.scrollUp()');
assert(isFunc(boundsContains), 'global.boundsContains()');
assert(isFunc(findOnce), 'global.findOnce()');
assert(isFunc(descEndsWith), 'global.descEndsWith()');
assert(isFunc(rowCount), 'global.rowCount()');
assert(isFunc(copy), 'global.copy()');
assert(isFunc(textContains), 'global.textContains()');
assert(isFunc(scrollable), 'global.scrollable()');
assert(isFunc(packageNameStartsWith), 'global.packageNameStartsWith()');
assert(isFunc(clearFocus), 'global.clearFocus()');
assert(isFunc(column), 'global.column()');
assert(isFunc(filter), 'global.filter()');
assert(isFunc(depth), 'global.depth()');
assert(isFunc(longClick), 'global.longClick()');
assert(isFunc(findOf), 'global.findOf()');
assert(isFunc(exists), 'global.exists()');
assert(isFunc(progress), 'global.progress()');
assert(isFunc(toString), 'global.toString()');
assert(isFunc(idStartsWith), 'global.idStartsWith()');
assert(isFunc(getClass), 'global.getClass()');
assert(isFunc(idEndsWith), 'global.idEndsWith()');
assert(isFunc(descStartsWith), 'global.descStartsWith()');
assert(isFunc(accessibilityFocused), 'global.accessibilityFocused()');
assert(isFunc(untilFindOne), 'global.untilFindOne()');
assert(isFunc(classNameEndsWith), 'global.classNameEndsWith()');
assert(isFunc(indexInParent), 'global.indexInParent()');
assert(isFunc(classNameContains), 'global.classNameContains()');
assert(isFunc(find), 'global.find()');
assert(isFunc(checked), 'global.checked()');
assert(isFunc(scrollLeft), 'global.scrollLeft()');
assert(isFunc(waitFor), 'global.waitFor()');
assert(isFunc(selected), 'global.selected()');
assert(isFunc(clearAccessibilityFocus), 'global.clearAccessibilityFocus()');
assert(isFunc(dismissable), 'global.dismissable()');
assert(isFunc(checkable), 'global.checkable()');
assert(isFunc(drawingOrder), 'global.drawingOrder()');
assert(isFunc(untilFind), 'global.untilFind()');
assert(isFunc(packageNameContains), 'global.packageNameContains()');
assert(isFunc(longClickable), 'global.longClickable()');
assert(isFunc(expand), 'global.expand()');
assert(isFunc(packageNameEndsWith), 'global.packageNameEndsWith()');
assert(isFunc(focused), 'global.focused()');
assert(isFunc(idContains), 'global.idContains()');
assert(isFunc(desc), 'global.desc()');
assert(isFunc(scrollForward), 'global.scrollForward()');
assert(isFunc(textEndsWith), 'global.textEndsWith()');
assert(isFunc(contentInvalid), 'global.contentInvalid()');
assert(isFunc(multiLine), 'global.multiLine()');
assert(isFunc(idMatches), 'global.idMatches()');
assert(isFunc(findOne), 'global.findOne()');
assert(isFunc(show), 'global.show()');
assert(isFunc(descContains), 'global.descContains()');
assert(isFunc(paste), 'global.paste()');
assert(isFunc(contextClickable), 'global.contextClickable()');
assert(isFunc(packageName), 'global.packageName()');
assert(isFunc(row), 'global.row()');
assert(isFunc(rowSpan), 'global.rowSpan()');
assert(isFunc(scrollDown), 'global.scrollDown()');
assert(isFunc(editable), 'global.editable()');
assert(isFunc(columnCount), 'global.columnCount()');
assert(isFunc(classNameMatches), 'global.classNameMatches()');
assert(isFunc(textStartsWith), 'global.textStartsWith()');
assert(isFunc(packageNameMatches), 'global.packageNameMatches()');
assert(isFunc(collapse), 'global.collapse()');
assert(isFunc(setText), 'global.setText()');
assert(noError(() => idMatches('rex').findOnce()), 'idMatches(rex: string)');
assert(noError(() => idMatches(/rex/).findOnce()), 'idMatches(rex: RegExp)');
assert(noError(() => idMatches(/\/rex\//).findOnce()), 'idMatches(rex: RegExp (with slashes))');
// @Test sensor
assert(isObjOrFunc(sensors), 'sensors');
assert(isObjOrFunc(sensors.register('gravity')), 'sensors.register()');
// @Test events
assert(isObjOrFunc(events), 'events');
assert(!isNullish(keys.home), 'keys.home');
assert(!isNullish(keys.menu), 'keys.menu');
assert(!isNullish(keys.back), 'keys.back');
assert(!isNullish(keys.volume_up), 'keys.volume_up');
assert(!isNullish(keys.volume_down), 'keys.volume_down');
assert(isFunc(events.observeKey), 'events.observeKey()');
assert(!isNullish(events.broadcast), 'events.broadcast');
// @Test tasks
assert(isObjOrFunc(tasks), 'tasks');
assert(Array.isArray(tasks.queryTimedTasks({path: files.cwd()})), 'tasks.queryTimedTasks()');
assert(tasks.timeFlagToDays(55).join('') === '01245', 'tasks.timeFlagToDays()');
assert(tasks.daysToTimeFlag([0, 1, 2, 4]) === 23, 'tasks.daysToTimeFlag()');
// @Test plugins
assert(isObjOrFunc(plugins), 'plugins');
assert(isFunc(plugins.load), 'plugins.load()');
// @Test web
assert(isObjOrFunc(web), 'web');
assert(isFunc(newInjectableWebClient), 'global.newInjectableWebClient()');
assert(isFunc(newInjectableWebView), 'global.newInjectableWebView()');
// @Test recorder
assert(isObjOrFunc(recorder), 'recorder');
assert(noError(() => recorder.save('test')), 'recorder.save()');
assert(recorder.has('test'), 'recorder.has()');
assert(typeof recorder.load('test') === 'number', 'recorder.load()');
assert(recorder.isLessThan('test', Infinity), 'recorder.isLessThan()');
assert(noError(() => recorder.remove('test')), 'recorder.remove()');
assert(noError(recorder.clear, recorder), 'recorder.clear()');
// @Test engines
assert(isObjOrFunc(engines), 'engines');
assert(engines.myEngine() instanceof JavaScriptEngine, 'engines.myEngine()');
assert(Array.isArray(engines.all()), 'engines.all()');
assert(typeof engines.myEngine().getSource().getName() === 'string', 'engines.myEngine().getSource().getName()');
// @Test base64
assert(isObjOrFunc(base64), 'base64');
assert(base64.decode(base64.encode(context.packageName)) === context.packageName, 'base64\'s consistency');
assert(base64.encode('\x03', 'iso-8859-1') === 'Aw==', 'base64.encode()');
assert(base64.decode('//4DAA==', 'utf-16') === '\x03', 'base64.decode()');
// @Test media
assert(isObjOrFunc(media), 'media');
assert(typeof media.isMusicPlaying() === 'boolean', 'media.isMusicPlaying()');
// @Test floaty
assert(isObjOrFunc(floaty), 'floaty');
assert(noError(() => floaty.rawWindow('<vertical/>')), 'floaty.rawWindow()');
assert(noError(() => floaty.closeAll()), 'floaty.closeAll()');
// @Test http
assert(isObjOrFunc(http), 'http');
assert(isFunc(http.get), 'http.get()');
assert(isFunc(http.post), 'http.post()');
assert(isFunc(http.postJson), 'http.postJson()');
assert(isFunc(http.postMultipart), 'http.postMultipart()');
// @Test RootAutomator
assert(isObjOrFunc(RootAutomator), 'RootAutomator');
assert(noError(() => autojs.isRootAvailable() && new RootAutomator().exit()), 'autojs.isRootAvailable() and new RootAutomator()');
// @Test continuation
assert(isObjOrFunc(continuation), 'continuation');
assert(typeof continuation.enabled === 'boolean', 'continuation.enabled');
// @Test shell
assert(isObjOrFunc(shell), 'shell');
assert(isFunc(Menu), 'global.Menu()');
assert(isFunc(Home), 'global.Home()');
assert(isFunc(Back), 'global.Back()');
assert(isFunc(Up), 'global.Up()');
assert(isFunc(Down), 'global.Down()');
assert(isFunc(Left), 'global.Left()');
assert(isFunc(Right), 'global.Right()');
assert(isFunc(OK), 'global.OK()');
assert(isFunc(VolumeUp), 'global.VolumeUp()');
assert(isFunc(VolumeDown), 'global.VolumeDown()');
assert(isFunc(Power), 'global.Power()');
assert(isFunc(Camera), 'global.Camera()');
assert(isFunc(Text), 'global.Text()');
assert(isFunc(Input), 'global.Input()');
assert(isFunc(Tap), 'global.Tap()');
assert(isFunc(Screencap), 'global.Screencap()');
assert(isFunc(KeyCode), 'global.KeyCode()');
assert(isFunc(SetScreenMetrics), 'global.SetScreenMetrics()');
assert(isFunc(Swipe), 'global.Swipe()');
assert(typeof shell('date', true).code === 'number', 'shell().code');
// @Test ui
assert(isObjOrFunc(ui), 'ui');
assert(ui.isUiThread() === false, 'ui.isUiThread()');
assert(isFunc(ui.run), 'ui.run()');
assert(noError(() => ui.run(() => void 0)), 'ui.run()');
assert(isFunc(ui.post), 'ui.post()');
assert(noError(() => ui.post(() => void 0)), 'ui.post()');
assert(isFunc(ui.layout), 'ui.layout()');
assert(hasError(() => ui.layout('</>')), 'ui.layout() without "ui" statement');
assert(isFunc(ui.Widget), 'ui.Widget');
// noinspection HtmlUnknownAttribute
assert(ui.inflate('<vertical><text text="123"/></vertical>') instanceof JsLinearLayout, 'ui.inflate()');

View File

@@ -0,0 +1,85 @@
/**
* Tests for AutoJs6 (v6.1.0 and above) in "ui" thread.
* A toast message should display when all tests passed (or not) within 3 seconds.
* Created by SuperMonster003 on May 7, 2022.
*/
// noinspection BadExpressionStatementJS
'ui';
const isFunc = o => typeof o === 'function';
const hasError = (f, thisArg) => !!(new Function('{try{arguments[0].call(arguments[1])}catch(e){return 1}}')(f, thisArg));
const noError = (f, thisArg) => !hasError(f, thisArg);
const assert = (value, message) => {
console.assert(value, message);
console.verbose(`${message} passed`);
};
const UiSelector = com.stardust.autojs.core.accessibility.UiSelector;
const JavaScriptEngine = com.stardust.autojs.engine.JavaScriptEngine;
const JsLinearLayout = com.stardust.autojs.core.ui.widget.JsLinearLayout;
// @Test auto
assert(noError(auto.waitFor, auto), 'auto.waitFor()');
assert(typeof auto.service /* nullable */ === 'object', 'auto.service');
// @Test Promise and timers
let timeoutId = setTimeout(() => toastLog('Timed out', 'long'), 3e3);
Promise.resolve().then(() => {
toastLog('All passed');
clearTimeout(timeoutId);
ui.finish();
});
// @Test images
// FIXME by SuperMonster003 on May 7, 2022.
// ! Auto.js freezes or won't respond when calling images.requestScreenCapture()
// assert(noError(images.requestScreenCapture, images), 'images.requestScreenCapture()');
// assert(noError(() => images.captureScreen()), 'images.captureScreen()');
// @Test dialogs
assert(noError(() => dialogs.build({customView: '<vertical><vertical/></vertical>'}).show().dismiss()), 'dialogs.build()');
// @Test threads
assert(noError(() => threads.start(() => sleep(9e3)).join(-1)), 'threads.join()');
// @Test device
assert(device.height * device.width > 0, 'device.height or device.width');
// @Test selector
assert(selector() instanceof UiSelector, 'selector()');
assert(noError(() => idMatches('rex').findOnce()), 'idMatches()');
// @Test engines
assert(engines.myEngine() instanceof JavaScriptEngine, 'engines.myEngine()');
assert(Array.isArray(engines.all()), 'engines.all()');
assert(typeof engines.myEngine().getSource().getName() === 'string', 'engines.myEngine().getSource().getName()');
// @Test floaty
// FIXME by SuperMonster003 on May 7, 2022.
// ! Auto.js freezes or won't respond when calling floaty.rawWindow()
// assert(noError(() => floaty.rawWindow('<vertical/>')), 'floaty.rawWindow()');
assert(noError(() => floaty.closeAll()), 'floaty.closeAll()');
// @Test continuation
assert(typeof continuation.enabled === 'boolean', 'continuation.enabled');
// @Test ui
assert(ui.isUiThread(), 'ui.isUiThread()');
assert(noError(() => ui.run(() => void 0)), 'ui.run()');
assert(noError(() => ui.post(() => void 0)), 'ui.post()');
assert(hasError(() => ui.layout('</>')), 'ui.layout() without "ui" statement');
// noinspection HtmlUnknownAttribute
assert(ui.inflate('<vertical><text text="123"/></vertical>') instanceof JsLinearLayout, 'ui.inflate()');
assert(isFunc(ui.finish), 'ui.finish()');

View File

@@ -34,7 +34,7 @@ paint.setStrokeWidth(2);
ui.board.on("draw", function(canvas){
w = canvas.getWidth();
h = canvas.getHeight();
if(minY == undefined){
if(minY === undefined){
minY = -(maxX - minX) * h / w / 2;
}
//计算y轴区间上限

View File

@@ -132,7 +132,7 @@ function move(dx, dy){
}
function snakeEatsApple(){
return snake[0].x == apple.x && snake[0].y == apple.y;
return snake[0].x === apple.x && snake[0].y === apple.y;
}
function generateApple(){
@@ -147,7 +147,7 @@ function generateApple(){
function isAppleValid(x, y){
for (var i = 0; i < snake.length; i++) {
if (snake[i].x == x && snake[i].y == y) {
if (snake[i].x === x && snake[i].y === y) {
return false;
}
}
@@ -164,7 +164,7 @@ function collisionTest(){
}
//检测蛇有没有撞到自己
for(var i = 1; i < snake.length; i++){
if(snake[i].x == head && snake[i].y == head){
if(snake[i].x === head && snake[i].y === head){
gameOver();
return;
}

View File

@@ -89,7 +89,7 @@ function move(dx, dy){
}
function snakeEatsApple(){
return snake[0].x == apple.x && snake[0].y == apple.y;
return snake[0].x === apple.x && snake[0].y === apple.y;
}
function generateApple(){
@@ -104,7 +104,7 @@ function generateApple(){
function isAppleValid(x, y){
for (var i = 0; i < snake.length; i++) {
if (snake[i].x == x && snake[i].y == y) {
if (snake[i].x === x && snake[i].y === y) {
return false;
}
}
@@ -227,5 +227,5 @@ function drawSnakeBody(canvas, paint){
}
function equals(point1, point2){
return point1.x == point2.x && point1.y == point2.y;
return point1.x === point2.x && point1.y === point2.y;
}

View File

@@ -27,7 +27,7 @@ var PrefCheckBox = (function() {
}
let id = this.view.attr("id");
if(!id){
throw new Error("should set a id or key to the checkbox");
throw Error("should set a id or key to the checkbox");
}
return id.replace("@+id/", "");
}

View File

@@ -26,7 +26,7 @@ ui.icons.on("item_click", function(icon){
ui.search.on("click", function(){
var text = ui.input.text();
if(text.length == 0){
if(text.length === 0){
return;
}
search(text);

View File

@@ -29,7 +29,7 @@ ui.layout(
ui.ok.click(()=>{
var text = ui.qq.text();
if(text.length == 0){
if(text.length === 0){
ui.qq.setError("输入不能为空");
return;
}

View File

@@ -25,7 +25,7 @@ ui.layout(
var downloadId = null;
ui.download.click(()=>{
if(downloadId != null){
if(downloadId){
stopDownload();
}else{
startDownload();
@@ -39,7 +39,7 @@ function stopDownload(){
}
function startDownload(){
if(ui.progress.getProgress() == 100){
if(ui.progress.getProgress() === 100){
ui.progress.setProgress(0);
}
ui.download.text("停止下载");

View File

@@ -5,6 +5,8 @@ toast(`${timeout} seconds counting down...`, 'l');
recorder.save(KEY);
while (recorder.isLessThan(KEY, timeout * 1e3)) ; // @EmptyLoopBody
// @EmptyLoopBody
// noinspection StatementWithEmptyBodyJS
while (recorder.isLessThan(KEY, timeout * 1e3)) ;
toast(`Finished.\nSpent ${recorder.load(KEY) / 1e3} s.`, 'l', 'f');

View File

@@ -1,4 +1,5 @@
// Sample A - Simple time-consumed function
// zh-CN: 示例 A - 简单的耗时函数
const f = function test() {
sleep(500, '±200');
@@ -7,6 +8,7 @@ const f = function test() {
console.log(`Function "${f.name}" spent ${recorder(f)} ms`);
// Sample B - Fibonacci without memoization
// zh-CN: 示例 B - 无记忆化的斐波那契数列
const fibonacci = (x) => x <= 2 ? 1 : fibonacci(x - 2) + fibonacci(x - 1);

View File

@@ -0,0 +1,18 @@
let delay = 240;
// 'SOS' in Morse (async)
// zh-CN: 'SOS' 的摩斯电码 (异步)
// The morse code is '··· --- ···'
// zh-CN: 摩斯密码为 '··· --- ···'
device.vibrate('SOS', delay);
toast(`This is a toast for test (should've appeared before vibration finished)`, 'l', 'f');
// If you need information about morse code, try code below.
// zh-CN: 如需获取摩斯电码的相关信息, 可尝试以下代码.
let morse = util.morseCode('SOS');
console.log(morse.toString());
// console.log('code: ' + morse.code);
// console.log('pattern: ' + morse.pattern);
// morse.vibrate(delay);

View File

@@ -0,0 +1,9 @@
let delay = 240;
// 'SOS' in Morse (async)
// zh-CN: 'SOS' 的摩斯电码 (异步)
// The morse code is '··· --- ···'
// zh-CN: 摩斯密码为 '··· --- ···'
device.vibrate([delay, 100, 100, 100, 100, 100, 300, 300, 100, 300, 100, 300, 300, 100, 100, 100, 100, 100]);
toast(`This is a toast for test (should've appeared before vibration finished)`, 'l', 'f');

View File

@@ -0,0 +1,17 @@
console.log(`屏幕宽度: ${device.width}
屏幕高度: ${device.height}
buildId: ${device.buildId}
主板: ${device.board}
制造商: ${device.brand}
型号: ${device.model}
产品名称: ${device.product}
bootloader版本: ${device.bootloader}
硬件名称: ${device.hardware}
唯一标识码: ${device.fingerprint}
IMEI: ${device.getIMEI('suppress_warnings')}
AndroidId: ${device.getAndroidId()}
MAC: ${device.getMacAddress()}
API: ${device.sdkInt}
电量: ${device.getBattery()}`);
console.launch();

View File

@@ -9,7 +9,7 @@ ui.layout(
);
//getBrightnessMode()返回亮度模式1为自动亮度
ui.auto.setChecked(device.getBrightnessMode() == 1);
ui.auto.setChecked(device.getBrightnessMode() === 1);
ui.auto.setOnCheckedChangeListener(function(v, checked){
device.setBrightnessMode(checked ? 1: 0);
});

View File

@@ -1,21 +0,0 @@
console.show();
var str = "";
str += "屏幕宽度:" + device.width;
str += "\n屏幕高度:" + device.height;
str += "\nbuildId:" + device.buildId;
str += "\n主板:" + device.board;
str += "\n制造商:" + device.brand;
str += "\n型号:" + device.model;
str += "\n产品名称:" + device.product;
str += "\nbootloader版本:" + device.bootloader;
str += "\n硬件名称:" + device.hardware;
str += "\n唯一标识码:" + device.fingerprint;
str += "\nIMEI: " + device.getIMEI();
str += "\nAndroidId: " + device.getAndroidId();
str += "\nMac: " + device.getMacAddress();
str += "\nAPI: " + device.sdkInt;
str += "\n电量: " + device.getBattery();
log(str);

View File

@@ -7,7 +7,6 @@
/**
* liveConnect.js: a simple demonstration of JavaScript-to-Java connectivity
*/
// Create a new StringBuffer. Note that the class name must be fully qualified
// by its package. Packages other than "java" must start with "Packages", i.e.,
// "Packages.javax.servlet...".

View File

@@ -2,13 +2,12 @@ package androidx.recyclerview.widget;
import android.content.Context;
import android.os.Build;
import androidx.annotation.Nullable;
import androidx.core.widget.EdgeEffectCompat;
import android.util.AttributeSet;
import android.widget.EdgeEffect;
import androidx.annotation.Nullable;
import androidx.core.widget.EdgeEffectCompat;
import com.stardust.theme.ThemeColor;
import com.stardust.theme.ThemeColorManager;
import com.stardust.theme.ThemeColorMutable;
@@ -72,19 +71,18 @@ public class ThemeColorRecyclerView extends RecyclerView implements ThemeColorMu
ThemeColorManager.add(this);
}
// TODO support api 21 below
private boolean setEdgeEffectColor(EdgeEffectCompat compat, int color) {
if (compat == null)
return false;
try {
if (Build.VERSION.SDK_INT >= 21) { // Android L
EdgeEffect edgeEffect = (EdgeEffect) mEdgeEffectField.get(compat);
EdgeEffect edgeEffect = (EdgeEffect) mEdgeEffectField.get(compat);
if (edgeEffect != null) {
edgeEffect.setColor(color);
}
return true;
} catch (Exception e) {
return true;
} catch (Exception ignored) {
}
return true;
}
@Override

View File

@@ -11,7 +11,7 @@ import android.widget.ImageView;
import android.widget.TextView;
import com.afollestad.materialdialogs.MaterialDialog;
import org.autojs.autojs.R;
import org.autojs.autojs6.R;
import java.util.ArrayList;
@@ -21,13 +21,12 @@ import butterknife.ButterKnife;
/**
* Created by Stardust on 2017/6/26.
*/
public class OperationDialogBuilder extends MaterialDialog.Builder {
private RecyclerView mOperations;
private ArrayList<Integer> mIds = new ArrayList<>();
private ArrayList<Integer> mIcons = new ArrayList<>();
private ArrayList<String> mTexts = new ArrayList<>();
private final RecyclerView mOperations;
private final ArrayList<Integer> mIds = new ArrayList<>();
private final ArrayList<Integer> mIcons = new ArrayList<>();
private final ArrayList<String> mTexts = new ArrayList<>();
private Object mOnItemClickTarget;
public OperationDialogBuilder(@NonNull Context context) {
@@ -35,13 +34,14 @@ public class OperationDialogBuilder extends MaterialDialog.Builder {
mOperations = new RecyclerView(context);
mOperations.setLayoutManager(new LinearLayoutManager(context));
mOperations.setAdapter(new RecyclerView.Adapter<ViewHolder>() {
@NonNull
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.operation_dialog_item, parent, false));
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
holder.itemView.setId(mIds.get(position));
holder.text.setText(mTexts.get(position));
holder.icon.setImageResource(mIcons.get(position));

View File

@@ -9,7 +9,6 @@ import androidx.core.content.ContextCompat;
/**
* Created by Stardust on 2017/3/5.
*/
public class ThemeColor {
private static final String KEY_COLOR_PRIMARY = "com.stardust.theme.ThemeColor.KEY_COLOR_PRIMARY";
@@ -21,8 +20,8 @@ public class ThemeColor {
public int colorPrimary, colorAccent, colorPrimaryDark;
public ThemeColor() {
}
}
public ThemeColor(int color) {
this(color, color, color);
@@ -67,8 +66,7 @@ public class ThemeColor {
if (this == obj) {
return true;
}
if (obj instanceof ThemeColor) {
ThemeColor color = (ThemeColor) obj;
if (obj instanceof ThemeColor color) {
return colorPrimary == color.colorPrimary && colorPrimaryDark == color.colorPrimaryDark
&& colorAccent == color.colorAccent;
}

View File

@@ -1,6 +1,5 @@
package com.stardust.theme;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.res.ColorStateList;
import android.graphics.Color;
@@ -8,9 +7,6 @@ import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.ShapeDrawable;
import android.os.Build;
import androidx.core.graphics.drawable.DrawableCompat;
import androidx.appcompat.widget.SwitchCompat;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
@@ -19,13 +15,15 @@ import android.view.WindowManager;
import android.widget.AbsListView;
import android.widget.Switch;
import androidx.appcompat.widget.SwitchCompat;
import androidx.core.graphics.drawable.DrawableCompat;
import com.stardust.theme.internal.ScrollingViewEdgeGlowColorHelper;
/**
* Created by Stardust on 2016/10/24.
*/
public class ThemeColorHelper {
private static final String TAG = "ThemeColorHelper";
@@ -58,10 +56,8 @@ public class ThemeColorHelper {
}
public static void setColorPrimary(Switch sw, int color) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
setThumbDrawableTintList(sw.getThumbDrawable(), color);
setTrackDrawableTintList(sw.getTrackDrawable(), color);
}
setThumbDrawableTintList(sw.getThumbDrawable(), color);
setTrackDrawableTintList(sw.getTrackDrawable(), color);
}
private static void setThumbDrawableTintList(Drawable drawable, int color) {
@@ -85,8 +81,6 @@ public class ThemeColorHelper {
return (color & 0xffffff) | (alpha << 24);
}
@TargetApi(21)
public static void setStatusBarColor(Activity activity, int color) {
Window window = activity.getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);

View File

@@ -1,13 +1,12 @@
package com.stardust.theme;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.graphics.Paint;
import android.os.Build;
import android.preference.PreferenceManager;
import android.view.View;
import androidx.preference.PreferenceManager;
import java.lang.ref.WeakReference;
import java.util.Iterator;
import java.util.LinkedList;
@@ -17,7 +16,6 @@ import java.util.Vector;
/**
* Created by Stardust on 2016/5/10.
*/
public class ThemeColorManager {
private static ThemeColor defaultThemeColor;
@@ -54,22 +52,19 @@ public class ThemeColorManager {
}
public static void addActivityNavigationBar(final Activity activity) {
if (Build.VERSION.SDK_INT > 19) {
ThemeColorWidgetReferenceManager.add(new ThemeColorMutableReference() {
WeakReference<Activity> weakReference = new WeakReference<>(activity);
ThemeColorWidgetReferenceManager.add(new ThemeColorMutableReference() {
final WeakReference<Activity> weakReference = new WeakReference<>(activity);
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public void setThemeColor(ThemeColor color) {
activity.getWindow().setNavigationBarColor(color.colorPrimary);
}
@Override
public void setThemeColor(ThemeColor color) {
activity.getWindow().setNavigationBarColor(color.colorPrimary);
}
@Override
public boolean isNull() {
return weakReference.get() == null;
}
});
}
@Override
public boolean isNull() {
return weakReference.get() == null;
}
});
}
public static int getColorPrimary() {
@@ -132,7 +127,7 @@ public class ThemeColorManager {
}
private static class BackgroundColorManager {
private static List<WeakReference<View>> views = new LinkedList<>();
private static final List<WeakReference<View>> views = new LinkedList<>();
public static void add(View view) {
views.add(new WeakReference<>(view));
@@ -155,16 +150,14 @@ public class ThemeColorManager {
}
private static class StatusBarManager {
private static Vector<WeakReference<Activity>> activities = new Vector<>();
private static final Vector<WeakReference<Activity>> activities = new Vector<>();
@TargetApi(21)
public static void add(Activity activity) {
activities.add(new WeakReference<>(activity));
if (shouldApplyThemeColor())
activity.getWindow().setStatusBarColor(themeColor.colorPrimary);
}
@TargetApi(21)
public static void setColor(int color) {
Iterator<WeakReference<Activity>> iterator = activities.iterator();
while (iterator.hasNext()) {
@@ -179,7 +172,7 @@ public class ThemeColorManager {
}
private static class PaintManager {
private static List<WeakReference<Paint>> paints = new LinkedList<>();
private static final List<WeakReference<Paint>> paints = new LinkedList<>();
public static void add(Paint paint) {
if (shouldApplyThemeColor())
@@ -202,7 +195,7 @@ public class ThemeColorManager {
private static class ThemeColorWidgetReferenceManager {
private static List<ThemeColorMutableReference> widgets = new LinkedList<>();
private static final List<ThemeColorMutableReference> widgets = new LinkedList<>();
public static void add(ThemeColorMutableReference widget) {
if (shouldApplyThemeColor())
@@ -226,7 +219,7 @@ public class ThemeColorManager {
private static class ThemeColorMutableManager {
private static List<WeakReference<ThemeColorMutable>> widgets = new LinkedList<>();
private static final List<WeakReference<ThemeColorMutable>> widgets = new LinkedList<>();
public static void add(ThemeColorMutable widget) {
if (shouldApplyThemeColor())

View File

@@ -3,7 +3,6 @@ package com.stardust.theme;
/**
* Created by Stardust on 2016/10/24.
*/
public interface ThemeColorMutable {
void setThemeColor(ThemeColor color);

View File

@@ -3,7 +3,6 @@ package com.stardust.theme;
/**
* Created by Stardust on 2016/10/24.
*/
public interface ThemeColorMutableReference {
void setThemeColor(ThemeColor color);

Some files were not shown because too many files have changed in this diff Show More