1.概述
当 Android 设备空闲时,它会首先调暗屏幕,然后关闭屏幕,最终关闭 CPU。这可以防止设备的电池电量快速耗尽。不过,有时您的应用可能需要采取不同的行为:
- 游戏或电影应用等应用可能需要使屏幕保持开启状态。
- 其他应用可能不需要屏幕始终处于开启状态,但可能需要 CPU 持续运行,直到某项关键操作完成。
2.保持屏幕开启状态
- FLAG_KEEP_SCREEN_ON
class MainActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
}
}
- 在应用的布局 XML 文件中,使用 android:keepScreenOn 属性:
例如:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:keepScreenOn="true">
...
</RelativeLayout>
上述两种方式的效果是一样的。如果需要清除状态,请调用getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)。
- PowerManager
一.添加权限
<uses-permission android:name="android.permission.WAKE_LOCK"/>
二.获取PowerManager
val pm = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
pm = ctx.getSystemService(PowerManager::class.java)
} else {
pm = ctx.getSystemService(Context.POWER_SERVICE)?.let {
it as PowerManager
}
}
三.创建WakeLock唤醒屏幕
val wakeLock = pm?.newWakeLock(
PowerManager.ACQUIRE_CAUSES_WAKEUP or PowerManager.SCREEN_BRIGHT_WAKE_LOCK,
"wakeUp:screen")
wakeLock?.acquire(5 * 1000L)//5秒后释放唤醒锁
- WakefulBroadcastReceiver(AndroidX已移除)
特殊类型的广播接收器,负责为应用创建和管理 PARTIAL_WAKE_LOCK。
一.创建广播接收器
class MyWakefulReceiver : WakefulBroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
Intent(context, MyIntentService::class.java).also { service ->
//启动服务进行业务逻辑处理,在任务处理完之前,设备不会进入休眠状态
WakefulBroadcastReceiver.startWakefulService(context, service)
}
}
}
二.在Manifest中添加
<receiver android:name=".MyWakefulReceiver"/>
三.释放
class MyIntentService : IntentService("MyIntentService") {
override fun onHandleIntent(intent: Intent) {
val extras: Bundle = intent.extras
//进行业务处理
MyWakefulReceiver.completeWakefulIntent(intent)//完成后释放
}
}
3.保持CPU运行状态
- AlarmManager
闹钟的类型:
- ELAPSED_REALTIME - 基于自设备启动以来所经过的时间触发待定 intent,但不会唤醒设备。经过时间包括设备处于休眠状态期间的任何时间。
- ELAPSED_REALTIME_WAKEUP - 唤醒设备,并在自设备启动以来特定时间过去之后触发待定 intent。
- RTC - 在指定的时间触发待定 intent,但不会唤醒设备。
- RTC_WAKEUP - 唤醒设备以在指定的时间触发待定 intent。
创建闹钟广播接收器
class AlarmReceiver: BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
//do things
}
}
创建一次性闹钟
val alarmIntent = Intent(application, AlarmReceiver::class.java).let {
intent ->
//如果需要传输数据可通过intent
PendingIntent.getBroadcast(application,0,intent,0)
}
alarmIntent
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
alarm?.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime()+delayTime,
alarmIntent)
}else{
alarm?.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime()+delayTime,
alarmIntent)
}
创建重复性闹钟
val alarmIntent = Intent(application, AlarmReceiver::class.java).let {
intent -> PendingIntent.getBroadcast(application,0,intent,0)
}
//非精确性重复性闹钟
alarm?.setInexactRepeating(AlarmManager.RTC_WAKEUP,
SystemClock.elapsedRealtime()+AlarmManager.INTERVAL_HALF_HOUR,
AlarmManager.INTERVAL_HALF_HOUR,//每隔半个小时触发一次
alarmIntent)
//精确性重复闹钟
alarm?.setRepeating(
AlarmManager.RTC_WAKEUP,
SystemClock.elapsedRealtime() + delayTime,
AlarmManager.INTERVAL_HALF_HOUR,
alarmIntent
)
对于大多数应用来说,setInexactRepeating() 是合适的选择。因为Android 会同步多个不精确的重复闹钟,并同时触发它们。这样可以减少耗电量。 对于具有严格时间要求的应用,请使用 setRepeating()。不过应尽量避免使用精确的闹钟。
在设备重启时重新启动闹钟
默认情况下,当设备关机时,所有闹钟都会被取消。为了防止出现这种情况,您可以将应用设计为在用户重启设备时,自动重新启动重复闹钟。这样可以确保 AlarmManager 继续执行其任务,而无需用户手动重新启动闹钟。
- 在Manifest中添加权限
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
用户必须启动过应用一次,否则无效
- 创建BroadcastReceiver接收启动广播
class SampleBootReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (intent.action == "android.intent.action.BOOT_COMPLETED") {
// 重新设置闹钟
}
}
}
- 在Manifest中添加receiver
<receiver android:name=".SampleBootReceiver"
android:enabled="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"></action>
</intent-filter>
</receiver>
- 启用广播接收器
val receiver = ComponentName(context, SampleBootReceiver::class.java)
context.packageManager.setComponentEnabledSetting(
receiver,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP
)
- 停用广播接收器
val receiver = ComponentName(context, SampleBootReceiver::class.java)
context.packageManager.setComponentEnabledSetting(
receiver,
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP
)