6.7.0 - Alpha8 - 新增 device.getSharedDeviceId 方法, 用于跨应用获取统一共享设备 ID (issue #455)

This commit is contained in:
SuperMonster003
2025-10-26 14:29:46 +08:00
parent 638ac7e2db
commit 1b5558a075
5 changed files with 97 additions and 7 deletions

View File

@@ -1,12 +1,12 @@
{
"$data": {
"v6.7.0": {
"released_date": "2025/10/19",
"released_date": "2025/10/26",
"feature": [
"zip 模块, 用于文件压缩与解压缩操作 (Ref to [Auto.js Pro](https://g.pro.autojs.org/)) (参阅 项目文档 > [Zip](https://docs.autojs6.com/#/zip))",
"mediainfo 模块, 用于查看媒体文件的详细信息 (参阅 项目文档 > [媒体信息](https://docs.autojs6.com/#/mediainfo))",
"UiObject#isShifted 方法, 用于检测控件位置变化",
"s13n.bytes 方法, 用于标准化点对象及时长对象 (参阅 项目文档 > [标准化](https://docs.autojs6.com/#/s13n))",
"device.getSharedDeviceId 方法, 用于跨应用获取统一共享设备 ID _[`issue #455`](http://issues.autojs6.com/455)_",
"structuredClone 全局方法, 用于深拷贝 JavaScript 对象 (参阅 [MDN](https://developer.mozilla.org/zh-CN/docs/Web/API/Window/structuredClone))",
"设置页面支持应用启动器图标设置选项 _[`issue #405`](http://issues.autojs6.com/405)_",
"Scrapers 工具 (run-scrapers.mjs) 用于自动更新 Gradle 构建脚本结构化数据/README 通用数据/README 模板数据等"

View File

@@ -481,6 +481,7 @@
<action android:name="android.intent.action.PACKAGE_DATA_CLEARED" />
<action android:name="android.intent.action.PACKAGE_REMOVED" />
<action android:name="android.intent.action.PACKAGE_RESTARTED" />
<data android:scheme="package" />
</intent-filter>
@@ -507,8 +508,10 @@
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<action android:name="android.intent.action.EDIT" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="file" />
<data android:scheme="content" />
<data android:mimeType="application/x-javascript" />
@@ -525,8 +528,10 @@
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<action android:name="android.intent.action.EDIT" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="file" />
<data android:scheme="content" />
<data android:mimeType="application/x-javascript" />
@@ -542,8 +547,10 @@
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<action android:name="android.intent.action.EDIT" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="file" />
<data android:scheme="content" />
<data android:mimeType="application/x-javascript" />
@@ -695,6 +702,11 @@
android:authorities="${applicationId}.mlkitinitprovider"
tools:node="remove" />
<provider
android:name="org.autojs.autojs.deviceid.DeviceIdProvider"
android:authorities="${applicationId}.deviceid.provider"
android:exported="true" />
</application>
</manifest>

View File

@@ -0,0 +1,65 @@
package org.autojs.autojs.deviceid
import android.content.ContentProvider
import android.content.ContentValues
import android.content.UriMatcher
import android.database.Cursor
import android.database.MatrixCursor
import android.net.Uri
import android.os.Bundle
import androidx.core.content.edit
import java.util.*
class DeviceIdProvider : ContentProvider() {
companion object {
private const val AUTH = "org.autojs.autojs6.deviceid.provider"
private const val PATH = "v1/device_id"
private const val CODE = 1
private const val COL = "device_id"
private const val SP_NAME = "device_id_prefs"
private const val SP_KEY = "device_id"
private val matcher = UriMatcher(UriMatcher.NO_MATCH).apply {
addURI(AUTH, PATH, CODE)
}
}
override fun onCreate(): Boolean {
ensureId()
return true
}
private fun ensureId(): String {
val sp = context!!.getSharedPreferences(SP_NAME, 0)
val exist = sp.getString(SP_KEY, null)
if (exist != null) return exist
val id = UUID.randomUUID().toString()
sp.edit { putString(SP_KEY, id) }
return id
}
override fun query(
uri: Uri, projection: Array<out String>?, selection: String?,
selectionArgs: Array<out String>?, sortOrder: String?,
): Cursor? {
if (matcher.match(uri) != CODE) return null
val id = ensureId()
val cursor = MatrixCursor(arrayOf(COL), 1)
cursor.addRow(arrayOf(id))
return cursor
}
override fun call(method: String, arg: String?, extras: Bundle?): Bundle? {
if (method == "getDeviceId") {
val id = ensureId()
return Bundle().apply { putString(COL, id) }
}
return super.call(method, arg, extras)
}
override fun getType(uri: Uri) = "vnd.android.cursor.item/$AUTH.$PATH"
override fun insert(uri: Uri, values: ContentValues?) = null
override fun delete(uri: Uri, selection: String?, selectionArgs: Array<out String>?) = 0
override fun update(uri: Uri, values: ContentValues?, selection: String?, selectionArgs: Array<out String>?) = 0
}

View File

@@ -9,8 +9,8 @@ import org.autojs.autojs.runtime.ScriptRuntime
import org.autojs.autojs.runtime.api.ScreenMetrics
import org.autojs.autojs.runtime.api.augment.Augmentable
import org.autojs.autojs.runtime.api.augment.util.MorseCode
import org.autojs.autojs.runtime.exception.WrappedIllegalArgumentException
import org.autojs.autojs.runtime.exception.ShouldNeverHappenException
import org.autojs.autojs.runtime.exception.WrappedIllegalArgumentException
import org.autojs.autojs.util.DeviceUtils
import org.autojs.autojs.util.NetworkUtils
import org.autojs.autojs.util.RhinoUtils.UNDEFINED
@@ -19,6 +19,7 @@ import org.mozilla.javascript.NativeArray
import org.mozilla.javascript.Undefined
import java.util.function.Supplier
import org.autojs.autojs.runtime.api.Device as ApiDevice
import androidx.core.net.toUri
@Suppress("unused", "UNUSED_PARAMETER")
class Device(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) {
@@ -36,6 +37,7 @@ class Device(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) {
::isActiveNetworkMetered.name,
::isConnectedOrConnecting.name,
::isWifiAvailable.name,
::getSharedDeviceId.name,
)
override val selfAssignmentGetters = listOf<Pair<String, Supplier<Any?>>>(
@@ -193,6 +195,17 @@ class Device(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) {
NetworkUtils.isWifiAvailable()
}
@JvmStatic
@RhinoRuntimeFunctionInterface
fun getSharedDeviceId(scriptRuntime: ScriptRuntime, args: Array<out Any?>): String? = ensureArgumentsIsEmpty(args) {
// val b = globalContext.contentResolver.call("content://org.autojs.autojs6.deviceid.provider".toUri(), "getDeviceId", null, null)
// b?.getString("device_id")
val uri = "content://org.autojs.autojs6.deviceid.provider/v1/device_id".toUri()
globalContext.contentResolver.query(uri, arrayOf("device_id"), null, null, null)?.use { c ->
if (c.moveToFirst()) c.getString(0) else null
}
}
private fun toVibrateTimingElement(it: Any?): Long {
return Context.toNumber(it).takeUnless { it.isNaN() }?.toLong()
?: throw WrappedIllegalArgumentException("Argument $it cannot be converted as a timing element for device.${::vibrate.name}")

View File

@@ -1,5 +1,5 @@
#Thu Oct 23 22:53:43 CST 2025
BUILD_TIME=1761231223404
#Sun Oct 26 14:23:07 CST 2025
BUILD_TIME=1761459787547
COMPILE_SDK_VERSION=36
IMAGE_QUANT_CMAKE_VERSION=3.22.1
IMAGE_QUANT_NDK_VERSION=26.1.10909125
@@ -27,6 +27,6 @@ RAPID_OCR_OPENCV_MOBILE_LABEL_VERSION=13
RAPID_OCR_OPENCV_MOBILE_VERSION=4.5.3
TARGET_SDK_VERSION=36
TARGET_SDK_VERSION_INRT=29
VERSION_BUILD=3434
VERSION_NAME=6.7.0 Alpha7
VERSION_BUILD=3440
VERSION_NAME=6.7.0 Alpha8
VSCODE_EXT_REQUIRED_VERSION=1.0.8