Android保持裝置喚醒
Contents
保持裝置喚醒
為了避免電量流失,Android裝置進入閒置狀態後很快就會睡眠。然而,有時應用需要裝置保持螢幕或者CPU處於喚醒狀態一直到完成某項工作。
應用的需求不同採取的策略也不同。然而一般原則是儘量使用輕量級的方法,最小化應用對系統資源的使用。下面的段落描述瞭如何處理這種情況,即裝置預設的睡眠行為和你的應用的需求不相容。
使用wakelock之外的選擇
在應用使用wakelock前,考慮是否你的需求滿足下面幾種不建議用wakelock的情況:
- 長時間執行的HTTP下載,考慮用DownloadManager。
- 應用需要從外部伺服器同步資料,考慮用sync adapter。
- 如果應用依賴於後臺服務,考慮用JobScheduler或者FCM定期觸發服務。
保持螢幕亮
一些應用需要保持螢幕亮,比如遊戲或視訊應用。最好的辦法是在Activity裡使用FLAG_KEEP_SCREEN_ON(只在Activity,而不在Service或其他應用元件中使用wakelock)。例如:
class MainActivity
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN
}
}
這種策略的好處是,不像使用wakelock,他不需要特殊許可權,平臺可以負責管理使用者在應用之間的切換,應用不用關心釋放資源的事情。
另一個實現方式是在應用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>
用android:keepScreenOn=”true”等同於FLAG_KEEP_SCREEN_ON,對你的應用來說,哪個好用就用哪個。在Activity中設定這個屬性的好處是,如果不需要了,你可以在後面的程式中選擇關掉它,這樣螢幕就不會長亮了。
注意:你不需要清除FLAG_KEEP_SCREEN_ON標誌,除非你不再需要螢幕保持長亮(例如,你希望在一定時間不活動之後螢幕時間超時)。當應用進入後臺執行或者重新進入前臺,Window Manager會負責螢幕的亮暗。但是如果你需要顯式清除這項標誌,以允許螢幕重新關掉,用clearFlags():getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)。
保持CPU執行
如果你希望裝置睡去之前保持CPU執行以完成某項工作,可以用PowerManager的系統服務功能wakelock。Wakelock允許你控制主機的電源狀態。
建立和持有wakelock對主機的電池影響巨大。所以只有在非常必要的時候使用wakelock,並且持有時間儘可能短。例如,你永遠不需要在Activity中使用wakelock。如上文所述,如果想在Activty中亮,使用FLAG_KEEP_SCREEN_ON。
一個合理的使用wakelock的情況是,後臺服務需要獲取wakelock,在螢幕關的時候保持CPU執行。再次強調,儘可能減少使用wakelock的時間,因為太耗電了。
要使用wakelock,先在應用manifest檔案中加入許可權:
<uses-permission android:name="android.permission.WAKE_LOCK" />
如果你的應用包含一個BroadcastReceiver,啟動一個服務做一些操作,可以通過WakefulBroadcastReceiver管理你的wakelock。
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE); WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyApp::MyWakelockTag"); wakeLock.acquire();
要釋放wakelock,呼叫wakelock.release()。及時釋放wakelock很重要。
用BroadcastReceiver保持裝置喚醒
用BroadcastReceiver和Service管理後臺任務的生命週期。
WakefulBroadcastReceiver是一個特殊的BroadcastReceiver,他負責為應用建立和管理PARTIAL_WAKE_LOCK。WakefulBroadcastReceiver把工作傳給Service(一般是IntentService),同時保證裝置在傳輸過程中不進入睡眠模式。如果你在傳輸過程中不保持wakelock,有可能裝置進入睡眠模式,而你的任務還沒有完成。
使用WakefulBroadcastReceiver的第一步是把它新增到manifest中,就像其他BroadcastReceiver一樣。
<receiver android:name=".MyWakefulReceiver"></receiver>
下面的程式碼用startWakefulService()啟動了MyIntentService。相比startService(),這個方法在啟動的時候持有一個wakelock。通過startWakefulService()傳遞的intent中有個extra,指定wakelock型別。
public class MyWakefulReceiver extends WakefulBroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { // Start the service, keeping the device awake while the service is // launching. This is the Intent to deliver to the service. Intent service = new Intent(context, MyIntentService.class); startWakefulService(context, service); } }
服務完成時呼叫MyWakefulReceiver.completeWakefulIntent()釋放wakelock。completeWakefulIntent()的引數與從WakefulBroadcastReceiver()傳遞過來的一樣。