-
-
Save TheMelody/5044dd1b697707b18e94b89f97f55db6 to your computer and use it in GitHub Desktop.
打开应用自启动权限-相关代码(自启动权限==白名单管理列表页面)手机系统一直更新,无法保证能一直跳转
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 防止内存泄漏 | |
*/ | |
open class DetachableClickListener(delegate: DialogInterface.OnClickListener?): DialogInterface.OnClickListener { | |
private var delegateOrNull: DialogInterface.OnClickListener? = delegate | |
companion object{ | |
fun wrap(delegate: DialogInterface.OnClickListener?): DetachableClickListener? { | |
return DetachableClickListener(delegate) | |
} | |
} | |
override fun onClick(dialog: DialogInterface?, which: Int) { | |
delegateOrNull?.onClick(dialog, which) | |
} | |
fun clearOnDetach(dialog: AlertDialog) { | |
dialog.window?.decorView?.viewTreeObserver | |
?.addOnWindowAttachListener(object : OnWindowAttachListener { | |
override fun onWindowAttached() { | |
} | |
override fun onWindowDetached() { | |
dialog.window?.decorView?.viewTreeObserver?.removeOnWindowAttachListener(this) | |
delegateOrNull = null | |
} | |
}) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
object RomUtil { | |
private const val TAG = "RomUtil" | |
private const val HARMONY_OS = "harmony" | |
private const val ROM_MIUI = "MIUI" | |
private const val ROM_EMUI = "EMUI" | |
private const val ROM_FLYME = "FLYME" | |
private const val ROM_OPPO = "OPPO" | |
private const val ROM_SMARTISAN = "SMARTISAN" | |
private const val ROM_VIVO = "VIVO" | |
private const val ROM_QIKU = "QIKU" | |
private val KEY_VERSION_MIUI = "ro.miui.ui.version.name" | |
private val KEY_VERSION_EMUI = "ro.build.version.emui" | |
private val KEY_VERSION_OPPO = "ro.build.version.opporom" | |
private val KEY_VERSION_SMARTISAN = "ro.smartisan.version" | |
private val KEY_VERSION_VIVO = "ro.vivo.os.version" | |
//华为 | |
fun isEmui(): Boolean { | |
return check(ROM_EMUI) | |
} | |
//小米 | |
fun isMiui(): Boolean { | |
return check(ROM_MIUI) | |
} | |
//vivo | |
fun isVivo(): Boolean { | |
return check(ROM_VIVO) | |
} | |
//oppo | |
fun isOppo(): Boolean { | |
return check(ROM_OPPO) | |
} | |
//魅族 | |
fun isFlyme(): Boolean { | |
return check(ROM_FLYME) | |
} | |
//360 | |
fun isQiku(): Boolean { | |
return check(ROM_QIKU) || check("360") | |
} | |
//锤子手机 | |
fun isSmartisan(): Boolean { | |
return check(ROM_SMARTISAN) | |
} | |
//乐视 | |
fun isLetv():Boolean = TextUtils.equals(Build.BRAND.toLowerCase(Locale.getDefault()),"letv") | |
//三星 | |
fun isSamsung():Boolean = TextUtils.equals(Build.BRAND.toLowerCase(Locale.getDefault()) ,"samsung") | |
//一加 | |
fun onePlus():Boolean = TextUtils.equals(Build.BRAND.toLowerCase(Locale.getDefault()) , "oneplus") | |
//鸿蒙系统 | |
fun isHarmonyOS(): Boolean { | |
try { | |
val clz = Class.forName("com.huawei.system.BuildEx") | |
val method: Method = clz.getMethod("getOsBrand") | |
val classLoader = clz.classLoader | |
//如果BuildEx为系统提供的,其classloader为BootClassLoader | |
//如果BuildEx为伪造的,其classloader一般为PathClassLoader | |
//Log.d(TAG, "classLoader: $classLoader") | |
//BootClassLoader的parent为null | |
if (classLoader != null && classLoader.parent == null) { | |
return HARMONY_OS == method.invoke(clz) | |
} | |
} catch (e: ClassNotFoundException) { | |
} catch (e: NoSuchMethodException) { | |
} catch (e: Exception) { | |
} | |
return false | |
} | |
private var sName: String? = null | |
private var sVersion: String? = null | |
private fun check(rom: String): Boolean { | |
if (sName != null) { | |
return sName == rom | |
} | |
if (!TextUtils.isEmpty(getProp(KEY_VERSION_MIUI).also { sVersion = it })) { | |
sName = ROM_MIUI | |
} else if (!TextUtils.isEmpty(getProp(KEY_VERSION_EMUI).also { sVersion = it })) { | |
sName = ROM_EMUI | |
} else if (!TextUtils.isEmpty(getProp(KEY_VERSION_OPPO).also { sVersion = it })) { | |
sName = ROM_OPPO | |
} else if (!TextUtils.isEmpty(getProp(KEY_VERSION_VIVO).also { sVersion = it })) { | |
sName = ROM_VIVO | |
} else if (!TextUtils.isEmpty(getProp(KEY_VERSION_SMARTISAN).also { | |
sVersion = it | |
})) { | |
sName = ROM_SMARTISAN | |
} else { | |
sVersion = Build.DISPLAY | |
if (sVersion!!.toUpperCase(Locale.getDefault()).contains(ROM_FLYME)) { | |
sName = ROM_FLYME | |
} else { | |
sVersion = Build.UNKNOWN | |
sName = Build.MANUFACTURER.toUpperCase(Locale.getDefault()) | |
} | |
} | |
return sName == rom | |
} | |
private fun getProp(name: String): String? { | |
val line: String? | |
var input: BufferedReader? = null | |
try { | |
val p = Runtime.getRuntime().exec("getprop $name") | |
input = BufferedReader(InputStreamReader(p.inputStream), 1024) | |
line = input.readLine() | |
input.close() | |
} catch (ex: IOException) { | |
Log.e(TAG, "Unable to read prop $name", ex) | |
return null | |
} finally { | |
if (input != null) { | |
try { | |
input.close() | |
} catch (e: IOException) { | |
Log.e(TAG, "BufferedReader.close()", e) | |
} | |
} | |
} | |
return line | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<string name="dialog_open_white_list_error_title">跳转失败</string> | |
<string name="open_white_list_other_tips">由于Android系统限制,请您手动开启本软件自启动权限,并将此软件设置为受保护应用以及允许后台运行,防止被系统关闭</string> | |
<string name="open_white_list_samsung_tips">请在三星【智能管理器】->【自动运行应用程序】里面找到「划一划手势」并开启,防止被系统关闭</string> | |
<string name="samsung_open_white_list_failed">请打开【智能管理器】->【自动运行应用程序】里面找到「划一划手势」并开启,加入白名单中,否则设备进入睡眠后会自动杀掉应用进程</string> | |
<string name="huawei_open_white_list_failed">请打开【手机管家】->【应用启动管理】里面找到「划一划手势」,点击之后弹出【手动管理】窗口,选择「允许后台运行」和「允许自启动」</string> | |
<string name="flyme_open_white_list_failed">两种方法将应用加入白名单:\n1.找到【手机管家】->【权限管理】->【后台管理】里面找到「划一划手势」选择「允许后台运行」。\n2.打开【设置】->【应用管理】->【所有应用】->【划一划手势】->【权限管理】->【后台管理】选择「允许后台运行」。\n两种方法选择其中一种即可。</string> | |
<string name="vivo_open_white_list_failed">请按照以下步骤开启应用白名单:\n1.打开【i管家】点击【应用管理】依次打开【自启动管理】和【软件权限管理】找到「划一划手势」并开启选项。\n2.打开【设置】->【电池】->【后台高耗电】找到「划一划手势」并选择开启</string> | |
<string name="oppo_open_white_list_failed">请打开【设置】->【电池】->【其他】里面找到「划一划手势」点击关闭【后台冻结】和【异常时自动优化】</string> | |
<string name="miui_open_white_list_failed">请打开【设置】->【电量和性能】->【应用配置】找到「划一划手势」,后台配置选择「不限制」</string> | |
<string name="oneplus_open_white_list_failed">请打开【设置】->【应用】里面找到「划一划手势」->【电池用量】选择允许后台运行</string> | |
<string name="smartisan_open_white_list_failed">请按照以下步骤开启应用白名单:\n1.打开【设置】->【安全中心】->【内存清理】找到「划一划手势」并打开「后台常驻」\n2.在【安全中心】->【应用程序权限管理】->【后台自启动】里面找到「划一划手势」,并选择「始终允许」</string> | |
<string name="other_open_white_list_failed">应用白名单界面跳转失败,请自行前往【手机管家】、【安全管家】或【电池管理】中打开自启动和允许后台运行,将应用加入白名单</string> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
////////////////////:具体怎么提示,下面的弹框「仅供参考」//////////////////// | |
/** | |
* 提示用户打开「白名单管理列表页面」失败(即:自启动权限) | |
*/ | |
fun openWhiteListErrorDialog(context:Context){ | |
val msgId = when { | |
RomUtil.isMiui() -> R.string.miui_open_white_list_failed | |
RomUtil.isSamsung() -> R.string.samsung_open_white_list_failed | |
RomUtil.isOnePlus() -> R.string.oneplus_open_white_list_failed | |
RomUtil.isEmui() -> R.string.huawei_open_white_list_failed | |
RomUtil.isVivo() -> R.string.vivo_open_white_list_failed | |
RomUtil.isFlyme() -> R.string.flyme_open_white_list_failed | |
RomUtil.isOppo() -> R.string.oppo_open_white_list_failed | |
RomUtil.isSmartisan() -> R.string.smartisan_open_white_list_failed | |
else -> R.string.open_white_list_failed | |
} | |
val checkDetachableClickListener = DetachableClickListener.wrap( | |
DialogInterface.OnClickListener { dialog, _ -> | |
dialog?.dismiss() | |
}) | |
val confirmDialog = AlertDialog.Builder(context) | |
.setTitle(R.string.dialog_open_white_list_error_title) | |
.setMessage(msgId) | |
.setPositiveButton(R.string.main_dialog_ok,checkDetachableClickListener).create() | |
confirmDialog.setCanceledOnTouchOutside(false) | |
checkDetachableClickListener?.clearOnDetach(confirmDialog) | |
confirmDialog.show() | |
} | |
/** | |
* 提示用户打开「白名单管理列表页面」(即:自启动权限) | |
*/ | |
fun openWhiteListDialog(context:Context){ | |
val message = when { | |
RomUtil.isSmartisan() -> R.string.smartisan_open_white_list_failed | |
RomUtil.isSamsung() -> R.string.open_white_list_samsung_tips | |
RomUtil.isEmui() -> R.string.huawei_open_white_list_failed | |
else -> R.string.open_white_list_common_tips | |
} | |
val checkDetachableClickListener = DetachableClickListener.wrap( | |
DialogInterface.OnClickListener { dialog, _ -> | |
dialog?.dismiss() | |
if(!startWhiteListSetting(context)){ | |
openWhiteListErrorDialog() | |
} | |
}) | |
val confirmDialog = AlertDialog.Builder(context) | |
.setMessage(message) | |
.setPositiveButton(R.string.main_dialog_setting,checkDetachableClickListener).create() | |
confirmDialog.setCanceledOnTouchOutside(false) | |
checkDetachableClickListener?.clearOnDetach(confirmDialog) | |
confirmDialog.show() | |
} | |
////////////////////仅供参考:具体怎么提示,上面的弹框「仅供参考」//////////////////// | |
/** | |
* 跳转到「白名单管理列表页面」(无法保证所有设备系统都能正常跳转,会有无法跳转提示和容错界面) | |
*/ | |
fun startWhiteListSetting(context: Context):Boolean{ | |
val intent = Intent() | |
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) | |
var componentName: ComponentName? = null | |
try { | |
when { | |
RomUtil.isMiui() -> { | |
intent.action = "miui.intent.action.OP_AUTO_START" | |
intent.addCategory(Intent.CATEGORY_DEFAULT) | |
} | |
RomUtil.isSamsung() -> componentName = getSanmSungComponentName() | |
RomUtil.isOnePlus() -> componentName = getOnePlusComponentName() | |
RomUtil.isEmui() -> componentName = getHuaweiComponentName() | |
RomUtil.isVivo() -> componentName = getViVoComponentName() | |
RomUtil.isFlyme() -> componentName = getFlyMeComponentName() | |
RomUtil.isOppo() -> componentName = getOppoComponentName() | |
RomUtil.isQiku() -> componentName = get360ComponentName() | |
RomUtil.isSmartisan() -> intent.action = Settings.ACTION_SETTINGS | |
RomUtil.isLetv() -> intent.action = "com.letv.android.permissionautoboot" | |
} | |
if (null != componentName || null!=intent.action) { | |
intent.component = componentName | |
context.startActivity(intent) | |
return true | |
} | |
} catch (e: Exception) { | |
} | |
return false | |
} | |
private fun getHuaweiComponentName(): ComponentName? { | |
when { | |
//鸿蒙系统跳转失败容错:直接打开手机管家首页 | |
isHarmonyOS() -> return ComponentName( | |
"com.huawei.systemmanager", | |
"com.huawei.systemmanager.mainscreen.MainScreenActivity" | |
) | |
(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && Build.VERSION.SDK_INT < Build.VERSION_CODES.P) -> return ComponentName( | |
"com.huawei.systemmanager", | |
"com.huawei.systemmanager.appcontrol.activity.StartupAppControlActivity" | |
) | |
Build.VERSION.SDK_INT >= Build.VERSION_CODES.P -> return ComponentName( | |
"com.huawei.systemmanager", | |
"com.huawei.systemmanager.startupmgr.ui.StartupNormalAppListActivity" | |
) | |
Build.VERSION.SDK_INT >= Build.VERSION_CODES.M -> return ComponentName( | |
"com.huawei.systemmanager", | |
"com.huawei.systemmanager.startupmgr.ui.StartupNormalAppListActivity" | |
) | |
else -> return ComponentName( | |
"com.huawei.systemmanager", | |
"com.huawei.systemmanager.optimize.process.ProtectActivity" | |
) | |
} | |
} | |
private fun getSanmSungComponentName(): ComponentName = ComponentName("com.samsung.android.sm_cn", | |
"com.samsung.android.sm.ui.cstyleboard.SmartManagerDashBoardActivity") | |
private fun getViVoComponentName(): ComponentName? { | |
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { | |
ComponentName.unflattenFromString("com.iqoo.secure/.safeguard.PurviewTabActivity") | |
} else { | |
ComponentName( | |
"com.iqoo.secure", | |
"com.iqoo.secure.ui.phoneoptimize.SoftwareManagerActivity" | |
) | |
} | |
} | |
private fun getOppoComponentName(): ComponentName? { | |
return ComponentName( | |
"com.coloros.safecenter", | |
"com.coloros.safecenter.startupapp.StartupAppListActivity" | |
) | |
} | |
private fun getOnePlusComponentName(): ComponentName = ComponentName( | |
"com.oneplus.security", | |
"com.oneplus.security.chainlaunch.view.ChainLaunchAppListActivity" | |
) | |
private fun get360ComponentName(): ComponentName = ComponentName( | |
"com.yulong.android.coolsafe", | |
"com.yulong.android.coolsafe.ui.activity.autorun.AutoRunListActivity" | |
) | |
private fun getFlyMeComponentName(): ComponentName? = | |
ComponentName.unflattenFromString("com.meizu.safe/.permission.PermissionMainActivity") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment