6.6.2 - Alpha7 - 优化 files.path 及相关方法传入空值路径参数时的兼容性

This commit is contained in:
SuperMonster003
2025-04-16 14:43:54 +08:00
parent 325271b060
commit 43d9fa9366
19 changed files with 215 additions and 185 deletions

View File

@@ -16,7 +16,7 @@
"notice 模块缺失 getBuilder 等扩展方法的问题 _[`issue #301`](http://issues.autojs6.com/301)_",
"shizuku/shell 等方法无法接受字符串参数的问题 _[`issue #310`](http://issues.autojs6.com/310)_",
"colors.pixel 方法无法接受单通道图像参数的问题 _[`issue #350`](http://issues.autojs6.com/350)_",
"engines.execScript/execScriptFile 等方法执行脚本时默认工作路径异常 _[`issue #340`](http://issues.autojs6.com/340)_ _[`issue #339`](http://issues.autojs6.com/339)_",
"engines.execScript/execScriptFile 等方法执行脚本时默认工作路径异常 _[`issue #358`](http://issues.autojs6.com/358)_ _[`issue #340`](http://issues.autojs6.com/340)_ _[`issue #339`](http://issues.autojs6.com/339)_",
"floaty.window/floaty.rawWindow 无法在子线程执行的问题",
"floaty.getClip 可能无法正常获取剪切板内容的问题 _[`issue #341`](http://issues.autojs6.com/341)_",
"ui.inflate 返回值丢失 attr/on/click 等原型方法的问题",
@@ -49,6 +49,7 @@
"尝试恢复 com.stardust 前缀包以便提升代码兼容性 _[`issue #290`](http://issues.autojs6.com/290)_",
"floaty.window/floaty.rawWindow 同时支持主线程和子线程执行",
"getClip 全局方法适时借助 floaty.getClip 方法以提升兼容性",
"files.path 及相关方法传入空值路径参数时的兼容性",
"同步最新的 Rhino 引擎官方上游代码并进行必要的代码适配",
"README.md 完善项目构建与运行相关内容 _[`issue #344`](http://issues.autojs6.com/344)_"
],

View File

@@ -26,7 +26,7 @@ public class Database extends SQLiteOpenHelper implements Closeable {
private final TypeAdapter mTypeAdapter;
public Database(@NonNull Context context, @NonNull ScriptRuntime scriptRuntime, @NonNull String name, int version, boolean readable, @Nullable DatabaseCallback databaseCallback, @NonNull TypeAdapter typeAdapter) {
super(context, scriptRuntime.files.path(name), null, version, databaseCallback == null ? null : new DatabaseErrorHandlerWrapper(databaseCallback));
super(context, scriptRuntime.files.nonNullPath(name), null, version, databaseCallback == null ? null : new DatabaseErrorHandlerWrapper(databaseCallback));
mTypeAdapter = typeAdapter;
mCallback = databaseCallback;
mScriptRuntime = scriptRuntime;

View File

@@ -50,11 +50,11 @@ open class ImageViewAttributes(scriptRuntime: ScriptRuntime, resourceParser: Res
}
private fun ScriptRuntime.getPath(s: String, def: String = s): String {
return if (this.files.exists(s)) this.files.path(s) else def
return if (this.files.exists(s)) this.files.nonNullPath(s) else def
}
private fun ScriptRuntime.getPath(s: String, def: (String) -> String): String {
return if (this.files.exists(s)) this.files.path(s) else def(s)
return if (this.files.exists(s)) this.files.nonNullPath(s) else def(s)
}
companion object {

View File

@@ -23,6 +23,7 @@ import java.io.File
import java.net.URL
import java.util.concurrent.Executors
import java.util.regex.Pattern
import androidx.core.graphics.drawable.toDrawable
/**
* Created by Stardust on Nov 3, 2017.
@@ -83,7 +84,7 @@ open class Drawables {
}
open fun decodeImage(context: Context, path: String?): Drawable? {
return BitmapDrawable(context.resources, BitmapFactory.decodeFile(path))
return BitmapFactory.decodeFile(path)?.toDrawable(context.resources)
}
fun parse(view: View, name: String) = parse(view.context, name)

View File

@@ -133,7 +133,7 @@ object AnyExtensions {
fun Any?.toRuntimePath(scriptRuntime: ScriptRuntime, isStrict: Boolean = false): String {
if (isStrict && this.isJsNullish()) throw IllegalArgumentException(str(R.string.error_cannot_convert_value_into_a_script_runtime_path, this.jsBrief()))
return scriptRuntime.files.path(coerceString(this, "."))
return scriptRuntime.files.nonNullPath(coerceString(this, "."))
}
}

View File

@@ -109,7 +109,7 @@ object PFiles {
@JvmOverloads
@JvmStatic
fun read(file: File?, encoding: String? = "utf-8"): String {
fun read(file: File?, encoding: String? = DEFAULT_ENCODING): String {
return try {
read(FileInputStream(file), encoding)
} catch (e: FileNotFoundException) {
@@ -118,21 +118,19 @@ object PFiles {
}
@JvmStatic
fun read(stream: InputStream, encoding: String?): String {
@JvmOverloads
fun read(inputStream: InputStream, encoding: String? = DEFAULT_ENCODING): String {
return try {
val bytes = ByteArray(stream.available())
stream.read(bytes)
val bytes = ByteArray(inputStream.available())
inputStream.read(bytes)
String(bytes, Charset.forName(encoding))
} catch (e: IOException) {
throw UncheckedIOException(e)
} finally {
closeSilently(stream)
closeSilently(inputStream)
}
}
@JvmStatic
fun read(inputStream: InputStream) = read(inputStream, "utf-8")
fun readBytes(stream: InputStream): ByteArray {
return try {
ByteArray(stream.available()).also { stream.read(it) }
@@ -203,7 +201,7 @@ object PFiles {
}
@JvmStatic
fun write(fileOutputStream: OutputStream, text: String) = write(fileOutputStream, text, "utf-8")
fun write(fileOutputStream: OutputStream, text: String) = write(fileOutputStream, text, DEFAULT_ENCODING)
fun write(outputStream: OutputStream, text: String, encoding: String?) {
try {

View File

@@ -616,7 +616,7 @@ class ScriptRuntime private constructor(builder: Builder) {
private fun doLoad(filter: FileFilter, vararg paths: String) {
for (path in paths) {
val file = File(files.path(path))
val file = File(files.nonNullPath(path))
if (file.isDirectory) {
val filtered = file.listFiles(filter)
if (filtered != null) {
@@ -636,7 +636,7 @@ class ScriptRuntime private constructor(builder: Builder) {
try {
val classLoader = sClassLoader
for (path in paths) {
val file = File(files.path(path))
val file = File(files.nonNullPath(path))
if (file.isDirectory) {
val filtered = file.listFiles(filter)
if (filtered != null) {
@@ -657,7 +657,7 @@ class ScriptRuntime private constructor(builder: Builder) {
try {
val classLoader = sClassLoader
for (path in paths) {
val file = File(files.path(path))
val file = File(files.nonNullPath(path))
if (file.isDirectory) {
val filtered = file.listFiles(filter)
if (filtered != null) {

View File

@@ -35,12 +35,12 @@ class Engines(private val mScriptRuntime: ScriptRuntime) {
return execScriptInternal(name, script, config)
}
fun execScriptFile(path: String?, config: ExecutionConfig?): ScriptExecution {
return AutoJs.instance.scriptEngineService.execute(JavaScriptFileSource(mScriptRuntime.files.path(path)), config)
fun execScriptFile(path: String, config: ExecutionConfig?): ScriptExecution {
return AutoJs.instance.scriptEngineService.execute(JavaScriptFileSource(mScriptRuntime.files.nonNullPath(path)), config)
}
fun execAutoFile(path: String?, config: ExecutionConfig?): ScriptExecution {
return AutoJs.instance.scriptEngineService.execute(AutoFileSource(mScriptRuntime.files.path(path)), config)
fun execAutoFile(path: String, config: ExecutionConfig?): ScriptExecution {
return AutoJs.instance.scriptEngineService.execute(AutoFileSource(mScriptRuntime.files.nonNullPath(path)), config)
}
fun all(): NativeArray = engines.toNativeArray()

View File

@@ -1,211 +1,229 @@
package org.autojs.autojs.runtime.api;
package org.autojs.autojs.runtime.api
import org.autojs.autojs.pio.PFileInterface;
import org.autojs.autojs.pio.PFiles;
import org.autojs.autojs.pio.UncheckedIOException;
import org.autojs.autojs.runtime.ScriptRuntime;
import org.autojs.autojs.tool.Func1;
import org.autojs.autojs.util.EnvironmentUtils;
import java.io.File;
import java.io.IOException;
import java.util.regex.Pattern;
import android.content.Context
import org.autojs.autojs.pio.PFileInterface
import org.autojs.autojs.pio.PFiles
import org.autojs.autojs.pio.PFiles.getElegantPath
import org.autojs.autojs.pio.PFiles.read
import org.autojs.autojs.pio.UncheckedIOException
import org.autojs.autojs.runtime.ScriptRuntime
import org.autojs.autojs.runtime.exception.WrappedIllegalArgumentException
import org.autojs.autojs.tool.Func1
import org.autojs.autojs.util.EnvironmentUtils.externalStoragePath
import org.autojs.autojs6.R
import java.io.File
import java.io.File.separator
import java.io.IOException
import java.lang.IllegalArgumentException
/**
* Created by Stardust on Jan 23, 2018.
* Modified by SuperMonster003 as of May 26, 2022.
* Transformed by SuperMonster003 on Apr 15, 2025.
*/
public class Files {
class Files(private val scriptRuntime: ScriptRuntime) {
private final ScriptRuntime mRuntime;
val context: Context
get() = scriptRuntime.uiHandler.applicationContext
public Files(ScriptRuntime runtime) {
mRuntime = runtime;
}
val sdcardPath: String
get() = externalStoragePath
// FIXME by Stardust on Oct 16, 2018.
// ! Is not correct in sub-directory?
// ! zh-CN (translated by SuperMonster003 on Jul 29, 2024):
// ! 子目录的处理不够准确吗?
public String path(String relativePath) {
String cwd = cwd();
if (cwd == null || relativePath == null || relativePath.startsWith(File.separator)) {
return relativePath;
fun path(relativePath: String?): String? {
relativePath ?: return null
val cwd = cwd() ?: return null
if (relativePath.startsWith(separator)) {
return relativePath
}
File f = new File(cwd);
String[] paths = relativePath.split(Pattern.quote(File.separator));
for (String path : paths) {
if (path.equals(".")) {
continue;
var file = File(cwd)
relativePath.split(separator).forEach { path ->
when {
path == ".." -> {
file = file.getParentFile() ?: return null
}
path != "." && path.isNotBlank() -> {
file = File(file, path)
}
}
if (path.equals("..")) {
f = f.getParentFile();
continue;
}
f = new File(f, path);
}
String path = f.getPath();
return relativePath.endsWith(File.separator) ? path + File.separator : path;
return when (relativePath.endsWith(separator)) {
true -> file.path + separator
else -> file.path
}
}
public String cwd() {
return mRuntime.engines.myEngine().cwd();
@Throws(IllegalArgumentException::class)
fun nonNullPath(relativePath: String): String {
return path(relativePath) ?: throw IllegalArgumentException(context.getString(R.string.error_resolved_path_for_a_relative_path_cannot_be_null))
}
public PFileInterface open(String path, String mode, String encoding, int bufferSize) {
return PFiles.open(path(path), mode, encoding, bufferSize);
fun cwd(): String? = scriptRuntime.engines.myEngine().cwd()
@JvmOverloads
fun open(path: String? = null, mode: String? = null, encoding: String? = null, bufferSize: Int? = null): PFileInterface {
return PFiles.open(path(path), mode, encoding, bufferSize)
}
public PFileInterface open(String path, String mode, String encoding) {
return PFiles.open(path(path), mode, encoding);
fun create(path: String?): Boolean {
return PFiles.create(path(path) ?: return false)
}
public PFileInterface open(String path, String mode) {
return PFiles.open(path(path), mode);
fun createIfNotExists(path: String?): Boolean {
return PFiles.createIfNotExists(path(path) ?: return false)
}
public PFileInterface open(String path) {
return PFiles.open(path(path));
fun createWithDirs(path: String?): Boolean {
return PFiles.createWithDirs(path(path) ?: return false)
}
public boolean create(String path) {
return PFiles.create(path(path));
fun exists(path: String?): Boolean {
return PFiles.exists(path(path))
}
public boolean createIfNotExists(String path) {
return PFiles.createIfNotExists(path(path));
fun ensureDir(path: String?): Boolean {
return PFiles.ensureDir(path(path) ?: return false)
}
public boolean createWithDirs(String path) {
return PFiles.createWithDirs(path(path));
@JvmOverloads
fun read(path: String?, encoding: String? = PFiles.DEFAULT_ENCODING): String {
return PFiles.read(path(path), encoding)
}
public boolean exists(String path) {
return PFiles.exists(path(path));
}
public boolean ensureDir(String path) {
return PFiles.ensureDir(path(path));
}
public String read(String path, String encoding) {
return PFiles.read(path(path), encoding);
}
public String read(String path) {
return PFiles.read(path(path));
}
public String readAssets(String path, String encoding) {
@JvmOverloads
fun readAssets(fileName: String?, encoding: String? = PFiles.DEFAULT_ENCODING): String {
val niceFileName = ensureFileNameNotNull(fileName, ::readAssets.name)
try {
return PFiles.read(mRuntime.getUiHandler().getApplicationContext().getAssets().open(path), encoding);
} catch (IOException e) {
throw new UncheckedIOException(e);
return read(context.assets.open(niceFileName), encoding)
} catch (e: IOException) {
throw UncheckedIOException(e)
}
}
public String readAssets(String path) {
return readAssets(path, "UTF-8");
fun readBytes(path: String?): ByteArray {
return PFiles.readBytes(path(path))
}
public byte[] readBytes(String path) {
return PFiles.readBytes(path(path));
@JvmOverloads
fun write(path: String?, text: String, encoding: String? = PFiles.DEFAULT_ENCODING) {
PFiles.write(path(path), text, encoding)
}
public void write(String path, String text) {
PFiles.write(path(path), text);
@JvmOverloads
fun append(path: String?, text: String, encoding: String? = PFiles.DEFAULT_ENCODING) {
PFiles.append(ensurePathNotNull(path, ::append.name), text, encoding)
}
public void write(String path, String text, String encoding) {
PFiles.write(path(path), text, encoding);
fun appendBytes(path: String?, bytes: ByteArray?) {
PFiles.appendBytes(ensurePathNotNull(path, ::appendBytes.name), bytes)
}
public void append(String path, String text) {
PFiles.append(path(path), text);
fun writeBytes(path: String?, bytes: ByteArray?) {
PFiles.writeBytes(ensurePathNotNull(path, ::writeBytes.name), bytes)
}
public void append(String path, String text, String encoding) {
PFiles.append(path(path), text, encoding);
fun copy(pathFrom: String?, pathTo: String?): Boolean = PFiles.copy(
ensurePathNotNull(pathFrom, ::copy.name, "pathFrom"),
ensurePathNotNull(pathTo, ::copy.name, "pathTo"),
)
fun renameWithoutExtension(path: String?, newName: String): Boolean {
return PFiles.renameWithoutExtension(ensurePathNotNull(path, ::renameWithoutExtension.name), newName)
}
public void appendBytes(String path, byte[] bytes) {
PFiles.appendBytes(path(path), bytes);
fun rename(path: String?, newName: String): Boolean {
return PFiles.rename(ensurePathNotNull(path, ::rename.name), newName)
}
public void writeBytes(String path, byte[] bytes) {
PFiles.writeBytes(path(path), bytes);
fun move(path: String?, newPath: String): Boolean {
return PFiles.move(ensurePathNotNull(path, ::move.name), newPath)
}
public boolean copy(String pathFrom, String pathTo) {
return PFiles.copy(path(pathFrom), path(pathTo));
fun getExtension(fileName: String?): String {
return PFiles.getExtension(ensureFileNameNotNull(fileName, ::getExtension.name))
}
public boolean renameWithoutExtension(String path, String newName) {
return PFiles.renameWithoutExtension(path(path), newName);
fun getName(filePath: String?): String {
return PFiles.getName(ensurePathNotNull(
pathToCheck = filePath,
funcName = ::getName.name,
pathArgName = "filePath",
shouldWrapWithPathMethod = false,
))
}
public boolean rename(String path, String newName) {
return PFiles.rename(path(path), newName);
fun getNameWithoutExtension(filePath: String?): String {
return PFiles.getNameWithoutExtension(ensurePathNotNull(
pathToCheck = filePath,
funcName = ::getNameWithoutExtension.name,
pathArgName = "filePath",
shouldWrapWithPathMethod = false,
))
}
public boolean move(String path, String newPath) {
return PFiles.move(path(path), newPath);
fun remove(path: String?): Boolean {
return PFiles.remove(path(path))
}
public String getExtension(String fileName) {
return PFiles.getExtension(fileName);
fun removeDir(path: String?): Boolean {
return PFiles.removeDir(path(path))
}
public String getName(String filePath) {
return PFiles.getName(filePath);
fun listDir(path: String?): Array<String> {
return PFiles.listDir(path(path))
}
public String getNameWithoutExtension(String filePath) {
return PFiles.getNameWithoutExtension(filePath);
fun listDir(path: String?, filter: Func1<String, Boolean?>): Array<String> {
return PFiles.listDir(path(path), filter)
}
public boolean remove(String path) {
return PFiles.remove(path(path));
fun isFile(path: String?): Boolean {
return PFiles.isFile(path(path))
}
public boolean removeDir(String path) {
return PFiles.removeDir(path(path));
fun isDir(path: String?): Boolean {
return PFiles.isDir(path(path))
}
public String getSdcardPath() {
return EnvironmentUtils.getExternalStoragePath();
fun isEmptyDir(path: String?): Boolean {
return PFiles.isEmptyDir(path(path))
}
public String[] listDir(String path) {
return PFiles.listDir(path(path));
fun getHumanReadableSize(bytes: Long): String {
return PFiles.getHumanReadableSize(bytes)
}
public String[] listDir(String path, Func1<String, Boolean> filter) {
return PFiles.listDir(path(path), filter);
fun getSimplifiedPath(path: String?): String {
return getElegantPath(ensurePathNotNull(path, ::getSimplifiedPath.name, shouldWrapWithPathMethod = false))
}
public boolean isFile(String path) {
return PFiles.isFile(path(path));
private fun ensureFileNameNotNull(fileNameToCheck: String?, funcName: String, fileNameArgName: String = "fileName"): String {
fileNameToCheck ?: throw WrappedIllegalArgumentException(
context.getString(
R.string.error_argument_name_for_class_name_and_member_func_name_cannot_be_nullish,
fileNameArgName, Files::class.java.simpleName, funcName,
)
)
return fileNameToCheck
}
public boolean isDir(String path) {
return PFiles.isDir(path(path));
private fun ensurePathNotNull(pathToCheck: String?, funcName: String, pathArgName: String = "path", shouldWrapWithPathMethod: Boolean = true): String {
val path = if (shouldWrapWithPathMethod) path(pathToCheck) else pathToCheck
path ?: throw WrappedIllegalArgumentException(
context.getString(
R.string.error_argument_name_for_class_name_and_member_func_name_cannot_be_nullish,
pathArgName, Files::class.java.simpleName, funcName,
)
)
return path
}
public boolean isEmptyDir(String path) {
return PFiles.isEmptyDir(path(path));
companion object {
fun join(parent: String?, vararg child: String?): String {
return PFiles.join(parent, *child)
}
}
public static String join(String parent, String... child) {
return PFiles.join(parent, child);
}
public String getHumanReadableSize(long bytes) {
return PFiles.getHumanReadableSize(bytes);
}
public String getSimplifiedPath(String path) {
return PFiles.getElegantPath(path);
}
}

View File

@@ -244,7 +244,7 @@ public class Images {
public boolean captureScreen(String path) {
ImageWrapper image = captureScreen();
return image != null && image.saveTo(mScriptRuntime.files.path(path));
return image != null && image.saveTo(mScriptRuntime.files.nonNullPath(path));
}
public ImageWrapper copy(@NonNull ImageWrapper image) {

View File

@@ -26,7 +26,7 @@ public class Media implements MediaScannerConnection.MediaScannerConnectionClien
public void scanFile(String path) {
String mimeType = Mime.fromFileOrWildcard(path);
mScannerConnection.scanFile(mRuntime.files.path(path), mimeType);
mScannerConnection.scanFile(mRuntime.files.nonNullPath(path), mimeType);
}
@Override
@@ -43,7 +43,7 @@ public class Media implements MediaScannerConnection.MediaScannerConnectionClien
}
public void playMusic(String path, float volume, boolean looping) {
path = mRuntime.files.path(path);
path = mRuntime.files.nonNullPath(path);
if (mMediaPlayer == null) {
mMediaPlayer = new MediaPlayerWrapper();
}

View File

@@ -37,6 +37,7 @@ import org.mozilla.javascript.Undefined
import java.io.File
import java.net.URI
import org.autojs.autojs.util.App as PresetApp
import androidx.core.net.toUri
@Suppress("unused", "UNUSED_PARAMETER")
class App(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) {
@@ -471,7 +472,7 @@ class App(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) {
fun parseUriRhinoWithRuntime(scriptRuntime: ScriptRuntime, uri: Any?): Uri? = when (uri) {
is String -> when {
uri.startsWith(PROTOCOL_FILE) -> getUriForFileRhinoWithRuntime(scriptRuntime, uri)
else -> Uri.parse(uri)
else -> uri.toUri()
}
is Uri -> parseUriRhinoWithRuntime(scriptRuntime, uri.host)
else -> null
@@ -501,7 +502,7 @@ class App(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) {
fun openUrlInternal(url: String) {
val prefix = "http://".takeUnless { url.contains("://") } ?: ""
Intent(Intent.ACTION_VIEW)
.setData(Uri.parse(prefix + url))
.setData((prefix + url).toUri())
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.let { globalContext.startActivity(it) }
}
@@ -510,7 +511,7 @@ class App(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) {
private fun openDualUrlInternal(scriptRuntime: ScriptRuntime, url: String) {
val prefix = "http://".takeUnless { url.contains("://") } ?: ""
Intent(Intent.ACTION_VIEW)
.setData(Uri.parse(prefix + url))
.setData((prefix + url).toUri())
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.let { startActivityForDualUser(scriptRuntime, it) }
}
@@ -523,16 +524,15 @@ class App(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) {
@JvmStatic
@RhinoFunctionBody
fun getUriForFileRhinoWithRuntime(scriptRuntime: ScriptRuntime, uri: String): Uri? = Uri.fromFile(
File(
scriptRuntime.files.path(
when {
uri.startsWith(PROTOCOL_FILE) -> uri.substring(PROTOCOL_FILE.length)
else -> uri
}
)
)
)
fun getUriForFileRhinoWithRuntime(scriptRuntime: ScriptRuntime, uri: String): Uri? {
val path = scriptRuntime.files.path(
when {
uri.startsWith(PROTOCOL_FILE) -> uri.substring(PROTOCOL_FILE.length)
else -> uri
}
) ?: return null
return Uri.fromFile(File(path))
}
@JvmStatic
@RhinoRuntimeFunctionInterface
@@ -702,7 +702,7 @@ class App(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) {
path.isJsNullish() -> false
path !is String -> throw RuntimeException("Cannot view $path as it isn't a string")
else -> {
val nicePath = scriptRuntime.files.path(path)
val nicePath = scriptRuntime.files.nonNullPath(path)
if (!scriptRuntime.files.exists(nicePath)) {
throw Error("Cannot view $path as it doesn't exist")
}
@@ -724,7 +724,7 @@ class App(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) {
path.isJsNullish() -> false
path !is String -> throw RuntimeException("Cannot edit $path as it isn't a string")
else -> {
val nicePath = scriptRuntime.files.path(path)
val nicePath = scriptRuntime.files.nonNullPath(path)
if (!scriptRuntime.files.exists(nicePath)) {
throw Error("Cannot edit $path as it doesn't exist")
}
@@ -908,13 +908,13 @@ class App(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) {
private fun launchDualSettingsInternal(scriptRuntime: ScriptRuntime, packageName: String) {
startActivityForDualUser(scriptRuntime, Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
data = Uri.parse("package:$packageName")
data = "package:$packageName".toUri()
})
}
private fun uninstallDualInternal(scriptRuntime: ScriptRuntime, packageName: String) {
startActivityForDualUser(scriptRuntime, Intent(Intent.ACTION_DELETE).apply {
data = Uri.parse("package:$packageName")
data = "package:$packageName".toUri()
})
}
@@ -995,7 +995,7 @@ class App(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) {
}
} else {
if (!o.prop("data").isJsNullish()) {
intent.setData(Uri.parse(Context.toString(o.prop("data"))))
intent.setData(Context.toString(o.prop("data")).toUri())
}
}

View File

@@ -511,7 +511,7 @@ class Console(scriptRuntime: ScriptRuntime) : AugmentableProxy(scriptRuntime) {
fun setGlobalLogConfig(scriptRuntime: ScriptRuntime, args: Array<out Any?>): Undefined = ensureArgumentsOnlyOne(args) { config ->
require(config is NativeObject) { "Argument for console.${::setGlobalLogConfig.name} must be a JavaScript Object" }
LogConfigurator().apply {
fileName = scriptRuntime.files.path(config.inquire("file", ::coerceString, "android-log4j.log"))
fileName = scriptRuntime.files.nonNullPath(config.inquire("file", ::coerceString, "android-log4j.log"))
filePattern = config.inquire("filePattern", ::coerceString, "%m%n")
maxFileSize = config.inquire("maxFileSize", ::coerceLongNumber, 512 * 1024)
maxBackupSize = config.inquire("maxBackupSize", ::coerceIntNumber, 5)

View File

@@ -111,14 +111,14 @@ class Engines(private val scriptRuntime: ScriptRuntime) : Augmentable(scriptRunt
val result = ExecutionConfig()
when (val config = if (o.isJsNullish()) newNativeObject() else o) {
is ExecutionConfig -> {
result.workingDirectory = config.workingDirectory.takeUnless { it.isEmpty() } ?: scriptRuntime.files.cwd()
result.workingDirectory = config.workingDirectory.takeUnless { it.isBlank() } ?: scriptRuntime.files.cwd() ?: ""
result.delay = config.delay.takeUnless { it < 0 } ?: 0L
result.interval = config.interval.takeUnless { it < 0 } ?: 0L
result.loopTimes = config.loopTimes.takeUnless { it < 0 } ?: 1
config.arguments.entries.forEach { result.setArgument(it.key, it.value) }
}
is ScriptableObject -> {
result.workingDirectory = config.inquire(listOf("path", "workingDirectory"), { o, _ -> o.toRuntimePath(scriptRuntime) }, scriptRuntime.files.cwd())
result.workingDirectory = config.inquire(listOf("path", "workingDirectory"), { o, _ -> o.toRuntimePath(scriptRuntime) }, scriptRuntime.files.cwd() ?: "")
result.delay = config.inquire("delay", ::coerceLongNumber, 0L)
result.interval = config.inquire("interval", ::coerceLongNumber, 0L)
result.loopTimes = config.inquire("loopTimes", ::coerceIntNumber, 1)

View File

@@ -1,6 +1,7 @@
package org.autojs.autojs.runtime.api.augment.files
import org.autojs.autojs.annotation.RhinoRuntimeFunctionInterface
import org.autojs.autojs.extension.AnyExtensions.isJsNullish
import org.autojs.autojs.extension.FlexibleArray
import org.autojs.autojs.pio.PFileInterface
import org.autojs.autojs.runtime.ScriptRuntime
@@ -16,6 +17,7 @@ class Files(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) {
override val selfAssignmentFunctions = listOf(
::open.name to AS_GLOBAL,
::path.name,
::join.name,
::toFile.name,
)
@@ -34,6 +36,16 @@ class Files(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) {
}
}
@JvmStatic
@RhinoRuntimeFunctionInterface
fun path(scriptRuntime: ScriptRuntime, args: Array<out Any?>): String? = ensureArgumentsAtMost(args, 1) { argList ->
val (o) = argList
when {
o.isJsNullish() -> scriptRuntime.files.path(null)
else -> scriptRuntime.files.path(Context.toString(o))
}
}
@JvmStatic
@RhinoRuntimeFunctionInterface
fun join(scriptRuntime: ScriptRuntime, args: Array<out Any?>): String = ensureArgumentsAtLeast(args, 1) {
@@ -43,7 +55,7 @@ class Files(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) {
@JvmStatic
@RhinoRuntimeFunctionInterface
fun toFile(scriptRuntime: ScriptRuntime, args: Array<out Any?>): File = ensureArgumentsOnlyOne(args) {
File(scriptRuntime.files.path(Context.toString(it)))
File(scriptRuntime.files.nonNullPath(Context.toString(it)))
}
}

View File

@@ -179,7 +179,7 @@ class Images(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime), AsEmitt
@JvmStatic
@RhinoRuntimeFunctionInterface
fun imread(scriptRuntime: ScriptRuntime, args: Array<out Any?>): AutoJsMat = ensureArgumentsOnlyOne(args) { path ->
ApiImages.imread(scriptRuntime.files.path(coerceString(path)))
ApiImages.imread(scriptRuntime.files.nonNullPath(coerceString(path)))
}
@JvmStatic
@@ -244,7 +244,7 @@ class Images(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime), AsEmitt
}
when {
path.isJsNullish() -> rtImages.captureScreen() as ImageWrapper
else -> rtImages.captureScreen(scriptRuntime.files.path(coerceString(path)))
else -> rtImages.captureScreen(scriptRuntime.files.nonNullPath(coerceString(path)))
}
}
@@ -301,7 +301,7 @@ class Images(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime), AsEmitt
val image = if (o is String) read(scriptRuntime, arrayOf<Any>(o, true)) else o
require(image is ImageWrapper) { "Argument image for images.save must be a ImageWrapper" }
require(!path.isJsNullish()) { "Argument path for images.save must be non-nullish" }
scriptRuntime.images.save(image, scriptRuntime.files.path(coerceString(path)), parseImageFormat(format), parseQuality(quality, DEFAULT_IMAGE_SAVE_QUALITY))
scriptRuntime.images.save(image, scriptRuntime.files.nonNullPath(coerceString(path)), parseImageFormat(format), parseQuality(quality, DEFAULT_IMAGE_SAVE_QUALITY))
}
@JvmStatic
@@ -311,7 +311,7 @@ class Images(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime), AsEmitt
val image = if (o is String) read(scriptRuntime, arrayOf<Any>(o, true)) else o
require(image is ImageWrapper) { "Argument image for images.saveImage must be a ImageWrapper" }
require(!path.isJsNullish()) { "Argument path for images.saveImage must be non-nullish" }
scriptRuntime.images.save(image, scriptRuntime.files.path(coerceString(path)), parseImageFormat(format), parseQuality(quality, DEFAULT_IMAGE_SAVE_QUALITY))
scriptRuntime.images.save(image, scriptRuntime.files.nonNullPath(coerceString(path)), parseImageFormat(format), parseQuality(quality, DEFAULT_IMAGE_SAVE_QUALITY))
}
@JvmStatic
@@ -1002,7 +1002,7 @@ class Images(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime), AsEmitt
val matcher = opt.inquire("matcher") {
coerceIntNumber(DescriptorMatcher::class.java.getField(coerceString(it)).get(null))
} ?: DescriptorMatcher.FLANNBASED
val drawMatches = opt.inquire("drawMatches") { scriptRuntime.files.path(coerceString(it)) }
val drawMatches = opt.inquire("drawMatches") { scriptRuntime.files.nonNullPath(coerceString(it)) }
val threshold = opt.inquire("threshold", ::coerceFloatNumber, 0.7f)
val result = ImageFeatureMatching.featureMatching(sceneFeatures.javaObject, objectFeatures.javaObject, matcher, drawMatches, threshold) ?: return@ensureArgumentsLengthInRange null
@@ -1070,7 +1070,7 @@ class Images(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime), AsEmitt
is OpencvMat, is Bitmap -> OpencvSize(getWidth(scriptRuntime, argList), getHeight(scriptRuntime, argList))
is String -> BitmapFactory.Options().apply { inJustDecodeBounds = true }.let { opt ->
require(scriptRuntime.files.exists(o)) { "Image source ($o) doesn't exist" }
BitmapFactory.decodeFile(scriptRuntime.files.path(o), opt)
BitmapFactory.decodeFile(scriptRuntime.files.nonNullPath(o), opt)
OpencvSize(opt.outWidth.toDouble(), opt.outHeight.toDouble())
}
else -> throw WrappedIllegalArgumentException("Unknown source to parse its size: $o")

View File

@@ -19,7 +19,7 @@ public class AutoFileSource extends ScriptSource {
mFile = file;
}
public AutoFileSource(String path) {
public AutoFileSource(@NonNull String path) {
this(new File(path));
}

View File

@@ -24,11 +24,11 @@ public class JavaScriptFileSource extends JavaScriptSource {
mFile = file;
}
public JavaScriptFileSource(String path) {
public JavaScriptFileSource(@NonNull String path) {
this(new File(path));
}
public JavaScriptFileSource(String name, File file) {
public JavaScriptFileSource(@NonNull String name, File file) {
super(name);
mCustomsName = true;
mFile = file;

View File

@@ -1,5 +1,5 @@
#Wed Apr 16 14:12:01 CST 2025
BUILD_TIME=1744783921920
#Wed Apr 16 14:34:09 CST 2025
BUILD_TIME=1744785249350
COMPILE_SDK_VERSION=35
JAVA_VERSION=23
JAVA_VERSION_MIN_RADICAL=0