1. 程式人生 > >Android保持裝置喚醒

Android保持裝置喚醒

Contents

保持裝置喚醒... 1

使用wakelock之外的選擇... 1

保持螢幕亮... 1

保持CPU執行... 2

用BroadcastReceiver保持裝置喚醒... 2

 

保持裝置喚醒

為了避免電量流失,Android裝置進入閒置狀態後很快就會睡眠。然而,有時應用需要裝置保持螢幕或者CPU處於喚醒狀態一直到完成某項工作。

應用的需求不同採取的策略也不同。然而一般原則是儘量使用輕量級的方法,最小化應用對系統資源的使用。下面的段落描述瞭如何處理這種情況,即裝置預設的睡眠行為和你的應用的需求不相容。

使用wakelock之外的選擇

在應用使用wakelock前,考慮是否你的需求滿足下面幾種不建議用wakelock的情況:

  • 長時間執行的HTTP下載,考慮用DownloadManager。
  • 應用需要從外部伺服器同步資料,考慮用sync adapter。
  • 如果應用依賴於後臺服務,考慮用JobScheduler或者FCM定期觸發服務。

保持螢幕亮

一些應用需要保持螢幕亮,比如遊戲或視訊應用。最好的辦法是在Activity裡使用FLAG_KEEP_SCREEN_ON(只在Activity,而不在Service或其他應用元件中使用wakelock)。例如:

class MainActivity

: Activity() {

   
override fun onCreate(savedInstanceState: Bundle?) {
       
super.onCreate(savedInstanceState)
        setContentView(R.layout.activity
_main)
        window.addFlags(
WindowManager.LayoutParams.FLAG_KEEP_SCREEN
_ON)
    }
}

這種策略的好處是,不像使用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()傳遞過來的一樣。