You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Kotlin编写的Android应用转为系统应用以实现程序化关机?

解决Android程序化关机的两个问题:转为系统应用与Magisk Root命令失效

一、将Kotlin应用转为系统应用的方法

要使用android.intent.action.ACTION_REQUEST_SHUTDOWN,应用必须是系统应用且持有android.permission.SHUTDOWN权限,以下是可行方案:

  • 方式1:手动将APK放入系统目录

    1. 确保设备已解锁Bootloader并获取Magisk Root权限
    2. 挂载系统分区为可写:执行su -c mount -o rw,remount /system(部分Android 10+设备可能是/system_root)
    3. 将编译好的APK推送到/system/priv-app/YourApp/目录(priv-app比/system/app/拥有更高权限,更适合需要系统级权限的应用)
    4. 修改APK文件权限:su -c chmod 644 /system/priv-app/YourApp/YourApp.apk
    5. 重启设备,此时应用会被识别为系统应用,SHUTDOWN权限会自动授予
  • 方式2:通过Magisk模块挂载(推荐)

    1. 制作一个Magisk模块:创建模块目录,在其中新建system/priv-app/YourApp/路径,放入你的APK
    2. 编写module.prop配置文件,定义模块名称、版本等信息
    3. 将模块打包为ZIP,通过Magisk Manager刷入
    4. 重启后,Magisk会自动将APK挂载到系统目录,既实现系统应用效果,又不会被系统OTA更新覆盖

注意:无论哪种方式,都需要在AndroidManifest.xml中添加权限声明:

<uses-permission android:name="android.permission.SHUTDOWN" />

二、Magisk Root执行关机命令失效的排查与解决

你提供的Java代码转Kotlin后,若执行无效,可按以下步骤排查:

  1. 确认应用已获取Root权限
    打开Magisk Manager的「超级用户」列表,检查你的应用是否被授予Root权限,且权限状态为「允许」

  2. 替换关机命令
    部分设备不支持reboot -p,可尝试用poweroff命令替代,Kotlin代码如下:

    try {
        val proc = Runtime.getRuntime().exec(arrayOf("su", "-c", "poweroff"))
        proc.waitFor()
    } catch (ex: Exception) {
        ex.printStackTrace()
    }
    
  3. 捕获命令执行的错误输出
    仅捕获异常无法定位具体问题,需读取进程的错误流:

    try {
        val proc = Runtime.getRuntime().exec(arrayOf("su", "-c", "reboot -p"))
        val errorReader = proc.errorStream.bufferedReader()
        val outputReader = proc.inputStream.bufferedReader()
        val errorMsg = errorReader.readText()
        val outputMsg = outputReader.readText()
        if (errorMsg.isNotEmpty()) {
            println("命令执行错误:$errorMsg")
        }
        if (outputMsg.isNotEmpty()) {
            println("命令输出:$outputMsg")
        }
        proc.waitFor()
    } catch (ex: Exception) {
        ex.printStackTrace()
    }
    

    通过错误信息可判断是命令不支持、权限不足还是SELinux限制

  4. 强制以Root用户0执行命令
    部分SU环境可能存在权限继承问题,尝试添加-0参数强制切换到UID 0:

    val proc = Runtime.getRuntime().exec(arrayOf("su", "-0", "-c", "reboot -p"))
    
  5. 临时关闭SELinux测试
    若SELinux处于Enforcing状态,可能阻止命令执行,可临时设置为Permissive:

    Runtime.getRuntime().exec(arrayOf("su", "-c", "setenforce 0"))
    // 再执行关机命令
    Runtime.getRuntime().exec(arrayOf("su", "-c", "reboot -p"))
    

    注意:长期关闭SELinux会降低设备安全性,测试后建议恢复为Enforcing

内容的提问来源于stack exchange,提问作者shamant

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 23:25:04