Flutter应用如何程序化实现Android设备开关机控制
Flutter 控制 Android TV(X96 Mini)开关机实现方案
你之前用MethodChannel方案失败,核心原因基本都是系统权限没配置对——关机、重启属于Android系统级操作,普通第三方应用默认没有调用权限,以下是可直接落地的实现步骤:
一、基础权限配置
首先在Android工程的AndroidManifest.xml中添加所需权限:
<uses-permission android:name="android.permission.SHUTDOWN" /> <uses-permission android:name="android.permission.REBOOT" /> <uses-permission android:name="android.permission.DEVICE_POWER" /> <uses-permission android:name="android.permission.WAKE_LOCK" />
以上权限属于signature|privileged级别,普通签名应用无法直接获取,针对X96 Mini这类可开放root权限的盒子,直接在系统设置里打开root开关即可,不需要额外刷系统签名;如果不想用root,可以通过adb命令将应用设置为设备所有者:
adb shell dpm set-device-owner 你的应用包名/.TvDeviceAdminReceiver
二、关机/重启功能实现(MethodChannel正确写法)
Flutter端代码
创建统一的方法通道,封装关机、重启调用逻辑:
const _controlChannel = MethodChannel('com.yourapp.tvcontrol'); // 执行关机 Future<void> triggerShutdown() async { try { await _controlChannel.invokeMethod('shutdown'); } on PlatformException catch (e) { debugPrint('关机执行失败:${e.message}'); } } // 执行重启 Future<void> triggerReboot() async { try { await _controlChannel.invokeMethod('reboot'); } on PlatformException catch (e) { debugPrint('重启执行失败:${e.message}'); } }
Android原生端配置
- 先创建设备管理员接收器类,继承
DeviceAdminReceiver:
class TvDeviceAdminReceiver : DeviceAdminReceiver()
- 在
AndroidManifest.xml中声明该接收器:
<receiver android:name=".TvDeviceAdminReceiver" android:permission="android.permission.BIND_DEVICE_ADMIN"> <meta-data android:name="android.app.device_admin" android:resource="@xml/device_admin_config" /> <intent-filter> <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" /> </intent-filter> </receiver>
- 在
res/xml目录下新建device_admin_config.xml,声明管理员权限:
<?xml version="1.0" encoding="utf-8"?> <device-admin> <uses-policies> <force-lock /> </uses-policies> </device-admin>
- 在
MainActivity中注册方法通道,处理原生调用逻辑。针对X96 Mini优先用root shell命令实现,兼容性远高于系统API:
override fun configureFlutterEngine(flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine) MethodChannel(flutterEngine.dartExecutor.binaryMessenger, "com.yourapp.tvcontrol") .setMethodCallHandler { call, result -> when (call.method) { "shutdown" -> { // X96 Mini 打开root后直接执行关机命令,适配所有固件版本 try { Runtime.getRuntime().exec(arrayOf("su", "-c", "reboot -p")) result.success(true) } catch (e: Exception) { // 无root时走系统API兜底 val powerManager = getSystemService(Context.POWER_SERVICE) as PowerManager try { val shutdownMethod = powerManager.javaClass.getMethod( "shutdown", Boolean::class.javaPrimitiveType, String::class.java, Boolean::class.javaPrimitiveType ) shutdownMethod.invoke(powerManager, false, null, false) result.success(true) } catch (ex: Exception) { result.error("SHUTDOWN_FAIL", "无执行关机的权限,请开启root或激活设备管理员", null) } } } "reboot" -> { try { Runtime.getRuntime().exec(arrayOf("su", "-c", "reboot")) result.success(true) } catch (e: Exception) { val rebootIntent = Intent(Intent.ACTION_REBOOT) rebootIntent.putExtra("nowait", 1) rebootIntent.putExtra("interval", 1) rebootIntent.putExtra("window", 0) sendBroadcast(rebootIntent) result.success(true) } } else -> result.notImplemented() } } }
三、开机功能实现
完全断电关机的设备没有任何软件方案可以直接触发开机,针对X96 Mini可以实现两种类开机场景:
- 休眠唤醒:如果设备只是进入锁屏休眠状态,通过
PowerManager唤醒屏幕即可,代码如下:val powerManager = getSystemService(Context.POWER_SERVICE) as PowerManager val wakeLock = powerManager.newWakeLock( PowerManager.SCREEN_BRIGHT_WAKE_LOCK or PowerManager.ACQUIRE_CAUSES_WAKEUP, "tvapp:screen_wake" ) wakeLock.acquire(3000) - 定时开机:X96 Mini搭载的Amlogic芯片支持RTC定时上电,通过root权限写入RTC唤醒时间戳即可实现定时开机,执行shell命令:
命令执行后设备正常关机,到设定时间会自动上电开机,全版本X96 Mini均支持该方案。su -c "echo 0 > /sys/class/rtc/rtc0/wakealarm; echo 开机时间的Unix时间戳 > /sys/class/rtc/rtc0/wakealarm"
四、X96 Mini适配注意事项
- 绝大多数市售X96 Mini默认在开发者选项里提供root开关,打开后直接执行su命令的方案兼容性最好,不需要折腾系统签名、设备管理员激活等复杂操作
- 部分第三方修改固件屏蔽了系统层关机API,哪怕拿到权限也会调用失败,直接走shell命令是最稳妥的方案
- 不要尝试不申请权限直接调用关机/重启接口,Android 4.4以上版本对这类系统操作做了严格的权限拦截,无权限状态下100%调用失败
内容的提问来源于stack exchange,提问作者Aakash Ghimire
相关产品推荐
相关产品推荐

