6.7.0 - Alpha17 - 修复浮动按钮 "运行脚本" 对话框后台操作崩溃并支持状态恢复; 优化后台启动 Activity 安全性

This commit is contained in:
SuperMonster003
2026-01-20 17:20:58 +08:00
parent a46d78b704
commit 068f8473e7
73 changed files with 594 additions and 310 deletions

View File

@@ -88,7 +88,7 @@
"版本历史页面部分系统因字体差别导致统计数据显示不完整的问题", "版本历史页面部分系统因字体差别导致统计数据显示不完整的问题",
"部分设备无法正常初始化 MLKit Google OCR 的问题 (试修) _[`issue #8`](http://issues.autojs6.com/8#issuecomment-3117061768)_", "部分设备无法正常初始化 MLKit Google OCR 的问题 (试修) _[`issue #8`](http://issues.autojs6.com/8#issuecomment-3117061768)_",
"部分设备无法正常触发文件管理器功能按钮点击事件的问题 (试修) _[`issue #465`](http://issues.autojs6.com/465)_", "部分设备无法正常触发文件管理器功能按钮点击事件的问题 (试修) _[`issue #465`](http://issues.autojs6.com/465)_",
"ErrorDialogActivity 可能无法正常启动或短时间自动消失的问题 _[`issue #471`](http://issues.autojs6.com/471)_ _[`issue #414`](http://issues.autojs6.com/414)_ _[`issue #340`](http://issues.autojs6.com/340#issuecomment-2973485826)_", "ErrorDialogActivity 可能无法正常启动或短时间自动消失的问题 _[`issue #479`](http://issues.autojs6.com/479)_ _[`issue #471`](http://issues.autojs6.com/471)_ _[`issue #414`](http://issues.autojs6.com/414)_ _[`issue #340`](http://issues.autojs6.com/340#issuecomment-2973485826)_",
"Canvas 构造函数可接受的参数类型错误 _[`issue #402`](http://issues.autojs6.com/402)_", "Canvas 构造函数可接受的参数类型错误 _[`issue #402`](http://issues.autojs6.com/402)_",
"崩溃报告页面复制详细信息功能失效的问题", "崩溃报告页面复制详细信息功能失效的问题",
"文件管理器删除项目文件夹后 UI 未能自动刷新的问题", "文件管理器删除项目文件夹后 UI 未能自动刷新的问题",
@@ -129,6 +129,8 @@
"客户端模式连接时支持特殊用途 IPv4 地址 (回环/广播/多播/保留/...) 检测提示", "客户端模式连接时支持特殊用途 IPv4 地址 (回环/广播/多播/保留/...) 检测提示",
"客户端模式连接时支持连接状态显示及管理 (修正地址/中止连接)", "客户端模式连接时支持连接状态显示及管理 (修正地址/中止连接)",
"服务端模式连接时支持显示已建立连接的客户端数量", "服务端模式连接时支持显示已建立连接的客户端数量",
"浮动按钮增强后台启动 Activity 的安全性以避免应用崩溃",
"浮动按钮 \"运行脚本\" 对话框支持最小化及状态恢复并尽最大努力保持窗口常驻或自动恢复",
"使用 LiveData 及 SharedFlow 替代已弃用的 LocalBroadcastManager", "使用 LiveData 及 SharedFlow 替代已弃用的 LocalBroadcastManager",
"Gradle 构建脚本提升 7z 格式文件的解压效率", "Gradle 构建脚本提升 7z 格式文件的解压效率",
"Gradle 构建脚本支持获取详细的 Android Studio IDE 版本 (如 \"2025.1.4.7\")", "Gradle 构建脚本支持获取详细的 Android Studio IDE 版本 (如 \"2025.1.4.7\")",

View File

@@ -24,6 +24,7 @@ import android.net.Uri;
import android.os.Binder; import android.os.Binder;
import android.provider.Settings; import android.provider.Settings;
import android.util.Log; import android.util.Log;
import org.autojs.autojs.util.IntentUtils;
import org.autojs.autojs.util.RomUtils; import org.autojs.autojs.util.RomUtils;
import java.lang.reflect.Method; import java.lang.reflect.Method;
@@ -72,7 +73,7 @@ public class SettingsCompat {
public static void manageWriteSettings(Context context) { public static void manageWriteSettings(Context context) {
Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS); Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS);
intent.setData(Uri.parse("package:" + context.getPackageName())); intent.setData(Uri.parse("package:" + context.getPackageName()));
context.startActivity(intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); IntentUtils.startSafely(intent, context);
} }
private static boolean checkOp(Context context, int op) { private static boolean checkOp(Context context, int op) {
@@ -88,8 +89,7 @@ public class SettingsCompat {
private static boolean startSafely(Context context, Intent intent) { private static boolean startSafely(Context context, Intent intent) {
if (context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY).size() > 0) { if (context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY).size() > 0) {
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); IntentUtils.startSafely(intent, context);
context.startActivity(intent);
return true; return true;
} else { } else {
Log.e(TAG, "Intent is not available! " + intent); Log.e(TAG, "Intent is not available! " + intent);

View File

@@ -1,3 +1,5 @@
@file:Suppress("unused")
package org.autojs.autojs.app package org.autojs.autojs.app
import android.app.Activity import android.app.Activity
@@ -6,7 +8,9 @@ import android.content.ContextWrapper
import android.content.DialogInterface import android.content.DialogInterface
import android.os.Build import android.os.Build
import android.os.Looper import android.os.Looper
import android.provider.Settings
import android.text.util.Linkify import android.text.util.Linkify
import android.util.Log
import android.view.Gravity import android.view.Gravity
import android.view.KeyEvent import android.view.KeyEvent
import android.view.View import android.view.View
@@ -15,6 +19,7 @@ import android.widget.CheckBox
import androidx.preference.PreferenceViewHolder import androidx.preference.PreferenceViewHolder
import com.afollestad.materialdialogs.DialogAction import com.afollestad.materialdialogs.DialogAction
import com.afollestad.materialdialogs.MaterialDialog import com.afollestad.materialdialogs.MaterialDialog
import org.autojs.autojs.annotation.ReservedForCompatibility
import org.autojs.autojs.theme.preference.LongClickablePreferenceLike import org.autojs.autojs.theme.preference.LongClickablePreferenceLike
import org.autojs.autojs.ui.explorer.ExplorerView import org.autojs.autojs.ui.explorer.ExplorerView
import org.autojs.autojs.util.ViewUtils.showSnack import org.autojs.autojs.util.ViewUtils.showSnack
@@ -22,42 +27,173 @@ import org.autojs.autojs6.R
/** /**
* Created by Stardust on Aug 4, 2017. * Created by Stardust on Aug 4, 2017.
* Modified by SuperMonster003 as of Sep 10, 2022.
* Transformed by SuperMonster003 on Oct 19, 2022. * Transformed by SuperMonster003 on Oct 19, 2022.
* Modified by JetBrains AI Assistant (GPT-5.2) as of Jan 18, 2026.
* Modified by OpenAI ChatGPT (GPT-5.2 Thinking) as of Jan 20, 2026.
* Modified by SuperMonster003 as of Jan 20, 2026.
*/ */
object DialogUtils { object DialogUtils {
private const val TAG = "DialogUtils"
@JvmStatic @JvmStatic
fun <T : MaterialDialog> showDialog(dialog: T): T { fun MaterialDialog.Builder.showAdaptive() = build().showAdaptive()
val context = dialog.context
if (!isActivityContext(context)) { @JvmStatic
val window = dialog.window fun MaterialDialog.showAdaptive() = showDialog(this)
val type = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY /**
* Show this [MaterialDialog] in a context-safe way.
*
* Behavior:
* 1) Always performs window operations and `show()` on the main thread.
* 2) If the dialog uses an [Activity] context, it is shown normally.
* 3) Otherwise, it tries to show as an overlay window:
* - `TYPE_APPLICATION_OVERLAY` on Android O+.
* - `TYPE_PHONE` on pre-O devices.
* Overlay requires "Draw over other apps" permission (SYSTEM_ALERT_WINDOW).
* If permission is missing, the dialog will NOT be shown and no exception will be thrown.
* 4) Avoids overriding `OnShowListener` to prevent breaking caller/library logic.
*
* zh-CN: 以 "上下文安全" 的方式显示 [MaterialDialog].
*
* 行为说明:
* 1) 所有 Window 参数操作和 `show()` 都保证在主线程执行.
* 2) 若对话框基于 [Activity] Context, 则按常规方式显示.
* 3) 否则尝试以 overlay 窗口显示:
* - Android O+ 使用 `TYPE_APPLICATION_OVERLAY`.
* - Android O 以下使用 `TYPE_PHONE`.
* overlay 依赖 "在其他应用上层显示" (SYSTEM_ALERT_WINDOW) 权限.
* 若检测到权限缺失, 将直接放弃显示且不会抛异常.
* 4) 不覆盖 `OnShowListener`, 避免破坏调用方或库内部逻辑.
*
* @param dialog The dialog instance to show.
* zh-CN: 需要显示的对话框实例.
* @param focusable Only affects overlay dialogs. If false, `FLAG_NOT_FOCUSABLE` is added,
* which makes the dialog less likely to be blocked when app is in background,
* but also prevents it from receiving some key/IME inputs.
* zh-CN: 仅影响 overlay 对话框. 为 false 时会添加 `FLAG_NOT_FOCUSABLE`,
* 更可能在后台可见, 但会影响按键/输入法等焦点相关能力.
*
* @return The same dialog instance.
* zh-CN: 返回同一个对话框实例.
*/
@JvmStatic
@JvmOverloads
@ReservedForCompatibility
fun <T : MaterialDialog> showDialog(dialog: T, focusable: Boolean = true): T {
runOnMain {
// Prevent duplicated show.
// zh-CN: 防止重复 show().
if (dialog.isShowing) return@runOnMain
val context = dialog.context
// Activity lifecycle guard.
// zh-CN: Activity 生命周期保护.
unwrapActivity(context)?.let { act ->
if (act.isFinishing || act.isDestroyed) {
Log.w(TAG, "Skip showing dialog: Activity is finishing/destroyed.")
return@runOnMain
}
}
val needsOverlay = !isActivityContext(context)
if (needsOverlay) {
// Permission check.
// zh-CN: 检查 overlay 权限.
if (!Settings.canDrawOverlays(context)) {
Log.w(TAG, "Skip showing overlay dialog: missing SYSTEM_ALERT_WINDOW permission.")
return@runOnMain
}
val type = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
} else {
@Suppress("DEPRECATION")
WindowManager.LayoutParams.TYPE_PHONE
}
fun applyOverlayWindowParams() {
// Ensure window exists; `create()` usually creates the underlying window for Dialog.
// zh-CN: 确保 window 存在; `create()` 通常会创建底层 window.
if (dialog.window == null) {
try {
dialog.create()
} catch (t: Throwable) {
Log.w(TAG, "dialog.create() failed (ignored).", t)
}
}
dialog.window?.let { w ->
try {
@Suppress("DEPRECATION")
w.setType(type)
} catch (t: Throwable) {
// Some ROMs may throw here; ignore and continue.
// zh-CN: 某些 ROM 可能在此抛异常; 忽略并继续.
Log.w(TAG, "Failed to set window type (ignored).", t)
}
if (focusable) {
// Keep default behavior for key/input handling.
// zh-CN: 保持默认行为以处理按键/输入.
w.clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE)
} else {
// Non-focusable overlay dialogs are more likely to show while app is in background.
// zh-CN: 不可聚焦的 overlay 对话框更可能在应用后台时正常显示.
w.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE)
}
}
}
// Apply before show.
// zh-CN: show() 前先尝试设置.
applyOverlayWindowParams()
try {
dialog.show()
} catch (t: Throwable) {
// BadTokenException / SecurityException etc.
// zh-CN: 可能出现 BadTokenException / SecurityException 等.
Log.w(TAG, "Failed to show overlay dialog.", t)
return@runOnMain
}
// Re-apply after show (some dialog libs may reset attributes during show).
// zh-CN: show() 后再补一次 (库内部可能在 show 过程中重置参数).
applyOverlayWindowParams()
} else { } else {
@Suppress("DEPRECATION") // Normal Activity dialog.
WindowManager.LayoutParams.TYPE_PHONE // zh-CN: Activity Context 正常对话框.
} try {
dialog.show()
// Try setting window type before show(). } catch (t: Throwable) {
// zh-CN: 尝试在 show() 之前设置窗口类型. Log.w(TAG, "Failed to show dialog.", t)
window?.setType(type) }
// Ensure window type is applied when window becomes available.
// zh-CN: 当 window 可用时确保窗口类型已正确应用.
dialog.setOnShowListener {
window?.setType(type)
} }
} }
if (Looper.getMainLooper() == Looper.myLooper()) {
dialog.show()
} else {
GlobalAppContext.post { dialog.show() }
}
return dialog return dialog
} }
private fun unwrapActivity(context: Context?): Activity? {
return when (context) {
is Activity -> context
is ContextWrapper -> unwrapActivity(context.baseContext)
else -> null
}
}
private inline fun runOnMain(crossinline block: () -> Unit) {
if (Looper.getMainLooper() == Looper.myLooper()) {
block()
} else {
GlobalAppContext.post { block() }
}
}
@JvmStatic @JvmStatic
fun <T : MaterialDialog> fixCheckBoxGravity(dialog: T): T = dialog.also { fun <T : MaterialDialog> fixCheckBoxGravity(dialog: T): T = dialog.also {
it.view.findViewById<CheckBox>(com.afollestad.materialdialogs.R.id.md_promptCheckbox)?.gravity = Gravity.CENTER_VERTICAL it.view.findViewById<CheckBox>(com.afollestad.materialdialogs.R.id.md_promptCheckbox)?.gravity = Gravity.CENTER_VERTICAL
@@ -65,7 +201,7 @@ object DialogUtils {
@JvmStatic @JvmStatic
fun isActivityContext(context: Context?): Boolean { fun isActivityContext(context: Context?): Boolean {
return context is Activity || context is ContextWrapper && isActivityContext(context.baseContext) return context is Activity || (context is ContextWrapper && isActivityContext(context.baseContext))
} }
fun toggleContentViewByItems(dialog: MaterialDialog) { fun toggleContentViewByItems(dialog: MaterialDialog) {
@@ -127,7 +263,7 @@ object DialogUtils {
text = text text = text
} }
} }
.let { showDialog(it) } .showAdaptive()
} }
} }
} }
@@ -143,7 +279,7 @@ object DialogUtils {
text = text text = text
} }
} }
.let { showDialog(it) } .showAdaptive()
true true
} ?: false } ?: false
} }

View File

@@ -15,6 +15,7 @@ import org.autojs.autojs.runtime.api.ProcessShell
import org.autojs.autojs.runtime.exception.ScriptException import org.autojs.autojs.runtime.exception.ScriptException
import org.autojs.autojs.runtime.exception.ScriptInterruptedException import org.autojs.autojs.runtime.exception.ScriptInterruptedException
import org.autojs.autojs.service.AccessibilityInteractionClient import org.autojs.autojs.service.AccessibilityInteractionClient
import org.autojs.autojs.util.IntentUtils.startSafely
import org.autojs.autojs.util.RootUtils import org.autojs.autojs.util.RootUtils
import org.autojs.autojs.util.SettingsUtils import org.autojs.autojs.util.SettingsUtils
import org.autojs.autojs.util.ViewUtils import org.autojs.autojs.util.ViewUtils
@@ -47,7 +48,7 @@ class AccessibilityTool(private val context: Context? = null) {
ViewUtils.showToast(mContext, it, true) ViewUtils.showToast(mContext, it, true)
} }
try { try {
mApplicationContext.startActivity(Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)) Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS).startSafely(mApplicationContext)
} catch (_: ActivityNotFoundException) { } catch (_: ActivityNotFoundException) {
ViewUtils.showToast(mContext, R.string.go_to_accessibility_settings, true) ViewUtils.showToast(mContext, R.string.go_to_accessibility_settings, true)
} }

View File

@@ -6,6 +6,7 @@ import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import org.autojs.autojs.tool.IntentExtras import org.autojs.autojs.tool.IntentExtras
import org.autojs.autojs.util.IntentUtils.startSafely
/** /**
* Created by SuperMonster003 on Dec 14, 2023. * Created by SuperMonster003 on Dec 14, 2023.
@@ -62,10 +63,8 @@ class StartForResultActivity : Activity() {
@JvmStatic @JvmStatic
fun start(context: Context, callback: Callback?) { fun start(context: Context, callback: Callback?) {
Intent(context, StartForResultActivity::class.java).also { intent -> Intent(context, StartForResultActivity::class.java).also { intent ->
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
intent.putExtra(IntentExtras.EXTRA_ID, IntentExtras().apply { map["callback"] = callback }.id) intent.putExtra(IntentExtras.EXTRA_ID, IntentExtras().apply { map["callback"] = callback }.id)
context.startActivity(intent) }.startSafely(context)
}
} }
} }

View File

@@ -39,6 +39,7 @@ import org.autojs.autojs.ui.enhancedfloaty.ResizableExpandableFloatyWindow
import org.autojs.autojs.ui.enhancedfloaty.gesture.DragGesture import org.autojs.autojs.ui.enhancedfloaty.gesture.DragGesture
import org.autojs.autojs.util.ClipboardUtils import org.autojs.autojs.util.ClipboardUtils
import org.autojs.autojs.util.ColorUtils import org.autojs.autojs.util.ColorUtils
import org.autojs.autojs.util.IntentUtils.startSafely
import org.autojs.autojs.util.StringUtils.key import org.autojs.autojs.util.StringUtils.key
import org.autojs.autojs.util.ViewUtils import org.autojs.autojs.util.ViewUtils
import org.autojs.autojs6.R import org.autojs.autojs6.R
@@ -286,9 +287,7 @@ open class ConsoleImpl(val uiHandler: UiHandler) : AbstractConsole() {
putExtra(Intent.EXTRA_TEXT, message) putExtra(Intent.EXTRA_TEXT, message)
type = Mime.TEXT_PLAIN type = Mime.TEXT_PLAIN
} }
applicationContext.startActivity(Intent.createChooser(sendIntent, null).apply { Intent.createChooser(sendIntent, null).startSafely(applicationContext)
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
})
} }
private fun cutOutEntries(maxLength: Int): MutableList<LogEntry> { private fun cutOutEntries(maxLength: Int): MutableList<LogEntry> {

View File

@@ -2,6 +2,7 @@ package org.autojs.autojs.core.permission;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import org.autojs.autojs.util.IntentUtils;
import java.util.ArrayList; import java.util.ArrayList;
@@ -37,8 +38,8 @@ public class Permissions {
} }
public static void requestPermissions(Context context, String[] permissions) { public static void requestPermissions(Context context, String[] permissions) {
context.startActivity(new Intent(context, PermissionRequestActivity.class) Intent intent = new Intent(context, PermissionRequestActivity.class)
.putExtra(PermissionRequestActivity.EXTRA_PERMISSIONS, permissions) .putExtra(PermissionRequestActivity.EXTRA_PERMISSIONS, permissions);
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); IntentUtils.startSafely(intent, context);
} }
} }

View File

@@ -13,6 +13,7 @@ import com.afollestad.materialdialogs.MaterialDialog
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.autojs.autojs.ui.BaseActivity import org.autojs.autojs.ui.BaseActivity
import org.autojs.autojs.ui.widget.SearchViewItem import org.autojs.autojs.ui.widget.SearchViewItem
import org.autojs.autojs.util.IntentUtils.startSafely
import org.autojs.autojs.util.ViewUtils import org.autojs.autojs.util.ViewUtils
import org.autojs.autojs.util.ViewUtils.onceGlobalLayout import org.autojs.autojs.util.ViewUtils.onceGlobalLayout
import org.autojs.autojs.util.ViewUtils.setMenuIconsColorByThemeColorLuminance import org.autojs.autojs.util.ViewUtils.setMenuIconsColorByThemeColorLuminance
@@ -187,8 +188,7 @@ class PluginCenterActivity : BaseActivity() {
fun startActivity(context: Context) { fun startActivity(context: Context) {
Intent(context, PluginCenterActivity::class.java) Intent(context, PluginCenterActivity::class.java)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) .startSafely(context)
.let { context.startActivity(it) }
} }
} }

View File

@@ -5,6 +5,7 @@ import android.content.Intent
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import androidx.core.net.toUri import androidx.core.net.toUri
import com.afollestad.materialdialogs.MaterialDialog import com.afollestad.materialdialogs.MaterialDialog
import org.autojs.autojs.util.IntentUtils.startSafely
import org.autojs.autojs6.R import org.autojs.autojs6.R
import org.joda.time.DateTime import org.joda.time.DateTime
import org.joda.time.format.DateTimeFormat import org.joda.time.format.DateTimeFormat
@@ -84,7 +85,8 @@ data class PluginCenterItem(
} }
fun uninstall(context: Context) { fun uninstall(context: Context) {
context.startActivity(Intent(Intent.ACTION_DELETE, "package:$packageName".toUri())) Intent(Intent.ACTION_DELETE, "package:$packageName".toUri())
.startSafely(context)
} }
fun uninstallWithPrompt(context: Context, dialog: MaterialDialog? = null) { fun uninstallWithPrompt(context: Context, dialog: MaterialDialog? = null) {

View File

@@ -17,6 +17,7 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.autojs.autojs.app.DialogUtils.showAdaptive
import org.autojs.autojs.extension.MaterialDialogExtensions.makeSettingsLaunchable import org.autojs.autojs.extension.MaterialDialogExtensions.makeSettingsLaunchable
import org.autojs.autojs.extension.MaterialDialogExtensions.makeTextCopyable import org.autojs.autojs.extension.MaterialDialogExtensions.makeTextCopyable
import org.autojs.autojs.extension.MaterialDialogExtensions.setCopyableTextIfAbsent import org.autojs.autojs.extension.MaterialDialogExtensions.setCopyableTextIfAbsent
@@ -119,7 +120,7 @@ object PluginInfoDialogManager {
.onNegative { d, _ -> d.dismiss() } .onNegative { d, _ -> d.dismiss() }
.autoDismiss(false) .autoDismiss(false)
.apply(builderApplier) .apply(builderApplier)
.show() .showAdaptive()
.apply { makeTextCopyable { titleView } } .apply { makeTextCopyable { titleView } }
// Hold the current dialog and package name for refreshing on onResume. // Hold the current dialog and package name for refreshing on onResume.
@@ -215,7 +216,7 @@ object PluginInfoDialogManager {
ViewUtils.showToast(context, R.string.text_done) ViewUtils.showToast(context, R.string.text_done)
parentDialog.dismiss() parentDialog.dismiss()
} }
.show() .showAdaptive()
} }
MaterialDialog.Builder(context) MaterialDialog.Builder(context)
@@ -244,7 +245,7 @@ object PluginInfoDialogManager {
.title(R.string.text_prompt) .title(R.string.text_prompt)
.content(R.string.error_no_available_url_provided_for_current_plugin) .content(R.string.error_no_available_url_provided_for_current_plugin)
.positiveText(R.string.dialog_button_dismiss) .positiveText(R.string.dialog_button_dismiss)
.show() .showAdaptive()
parentDialog parentDialog
?.getActionButton(DialogAction.POSITIVE) ?.getActionButton(DialogAction.POSITIVE)
?.setTextColor(context.getColor(R.color.dialog_button_unavailable)) ?.setTextColor(context.getColor(R.color.dialog_button_unavailable))

View File

@@ -19,6 +19,7 @@ import org.autojs.autojs.util.FileUtils
import org.autojs.autojs.util.FileUtils.toCacheFile import org.autojs.autojs.util.FileUtils.toCacheFile
import org.autojs.autojs.util.IntentUtils import org.autojs.autojs.util.IntentUtils
import org.autojs.autojs.util.IntentUtils.SnackExceptionHolder import org.autojs.autojs.util.IntentUtils.SnackExceptionHolder
import org.autojs.autojs.util.IntentUtils.startSafely
import org.autojs.autojs.util.ViewUtils import org.autojs.autojs.util.ViewUtils
import org.autojs.autojs6.R import org.autojs.autojs6.R
import java.io.EOFException import java.io.EOFException
@@ -78,12 +79,10 @@ object PluginInstaller {
} }
fun installFromFileUri(context: Context, uri: Uri) { fun installFromFileUri(context: Context, uri: Uri) {
val intent = Intent(Intent.ACTION_VIEW).apply { Intent(Intent.ACTION_VIEW).apply {
setDataAndType(uri, Mime.APPLICATION_VND_ANDROID_PACKAGE_ARCHIVE) setDataAndType(uri, Mime.APPLICATION_VND_ANDROID_PACKAGE_ARCHIVE)
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) }.startSafely(context)
}
context.startActivity(intent)
} }
suspend fun installFromUrlWithPrompt(context: Context, url: String, expectedSha256: String? = null) { suspend fun installFromUrlWithPrompt(context: Context, url: String, expectedSha256: String? = null) {

View File

@@ -18,7 +18,6 @@ import org.autojs.autojs6.R;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
import static org.autojs.autojs.util.RhinoUtils.isBackgroundThread;
import static org.autojs.autojs.util.RhinoUtils.isMainThread; import static org.autojs.autojs.util.RhinoUtils.isMainThread;
/** /**
@@ -185,7 +184,7 @@ public class GlobalActionRecorder implements Recorder.OnStateChangedListener {
.positiveColorRes(R.color.dialog_button_attraction) .positiveColorRes(R.color.dialog_button_attraction)
.canceledOnTouchOutside(false); .canceledOnTouchOutside(false);
MaterialDialogExtensions.choiceWidgetThemeColor(builder); MaterialDialogExtensions.choiceWidgetThemeColor(builder);
DialogUtils.showDialog(builder.build()); DialogUtils.showAdaptive(builder.build());
} }
private String getString(int res) { private String getString(int res) {

View File

@@ -2,13 +2,11 @@ package org.autojs.autojs.external.tasker;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import com.twofortyfouram.locale.sdk.client.receiver.AbstractPluginSettingReceiver; import com.twofortyfouram.locale.sdk.client.receiver.AbstractPluginSettingReceiver;
import org.autojs.autojs.external.ScriptIntents; import org.autojs.autojs.external.ScriptIntents;
import org.autojs.autojs.external.open.RunIntentActivity; import org.autojs.autojs.external.open.RunIntentActivity;
import org.autojs.autojs.util.IntentUtils;
import org.json.JSONObject; import org.json.JSONObject;
/** /**
@@ -28,9 +26,9 @@ public class FireSettingReceiver extends AbstractPluginSettingReceiver {
@Override @Override
protected void firePluginSetting(@NonNull Context context, @NonNull JSONObject jsonObject) { protected void firePluginSetting(@NonNull Context context, @NonNull JSONObject jsonObject) {
context.startActivity(new Intent(context, RunIntentActivity.class) Intent intent = new Intent(context, RunIntentActivity.class)
.putExtra(ScriptIntents.EXTRA_KEY_JSON, jsonObject.toString()) .putExtra(ScriptIntents.EXTRA_KEY_JSON, jsonObject.toString());
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); IntentUtils.startSafely(intent, context);
} }
} }

View File

@@ -17,6 +17,7 @@ import org.autojs.autojs.pio.UncheckedIOException
import org.autojs.autojs.project.ProjectConfig import org.autojs.autojs.project.ProjectConfig
import org.autojs.autojs.script.JavaScriptFileSource import org.autojs.autojs.script.JavaScriptFileSource
import org.autojs.autojs.script.JavaScriptSource import org.autojs.autojs.script.JavaScriptSource
import org.autojs.autojs.util.IntentUtils.startSafely
import java.io.File import java.io.File
import java.io.IOException import java.io.IOException
@@ -46,10 +47,9 @@ open class AssetsProjectLauncher(private val mAssetsProjectDir: String, private
} else { } else {
// 否则显示日志界面并在日志界面中运行脚本 // 否则显示日志界面并在日志界面中运行脚本
mHandler.post { mHandler.post {
activity.startActivity( Intent(mActivity, LogActivity::class.java)
Intent(mActivity, LogActivity::class.java) .putExtra(LogActivity.EXTRA_LAUNCH_SCRIPT, true)
.putExtra(LogActivity.EXTRA_LAUNCH_SCRIPT, true) .startSafely(activity)
)
activity.finish() activity.finish()
} }
} }

View File

@@ -16,6 +16,7 @@ import org.autojs.autojs.ui.common.NotAskAgainDialog
import org.autojs.autojs.ui.main.MainActivity import org.autojs.autojs.ui.main.MainActivity
import org.autojs.autojs.ui.main.drawer.PermissionItemHelper import org.autojs.autojs.ui.main.drawer.PermissionItemHelper
import org.autojs.autojs.util.IntentUtils import org.autojs.autojs.util.IntentUtils
import org.autojs.autojs.util.IntentUtils.startSafely
import org.autojs.autojs.util.StringUtils.key import org.autojs.autojs.util.StringUtils.key
import org.autojs.autojs6.R import org.autojs.autojs6.R
@@ -56,17 +57,16 @@ class AllFilesAccessPermission(override val context: Context) : PermissionItemHe
} }
@RequiresApi(Build.VERSION_CODES.R) @RequiresApi(Build.VERSION_CODES.R)
private fun manageAllFilesAccess(): Boolean = runCatching { private fun manageAllFilesAccess(): Boolean = when {
Intent() Intent()
.setAction(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION) .setAction(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION)
.setData(Uri.fromParts("package", context.packageName, null)) .setData(Uri.fromParts("package", context.packageName, null))
.let { context.startActivity(it) } .startSafely(context) -> true
true
}.isSuccess || runCatching {
Intent() Intent()
.setAction(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION) .setAction(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION)
.let { context.startActivity(it) } .startSafely(context) -> true
}.isSuccess else -> false
}
private fun launchAppDetailsSettings() = IntentUtils.launchAppDetailsSettings(context) private fun launchAppDetailsSettings() = IntentUtils.launchAppDetailsSettings(context)

View File

@@ -7,6 +7,7 @@ import android.os.PowerManager
import android.provider.Settings import android.provider.Settings
import androidx.core.net.toUri import androidx.core.net.toUri
import org.autojs.autojs.ui.main.drawer.PermissionItemHelper import org.autojs.autojs.ui.main.drawer.PermissionItemHelper
import org.autojs.autojs.util.IntentUtils.startSafely
import org.autojs.autojs.util.ViewUtils import org.autojs.autojs.util.ViewUtils
import org.autojs.autojs6.R import org.autojs.autojs6.R
@@ -24,19 +25,14 @@ class IgnoreBatteryOptimizationsPermission(override val context: Context) : Perm
override fun request() = Intent() override fun request() = Intent()
.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS) .setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)
.setData("package:${context.packageName}".toUri()) .setData("package:${context.packageName}".toUri())
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK) .startSafely(context, true) {
.let { tryStartActivity(it) } ViewUtils.showToast(context, R.string.text_failed)
}
override fun revoke() = Intent() override fun revoke() = Intent()
.setAction(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS) .setAction(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK) .startSafely(context, true) {
.let { tryStartActivity(it) } ViewUtils.showToast(context, R.string.text_failed)
}
private fun tryStartActivity(i: Intent) = runCatching {
context.startActivity(i)
}.onFailure {
it.printStackTrace()
ViewUtils.showToast(context, R.string.text_failed)
}.isSuccess
} }

View File

@@ -5,6 +5,7 @@ import android.content.Intent
import android.net.Uri import android.net.Uri
import android.provider.Settings import android.provider.Settings
import org.autojs.autojs.ui.main.drawer.PermissionItemHelper import org.autojs.autojs.ui.main.drawer.PermissionItemHelper
import org.autojs.autojs.util.IntentUtils.startSafely
class WriteSystemSettingsPermission(override val context: Context) : PermissionItemHelper { class WriteSystemSettingsPermission(override val context: Context) : PermissionItemHelper {
@@ -14,10 +15,8 @@ class WriteSystemSettingsPermission(override val context: Context) : PermissionI
override fun revoke() = false.also { config() } override fun revoke() = false.also { config() }
fun config() = context.startActivity( fun config() = Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS)
Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS) .setData(Uri.parse("package:${context.packageName}"))
.setData(Uri.parse("package:${context.packageName}")) .startSafely(context)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
)
} }

View File

@@ -27,6 +27,8 @@ import org.autojs.autojs.ui.settings.AboutActivity
import org.autojs.autojs.ui.settings.PreferencesActivity import org.autojs.autojs.ui.settings.PreferencesActivity
import org.autojs.autojs.util.App import org.autojs.autojs.util.App
import org.autojs.autojs.util.IntentUtils import org.autojs.autojs.util.IntentUtils
import org.autojs.autojs.util.IntentUtils.start
import org.autojs.autojs.util.IntentUtils.startSafely
import org.autojs.autojs6.R import org.autojs.autojs6.R
import java.lang.ref.WeakReference import java.lang.ref.WeakReference
import java.net.URI import java.net.URI
@@ -63,7 +65,7 @@ class AppUtils(context: Context, @get:ScriptInterface val fileProviderAuthority:
o ?: return false o ?: return false
val nicePackageName = getAppByAlias(alias = o)?.packageName ?: (/* packageName = */ o) val nicePackageName = getAppByAlias(alias = o)?.packageName ?: (/* packageName = */ o)
val intent = mPackageManager.getLaunchIntentForPackage(nicePackageName) ?: return false val intent = mPackageManager.getLaunchIntentForPackage(nicePackageName) ?: return false
mContext.startActivity(intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)) intent.start(mContext)
}.isSuccess }.isSuccess
@ScriptInterface @ScriptInterface
@@ -155,8 +157,7 @@ class AppUtils(context: Context, @get:ScriptInterface val fileProviderAuthority:
@ScriptInterface @ScriptInterface
fun uninstall(packageName: String) { fun uninstall(packageName: String) {
Intent(Intent.ACTION_DELETE, "package:$packageName".toUri()) Intent(Intent.ACTION_DELETE, "package:$packageName".toUri())
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) .startSafely(mContext)
.let { mContext.startActivity(it) }
} }
@ScriptInterface @ScriptInterface

View File

@@ -30,6 +30,7 @@ import org.autojs.autojs.core.pref.Language;
import org.autojs.autojs.runtime.ScriptRuntime; import org.autojs.autojs.runtime.ScriptRuntime;
import org.autojs.autojs.runtime.exception.ScriptException; import org.autojs.autojs.runtime.exception.ScriptException;
import org.autojs.autojs.tool.MapBuilder; import org.autojs.autojs.tool.MapBuilder;
import org.autojs.autojs.util.IntentUtils;
import org.autojs.autojs6.R; import org.autojs.autojs6.R;
import org.mozilla.javascript.BaseFunction; import org.mozilla.javascript.BaseFunction;
@@ -240,9 +241,8 @@ public class Events extends EventEmitter implements OnKeyListener, TouchObserver
NotificationListenerService.getInstance().addListener(this); NotificationListenerService.getInstance().addListener(this);
return; return;
} }
Intent intent = new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS) Intent intent = new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS);
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); IntentUtils.startSafely(intent, mContext);
mContext.startActivity(intent);
throw new ScriptException(mContext.getString(R.string.text_notification_service_disabled)); throw new ScriptException(mContext.getString(R.string.text_notification_service_disabled));
} }

View File

@@ -8,6 +8,7 @@ import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts.RequestMultiplePermissions import androidx.activity.result.contract.ActivityResultContracts.RequestMultiplePermissions
import androidx.fragment.app.FragmentActivity import androidx.fragment.app.FragmentActivity
import org.autojs.autojs.core.pref.Pref import org.autojs.autojs.core.pref.Pref
import org.autojs.autojs.util.IntentUtils.startSafely
import org.autojs.autojs.util.RomUtils import org.autojs.autojs.util.RomUtils
import org.autojs.autojs6.R import org.autojs.autojs6.R
@@ -20,18 +21,19 @@ class Permissions(private val context: Context) {
var backgroundStart = object : IPermissionToggleable { var backgroundStart = object : IPermissionToggleable {
override val description = "后台弹出界面 / Start in background" override val description = "后台弹出界面 / Start in background"
override fun has() = RomUtils.isBackgroundStartGranted(context) override fun has() = RomUtils.isBackgroundStartGranted(context)
override fun config() = when { override fun config() {
RomUtils.isMiui() -> { when {
Intent("miui.intent.action.APP_PERM_EDITOR").apply { RomUtils.isMiui() -> {
setClassName( Intent("miui.intent.action.APP_PERM_EDITOR").apply {
"com.miui.securitycenter", setClassName(
"com.miui.permcenter.permissions.PermissionsEditorActivity", "com.miui.securitycenter",
) "com.miui.permcenter.permissions.PermissionsEditorActivity",
putExtra("extra_pkgname", context.packageName) )
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) putExtra("extra_pkgname", context.packageName)
}.let { context.startActivity(it) } }.startSafely(context)
}
else -> super.config()
} }
else -> super.config()
} }
} }
var displayOverOtherApps: IPermissionToggleable? = null var displayOverOtherApps: IPermissionToggleable? = null

View File

@@ -15,6 +15,7 @@ import org.autojs.autojs.app.GlobalAppContext
import org.autojs.autojs.core.shizuku.IUserService import org.autojs.autojs.core.shizuku.IUserService
import org.autojs.autojs.core.shizuku.UserService import org.autojs.autojs.core.shizuku.UserService
import org.autojs.autojs.util.App.SHIZUKU import org.autojs.autojs.util.App.SHIZUKU
import org.autojs.autojs.util.IntentUtils.startSafely
import org.autojs.autojs.util.ViewUtils import org.autojs.autojs.util.ViewUtils
import org.autojs.autojs6.R import org.autojs.autojs6.R
import rikka.shizuku.Shizuku import rikka.shizuku.Shizuku
@@ -151,7 +152,7 @@ object WrappedShizuku {
fun config(isRequest: Boolean? = null) = configWithContext(GlobalAppContext.get(), isRequest) fun config(isRequest: Boolean? = null) = configWithContext(GlobalAppContext.get(), isRequest)
fun configWithContext(context: Context, isRequest: Boolean? = null): Intent? = getLaunchIntent(context)?.also { fun configWithContext(context: Context, isRequest: Boolean? = null): Intent? = getLaunchIntent(context)?.also {
context.startActivity(it) it.startSafely(context)
val message = when (isRequest) { val message = when (isRequest) {
true -> "${context.getString(R.string.text_grant_autojs6_access_in_shizuku_app)} (${context.getString(R.string.text_shizuku_service_may_need_to_be_run_first)})" true -> "${context.getString(R.string.text_grant_autojs6_access_in_shizuku_app)} (${context.getString(R.string.text_shizuku_service_may_need_to_be_run_first)})"
false -> context.getString(R.string.text_revoke_autojs6_access_in_shizuku_app) false -> context.getString(R.string.text_revoke_autojs6_access_in_shizuku_app)

View File

@@ -36,6 +36,7 @@ import org.autojs.autojs.runtime.api.augment.shell.Shell
import org.autojs.autojs.runtime.exception.ShouldNeverHappenException import org.autojs.autojs.runtime.exception.ShouldNeverHappenException
import org.autojs.autojs.runtime.exception.WrappedIllegalArgumentException import org.autojs.autojs.runtime.exception.WrappedIllegalArgumentException
import org.autojs.autojs.timing.TimedTaskManager import org.autojs.autojs.timing.TimedTaskManager
import org.autojs.autojs.util.IntentUtils.startSafely
import org.autojs.autojs.util.RhinoUtils import org.autojs.autojs.util.RhinoUtils
import org.autojs.autojs.util.RhinoUtils.UNDEFINED import org.autojs.autojs.util.RhinoUtils.UNDEFINED
import org.autojs.autojs.util.RhinoUtils.coerceBoolean import org.autojs.autojs.util.RhinoUtils.coerceBoolean
@@ -551,8 +552,7 @@ class App(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) {
val prefix = "http://".takeUnless { url.contains("://") } ?: "" val prefix = "http://".takeUnless { url.contains("://") } ?: ""
Intent(Intent.ACTION_VIEW) Intent(Intent.ACTION_VIEW)
.setData((prefix + url).toUri()) .setData((prefix + url).toUri())
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) .startSafely(globalContext)
.let { globalContext.startActivity(it) }
} }
@Suppress("HttpUrlsUsage") @Suppress("HttpUrlsUsage")
@@ -906,7 +906,7 @@ class App(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) {
} }
private fun startActivityWithGlobalContext(o: Intent) { private fun startActivityWithGlobalContext(o: Intent) {
globalContext.startActivity(o.apply { addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) }) o.startSafely(globalContext)
} }
private fun startActivityForDualUser(scriptRuntime: ScriptRuntime, o: Any?) { private fun startActivityForDualUser(scriptRuntime: ScriptRuntime, o: Any?) {

View File

@@ -5,6 +5,7 @@ import android.content.Intent
import android.provider.Settings import android.provider.Settings
import org.autojs.autojs.core.notification.NotificationListenerService import org.autojs.autojs.core.notification.NotificationListenerService
import org.autojs.autojs.ui.main.drawer.ServiceItemHelper import org.autojs.autojs.ui.main.drawer.ServiceItemHelper
import org.autojs.autojs.util.IntentUtils.startSafely
class NotificationService(override val context: Context) : ServiceItemHelper { class NotificationService(override val context: Context) : ServiceItemHelper {
@@ -16,7 +17,7 @@ class NotificationService(override val context: Context) : ServiceItemHelper {
override fun stop(): Boolean = false.also { config() } override fun stop(): Boolean = false.also { config() }
fun config() { fun config() {
context.startActivity(Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS)) Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS).startSafely(context)
} }
} }

View File

@@ -13,6 +13,7 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.autojs.autojs.app.DialogUtils.showAdaptive
import org.autojs.autojs.extension.MaterialDialogExtensions.makeTextCopyable import org.autojs.autojs.extension.MaterialDialogExtensions.makeTextCopyable
import org.autojs.autojs.extension.MaterialDialogExtensions.setCopyableText import org.autojs.autojs.extension.MaterialDialogExtensions.setCopyableText
import org.autojs.autojs.runtime.api.augment.colors.Colors import org.autojs.autojs.runtime.api.augment.colors.Colors
@@ -35,7 +36,7 @@ object ColorInfoDialogManager {
.content(R.string.error_invalid_color) .content(R.string.error_invalid_color)
.positiveText(R.string.dialog_button_dismiss) .positiveText(R.string.dialog_button_dismiss)
.positiveColorRes(R.color.dialog_button_default) .positiveColorRes(R.color.dialog_button_default)
.show() .showAdaptive()
return return
} }
val binding = ColorInfoDialogItemsBinding.inflate(LayoutInflater.from(context)) val binding = ColorInfoDialogItemsBinding.inflate(LayoutInflater.from(context))

View File

@@ -46,6 +46,7 @@ import org.autojs.autojs.theme.app.ColorLibrariesActivity.Companion.presetColorL
import org.autojs.autojs.ui.BaseActivity import org.autojs.autojs.ui.BaseActivity
import org.autojs.autojs.ui.main.drawer.DrawerFragment.Companion.Event.ThemeColorLayoutSwitchedEvent import org.autojs.autojs.ui.main.drawer.DrawerFragment.Companion.Event.ThemeColorLayoutSwitchedEvent
import org.autojs.autojs.util.ColorUtils import org.autojs.autojs.util.ColorUtils
import org.autojs.autojs.util.IntentUtils.startSafely
import org.autojs.autojs.util.ViewUtils import org.autojs.autojs.util.ViewUtils
import org.autojs.autojs.util.ViewUtils.onceGlobalLayout import org.autojs.autojs.util.ViewUtils.onceGlobalLayout
import org.autojs.autojs.util.ViewUtils.setColorsByColorLuminance import org.autojs.autojs.util.ViewUtils.setColorsByColorLuminance
@@ -523,8 +524,7 @@ abstract class ColorSelectBaseActivity : BaseActivity() {
protected fun showColorSearchHelp() { protected fun showColorSearchHelp() {
Intent(this, ColorSearchHelpActivity::class.java) Intent(this, ColorSearchHelpActivity::class.java)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) .startSafely(this)
.let { startActivity(it) }
} }
protected fun filterColorsFromColorItems(query: String?, colorItems: List<PresetColorItem>, colorItemAdapter: ColorItemAdapter) { protected fun filterColorsFromColorItems(query: String?, colorItems: List<PresetColorItem>, colorItemAdapter: ColorItemAdapter) {
@@ -659,7 +659,7 @@ abstract class ColorSelectBaseActivity : BaseActivity() {
intent.putExtra("currentColor", context.currentColor) intent.putExtra("currentColor", context.currentColor)
context.finish() context.finish()
} }
context.startActivity(intent) intent.startSafely(context)
} }
@JvmStatic @JvmStatic

View File

@@ -7,8 +7,10 @@ import android.os.Build
import android.provider.Settings import android.provider.Settings
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
import androidx.core.net.toUri import androidx.core.net.toUri
import org.autojs.autojs.app.DialogUtils.showAdaptive
import org.autojs.autojs.extension.MaterialDialogExtensions.widgetThemeColor import org.autojs.autojs.extension.MaterialDialogExtensions.widgetThemeColor
import org.autojs.autojs.ui.common.NotAskAgainDialog import org.autojs.autojs.ui.common.NotAskAgainDialog
import org.autojs.autojs.util.IntentUtils.startSafely
import org.autojs.autojs.util.StringUtils.key import org.autojs.autojs.util.StringUtils.key
import org.autojs.autojs.util.ViewUtils import org.autojs.autojs.util.ViewUtils
import org.autojs.autojs6.R import org.autojs.autojs6.R
@@ -26,7 +28,7 @@ object ExactAlarmPermissionHelper {
val intent = Intent() val intent = Intent()
.setAction(Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM) .setAction(Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM)
.setData("package:${context.packageName}".toUri()) .setData("package:${context.packageName}".toUri())
return runCatching { context.startActivity(intent) }.isSuccess return runCatching { intent.startSafely(context) }.isSuccess
} }
// Check canScheduleExactAlarms permission and prompt user if needed. // Check canScheduleExactAlarms permission and prompt user if needed.
@@ -57,7 +59,7 @@ object ExactAlarmPermissionHelper {
} }
.cancelable(false) .cancelable(false)
.autoDismiss(false) .autoDismiss(false)
.show() .showAdaptive()
} }
} }

View File

@@ -6,6 +6,7 @@ import android.util.Log
import org.autojs.autojs.app.GlobalAppContext import org.autojs.autojs.app.GlobalAppContext
import org.autojs.autojs.core.accessibility.AccessibilityService import org.autojs.autojs.core.accessibility.AccessibilityService
import org.autojs.autojs.runtime.ScriptRuntime import org.autojs.autojs.runtime.ScriptRuntime
import org.autojs.autojs.util.IntentUtils.startSafely
import java.lang.Thread.UncaughtExceptionHandler import java.lang.Thread.UncaughtExceptionHandler
import java.lang.ref.WeakReference import java.lang.ref.WeakReference
import kotlin.system.exitProcess import kotlin.system.exitProcess
@@ -48,11 +49,12 @@ class CrashHandler(private val errorReportClass: Class<*>) : UncaughtExceptionHa
} }
private fun startCrashReportActivity(msg: String, detail: String) { private fun startCrashReportActivity(msg: String, detail: String) {
Intent(GlobalAppContext.get(), errorReportClass).apply { val context = GlobalAppContext.get()
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_SINGLE_TOP) Intent(context, errorReportClass).apply {
addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
putExtra("message", msg) putExtra("message", msg)
putExtra("error", detail) putExtra("error", detail)
}.let { GlobalAppContext.get().startActivity(it) } }.startSafely(context)
} }
companion object { companion object {

View File

@@ -66,7 +66,7 @@ public class ScriptLoopDialog {
} }
public void show() { public void show() {
DialogUtils.showDialog(mDialog); DialogUtils.showAdaptive(mDialog);
} }
} }

View File

@@ -43,6 +43,7 @@ import org.autojs.autojs.ui.filechooser.FileChooserDialogBuilder;
import org.autojs.autojs.ui.shortcut.ShortcutCreateActivity; import org.autojs.autojs.ui.shortcut.ShortcutCreateActivity;
import org.autojs.autojs.ui.timing.TimedTaskSettingActivity; import org.autojs.autojs.ui.timing.TimedTaskSettingActivity;
import org.autojs.autojs.util.EnvironmentUtils; import org.autojs.autojs.util.EnvironmentUtils;
import org.autojs.autojs.util.IntentUtils;
import org.autojs.autojs.util.ShortcutUtils; import org.autojs.autojs.util.ShortcutUtils;
import org.autojs.autojs.util.ViewUtils; import org.autojs.autojs.util.ViewUtils;
import org.autojs.autojs.util.WorkingDirectoryUtils; import org.autojs.autojs.util.WorkingDirectoryUtils;
@@ -61,7 +62,6 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import static org.autojs.autojs.app.DialogUtils.fixCheckBoxGravity; import static org.autojs.autojs.app.DialogUtils.fixCheckBoxGravity;
import static org.autojs.autojs.app.DialogUtils.showDialog;
import static org.autojs.autojs.util.FileUtils.TYPE.JAVASCRIPT; import static org.autojs.autojs.util.FileUtils.TYPE.JAVASCRIPT;
import static org.autojs.autojs.util.RhinoUtils.isMainThread; import static org.autojs.autojs.util.RhinoUtils.isMainThread;
@@ -198,14 +198,14 @@ public class ScriptOperations {
.negativeText(R.string.dialog_button_back); .negativeText(R.string.dialog_button_back);
MaterialDialogExtensions.choiceWidgetThemeColor(builderDefaultPrefix); MaterialDialogExtensions.choiceWidgetThemeColor(builderDefaultPrefix);
MaterialDialog dialogDefaultPrefix = builderDefaultPrefix.build(); MaterialDialog dialogDefaultPrefix = builderDefaultPrefix.build();
showDialog(dialogDefaultPrefix); DialogUtils.showAdaptive(dialogDefaultPrefix);
}) })
.autoDismiss(false); .autoDismiss(false);
MaterialDialogExtensions.widgetThemeColor(builder); MaterialDialogExtensions.widgetThemeColor(builder);
MaterialDialog dialog = builder.build(); MaterialDialog dialog = builder.build();
dialogRef.set(dialog); dialogRef.set(dialog);
showDialog(fixCheckBoxGravity(dialog)); DialogUtils.showAdaptive(fixCheckBoxGravity(dialog));
} }
private String getNewFileNamePresetPrefill(CharSequence prefix) { private String getNewFileNamePresetPrefill(CharSequence prefix) {
@@ -339,7 +339,7 @@ public class ScriptOperations {
}) })
.canceledOnTouchOutside(false); .canceledOnTouchOutside(false);
MaterialDialogExtensions.widgetThemeColor(builder); MaterialDialogExtensions.widgetThemeColor(builder);
showDialog(builder.build()); DialogUtils.showAdaptive(builder.build());
return input; return input;
} }
@@ -384,13 +384,12 @@ public class ScriptOperations {
return; return;
} }
Intent intent = new Intent(mContext, ShortcutCreateActivity.class) Intent intent = new Intent(mContext, ShortcutCreateActivity.class)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.putExtra(ShortcutCreateActivity.EXTRA_FILE, file); .putExtra(ShortcutCreateActivity.EXTRA_FILE, file);
mContext.startActivity(intent); IntentUtils.startSafely(intent, mContext);
} }
public void delete(final ScriptFile scriptFile) { public void delete(final ScriptFile scriptFile) {
DialogUtils.showDialog(new MaterialDialog.Builder(mContext) DialogUtils.showAdaptive(new MaterialDialog.Builder(mContext)
.title(mContext.getString(R.string.text_confirm_to_delete)) .title(mContext.getString(R.string.text_confirm_to_delete))
.content(scriptFile.getName()) .content(scriptFile.getName())
.negativeText(R.string.text_cancel) .negativeText(R.string.text_cancel)
@@ -409,7 +408,7 @@ public class ScriptOperations {
} }
String content = mContext.getString(R.string.text_old_path) + ": " + oldPath + "\n" String content = mContext.getString(R.string.text_old_path) + ": " + oldPath + "\n"
+ mContext.getString(R.string.text_new_path) + ": " + newPath; + mContext.getString(R.string.text_new_path) + ": " + newPath;
DialogUtils.showDialog(new MaterialDialog.Builder(mContext) DialogUtils.showAdaptive(new MaterialDialog.Builder(mContext)
.title(mContext.getString(R.string.text_prompt)) .title(mContext.getString(R.string.text_prompt))
.content(content) .content(content)
.negativeText(R.string.text_cancel) .negativeText(R.string.text_cancel)
@@ -489,7 +488,7 @@ public class ScriptOperations {
} }
public void importFile() { public void importFile() {
DialogUtils.showDialog(new FileChooserDialogBuilder(mContext) DialogUtils.showAdaptive(new FileChooserDialogBuilder(mContext)
.dir(EnvironmentUtils.getExternalStoragePath()) .dir(EnvironmentUtils.getExternalStoragePath())
.justScriptFile() .justScriptFile()
.singleChoice(file -> importFile(file.getPath()).subscribe()) .singleChoice(file -> importFile(file.getPath()).subscribe())
@@ -502,7 +501,7 @@ public class ScriptOperations {
public void timedTask(ScriptFile scriptFile) { public void timedTask(ScriptFile scriptFile) {
Intent intent = new Intent(mContext, TimedTaskSettingActivity.class) Intent intent = new Intent(mContext, TimedTaskSettingActivity.class)
.putExtra(ScriptIntents.EXTRA_KEY_PATH, scriptFile.getPath()); .putExtra(ScriptIntents.EXTRA_KEY_PATH, scriptFile.getPath());
mContext.startActivity(intent); IntentUtils.startSafely(intent, mContext);
} }
private class InputCallback implements MaterialDialog.InputCallback { private class InputCallback implements MaterialDialog.InputCallback {

View File

@@ -10,6 +10,7 @@ import android.view.View
import android.widget.TextView import android.widget.TextView
import com.afollestad.materialdialogs.MaterialDialog import com.afollestad.materialdialogs.MaterialDialog
import org.autojs.autojs.ui.widget.EWebView import org.autojs.autojs.ui.widget.EWebView
import org.autojs.autojs.util.IntentUtils.startSafely
import org.autojs.autojs6.databinding.FloatingManualDialogBinding import org.autojs.autojs6.databinding.FloatingManualDialogBinding
/** /**
@@ -62,7 +63,7 @@ class ManualDialog(private val mContext: Context) {
mDialog.dismiss() mDialog.dismiss()
Intent(mContext, DocumentationActivity::class.java) Intent(mContext, DocumentationActivity::class.java)
.putExtra(DocumentationActivity.EXTRA_URL, mEWebView.webView.url) .putExtra(DocumentationActivity.EXTRA_URL, mEWebView.webView.url)
.let { mContext.startActivity(it) } .startSafely(mContext)
} }
} }

View File

@@ -16,6 +16,8 @@ import android.view.ActionMode
import android.view.Menu import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import android.widget.TextView import android.widget.TextView
import androidx.core.view.get
import androidx.core.view.size
import com.afollestad.materialdialogs.MaterialDialog import com.afollestad.materialdialogs.MaterialDialog
import io.reactivex.Observable import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.android.schedulers.AndroidSchedulers
@@ -33,6 +35,7 @@ import org.autojs.autojs.theme.widget.ThemeColorToolbar
import org.autojs.autojs.ui.BaseActivity import org.autojs.autojs.ui.BaseActivity
import org.autojs.autojs.ui.main.MainActivity import org.autojs.autojs.ui.main.MainActivity
import org.autojs.autojs.ui.main.scripts.EditableFileInfoDialogManager import org.autojs.autojs.ui.main.scripts.EditableFileInfoDialogManager
import org.autojs.autojs.util.IntentUtils.startSafely
import org.autojs.autojs.util.Observers import org.autojs.autojs.util.Observers
import org.autojs.autojs.util.ViewUtils.onceGlobalLayout import org.autojs.autojs.util.ViewUtils.onceGlobalLayout
import org.autojs.autojs.util.ViewUtils.setMenuIconsColorByThemeColorLuminance import org.autojs.autojs.util.ViewUtils.setMenuIconsColorByThemeColorLuminance
@@ -40,8 +43,6 @@ import org.autojs.autojs6.R
import org.autojs.autojs6.databinding.ActivityEditBinding import org.autojs.autojs6.databinding.ActivityEditBinding
import java.io.File import java.io.File
import java.io.IOException import java.io.IOException
import androidx.core.view.get
import androidx.core.view.size
/** /**
* Created by Stardust on Jan 29, 2017. * Created by Stardust on Jan 29, 2017.
@@ -364,50 +365,46 @@ open class EditActivity : BaseActivity(), DelegateHost, PermissionRequestProxyAc
private const val LOG_TAG = "EditActivity" private const val LOG_TAG = "EditActivity"
@JvmStatic @JvmStatic
fun editFile(context: Context, path: String?, newTask: Boolean) { fun editFile(context: Context, path: String?, newTask: Boolean) =
editFile(context, null, path, newTask) editFile(context, null, path, newTask)
}
@JvmStatic @JvmStatic
fun editFile(context: Context, uri: Uri?, newTask: Boolean) { fun editFile(context: Context, uri: Uri?, newTask: Boolean) =
runCatching { when {
context.startActivity(newIntent(context).setData(uri)) newIntent(context).setData(uri).startSafely(context) -> true
}.getOrElse { newIntentFallback(context, newTask).setData(uri).startSafely(context) -> true
context.startActivity(newIntentFallback(context, newTask).setData(uri)) else -> false
} }
}
@JvmStatic @JvmStatic
fun editFile(context: Context, name: String?, path: String?, newTask: Boolean) { fun editFile(context: Context, name: String?, path: String?, newTask: Boolean) =
runCatching { when {
context.startActivity(newIntent(context).apply { newIntent(context).apply {
putExtra(EditorView.EXTRA_PATH, path) putExtra(EditorView.EXTRA_PATH, path)
putExtra(EditorView.EXTRA_NAME, name) putExtra(EditorView.EXTRA_NAME, name)
}) }.startSafely(context) -> true
}.getOrElse { newIntentFallback(context, newTask).apply {
context.startActivity(newIntentFallback(context, newTask).apply {
putExtra(EditorView.EXTRA_PATH, path) putExtra(EditorView.EXTRA_PATH, path)
putExtra(EditorView.EXTRA_NAME, name) putExtra(EditorView.EXTRA_NAME, name)
}) }.startSafely(context) -> true
else -> false
} }
}
@JvmStatic @JvmStatic
fun viewContent(context: Context, name: String?, content: String?, newTask: Boolean) { fun viewContent(context: Context, name: String?, content: String?, newTask: Boolean) =
runCatching { when {
context.startActivity(newIntent(context).apply { newIntent(context).apply {
putExtra(EditorView.EXTRA_CONTENT, content) putExtra(EditorView.EXTRA_CONTENT, content)
putExtra(EditorView.EXTRA_NAME, name) putExtra(EditorView.EXTRA_NAME, name)
putExtra(EditorView.EXTRA_READ_ONLY, true) putExtra(EditorView.EXTRA_READ_ONLY, true)
}) }.startSafely(context) -> true
}.getOrElse { newIntentFallback(context, newTask).apply {
context.startActivity(newIntentFallback(context, newTask).apply {
putExtra(EditorView.EXTRA_CONTENT, content) putExtra(EditorView.EXTRA_CONTENT, content)
putExtra(EditorView.EXTRA_NAME, name) putExtra(EditorView.EXTRA_NAME, name)
putExtra(EditorView.EXTRA_READ_ONLY, true) putExtra(EditorView.EXTRA_READ_ONLY, true)
}) }.startSafely(context) -> true
else -> false
} }
}
private fun newIntent(context: Context): Intent { private fun newIntent(context: Context): Intent {
// @Caution by SuperMonster003 on Sep 11, 2022. // @Caution by SuperMonster003 on Sep 11, 2022.

View File

@@ -22,9 +22,9 @@ public class FloatingWindowPermissionUtil {
public static void goToFloatingWindowPermissionSetting(Context context) { public static void goToFloatingWindowPermissionSetting(Context context) {
String packageName = context.getPackageName(); String packageName = context.getPackageName();
try { try {
context.startActivity(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + packageName)) Uri.parse("package:" + packageName));
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); IntentUtils.start(intent, context);
} catch (Exception e) { } catch (Exception e) {
IntentUtils.launchAppDetailsSettings(context, packageName); IntentUtils.launchAppDetailsSettings(context, packageName);
} }

View File

@@ -7,6 +7,7 @@ import org.autojs.autojs.runtime.api.augment.util.VersionCodesInfo.briefOfCurren
import org.autojs.autojs.ui.BaseActivity import org.autojs.autojs.ui.BaseActivity
import org.autojs.autojs.ui.main.MainActivity import org.autojs.autojs.ui.main.MainActivity
import org.autojs.autojs.util.ClipboardUtils import org.autojs.autojs.util.ClipboardUtils
import org.autojs.autojs.util.IntentUtils.startSafely
import org.autojs.autojs.util.ViewUtils import org.autojs.autojs.util.ViewUtils
import org.autojs.autojs6.BuildConfig import org.autojs.autojs6.BuildConfig
import org.autojs.autojs6.R import org.autojs.autojs6.R
@@ -70,9 +71,9 @@ class CrashReportActivity : BaseActivity() {
val intent = packageManager.getLaunchIntentForPackage(packageName)?.apply { val intent = packageManager.getLaunchIntentForPackage(packageName)?.apply {
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
} ?: Intent(this, MainActivity::class.java).apply { } ?: Intent(this, MainActivity::class.java).apply {
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK) addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
} }
startActivity(intent) intent.startSafely(this)
exit() exit()
} }

View File

@@ -7,6 +7,7 @@ import com.afollestad.materialdialogs.MaterialDialog;
import org.autojs.autojs.extension.MaterialDialogExtensions; import org.autojs.autojs.extension.MaterialDialogExtensions;
import org.autojs.autojs.ui.BaseActivity; import org.autojs.autojs.ui.BaseActivity;
import org.autojs.autojs.util.ClipboardUtils; import org.autojs.autojs.util.ClipboardUtils;
import org.autojs.autojs.util.IntentUtils;
import org.autojs.autojs.util.ViewUtils; import org.autojs.autojs.util.ViewUtils;
import org.autojs.autojs6.R; import org.autojs.autojs6.R;
@@ -75,8 +76,7 @@ public class ErrorDialogActivity extends BaseActivity {
Intent intent = new Intent(context, ErrorDialogActivity.class); Intent intent = new Intent(context, ErrorDialogActivity.class);
intent.putExtra(EXTRA_TITLE, context.getString(titleRes)); intent.putExtra(EXTRA_TITLE, context.getString(titleRes));
intent.putExtra(EXTRA_MESSAGE, message); intent.putExtra(EXTRA_MESSAGE, message);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); IntentUtils.startSafely(intent, context);
context.startActivity(intent);
} }
/** /**
@@ -88,8 +88,7 @@ public class ErrorDialogActivity extends BaseActivity {
intent.putExtra(EXTRA_TITLE, context.getString(titleRes)); intent.putExtra(EXTRA_TITLE, context.getString(titleRes));
intent.putExtra(EXTRA_MESSAGE, message); intent.putExtra(EXTRA_MESSAGE, message);
intent.putExtra(EXTRA_POSITIVE_BUTTON_TEXT, context.getString(positiveButtonTextRes)); intent.putExtra(EXTRA_POSITIVE_BUTTON_TEXT, context.getString(positiveButtonTextRes));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); IntentUtils.startSafely(intent, context);
context.startActivity(intent);
} }
} }

View File

@@ -21,6 +21,7 @@ import org.autojs.autojs.project.ProjectConfig;
import org.autojs.autojs.project.ProjectLauncher; import org.autojs.autojs.project.ProjectLauncher;
import org.autojs.autojs.ui.project.BuildActivity; import org.autojs.autojs.ui.project.BuildActivity;
import org.autojs.autojs.ui.project.ProjectConfigActivity; import org.autojs.autojs.ui.project.ProjectConfigActivity;
import org.autojs.autojs.util.IntentUtils;
import org.autojs.autojs6.R; import org.autojs.autojs6.R;
import org.autojs.autojs6.databinding.ExplorerProjectToolbarBinding; import org.autojs.autojs6.databinding.ExplorerProjectToolbarBinding;
import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.Subscribe;
@@ -148,9 +149,8 @@ public class ExplorerProjectToolbar extends CardView {
void edit() { void edit() {
Intent intent = new Intent(getContext(), ProjectConfigActivity.class) Intent intent = new Intent(getContext(), ProjectConfigActivity.class)
.putExtra(ProjectConfigActivity.EXTRA_DIRECTORY, mDirectory.getPath()) .putExtra(ProjectConfigActivity.EXTRA_DIRECTORY, mDirectory.getPath());
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); IntentUtils.startSafely(intent, getContext());
getContext().startActivity(intent);
} }
public void setRunnableOnly(boolean b) { public void setRunnableOnly(boolean b) {

View File

@@ -81,8 +81,9 @@ import java.util.concurrent.Callable
/** /**
* Created by Stardust on Aug 21, 2017. * Created by Stardust on Aug 21, 2017.
* Modified by SuperMonster003 as of Apr 1, 2023.
* Transformed by SuperMonster003 on Nov 23, 2024. * Transformed by SuperMonster003 on Nov 23, 2024.
* Modified by JetBrains AI Assistant (GPT-5.2) as of Apr 20, 2026.
* Modified by SuperMonster003 as of Apr 20, 2026.
*/ */
@SuppressLint("CheckResult", "NonConstantResourceId", "NotifyDataSetChanged") @SuppressLint("CheckResult", "NonConstantResourceId", "NotifyDataSetChanged")
open class ExplorerView : ThemeColorSwipeRefreshLayout, SwipeRefreshLayout.OnRefreshListener, PopupMenu.OnMenuItemClickListener { open class ExplorerView : ThemeColorSwipeRefreshLayout, SwipeRefreshLayout.OnRefreshListener, PopupMenu.OnMenuItemClickListener {
@@ -134,6 +135,11 @@ open class ExplorerView : ThemeColorSwipeRefreshLayout, SwipeRefreshLayout.OnRef
ColorStateList.valueOf(context.getColor(R.color.explorer_file_operation_button)) ColorStateList.valueOf(context.getColor(R.color.explorer_file_operation_button))
} }
// Request host dialog to hide/show without losing state.
// zh-CN: 请求宿主对话框隐藏/显示且不丢失状态.
private var mRequestHostDialogHide: Runnable? = null
private var mRequestHostDialogShow: Runnable? = null
constructor(context: Context) : super(context) { constructor(context: Context) : super(context) {
init(context) init(context)
} }
@@ -142,6 +148,18 @@ open class ExplorerView : ThemeColorSwipeRefreshLayout, SwipeRefreshLayout.OnRef
init(context) init(context)
} }
// Set hide callback from Java callers (e.g. CircularMenu).
// zh-CN: 提供给 Java 调用方 (例如 CircularMenu) 设置 hide 回调.
fun setRequestHostDialogHide(runnable: Runnable?) {
mRequestHostDialogHide = runnable
}
// Set show callback from Java callers (e.g. CircularMenu).
// zh-CN: 提供给 Java 调用方 (例如 CircularMenu) 设置 show 回调.
fun setRequestHostDialogShow(runnable: Runnable?) {
mRequestHostDialogShow = runnable
}
private fun init(context: Context) { private fun init(context: Context) {
ExplorerViewBinding.inflate(LayoutInflater.from(context), this, true).also { binding -> ExplorerViewBinding.inflate(LayoutInflater.from(context), this, true).also { binding ->
this.binding = binding this.binding = binding
@@ -248,6 +266,7 @@ open class ExplorerView : ThemeColorSwipeRefreshLayout, SwipeRefreshLayout.OnRef
R.id.create_shortcut -> { R.id.create_shortcut -> {
ScriptOperations(context, this@ExplorerView, currentPage) ScriptOperations(context, this@ExplorerView, currentPage)
.createShortcut(selectedItem!!.toScriptFile()) .createShortcut(selectedItem!!.toScriptFile())
mRequestHostDialogHide?.run()
} }
R.id.open_by_other_apps -> { R.id.open_by_other_apps -> {
Scripts.openByOtherApps(selectedItem!!.toScriptFile()) Scripts.openByOtherApps(selectedItem!!.toScriptFile())
@@ -256,15 +275,18 @@ open class ExplorerView : ThemeColorSwipeRefreshLayout, SwipeRefreshLayout.OnRef
R.id.send -> { R.id.send -> {
Scripts.send(context, selectedItem!!.toScriptFile()) Scripts.send(context, selectedItem!!.toScriptFile())
notifyItemOperated() notifyItemOperated()
mRequestHostDialogHide?.run()
} }
R.id.timed_task -> { R.id.timed_task -> {
ScriptOperations(context, this@ExplorerView, currentPage) ScriptOperations(context, this@ExplorerView, currentPage)
.timedTask(selectedItem!!.toScriptFile()) .timedTask(selectedItem!!.toScriptFile())
notifyItemOperated() notifyItemOperated()
mRequestHostDialogHide?.run()
} }
R.id.action_build_apk -> { R.id.action_build_apk -> {
BuildActivity.launch(context, selectedItem!!.path) BuildActivity.launch(context, selectedItem!!.path)
notifyItemOperated() notifyItemOperated()
mRequestHostDialogHide?.run()
} }
R.id.reset -> { R.id.reset -> {
val o = Explorers.Providers.workspace() val o = Explorers.Providers.workspace()
@@ -844,6 +866,7 @@ open class ExplorerView : ThemeColorSwipeRefreshLayout, SwipeRefreshLayout.OnRef
} }
private fun run() { private fun run() {
mRequestHostDialogHide?.run()
when { when {
mExplorerItem.isExecutable -> { mExplorerItem.isExecutable -> {
Scripts.run(context, ScriptFile(mExplorerItem.path)) Scripts.run(context, ScriptFile(mExplorerItem.path))
@@ -857,6 +880,8 @@ open class ExplorerView : ThemeColorSwipeRefreshLayout, SwipeRefreshLayout.OnRef
} }
private fun edit() { private fun edit() {
mRequestHostDialogHide?.run()
when { when {
mExplorerItem.isTextEditable -> { mExplorerItem.isTextEditable -> {
Scripts.edit(context, ScriptFile(mExplorerItem.path)) Scripts.edit(context, ScriptFile(mExplorerItem.path))
@@ -870,19 +895,32 @@ open class ExplorerView : ThemeColorSwipeRefreshLayout, SwipeRefreshLayout.OnRef
} }
private fun showInfo() { private fun showInfo() {
// Hide host overlay dialog so the info dialog can be shown on top.
// zh-CN: 隐藏宿主 overlay 对话框, 让信息对话框显示在最上层.
mRequestHostDialogHide?.run()
when { when {
mExplorerItem.isInstallable -> { mExplorerItem.isInstallable -> {
ApkInfoDialogManager.showApkInfoDialog(context, mExplorerItem.toScriptFile()) ApkInfoDialogManager.showApkInfoDialog(context, mExplorerItem.toScriptFile(), null) {
// Restore host dialog after the info dialog is dismissed.
// zh-CN: 信息对话框关闭后恢复宿主对话框.
mRequestHostDialogShow?.run()
}
notifyItemOperated() notifyItemOperated()
} }
mExplorerItem.isMediaMenu || mExplorerItem.isMediaPlayable -> { mExplorerItem.isMediaMenu || mExplorerItem.isMediaPlayable -> {
MediaInfoDialogManager.showMediaInfoDialog(context, mExplorerItem) MediaInfoDialogManager.showMediaInfoDialog(context, mExplorerItem, null) {
// Restore host dialog after the info dialog is dismissed.
// zh-CN: 信息对话框关闭后恢复宿主对话框.
mRequestHostDialogShow?.run()
}
notifyItemOperated() notifyItemOperated()
} }
} }
} }
private fun install() { private fun install() {
mRequestHostDialogHide?.run()
when { when {
mExplorerItem.isInstallable -> { mExplorerItem.isInstallable -> {
mExplorerItem.install(this@ExplorerView) mExplorerItem.install(this@ExplorerView)
@@ -1001,6 +1039,7 @@ open class ExplorerView : ThemeColorSwipeRefreshLayout, SwipeRefreshLayout.OnRef
.setAsWorkingDir(selectedItem!!.toScriptFile()) .setAsWorkingDir(selectedItem!!.toScriptFile())
} }
R.id.action_build_apk -> { R.id.action_build_apk -> {
mRequestHostDialogHide?.run()
BuildActivity.launch(context, selectedItem!!.path) BuildActivity.launch(context, selectedItem!!.path)
} }
R.id.reset -> { R.id.reset -> {

View File

@@ -50,6 +50,8 @@ import java.text.MessageFormat;
/** /**
* Created by Stardust on Oct 18, 2017. * Created by Stardust on Oct 18, 2017.
* Modified by JetBrains AI Assistant (GPT-5.2) as of Jan 20, 2026.
* Modified by SuperMonster003 as of Jan 20, 2026.
*/ */
public class CircularMenu implements LayoutInspector.CaptureAvailableListener { public class CircularMenu implements LayoutInspector.CaptureAvailableListener {
@@ -70,6 +72,8 @@ public class CircularMenu implements LayoutInspector.CaptureAvailableListener {
private final Recorder.OnStateChangedListener mRecorderStateListener; private final Recorder.OnStateChangedListener mRecorderStateListener;
private CircularActionMenuBinding binding; private CircularActionMenuBinding binding;
private MaterialDialog mSettingsDialog; private MaterialDialog mSettingsDialog;
private MaterialDialog mScriptListDialog;
private ExplorerView mScriptListDialogExplorerView;
private MaterialDialog mLayoutInspectDialog; private MaterialDialog mLayoutInspectDialog;
private String mRunningPackage; private String mRunningPackage;
private String mRunningActivity; private String mRunningActivity;
@@ -135,53 +139,82 @@ public class CircularMenu implements LayoutInspector.CaptureAvailableListener {
private void setupBindingListeners() { private void setupBindingListeners() {
binding.scriptList.setOnClickListener(v -> { binding.scriptList.setOnClickListener(v -> {
mWindow.collapse(); mWindow.collapse();
ExplorerView explorerView = new ExplorerView(mContext);
explorerView.setExplorer(Explorers.workspace(), ExplorerDirPage.createRoot(WorkingDirectoryUtils.getPath()));
explorerView.setDirectorySpanSize(2);
final MaterialDialog dialog = new MaterialDialog.Builder(mContext)
.title(R.string.text_run_script)
.titleColorRes(R.color.day_night)
.customView(explorerView, false)
.backgroundColorRes(R.color.window_background)
.positiveText(R.string.dialog_button_dismiss)
.positiveColorRes(R.color.dialog_button_default)
.cancelable(false)
.build();
// Only dismiss on clicking the item itself. if (mScriptListDialog == null) {
// zh-CN: 仅在点击条目本体时关闭对话框.
explorerView.setOnItemClickListener((view, item) -> {
if (item.isExecutable()) {
dialog.dismiss();
Scripts.run(view != null ? view.getContext() : explorerView.getContext(), item.toScriptFile());
} else {
DialogUtils.showDialog(new MaterialDialog.Builder(mContext)
.title(mContext.getString(R.string.error_failed_to_run_script))
.content(mContext.getString(
R.string.text_file_with_abs_path_is_not_an_executable_script,
item.toScriptFile().getAbsolutePath()
))
.positiveText(R.string.dialog_button_dismiss)
.positiveColorRes(R.color.dialog_button_failure)
.build());
}
});
// Do not dismiss on action buttons (run/edit/delete/rename/etc.). mScriptListDialogExplorerView = new ExplorerView(mContext);
// zh-CN: 点击右侧操作按钮 (运行/编辑/删除/重命名等) 时不关闭对话框. mScriptListDialogExplorerView.setExplorer(Explorers.workspace(), ExplorerDirPage.createRoot(WorkingDirectoryUtils.getPath()));
explorerView.setOnItemOperateListener(null); mScriptListDialogExplorerView.setDirectorySpanSize(2);
explorerView.setOnProjectToolbarOperateListener(toolbar -> dialog.dismiss()); mScriptListDialog = new MaterialDialog.Builder(mContext)
explorerView.setOnProjectToolbarClickListener(toolbar -> toolbar.findViewById(R.id.project_run).performClick()); .title(R.string.text_run_script)
explorerView.setProjectToolbarRunnableOnly(true); .titleColorRes(R.color.day_night)
.customView(mScriptListDialogExplorerView, false)
.backgroundColorRes(R.color.window_background)
.neutralText(R.string.dialog_button_minimize)
.neutralColorRes(R.color.dialog_button_reset)
.onNeutral((dialog, which) -> {
mScriptListDialog.hide();
})
.positiveText(R.string.dialog_button_dismiss)
.positiveColorRes(R.color.dialog_button_default)
.onPositive((dialog, which) -> {
dialog.dismiss();
mScriptListDialog = null;
mScriptListDialogExplorerView = null;
})
.cancelable(false)
.autoDismiss(false)
.build();
DialogUtils.adaptToExplorer(dialog, explorerView); var scriptListDialog = mScriptListDialog;
DialogUtils.showDialog(dialog);
// Hide host dialog before launching Activity or showing secondary dialogs.
// zh-CN: 在启动 Activity 或显示二级对话框之前隐藏宿主对话框.
mScriptListDialogExplorerView.setRequestHostDialogHide(scriptListDialog::hide);
// Restore host dialog (overlay) when needed, keeping state.
// zh-CN: 需要时恢复宿主对话框 (overlay), 并保留状态.
mScriptListDialogExplorerView.setRequestHostDialogShow(() -> {
if (!scriptListDialog.isShowing()) {
DialogUtils.showDialog(scriptListDialog);
}
});
// Only dismiss on clicking the item itself.
// zh-CN: 仅在点击条目本体时关闭对话框.
mScriptListDialogExplorerView.setOnItemClickListener((view, item) -> {
if (item.isExecutable()) {
scriptListDialog.hide();
Scripts.run(view != null ? view.getContext() : mScriptListDialogExplorerView.getContext(), item.toScriptFile());
} else {
DialogUtils.showAdaptive(new MaterialDialog.Builder(mContext)
.title(mContext.getString(R.string.error_failed_to_run_script))
.content(mContext.getString(
R.string.text_file_with_abs_path_is_not_an_executable_script,
item.toScriptFile().getAbsolutePath()
))
.positiveText(R.string.dialog_button_dismiss)
.positiveColorRes(R.color.dialog_button_failure)
.build());
}
});
mScriptListDialogExplorerView.setOnItemOperateListener(null);
mScriptListDialogExplorerView.setOnProjectToolbarOperateListener(toolbar -> scriptListDialog.hide());
mScriptListDialogExplorerView.setOnProjectToolbarClickListener(toolbar -> toolbar.findViewById(R.id.project_run).performClick());
mScriptListDialogExplorerView.setProjectToolbarRunnableOnly(true);
DialogUtils.adaptToExplorer(scriptListDialog, mScriptListDialogExplorerView);
}
DialogUtils.showAdaptive(mScriptListDialog);
}); });
binding.record.setOnClickListener(v -> { binding.record.setOnClickListener(v -> {
mWindow.collapse(); mWindow.collapse();
if (!RootUtils.isRootAvailable()) { if (!RootUtils.isRootAvailable()) {
DialogUtils.showDialog(new AppLevelThemeDialogBuilder(mContext) DialogUtils.showAdaptive(new AppLevelThemeDialogBuilder(mContext)
.title(mContext.getString(R.string.text_no_root_access)) .title(mContext.getString(R.string.text_no_root_access))
.content(mContext.getString(R.string.no_root_access_for_record)) .content(mContext.getString(R.string.no_root_access_for_record))
.positiveText(R.string.dialog_button_abandon) .positiveText(R.string.dialog_button_abandon)
@@ -199,7 +232,7 @@ public class CircularMenu implements LayoutInspector.CaptureAvailableListener {
.item(R.drawable.ic_circular_menu_hierarchy, mContext.getString(R.string.text_inspect_layout_hierarchy), mCollapseWindowAndInspectLayoutHierarchyListener) .item(R.drawable.ic_circular_menu_hierarchy, mContext.getString(R.string.text_inspect_layout_hierarchy), mCollapseWindowAndInspectLayoutHierarchyListener)
.title(mContext.getString(R.string.text_inspect_layout)) .title(mContext.getString(R.string.text_inspect_layout))
.build(); .build();
DialogUtils.showDialog(mLayoutInspectDialog); DialogUtils.showAdaptive(mLayoutInspectDialog);
return true; return true;
}); });
binding.stopAllScripts.setOnClickListener(v -> { binding.stopAllScripts.setOnClickListener(v -> {
@@ -248,7 +281,7 @@ public class CircularMenu implements LayoutInspector.CaptureAvailableListener {
.title(mContext.getString(R.string.text_more)) .title(mContext.getString(R.string.text_more))
.build(); .build();
DialogUtils.showDialog(mSettingsDialog); DialogUtils.showAdaptive(mSettingsDialog);
}); });
} }
@@ -276,6 +309,7 @@ public class CircularMenu implements LayoutInspector.CaptureAvailableListener {
private View.OnClickListener onCircularMenuItemClick(View.OnClickListener listener) { private View.OnClickListener onCircularMenuItemClick(View.OnClickListener listener) {
return v -> { return v -> {
dismissSettingsDialog(); dismissSettingsDialog();
dismissScriptListDialog();
listener.onClick(v); listener.onClick(v);
}; };
} }
@@ -392,6 +426,16 @@ public class CircularMenu implements LayoutInspector.CaptureAvailableListener {
} }
} }
private void dismissScriptListDialog() {
if (mScriptListDialog != null) {
mScriptListDialog.dismiss();
mScriptListDialog = null;
}
if (mScriptListDialogExplorerView != null) {
mScriptListDialogExplorerView = null;
}
}
@NonNull @NonNull
private String getTextAlreadyCopied(int actionResId) { private String getTextAlreadyCopied(int actionResId) {
return MessageFormat.format("{0} ({1})", return MessageFormat.format("{0} ({1})",
@@ -401,6 +445,7 @@ public class CircularMenu implements LayoutInspector.CaptureAvailableListener {
public void close() { public void close() {
dismissSettingsDialog(); dismissSettingsDialog();
dismissScriptListDialog();
try { try {
mWindow.close(); mWindow.close();
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {

View File

@@ -86,7 +86,7 @@ public class CodeGenerateDialog extends AppLevelThemeDialogBuilder {
String code = generateCode(); String code = generateCode();
AppLevelThemeDialogBuilder builder = new AppLevelThemeDialogBuilder(context); AppLevelThemeDialogBuilder builder = new AppLevelThemeDialogBuilder(context);
if (code != null) { if (code != null) {
DialogUtils.showDialog(builder DialogUtils.showAdaptive(builder
.title(R.string.text_generated_code) .title(R.string.text_generated_code)
.content(code) .content(code)
.negativeText(R.string.dialog_button_cancel) .negativeText(R.string.dialog_button_cancel)
@@ -99,7 +99,7 @@ public class CodeGenerateDialog extends AppLevelThemeDialogBuilder {
})) }))
.build()); .build());
} else { } else {
DialogUtils.showDialog(builder DialogUtils.showAdaptive(builder
.title(R.string.text_prompt) .title(R.string.text_prompt)
.content(R.string.text_failed_to_generate) .content(R.string.text_failed_to_generate)
.positiveText(R.string.dialog_button_dismiss) .positiveText(R.string.dialog_button_dismiss)

View File

@@ -5,7 +5,7 @@ import android.view.ContextThemeWrapper
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import org.autojs.autojs.app.AppLevelThemeDialogBuilder import org.autojs.autojs.app.AppLevelThemeDialogBuilder
import org.autojs.autojs.app.DialogUtils import org.autojs.autojs.app.DialogUtils.showAdaptive
import org.autojs.autojs.core.accessibility.Capture import org.autojs.autojs.core.accessibility.Capture
import org.autojs.autojs.core.accessibility.NodeInfo import org.autojs.autojs.core.accessibility.NodeInfo
import org.autojs.autojs.core.accessibility.WindowInfo import org.autojs.autojs.core.accessibility.WindowInfo
@@ -111,7 +111,7 @@ abstract class LayoutFloatyWindow(
protected fun generateCode() { protected fun generateCode() {
CodeGenerateDialog(context, capture.root, mLayoutSelectedNode) CodeGenerateDialog(context, capture.root, mLayoutSelectedNode)
.build() .build()
.let { DialogUtils.showDialog(it) } .showAdaptive()
} }
protected fun switchWindow() { protected fun switchWindow() {
@@ -129,7 +129,7 @@ abstract class LayoutFloatyWindow(
val builder = WindowSwitchingDialog(context, windowInfoList).apply { val builder = WindowSwitchingDialog(context, windowInfoList).apply {
sortItems(compareBy { it.order.rawValue }) sortItems(compareBy { it.order.rawValue })
} }
val dialog = DialogUtils.showDialog(builder.build()) val dialog = builder.build().showAdaptive()
builder.itemsClickCallback = { _, position -> builder.itemsClickCallback = { _, position ->
builder.itemList[position].window.root?.let { builder.itemList[position].window.root?.let {
dialog.dismiss() dialog.dismiss()

View File

@@ -21,6 +21,7 @@ import org.autojs.autojs.core.pref.Pref
import org.autojs.autojs.ui.BaseActivity import org.autojs.autojs.ui.BaseActivity
import org.autojs.autojs.ui.keystore.NewKeyStoreDialog.NewKeyStoreConfigs import org.autojs.autojs.ui.keystore.NewKeyStoreDialog.NewKeyStoreConfigs
import org.autojs.autojs.ui.viewmodel.KeyStoreViewModel import org.autojs.autojs.ui.viewmodel.KeyStoreViewModel
import org.autojs.autojs.util.IntentUtils.startSafely
import org.autojs.autojs.util.ViewUtils.excludeFloatingActionButtonFromBottomNavigationBar import org.autojs.autojs.util.ViewUtils.excludeFloatingActionButtonFromBottomNavigationBar
import org.autojs.autojs.util.ViewUtils.excludePaddingClippableViewFromBottomNavigationBar import org.autojs.autojs.util.ViewUtils.excludePaddingClippableViewFromBottomNavigationBar
import org.autojs.autojs.util.ViewUtils.setMenuIconsColorByThemeColorLuminance import org.autojs.autojs.util.ViewUtils.setMenuIconsColorByThemeColorLuminance
@@ -38,7 +39,7 @@ class ManageKeyStoreActivity : BaseActivity() {
companion object { companion object {
fun startActivity(context: Context) { fun startActivity(context: Context) {
context.startActivity(Intent(context, ManageKeyStoreActivity::class.java)) Intent(context, ManageKeyStoreActivity::class.java).startSafely(context)
} }
} }

View File

@@ -10,6 +10,7 @@ import org.autojs.autojs.AutoJs.Companion.instance
import org.autojs.autojs.core.console.GlobalConsole import org.autojs.autojs.core.console.GlobalConsole
import org.autojs.autojs.runtime.api.Mime import org.autojs.autojs.runtime.api.Mime
import org.autojs.autojs.ui.BaseActivity import org.autojs.autojs.ui.BaseActivity
import org.autojs.autojs.util.IntentUtils.startSafelyWithOptions
import org.autojs.autojs.util.ViewUtils.excludeFloatingActionButtonFromBottomNavigationBar import org.autojs.autojs.util.ViewUtils.excludeFloatingActionButtonFromBottomNavigationBar
import org.autojs.autojs.util.ViewUtils.showToast import org.autojs.autojs.util.ViewUtils.showToast
import org.autojs.autojs6.R import org.autojs.autojs6.R
@@ -97,9 +98,9 @@ class LogActivity : BaseActivity() {
@JvmStatic @JvmStatic
fun launch(context: Context) { fun launch(context: Context) {
val intent = Intent(context, LogActivity::class.java).apply { addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) } val intent = Intent(context, LogActivity::class.java)
val options = ActivityOptions.makeCustomAnimation(context, R.anim.no_anim_fade_in, R.anim.no_anim_fade_out) val options = ActivityOptions.makeCustomAnimation(context, R.anim.no_anim_fade_in, R.anim.no_anim_fade_out)
context.startActivity(intent, options.toBundle()) intent.startSafelyWithOptions(context, options.toBundle())
} }
} }

View File

@@ -54,6 +54,7 @@ import org.autojs.autojs.ui.settings.PreferencesActivity
import org.autojs.autojs.ui.widget.DrawerAutoClose import org.autojs.autojs.ui.widget.DrawerAutoClose
import org.autojs.autojs.ui.widget.SearchViewItem import org.autojs.autojs.ui.widget.SearchViewItem
import org.autojs.autojs.util.IntentUtils import org.autojs.autojs.util.IntentUtils
import org.autojs.autojs.util.IntentUtils.startSafely
import org.autojs.autojs.util.StringUtils.key import org.autojs.autojs.util.StringUtils.key
import org.autojs.autojs.util.UpdateUtils import org.autojs.autojs.util.UpdateUtils
import org.autojs.autojs.util.ViewUtils import org.autojs.autojs.util.ViewUtils
@@ -451,7 +452,7 @@ class MainActivity : BaseActivity(), DelegateHost, HostActivity {
var shouldRecreateMainActivity = false var shouldRecreateMainActivity = false
@JvmStatic @JvmStatic
fun launch(context: Context) = context.startActivity(getIntent(context).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)) fun launch(context: Context) = getIntent(context).startSafely(context)
@JvmStatic @JvmStatic
fun getIntent(context: Context?) = Intent(context, MainActivity::class.java) fun getIntent(context: Context?) = Intent(context, MainActivity::class.java)

View File

@@ -50,6 +50,7 @@ import org.autojs.autojs.ui.settings.PreferencesActivity
import org.autojs.autojs.util.DisplayUtils import org.autojs.autojs.util.DisplayUtils
import org.autojs.autojs.util.IntentUtils.App.exit import org.autojs.autojs.util.IntentUtils.App.exit
import org.autojs.autojs.util.IntentUtils.App.restart import org.autojs.autojs.util.IntentUtils.App.restart
import org.autojs.autojs.util.IntentUtils.startSafely
import org.autojs.autojs.util.NetworkUtils import org.autojs.autojs.util.NetworkUtils
import org.autojs.autojs.util.NotificationUtils import org.autojs.autojs.util.NotificationUtils
import org.autojs.autojs.util.RomUtils import org.autojs.autojs.util.RomUtils
@@ -172,10 +173,8 @@ open class DrawerFragment : Fragment() {
} }
} }
item.setOnLaunchSettingsListener { item.setOnLaunchSettingsListener {
Intent().apply { Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS)
action = Settings.ACTION_ACCESSIBILITY_SETTINGS .startSafely(mContext)
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}.let { i -> mContext.startActivity(i) }
} }
} }
@@ -375,10 +374,8 @@ open class DrawerFragment : Fragment() {
descriptionRes = R.string.description_ignore_battery_optimizations, descriptionRes = R.string.description_ignore_battery_optimizations,
).also { item -> ).also { item ->
item.setOnLaunchSettingsListener { item.setOnLaunchSettingsListener {
Intent().apply { Intent(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS)
action = Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS .startSafely(mContext)
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}.let { i -> mContext.startActivity(i) }
} }
} }
@@ -463,9 +460,9 @@ open class DrawerFragment : Fragment() {
Shizuku.isPreV11() -> { Shizuku.isPreV11() -> {
ViewUtils.showSnack(d.view, R.string.error_shizuku_version_is_not_supported) ViewUtils.showSnack(d.view, R.string.error_shizuku_version_is_not_supported)
} }
else -> WrappedShizuku.getLaunchIntent(mContext)?.let { else -> WrappedShizuku.getLaunchIntent(mContext)
runCatching { mContext.startActivity(it) }.getOrNull() ?.startSafely(mContext)
} ?: ViewUtils.showSnack(d.view, R.string.error_failed_to_revoke_shizuku_access) ?: ViewUtils.showSnack(d.view, R.string.error_failed_to_revoke_shizuku_access)
} }
} }
} }
@@ -503,10 +500,8 @@ open class DrawerFragment : Fragment() {
prefKey = R.string.key_auto_night_mode_enabled, prefKey = R.string.key_auto_night_mode_enabled,
).also { item -> ).also { item ->
item.setOnLaunchSettingsListener { item.setOnLaunchSettingsListener {
Intent().apply { Intent(Settings.ACTION_DISPLAY_SETTINGS)
action = Settings.ACTION_DISPLAY_SETTINGS .startSafely(mContext)
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}.let { i -> mContext.startActivity(i) }
} }
item.isHidden = !ViewUtils.AutoNightMode.isFunctional() item.isHidden = !ViewUtils.AutoNightMode.isFunctional()
} }
@@ -539,10 +534,8 @@ open class DrawerFragment : Fragment() {
descriptionRes = R.string.description_night_mode, descriptionRes = R.string.description_night_mode,
prefKey = R.string.key_night_mode_enabled, prefKey = R.string.key_night_mode_enabled,
).setOnLaunchSettingsListener { ).setOnLaunchSettingsListener {
Intent().apply { Intent(Settings.ACTION_DISPLAY_SETTINGS)
action = Settings.ACTION_DISPLAY_SETTINGS .startSafely(mContext)
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}.let { i -> mContext.startActivity(i) }
} }
mKeepScreenOnWhenInForegroundItem = DrawerMenuToggleableItem( mKeepScreenOnWhenInForegroundItem = DrawerMenuToggleableItem(

View File

@@ -2,6 +2,7 @@ package org.autojs.autojs.ui.main.scripts
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.content.DialogInterface
import android.content.pm.PackageInfo import android.content.pm.PackageInfo
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.content.pm.PackageManager.GET_META_DATA import android.content.pm.PackageManager.GET_META_DATA
@@ -24,6 +25,7 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.selects.select import kotlinx.coroutines.selects.select
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import net.dongliu.apk.parser.ApkFile import net.dongliu.apk.parser.ApkFile
import org.autojs.autojs.app.DialogUtils.showAdaptive
import org.autojs.autojs.extension.MaterialDialogExtensions.makeSettingsLaunchable import org.autojs.autojs.extension.MaterialDialogExtensions.makeSettingsLaunchable
import org.autojs.autojs.extension.MaterialDialogExtensions.makeTextCopyable import org.autojs.autojs.extension.MaterialDialogExtensions.makeTextCopyable
import org.autojs.autojs.extension.MaterialDialogExtensions.setCopyableTextIfAbsent import org.autojs.autojs.extension.MaterialDialogExtensions.setCopyableTextIfAbsent
@@ -43,7 +45,20 @@ object ApkInfoDialogManager {
@JvmStatic @JvmStatic
@JvmOverloads @JvmOverloads
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
fun showApkInfoDialog(context: Context, apkFile: File, builderApplier: (MaterialDialog.Builder.() -> Unit)? = null) { fun showApkInfoDialog(
context: Context,
apkFile: File,
builderApplier: (MaterialDialog.Builder.() -> Unit)? = null,
) = showApkInfoDialog(context, apkFile, builderApplier, null)
@JvmStatic
@SuppressLint("SetTextI18n")
fun showApkInfoDialog(
context: Context,
apkFile: File,
builderApplier: (MaterialDialog.Builder.() -> Unit)?,
onDismissListener: DialogInterface.OnDismissListener?,
) {
val binding = ApkFileInfoDialogItemsBinding.inflate(LayoutInflater.from(context)) val binding = ApkFileInfoDialogItemsBinding.inflate(LayoutInflater.from(context))
// Create an independent Scope for the Dialog, bind its lifecycle with the Dialog. // Create an independent Scope for the Dialog, bind its lifecycle with the Dialog.
@@ -75,11 +90,16 @@ object ApkInfoDialogManager {
.neutralColorRes(R.color.dialog_button_hint) .neutralColorRes(R.color.dialog_button_hint)
.onNegative { materialDialog, _ -> materialDialog.dismiss() } .onNegative { materialDialog, _ -> materialDialog.dismiss() }
.also { builder -> builderApplier?.invoke(builder) } .also { builder -> builderApplier?.invoke(builder) }
.show() .build()
.apply { .apply {
makeTextCopyable { titleView } makeTextCopyable { titleView }
setOnDismissListener { scope.cancel() } setOnDismissListener {
scope.cancel()
onDismissListener?.onDismiss(this)
}
} }
.showAdaptive()
scope.launch { scope.launch {
val apkInfoDeferred = async(Dispatchers.IO) { getApkInfo(apkFile) } val apkInfoDeferred = async(Dispatchers.IO) { getApkInfo(apkFile) }

View File

@@ -5,6 +5,7 @@ import android.content.Intent
import io.noties.prism4j.GrammarLocator import io.noties.prism4j.GrammarLocator
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.autojs.autojs.util.IntentUtils.startSafely
import org.autojs.autojs6.R import org.autojs.autojs6.R
import java.io.File import java.io.File
import java.util.regex.Pattern import java.util.regex.Pattern
@@ -84,7 +85,7 @@ class DisplayManifestActivity : BaseDisplayContentActivity() {
putExtra(PATH_IDENTIFIER_MANIFEST, manifestFile.path) putExtra(PATH_IDENTIFIER_MANIFEST, manifestFile.path)
putExtra(INTENT_IDENTIFIER_PERMISSIONS, usesPermissions.toTypedArray()) putExtra(INTENT_IDENTIFIER_PERMISSIONS, usesPermissions.toTypedArray())
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}.let { context.startActivity(it) } }.startSafely(context)
} }
private fun parsePermissionsFromManifest(manifestContent: CharSequence): Array<String> { private fun parsePermissionsFromManifest(manifestContent: CharSequence): Array<String> {

View File

@@ -5,6 +5,7 @@ import android.content.Intent
import io.noties.prism4j.GrammarLocator import io.noties.prism4j.GrammarLocator
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.autojs.autojs.util.IntentUtils.startSafely
import org.autojs.autojs6.R import org.autojs.autojs6.R
class DisplayMediaInfoActivity : BaseDisplayContentActivity() { class DisplayMediaInfoActivity : BaseDisplayContentActivity() {
@@ -27,10 +28,9 @@ class DisplayMediaInfoActivity : BaseDisplayContentActivity() {
@JvmStatic @JvmStatic
fun launch(context: Context, mediaInfo: String) { fun launch(context: Context, mediaInfo: String) {
val intent = Intent(context, DisplayMediaInfoActivity::class.java) Intent(context, DisplayMediaInfoActivity::class.java).apply {
intent.putExtra(INTENT_IDENTIFIER_MEDIA_INFO, mediaInfo) putExtra(INTENT_IDENTIFIER_MEDIA_INFO, mediaInfo)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) }.startSafely(context)
context.startActivity(intent)
} }
} }

View File

@@ -13,6 +13,7 @@ import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.autojs.autojs.app.DialogUtils.showAdaptive
import org.autojs.autojs.extension.MaterialDialogExtensions.makeTextCopyable import org.autojs.autojs.extension.MaterialDialogExtensions.makeTextCopyable
import org.autojs.autojs.extension.MaterialDialogExtensions.setCopyableTextIfAbsent import org.autojs.autojs.extension.MaterialDialogExtensions.setCopyableTextIfAbsent
import org.autojs.autojs.external.fileprovider.AppFileProvider import org.autojs.autojs.external.fileprovider.AppFileProvider
@@ -37,7 +38,7 @@ object EditableFileInfoDialogManager {
MaterialDialog.Builder(context) MaterialDialog.Builder(context)
.title(R.string.text_failed) .title(R.string.text_failed)
.content(R.string.file_not_exist_or_readable) .content(R.string.file_not_exist_or_readable)
.show() .showAdaptive()
return return
} }
val binding = EditableFileInfoDialogItemsBinding.inflate(LayoutInflater.from(context)) val binding = EditableFileInfoDialogItemsBinding.inflate(LayoutInflater.from(context))
@@ -55,7 +56,7 @@ object EditableFileInfoDialogManager {
.limitIconToDefaultSize() .limitIconToDefaultSize()
.positiveText(R.string.dialog_button_dismiss) .positiveText(R.string.dialog_button_dismiss)
.positiveColorRes(R.color.dialog_button_default) .positiveColorRes(R.color.dialog_button_default)
.show() .showAdaptive()
.apply { .apply {
makeTextCopyable { titleView } makeTextCopyable { titleView }
setOnDismissListener { scope.cancel() } setOnDismissListener { scope.cancel() }

View File

@@ -32,6 +32,7 @@ import org.autojs.autojs.ui.widget.ScrollAwareFABBehavior
import org.autojs.autojs.util.IntentUtils import org.autojs.autojs.util.IntentUtils
import org.autojs.autojs.util.IntentUtils.SnackExceptionHolder import org.autojs.autojs.util.IntentUtils.SnackExceptionHolder
import org.autojs.autojs.util.IntentUtils.ToastExceptionHolder import org.autojs.autojs.util.IntentUtils.ToastExceptionHolder
import org.autojs.autojs.util.IntentUtils.startSafely
import org.autojs.autojs.util.ViewUtils.excludePaddingClippableViewFromBottomNavigationBar import org.autojs.autojs.util.ViewUtils.excludePaddingClippableViewFromBottomNavigationBar
import org.autojs.autojs6.R import org.autojs.autojs6.R
import org.autojs.autojs6.databinding.FragmentExplorerBinding import org.autojs.autojs6.databinding.FragmentExplorerBinding
@@ -215,18 +216,17 @@ class ExplorerFragment : ViewPagerFragment(0), OnFloatingActionButtonClickListen
override fun onClick(button: FloatingActionButton, pos: Int) { override fun onClick(button: FloatingActionButton, pos: Int) {
mExplorerView?.let { view -> mExplorerView?.let { view ->
val ctx = context ?: return@let
when (pos) { when (pos) {
3 -> context?.startActivity( 3 -> Intent(ctx, ProjectConfigActivity::class.java)
Intent(context, ProjectConfigActivity::class.java) .putExtra(ProjectConfigActivity.EXTRA_PARENT_DIRECTORY, view.currentPage.path)
.putExtra(ProjectConfigActivity.EXTRA_PARENT_DIRECTORY, view.currentPage.path) .putExtra(ProjectConfigActivity.EXTRA_NEW_PROJECT, true)
.putExtra(ProjectConfigActivity.EXTRA_NEW_PROJECT, true) .startSafely(ctx)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) 2 -> ScriptOperations(ctx, view, view.currentPage)
)
2 -> ScriptOperations(context, view, view.currentPage)
.importFile() .importFile()
1 -> ScriptOperations(context, view, view.currentPage) 1 -> ScriptOperations(ctx, view, view.currentPage)
.newFile() .newFile()
0 -> ScriptOperations(context, view, view.currentPage) 0 -> ScriptOperations(ctx, view, view.currentPage)
.newDirectory() .newDirectory()
else -> Unit else -> Unit
} }

View File

@@ -2,6 +2,7 @@ package org.autojs.autojs.ui.main.scripts
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.content.DialogInterface
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View.MeasureSpec.UNSPECIFIED import android.view.View.MeasureSpec.UNSPECIFIED
import android.widget.TextView import android.widget.TextView
@@ -16,6 +17,7 @@ import kotlinx.coroutines.async
import kotlinx.coroutines.cancel import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.autojs.autojs.app.DialogUtils.showAdaptive
import org.autojs.autojs.extension.MaterialDialogExtensions.makeTextCopyable import org.autojs.autojs.extension.MaterialDialogExtensions.makeTextCopyable
import org.autojs.autojs.extension.MaterialDialogExtensions.setCopyableText import org.autojs.autojs.extension.MaterialDialogExtensions.setCopyableText
import org.autojs.autojs.model.explorer.ExplorerItem import org.autojs.autojs.model.explorer.ExplorerItem
@@ -32,8 +34,22 @@ object MediaInfoDialogManager {
private const val MEDIA_INFO_ERROR_OPENING_FILE = "Error opening file..." private const val MEDIA_INFO_ERROR_OPENING_FILE = "Error opening file..."
@JvmStatic @JvmStatic
@JvmOverloads
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
fun showMediaInfoDialog(context: Context, explorerItem: ExplorerItem) { fun showMediaInfoDialog(
context: Context,
explorerItem: ExplorerItem,
builderApplier: (MaterialDialog.Builder.() -> Unit)? = null,
) = showMediaInfoDialog(context, explorerItem, builderApplier, null)
@JvmStatic
@SuppressLint("SetTextI18n")
fun showMediaInfoDialog(
context: Context,
explorerItem: ExplorerItem,
builderApplier: (MaterialDialog.Builder.() -> Unit)?,
onDismissListener: DialogInterface.OnDismissListener?,
) {
val binding = MediaFileInfoDialogItemsBinding.inflate(LayoutInflater.from(context)) val binding = MediaFileInfoDialogItemsBinding.inflate(LayoutInflater.from(context))
// Create an independent Scope for the Dialog, bind its lifecycle with the Dialog. // Create an independent Scope for the Dialog, bind its lifecycle with the Dialog.
@@ -52,11 +68,16 @@ object MediaInfoDialogManager {
.onNegative { materialDialog, _ -> materialDialog.dismiss() } .onNegative { materialDialog, _ -> materialDialog.dismiss() }
.neutralText(R.string.ellipsis_six) .neutralText(R.string.ellipsis_six)
.neutralColorRes(R.color.dialog_button_unavailable) .neutralColorRes(R.color.dialog_button_unavailable)
.show() .also { builder -> builderApplier?.invoke(builder) }
.build()
.apply { .apply {
makeTextCopyable { titleView } makeTextCopyable { titleView }
setOnDismissListener { scope.cancel() } setOnDismissListener {
scope.cancel()
onDismissListener?.onDismiss(this)
}
} }
.showAdaptive()
scope.launch { scope.launch {
val mediaInfo = MediaInfo() val mediaInfo = MediaInfo()

View File

@@ -32,6 +32,7 @@ import org.autojs.autojs.timing.TimedTaskManager;
import org.autojs.autojs.ui.timing.TimedTaskSettingActivity; import org.autojs.autojs.ui.timing.TimedTaskSettingActivity;
import org.autojs.autojs.util.ColorUtils; import org.autojs.autojs.util.ColorUtils;
import org.autojs.autojs.util.FileUtils; import org.autojs.autojs.util.FileUtils;
import org.autojs.autojs.util.IntentUtils;
import org.autojs.autojs6.R; import org.autojs.autojs6.R;
import org.autojs.autojs6.databinding.ExplorerFirstCharIconBinding; import org.autojs.autojs6.databinding.ExplorerFirstCharIconBinding;
import org.autojs.autojs6.databinding.TaskListRecyclerViewItemBinding; import org.autojs.autojs6.databinding.TaskListRecyclerViewItemBinding;
@@ -307,7 +308,7 @@ public class TaskListRecyclerView extends ThemeColorRecyclerView {
: TimedTaskSettingActivity.EXTRA_TASK_ID; : TimedTaskSettingActivity.EXTRA_TASK_ID;
Intent intent = new Intent(getContext(), TimedTaskSettingActivity.class) Intent intent = new Intent(getContext(), TimedTaskSettingActivity.class)
.putExtra(extra, task.getId()); .putExtra(extra, task.getId());
getContext().startActivity(intent); IntentUtils.startSafely(intent, getContext());
} }
} }
} }

View File

@@ -1070,7 +1070,7 @@ public class BuildActivity extends BaseActivity implements ApkBuilder.ProgressCa
public static void launch(Context context, String extraSource) { public static void launch(Context context, String extraSource) {
Intent intent = new Intent(context, BuildActivity.class) Intent intent = new Intent(context, BuildActivity.class)
.putExtra(BuildActivity.EXTRA_SOURCE, extraSource); .putExtra(BuildActivity.EXTRA_SOURCE, extraSource);
context.startActivity(intent); IntentUtils.startSafely(intent, context);
} }
} }

View File

@@ -18,6 +18,7 @@ import org.autojs.autojs.ui.BaseActivity
import org.autojs.autojs.ui.common.NotAskAgainDialog import org.autojs.autojs.ui.common.NotAskAgainDialog
import org.autojs.autojs.util.ClipboardUtils import org.autojs.autojs.util.ClipboardUtils
import org.autojs.autojs.util.DeviceUtils import org.autojs.autojs.util.DeviceUtils
import org.autojs.autojs.util.IntentUtils.startSafely
import org.autojs.autojs.util.ViewUtils import org.autojs.autojs.util.ViewUtils
import org.autojs.autojs6.BuildConfig import org.autojs.autojs6.BuildConfig
import org.autojs.autojs6.R import org.autojs.autojs6.R
@@ -135,7 +136,7 @@ open class AboutActivity : BaseActivity() {
} }
private fun launchDeveloperOptions() { private fun launchDeveloperOptions() {
startActivity(Intent(this, DeveloperOptionsActivity::class.java).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)) Intent(this, DeveloperOptionsActivity::class.java).startSafely(this)
} }
private fun toastForFirstDeveloperIdentifier() { private fun toastForFirstDeveloperIdentifier() {
@@ -189,16 +190,14 @@ open class AboutActivity : BaseActivity() {
private fun launchGithubIssuesPage() { private fun launchGithubIssuesPage() {
Intent(Intent.ACTION_VIEW) Intent(Intent.ACTION_VIEW)
.setData(getString(R.string.url_github_autojs6_issues).toUri()) .setData(getString(R.string.url_github_autojs6_issues).toUri())
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) .startSafely(this)
.let { startActivity(it) }
} }
companion object { companion object {
fun startActivity(context: Context) { fun startActivity(context: Context) {
Intent(context, AboutActivity::class.java) Intent(context, AboutActivity::class.java)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) .startSafely(context)
.let { context.startActivity(it) }
} }
} }

View File

@@ -5,10 +5,10 @@ import android.content.Intent
import android.net.Uri import android.net.Uri
import android.text.util.Linkify import android.text.util.Linkify
import android.util.AttributeSet import android.util.AttributeSet
import androidx.preference.Preference.SummaryProvider
import com.afollestad.materialdialogs.DialogAction import com.afollestad.materialdialogs.DialogAction
import com.afollestad.materialdialogs.MaterialDialog import com.afollestad.materialdialogs.MaterialDialog
import org.autojs.autojs.theme.preference.MaterialPreference import org.autojs.autojs.theme.preference.MaterialPreference
import org.autojs.autojs.util.IntentUtils.startSafely
import org.autojs.autojs.util.ViewUtils import org.autojs.autojs.util.ViewUtils
import org.autojs.autojs6.BuildConfig import org.autojs.autojs6.BuildConfig
import org.autojs.autojs6.R import org.autojs.autojs6.R
@@ -42,22 +42,20 @@ class AboutAppAndDeveloperPreference : MaterialPreference {
d?.getActionButton(DialogAction.NEUTRAL)!!.apply { d?.getActionButton(DialogAction.NEUTRAL)!!.apply {
setTextColor(context.getColor(R.color.dialog_button_hint)) setTextColor(context.getColor(R.color.dialog_button_hint))
setOnClickListener { setOnClickListener {
try { when {
Intent().apply { Intent().apply {
@Suppress("SpellCheckingInspection") @Suppress("SpellCheckingInspection")
data = Uri.parse( data = Uri.parse(
"mqqopensdkapi://bizAgent/qm/qr" + "mqqopensdkapi://bizAgent/qm/qr" +
"?" + "url" + "=" + "http%3A%2F%2Fqm.qq.com" + "?" + "url" + "=" + "http%3A%2F%2Fqm.qq.com" +
"%2F" + "cgi-bin" + "%2F" + "qm" + "%2F" + "qr" + "%2F" + "cgi-bin" + "%2F" + "qm" + "%2F" + "qr" +
"%3F" + "from" + "%3D" + "app" + "%3F" + "from" + "%3D" + "app" +
"%26" + "p" + "%3D" + "android" + "%26" + "p" + "%3D" + "android" +
"%26" + "jump_from" + "%3D" + "webapi" + "%26" + "jump_from" + "%3D" + "webapi" +
"%26" + "k" + "%3D" + "6BH7HuJj29dwE0AIcUuxtAlK6NWlefmH" "%26" + "k" + "%3D" + "6BH7HuJj29dwE0AIcUuxtAlK6NWlefmH"
) )
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) }.startSafely(context) -> Unit
}.let { context.startActivity(it) } else -> context.getString(
} catch (e: Exception) {
context.getString(
R.string.error_app_not_installed_with_name, R.string.error_app_not_installed_with_name,
context.getString(R.string.app_name_qq), context.getString(R.string.app_name_qq),
).let { msg -> ViewUtils.showToast(context, msg, true) } ).let { msg -> ViewUtils.showToast(context, msg, true) }

View File

@@ -8,6 +8,7 @@ import org.autojs.autojs.app.GlobalAppContext
import org.autojs.autojs.core.pref.Language import org.autojs.autojs.core.pref.Language
import org.autojs.autojs.theme.preference.MaterialListPreference import org.autojs.autojs.theme.preference.MaterialListPreference
import org.autojs.autojs.ui.BaseActivity import org.autojs.autojs.ui.BaseActivity
import org.autojs.autojs.util.IntentUtils.startSafely
import org.autojs.autojs.util.LocaleUtils import org.autojs.autojs.util.LocaleUtils
class AppLanguagePreference : MaterialListPreference { class AppLanguagePreference : MaterialListPreference {
@@ -27,9 +28,7 @@ class AppLanguagePreference : MaterialListPreference {
override fun onNeutral() { override fun onNeutral() {
Intent(Intent.ACTION_MAIN).apply { Intent(Intent.ACTION_MAIN).apply {
setClassName("com.android.settings", "com.android.settings.LanguageSettings") setClassName("com.android.settings", "com.android.settings.LanguageSettings")
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) }.startSafely(prefContext)
prefContext.startActivity(this)
}
} }
override fun onChangeConfirmed(dialog: MaterialDialog) { override fun onChangeConfirmed(dialog: MaterialDialog) {

View File

@@ -34,6 +34,7 @@ import org.autojs.autojs.ui.BaseActivity
import org.autojs.autojs.ui.settings.VersionHistoryRepository.Companion.Category import org.autojs.autojs.ui.settings.VersionHistoryRepository.Companion.Category
import org.autojs.autojs.ui.settings.VersionHistoryRepository.Companion.DEFAULT_FILTER import org.autojs.autojs.ui.settings.VersionHistoryRepository.Companion.DEFAULT_FILTER
import org.autojs.autojs.ui.settings.VersionHistoryRepository.Companion.DEFAULT_VERSION_NAME import org.autojs.autojs.ui.settings.VersionHistoryRepository.Companion.DEFAULT_VERSION_NAME
import org.autojs.autojs.util.IntentUtils.startSafely
import org.autojs.autojs.util.ProcessLogger import org.autojs.autojs.util.ProcessLogger
import org.autojs.autojs.util.ViewUtils.excludePaddingClippableViewFromBottomNavigationBar import org.autojs.autojs.util.ViewUtils.excludePaddingClippableViewFromBottomNavigationBar
import org.autojs.autojs.util.ViewUtils.setMenuIconsColorByThemeColorLuminance import org.autojs.autojs.util.ViewUtils.setMenuIconsColorByThemeColorLuminance
@@ -250,9 +251,8 @@ class DisplayVersionHistoriesActivity : BaseActivity() {
@JvmStatic @JvmStatic
fun launch(context: Context) { fun launch(context: Context) {
Intent(context, DisplayVersionHistoriesActivity::class.java).apply { Intent(context, DisplayVersionHistoriesActivity::class.java)
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) .startSafely(context)
}.let { context.startActivity(it) }
} }
class NoFadeItemAnimator : DefaultItemAnimator() { class NoFadeItemAnimator : DefaultItemAnimator() {

View File

@@ -6,6 +6,7 @@ import android.os.Bundle
import org.autojs.autojs.app.GlobalAppContext import org.autojs.autojs.app.GlobalAppContext
import org.autojs.autojs.theme.ThemeColorManager import org.autojs.autojs.theme.ThemeColorManager
import org.autojs.autojs.ui.BaseActivity import org.autojs.autojs.ui.BaseActivity
import org.autojs.autojs.util.IntentUtils.startSafely
import org.autojs.autojs6.R import org.autojs.autojs6.R
import org.autojs.autojs6.databinding.ActivityPreferencesBinding import org.autojs.autojs6.databinding.ActivityPreferencesBinding
@@ -46,8 +47,7 @@ open class PreferencesActivity : BaseActivity() {
@JvmOverloads @JvmOverloads
fun launch(context: Context = GlobalAppContext.get()) { fun launch(context: Context = GlobalAppContext.get()) {
Intent(context, PreferencesActivity::class.java) Intent(context, PreferencesActivity::class.java)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) .startSafely(context)
.let { context.startActivity(it) }
} }
} }

View File

@@ -76,7 +76,6 @@ class ScheduledRestartSettingsDialogBuilder(context: Context) : MaterialDialog.B
} }
mSeekBar.progress = (context.resources.getInteger(R.integer.scheduled_restart_start_delay_default_value) - mStartDelayMinValue) / 100 mSeekBar.progress = (context.resources.getInteger(R.integer.scheduled_restart_start_delay_default_value) - mStartDelayMinValue) / 100
})) }))
autoDismiss(false)
negativeText(R.string.dialog_button_cancel) negativeText(R.string.dialog_button_cancel)
negativeColorRes(R.color.dialog_button_default) negativeColorRes(R.color.dialog_button_default)
onNegative { d, _ -> d.dismiss() } onNegative { d, _ -> d.dismiss() }
@@ -90,10 +89,11 @@ class ScheduledRestartSettingsDialogBuilder(context: Context) : MaterialDialog.B
Pref.putInt(R.string.key_scheduled_restart_delay, mStartDelayMinValue + mSeekBar.progress * 100) Pref.putInt(R.string.key_scheduled_restart_delay, mStartDelayMinValue + mSeekBar.progress * 100)
d.dismiss() d.dismiss()
} }
autoDismiss(false)
} }
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) { override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
binding.scheduledRestartStartDelayTitle.text = "$mScheduledRestartStartDelayTitlePrefix: ${mStartDelayMinValue + progress * 100}ms" binding.scheduledRestartStartDelayTitle.text = context.getString(R.string.text_property_colon_value_unit, mScheduledRestartStartDelayTitlePrefix, mStartDelayMinValue + progress * 100, "ms")
} }
override fun onStartTrackingTouch(seekBar: SeekBar) { override fun onStartTrackingTouch(seekBar: SeekBar) {

View File

@@ -10,6 +10,7 @@ import android.widget.FrameLayout
import androidx.core.net.toUri import androidx.core.net.toUri
import com.afollestad.materialdialogs.MaterialDialog import com.afollestad.materialdialogs.MaterialDialog
import org.autojs.autojs.runtime.api.Mime import org.autojs.autojs.runtime.api.Mime
import org.autojs.autojs.util.IntentUtils.startSafely
import org.autojs.autojs.util.TextUtils.markdownToHtml import org.autojs.autojs.util.TextUtils.markdownToHtml
/** /**
@@ -47,13 +48,13 @@ class CommonMarkdownView : WebView {
} }
override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean { override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean {
context.startActivity(Intent(Intent.ACTION_VIEW).setData(request.url).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)) Intent(Intent.ACTION_VIEW).setData(request.url).startSafely(context)
return true return true
} }
@Deprecated("Deprecated in Java") @Deprecated("Deprecated in Java")
override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean { override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
context.startActivity(Intent(Intent.ACTION_VIEW).setData(url.toUri()).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)) Intent(Intent.ACTION_VIEW).setData(url.toUri()).startSafely(context)
return true return true
} }
} }

View File

@@ -2,7 +2,6 @@ package org.autojs.autojs.ui.widget;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.app.Activity; import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.ResolveInfo; import android.content.pm.ResolveInfo;
@@ -17,20 +16,18 @@ import android.webkit.WebView;
import android.webkit.WebViewClient; import android.webkit.WebViewClient;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import org.autojs.autojs.app.OnActivityResultDelegate; import org.autojs.autojs.app.OnActivityResultDelegate;
import org.autojs.autojs.tool.ImageSelector; import org.autojs.autojs.tool.ImageSelector;
import org.autojs.autojs.util.IntentUtils;
import org.autojs.autojs6.R; import org.autojs.autojs6.R;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
/** /**
* Created by Stardust on Aug 22, 2017. * Created by Stardust on Aug 22, 2017.
*/ */
@@ -124,7 +121,7 @@ public class EWebView extends FrameLayout implements SwipeRefreshLayout.OnRefres
public boolean openFileChooser(ValueCallback<Uri> valueCallback, public boolean openFileChooser(ValueCallback<Uri> valueCallback,
String[] acceptType) { String[] acceptType) {
if (getContext() instanceof OnActivityResultDelegate.DelegateHost && if (getContext() instanceof OnActivityResultDelegate.DelegateHost &&
getContext() instanceof Activity && isImageType(acceptType)) { getContext() instanceof Activity && isImageType(acceptType)) {
chooseImage(valueCallback); chooseImage(valueCallback);
return true; return true;
} }
@@ -201,12 +198,7 @@ public class EWebView extends FrameLayout implements SwipeRefreshLayout.OnRefres
if (intentActivities.isEmpty()) { if (intentActivities.isEmpty()) {
return false; return false;
} }
try { return IntentUtils.startSafely(Intent.createChooser(intent, getResources().getString(R.string.text_open_with)), getContext());
getContext().startActivity(Intent.createChooser(intent, getResources().getString(R.string.text_open_with)));
} catch (ActivityNotFoundException e) {
e.printStackTrace();
return false;
}
} }
return true; return true;
} }

View File

@@ -7,6 +7,7 @@ import android.content.Context
import android.content.Context.ALARM_SERVICE import android.content.Context.ALARM_SERVICE
import android.content.Intent import android.content.Intent
import android.net.Uri import android.net.Uri
import android.os.Bundle
import android.os.SystemClock import android.os.SystemClock
import android.provider.OpenableColumns import android.provider.OpenableColumns
import android.provider.Settings import android.provider.Settings
@@ -59,6 +60,16 @@ object IntentUtils {
onFailure?.invoke(t) onFailure?.invoke(t)
}.isSuccess }.isSuccess
@JvmStatic
@JvmOverloads
fun Intent.startSafelyWithOptions(context: Context, options: Bundle? = null, printStackTrace: Boolean = false, onFailure: ((Throwable) -> Unit)? = null): Boolean =
runCatching {
startWithOptions(context, options)
}.onFailure { t ->
if (printStackTrace) t.printStackTrace()
onFailure?.invoke(t)
}.isSuccess
@JvmStatic @JvmStatic
fun Intent.start(context: Context) { fun Intent.start(context: Context) {
val activity = context.findActivity() val activity = context.findActivity()
@@ -70,6 +81,17 @@ object IntentUtils {
} }
} }
@JvmStatic
fun Intent.startWithOptions(context: Context, options: Bundle? = null) {
val activity = context.findActivity()
if (activity != null) {
activity.startActivity(this, options)
} else {
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
context.startActivity(this, options)
}
}
@Suppress("SpellCheckingInspection") @Suppress("SpellCheckingInspection")
fun chatWithQQ(context: Context, qq: String): Boolean { fun chatWithQQ(context: Context, qq: String): Boolean {
val uri = "mqqwpa://im/chat?chat_type=wpa&uin=$qq".toUri() val uri = "mqqwpa://im/chat?chat_type=wpa&uin=$qq".toUri()

View File

@@ -155,8 +155,7 @@ object NotificationUtils {
@JvmStatic @JvmStatic
fun launchSettings() { fun launchSettings() {
val localIntent = createAppNotificationIntent(globalAppContext) createAppNotificationIntent(globalAppContext).startSafely(globalAppContext)
globalAppContext.startActivity(localIntent)
} }
@JvmStatic @JvmStatic

View File

@@ -1191,5 +1191,6 @@
<string name="error_plugin_returned_empty_info">أعاد المكوّن الإضافي %1$s معلومات فارغة.</string> <string name="error_plugin_returned_empty_info">أعاد المكوّن الإضافي %1$s معلومات فارغة.</string>
<string name="error_plugin_returned_invalid_variant">أعاد المكوّن الإضافي %1$s variant غير صالح: %2$s.</string> <string name="error_plugin_returned_invalid_variant">أعاد المكوّن الإضافي %1$s variant غير صالح: %2$s.</string>
<string name="error_no_embedded_paddle_ocr_assets_found">لم يتم العثور على موارد Paddle OCR المضمّنة. يُرجى إعادة الحزم مع تفعيل Paddle OCR.</string> <string name="error_no_embedded_paddle_ocr_assets_found">لم يتم العثور على موارد Paddle OCR المضمّنة. يُرجى إعادة الحزم مع تفعيل Paddle OCR.</string>
<string name="dialog_button_minimize">تصغير</string>
</resources> </resources>

View File

@@ -1186,5 +1186,6 @@
<string name="error_plugin_returned_empty_info">%1$s plugin returned empty info.</string> <string name="error_plugin_returned_empty_info">%1$s plugin returned empty info.</string>
<string name="error_plugin_returned_invalid_variant">%1$s plugin returned invalid variant: %2$s.</string> <string name="error_plugin_returned_invalid_variant">%1$s plugin returned invalid variant: %2$s.</string>
<string name="error_no_embedded_paddle_ocr_assets_found">No embedded Paddle OCR assets found. Please re-package with Paddle OCR enabled.</string> <string name="error_no_embedded_paddle_ocr_assets_found">No embedded Paddle OCR assets found. Please re-package with Paddle OCR enabled.</string>
<string name="dialog_button_minimize">Minimize</string>
</resources> </resources>

View File

@@ -1189,5 +1189,6 @@
<string name="error_plugin_returned_empty_info">El plugin %1$s devolvió información vacía.</string> <string name="error_plugin_returned_empty_info">El plugin %1$s devolvió información vacía.</string>
<string name="error_plugin_returned_invalid_variant">El plugin %1$s devolvió una variante no válida: %2$s.</string> <string name="error_plugin_returned_invalid_variant">El plugin %1$s devolvió una variante no válida: %2$s.</string>
<string name="error_no_embedded_paddle_ocr_assets_found">No se encontraron recursos integrados de Paddle OCR. Vuelve a empaquetar con Paddle OCR habilitado.</string> <string name="error_no_embedded_paddle_ocr_assets_found">No se encontraron recursos integrados de Paddle OCR. Vuelve a empaquetar con Paddle OCR habilitado.</string>
<string name="dialog_button_minimize">Minimizar</string>
</resources> </resources>

View File

@@ -1189,5 +1189,6 @@
<string name="error_plugin_returned_empty_info">Le plugin %1$s a renvoyé des informations vides.</string> <string name="error_plugin_returned_empty_info">Le plugin %1$s a renvoyé des informations vides.</string>
<string name="error_plugin_returned_invalid_variant">Le plugin %1$s a renvoyé une variante invalide: %2$s.</string> <string name="error_plugin_returned_invalid_variant">Le plugin %1$s a renvoyé une variante invalide: %2$s.</string>
<string name="error_no_embedded_paddle_ocr_assets_found">Aucune ressource Paddle OCR intégrée n\'a été trouvée. Veuillez reconditionner avec Paddle OCR activé.</string> <string name="error_no_embedded_paddle_ocr_assets_found">Aucune ressource Paddle OCR intégrée n\'a été trouvée. Veuillez reconditionner avec Paddle OCR activé.</string>
<string name="dialog_button_minimize">Réduire</string>
</resources> </resources>

View File

@@ -1190,5 +1190,6 @@
<string name="error_plugin_returned_empty_info">%1$s プラグインが空の info を返しました.</string> <string name="error_plugin_returned_empty_info">%1$s プラグインが空の info を返しました.</string>
<string name="error_plugin_returned_invalid_variant">%1$s プラグインが無効な variant を返しました: %2$s.</string> <string name="error_plugin_returned_invalid_variant">%1$s プラグインが無効な variant を返しました: %2$s.</string>
<string name="error_no_embedded_paddle_ocr_assets_found">埋め込みの Paddle OCR assets が見つかりません. Paddle OCR を有効にして再パッケージしてください.</string> <string name="error_no_embedded_paddle_ocr_assets_found">埋め込みの Paddle OCR assets が見つかりません. Paddle OCR を有効にして再パッケージしてください.</string>
<string name="dialog_button_minimize">最小化</string>
</resources> </resources>

View File

@@ -1191,5 +1191,6 @@
<string name="error_plugin_returned_empty_info">%1$s 플러그인이 빈 info를 반환했습니다.</string> <string name="error_plugin_returned_empty_info">%1$s 플러그인이 빈 info를 반환했습니다.</string>
<string name="error_plugin_returned_invalid_variant">%1$s 플러그인이 잘못된 variant를 반환했습니다: %2$s.</string> <string name="error_plugin_returned_invalid_variant">%1$s 플러그인이 잘못된 variant를 반환했습니다: %2$s.</string>
<string name="error_no_embedded_paddle_ocr_assets_found">내장된 Paddle OCR assets를 찾을 수 없습니다. Paddle OCR을 활성화하여 다시 패키징해 주세요.</string> <string name="error_no_embedded_paddle_ocr_assets_found">내장된 Paddle OCR assets를 찾을 수 없습니다. Paddle OCR을 활성화하여 다시 패키징해 주세요.</string>
<string name="dialog_button_minimize">최소화</string>
</resources> </resources>

View File

@@ -1189,5 +1189,6 @@
<string name="error_plugin_returned_empty_info">Плагин %1$s вернул пустую информацию.</string> <string name="error_plugin_returned_empty_info">Плагин %1$s вернул пустую информацию.</string>
<string name="error_plugin_returned_invalid_variant">Плагин %1$s вернул недопустимый variant: %2$s.</string> <string name="error_plugin_returned_invalid_variant">Плагин %1$s вернул недопустимый variant: %2$s.</string>
<string name="error_no_embedded_paddle_ocr_assets_found">Не найдены встроенные ресурсы Paddle OCR. Перепакуйте приложение с включённым Paddle OCR.</string> <string name="error_no_embedded_paddle_ocr_assets_found">Не найдены встроенные ресурсы Paddle OCR. Перепакуйте приложение с включённым Paddle OCR.</string>
<string name="dialog_button_minimize">Свернуть</string>
</resources> </resources>

View File

@@ -1187,5 +1187,6 @@
<string name="error_plugin_returned_empty_info">%1$s 插件返回的 info 為空.</string> <string name="error_plugin_returned_empty_info">%1$s 插件返回的 info 為空.</string>
<string name="error_plugin_returned_invalid_variant">%1$s 插件返回的 variant 無效: %2$s.</string> <string name="error_plugin_returned_invalid_variant">%1$s 插件返回的 variant 無效: %2$s.</string>
<string name="error_no_embedded_paddle_ocr_assets_found">未找到內置 Paddle OCR 資源, 請在打包時勾選並注入 Paddle OCR 後重試.</string> <string name="error_no_embedded_paddle_ocr_assets_found">未找到內置 Paddle OCR 資源, 請在打包時勾選並注入 Paddle OCR 後重試.</string>
<string name="dialog_button_minimize">最小化</string>
</resources> </resources>

View File

@@ -1187,5 +1187,6 @@
<string name="error_plugin_returned_empty_info">%1$s 外掛返回的 info 為空.</string> <string name="error_plugin_returned_empty_info">%1$s 外掛返回的 info 為空.</string>
<string name="error_plugin_returned_invalid_variant">%1$s 外掛返回的 variant 無效: %2$s.</string> <string name="error_plugin_returned_invalid_variant">%1$s 外掛返回的 variant 無效: %2$s.</string>
<string name="error_no_embedded_paddle_ocr_assets_found">未找到內建 Paddle OCR 資源, 請在打包時勾選並注入 Paddle OCR 後重試.</string> <string name="error_no_embedded_paddle_ocr_assets_found">未找到內建 Paddle OCR 資源, 請在打包時勾選並注入 Paddle OCR 後重試.</string>
<string name="dialog_button_minimize">最小化</string>
</resources> </resources>

View File

@@ -1187,5 +1187,6 @@
<string name="error_plugin_returned_empty_info">%1$s 插件返回的 info 为空.</string> <string name="error_plugin_returned_empty_info">%1$s 插件返回的 info 为空.</string>
<string name="error_plugin_returned_invalid_variant">%1$s 插件返回的 variant 无效: %2$s.</string> <string name="error_plugin_returned_invalid_variant">%1$s 插件返回的 variant 无效: %2$s.</string>
<string name="error_no_embedded_paddle_ocr_assets_found">未找到内置 Paddle OCR 资源, 请在打包时勾选并注入 Paddle OCR 后重试.</string> <string name="error_no_embedded_paddle_ocr_assets_found">未找到内置 Paddle OCR 资源, 请在打包时勾选并注入 Paddle OCR 后重试.</string>
<string name="dialog_button_minimize">Minimize</string>
</resources> </resources>

View File

@@ -1444,5 +1444,6 @@
<string name="error_plugin_returned_empty_info">%1$s plugin returned empty info.</string> <string name="error_plugin_returned_empty_info">%1$s plugin returned empty info.</string>
<string name="error_plugin_returned_invalid_variant">%1$s plugin returned invalid variant: %2$s.</string> <string name="error_plugin_returned_invalid_variant">%1$s plugin returned invalid variant: %2$s.</string>
<string name="error_no_embedded_paddle_ocr_assets_found">No embedded Paddle OCR assets found. Please re-package with Paddle OCR enabled.</string> <string name="error_no_embedded_paddle_ocr_assets_found">No embedded Paddle OCR assets found. Please re-package with Paddle OCR enabled.</string>
<string name="dialog_button_minimize">Minimize</string>
</resources> </resources>

View File

@@ -1,5 +1,5 @@
#Sun Jan 18 22:49:01 CST 2026 #Tue Jan 20 15:19:53 CST 2026
BUILD_TIME=1768747741064 BUILD_TIME=1768893593849
COMPILE_SDK_VERSION=36 COMPILE_SDK_VERSION=36
IMAGE_QUANT_CMAKE_VERSION=3.22.1 IMAGE_QUANT_CMAKE_VERSION=3.22.1
IMAGE_QUANT_NDK_VERSION=26.1.10909125 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 RAPID_OCR_OPENCV_MOBILE_VERSION=4.5.3
TARGET_SDK_VERSION=36 TARGET_SDK_VERSION=36
TARGET_SDK_VERSION_INRT=29 TARGET_SDK_VERSION_INRT=29
VERSION_BUILD=3630 VERSION_BUILD=3636
VERSION_NAME=6.7.0 Alpha16 VERSION_NAME=6.7.0 Alpha17
VSCODE_EXT_REQUIRED_VERSION=1.0.13 VSCODE_EXT_REQUIRED_VERSION=1.0.13