You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Android设备定时休眠唤醒编程实现及API21后替代方案问询

Android API 21+ 实现设备休眠与唤醒的替代方案

确实,从API 21开始,PowerManager.goToSleep()被标记为系统隐藏方法,普通应用没法直接调用了。不过有几种靠谱的替代方案,能帮你实现特定条件下休眠/唤醒设备的需求,我给你详细说说:

一、临时修改屏幕超时时间(适配普通应用场景)

你代码里提到的修改SCREEN_OFF_TIMEOUT的思路是可行的——本质是让系统根据你设置的超时时间自动休眠,之后再恢复原来的设置。这个方法不需要特殊的管理员权限,但需要申请WRITE_SETTINGS权限,而且API 23+还要动态申请用户授权。

完整代码示例:

  1. 首先在Manifest里声明权限:
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
  1. 动态申请权限(API 23+):
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    if (!Settings.System.canWrite(context)) {
        Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS);
        intent.setData(Uri.parse("package:" + context.getPackageName()));
        context.startActivity(intent);
    }
}
  1. 修改屏幕超时实现休眠,之后恢复原设置:
// 保存原有的超时时间
int originalTimeout = Settings.System.getInt(getContentResolver(), 
    Settings.System.SCREEN_OFF_TIMEOUT, 60000);

// 设置为立即休眠(比如100毫秒,系统会很快触发休眠)
Settings.System.putInt(getContentResolver(), 
    Settings.System.SCREEN_OFF_TIMEOUT, 100);

// 休眠完成后记得恢复原设置(可以用Handler延迟执行,或者在唤醒后恢复)
new Handler(Looper.getMainLooper()).postDelayed(() -> {
    Settings.System.putInt(getContentResolver(), 
        Settings.System.SCREEN_OFF_TIMEOUT, originalTimeout);
}, 500); // 延迟时间可以根据实际情况调整

注意:这个方法是让系统自动触发休眠,不是立即执行,适合能接受短暂延迟的场景。

二、使用设备管理员权限(实现立即休眠)

如果需要让设备立即休眠,最可靠的方式是借助DevicePolicyManagerlockNow()方法,但前提是你的应用要获得设备管理员权限(需要用户手动授权)。

实现步骤:

  1. 创建一个DeviceAdminReceiver子类:
public class MyDeviceAdminReceiver extends DeviceAdminReceiver {
    // 这里可以重写一些回调方法,比如管理员激活/取消的通知
}
  1. 在Manifest里注册这个Receiver,添加必要的权限和元数据:
<uses-permission android:name="android.permission.BIND_DEVICE_ADMIN" />

<receiver
    android:name=".MyDeviceAdminReceiver"
    android:permission="android.permission.BIND_DEVICE_ADMIN">
    <meta-data
        android:name="android.app.device_admin"
        android:resource="@xml/device_admin" />
    <intent-filter>
        <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
    </intent-filter>
</receiver>
  1. 在res/xml目录下创建device_admin.xml配置文件:
<device-admin xmlns:android="http://schemas.android.com/apk/res/android">
    <uses-policies>
        <force-lock /> <!-- 必须声明这个权限才能使用lockNow() -->
    </uses-policies>
</device-admin>
  1. 引导用户激活设备管理员,之后调用休眠方法:
DevicePolicyManager dpm = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
ComponentName adminComponent = new ComponentName(this, MyDeviceAdminReceiver.class);

// 检查是否已获得管理员权限
if (!dpm.isAdminActive(adminComponent)) {
    // 引导用户激活管理员
    Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
    intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, adminComponent);
    intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION, "需要激活设备管理员权限以实现一键休眠");
    startActivity(intent);
} else {
    // 立即锁定设备(休眠)
    dpm.lockNow();
}

三、设备唤醒的实现方案

对应休眠,唤醒设备的话可以用以下两种方式:

1. 保持屏幕唤醒(前台场景)

如果是在Activity或Service前台运行时需要唤醒屏幕,最简单的方式是在布局里添加属性:

<LinearLayout
    ...
    android:keepScreenOn="true">
</LinearLayout>

或者在代码中设置:

getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

2. 使用WakeLock(需要权限)

如果需要在后台唤醒屏幕,可以使用PowerManager.WakeLock,但要注意API 26+对后台WakeLock的限制:

// 声明权限
<uses-permission android:name="android.permission.WAKE_LOCK" />

// 使用WakeLock唤醒屏幕
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wakeLock = pm.newWakeLock(
    PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP,
    "MyApp:WakeLockTag"
);
wakeLock.acquire(10000); // 唤醒并保持10秒,之后自动释放
// 用完记得手动释放:wakeLock.release();

一些重要提醒

  • 权限合规:WRITE_SETTINGS和设备管理员权限都需要用户手动授权,不能静默获取,要做好用户引导
  • 后台限制:Android 8.0+对后台操作限制严格,尽量在前台或使用前台服务执行休眠/唤醒操作
  • 功能滥用:避免频繁触发休眠/唤醒,不仅影响用户体验,还可能导致Google Play审核不通过

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

火山引擎 最新活动