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