W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
編寫:jdneo - 原文:http://developer.android.com/training/scheduling/wakelock.html
為了避免電量過度消耗,Android設(shè)備會在被閑置之后迅速進入睡眠狀態(tài)。然而有時候應(yīng)用會需要喚醒屏幕或者是喚醒CPU并且保持它們的喚醒狀態(tài),直至一些任務(wù)被完成。
想要做到這一點,所采取的方法依賴于應(yīng)用的具體需求。但是通常來說,我們應(yīng)該使用最輕量級的方法,減小其對系統(tǒng)資源的影響。在接下來的部分中,我們將會描述在設(shè)備默認(rèn)的睡眠行為與應(yīng)用的需求不相符合的情況下,我們應(yīng)該如何進行對應(yīng)的處理。
某些應(yīng)用需要保持屏幕常亮,比如游戲與視頻應(yīng)用。最好的方式是在你的Activity中(且僅在Activity中,而不是在Service或其他應(yīng)用組件里)使用FLAG_KEEP_SCREEN_ON屬性,例如:
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
該方法的優(yōu)點與喚醒鎖(Wake Locks)不同(喚醒鎖的內(nèi)容在本章節(jié)后半部分),它不需要任何特殊的權(quán)限,系統(tǒng)會正確地 管理應(yīng)用之間的切換,且不必關(guān)心釋放資源的問題。
另外一種方法是在應(yīng)用的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_SCRRE_ON等效。你可以選擇最適合你的應(yīng)用的方法。在Activity中通過代碼設(shè)置常亮標(biāo)識的優(yōu)點在于:你可以通過代碼動態(tài)清除這個標(biāo)示,從而使屏幕可以關(guān)閉。
Notes:除非你不再希望正在運行的應(yīng)用長時間點亮屏幕(例如:在一定時間無操作發(fā)生后,你想要將屏幕關(guān)閉),否則你是不需要清除FLAG_KEEP_SCRRE_ON 標(biāo)識的。WindowManager會在應(yīng)用進入后臺或者返回前臺時,正確管理屏幕的點亮或者關(guān)閉。但是如果你想要顯式地清除這一標(biāo)識,從而使得屏幕能夠關(guān)閉,可以使用
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
方法。
如果你需要在設(shè)備睡眠之前,保持CPU運行來完成一些工作,你可以使用PowerManager系統(tǒng)服務(wù)中的喚醒鎖功能。喚醒鎖允許應(yīng)用控制設(shè)備的電源狀態(tài)。
創(chuàng)建和保持喚醒鎖會對設(shè)備的電源壽命產(chǎn)生巨大影響。因此你應(yīng)該僅在你確實需要時使用喚醒鎖,且使用的時間應(yīng)該越短越好。如果想要在Activity中使用喚醒鎖就顯得沒有必要了。如上所述,可以在Activity中使用FLAG_KEEP_SCRRE_ON讓屏幕保持常亮。
使用喚醒鎖的一種合理情況可能是:一個后臺服務(wù)需要在屏幕關(guān)閉時利用喚醒鎖保持CPU運行。再次強調(diào),應(yīng)該盡可能規(guī)避使用該方法,因為它會影響到電池壽命。
不必使用喚醒鎖的情況:
- 如果你的應(yīng)用正在執(zhí)行一個HTTP長連接的下載任務(wù),可以考慮使用DownloadManager。
- 如果你的應(yīng)用正在從一個外部服務(wù)器同步數(shù)據(jù),可以考慮創(chuàng)建一個SyncAdapter
- 如果你的應(yīng)用需要依賴于某些后臺服務(wù),可以考慮使用RepeatingAlarm或者Google Cloud Messaging,以此每隔特定的時間,將這些服務(wù)激活。
為了使用喚醒鎖,首先需要在應(yīng)用的Manifest清單文件中增加WAKE_LOCK權(quán)限:
<uses-permission android:name="android.permission.WAKE_LOCK" />
如果你的應(yīng)用包含一個BroadcastReceiver并使用Service來完成一些工作,你可以通過WakefulBroadcastReceiver管理你喚醒鎖。后續(xù)章節(jié)中將會提到,這是一種推薦的方法。如果你的應(yīng)用不滿足上述情況,可以使用下面的方法直接設(shè)置喚醒鎖:
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
Wakelock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"MyWakelockTag");
wakeLock.acquire();
可以調(diào)用wakelock.release()
來釋放喚醒鎖。當(dāng)應(yīng)用使用完畢時,應(yīng)該釋放該喚醒鎖,以避免電量過度消耗。
你可以將BroadcastReceiver和Service結(jié)合使用,以此來管理后臺任務(wù)的生命周期。WakefulBroadcastReceiver是一種特殊的BroadcastReceiver,它專注于創(chuàng)建和管理應(yīng)用的PARTIAL_WAKE_LOCK。WakefulBroadcastReceiver會將任務(wù)交付給Service(一般會是一個IntentService),同時確保設(shè)備在此過程中不會進入睡眠狀態(tài)。如果在該過程當(dāng)中沒有保持住喚醒鎖,那么還沒等任務(wù)完成,設(shè)備就有可能進入睡眠狀態(tài)了。其結(jié)果就是:應(yīng)用可能會在未來的某一個時間節(jié)點才把任務(wù)完成,這顯然不是你所期望的。
要使用WakefulBroadcastReceiver,首先在Manifest文件添加一個標(biāo)簽:
<receiver android:name=".MyWakefulReceiver"></receiver>
下面的代碼通過startWakefulService()
啟動MyIntentService
。該方法和startService()
類似,除了WakeflBroadcastReceiver會在Service啟動后將喚醒鎖保持住。傳遞給startWakefulService()
的Intent會攜帶有一個Extra數(shù)據(jù),用來標(biāo)識喚醒鎖。
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);
}
}
當(dāng)Service結(jié)束之后,它會調(diào)用MyWakefulReceiver.completeWakefulIntent()
來釋放喚醒鎖。completeWakefulIntent()
方法中的Intent參數(shù)是和WakefulBroadcastReceiver傳遞進來的Intent參數(shù)一致的:
public class MyIntentService extends IntentService {
public static final int NOTIFICATION_ID = 1;
private NotificationManager mNotificationManager;
NotificationCompat.Builder builder;
public MyIntentService() {
super("MyIntentService");
}
@Override
protected void onHandleIntent(Intent intent) {
Bundle extras = intent.getExtras();
// Do the work that requires your app to keep the CPU running.
// ...
// Release the wake lock provided by the WakefulBroadcastReceiver.
MyWakefulReceiver.completeWakefulIntent(intent);
}
}
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: