6.6.2 - Alpha7 - 优化 files.path 及相关方法传入空值路径参数时的兼容性
This commit is contained in:
@@ -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)_"
|
||||
],
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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, "."))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -19,7 +19,7 @@ public class AutoFileSource extends ScriptSource {
|
||||
mFile = file;
|
||||
}
|
||||
|
||||
public AutoFileSource(String path) {
|
||||
public AutoFileSource(@NonNull String path) {
|
||||
this(new File(path));
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user