它會先變暗,關閉螢幕,最後關閉 CPU 以節省電源
但有時我們需要螢幕長時間開啟(如遊戲或影片)
或不需要螢幕開啟但是希望保持 CPU 運作直到某些操作完成
就需要一些方法
Keep the Screen On
設定 FLAG_KEEP_SCREEN_ON (只能在 Activity 而不能在 service 或其他 app component)
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); }這不需要特別的 permission 而且使用者在不同 app 間切換時我們不需要擔心資源會被釋放掉
另一個方法是在 layout xml 檔案中使用 android:keepScreenOn 屬性
這等同於使用 FLAG_KEEP_SCREEN_ON
但是若之後需要將 flag 移掉的話用 FLAG_KEEP_SCREEN_ON 會比較方便
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:keepScreenOn="true"> ... </RelativeLayout>
Keep the CPU On
如果要保持 CPU 持續運作以完成某些工作
可以用 WAKE_LOCK 這個 PowerManager 的 system service
但因為這很容易讓電池電量被榨乾
所以官方強烈建議只在必要時適當使用(例如不應該在 activity 中使用,要保持 activity 螢幕開啟應使用 FLAG_KEEP_SCREEN_ON)
其他可選的方案有:
1. 如果 app 要進行長時間的 HTTP download,使用 DownloadManager
2. 如果 app 要從外部 server 同步資料,那就建立一個 sync adapter
3. 如果 app 要依賴 background service,使用 repeating alarms 或 Google Cloud Messaging 來觸發
要使用 WAKE_LOCK 首先要宣告 uses-permission
<uses-permission android:name="android.permission.WAKE_LOCK" />
然後建議的方法是使用 WakefulBroadcastReceiver 來管理 WAKE_LOCK
不過如果不是用這方法可以直接用 code 設定
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE); WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyWakelockTag"); wakeLock.acquire();
//釋放 wake lock wakelock.release()
接下來就來介紹 WakefulBroadcastReceiver
WakefulBroadcastReceiver 是一種特別的 broadcast receiver
它負責創建並管理我們 app 中的 PARTIAL_WAKE_LOCK
將工作傳給 service (通常是 IntentService)並確保 device 不會休眠
如果我們沒有持有 wake lock 就把工作丟給 service 就無法確保 device 不會在工作完成前就休眠
使用 WakefulBroadcastReceiver 的第一步是在 manifest 宣告
<receiver android:name=".MyWakefulReceiver"></receiver>
接著使用 startWakefulService 就可以在 service 啟動時持有 wake lock
傳入的 Intent 包含一個 extra 用來識別 wake lock
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); } }
當 service 完成時會呼叫 WakefulBroadcastReceiver 的 completeWakefulIntent() 以釋放 wake lock
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(); // 進行一些工作 ...(省略) // 最後釋放 WakefulBroadcastReceiver 提供的 wake lock MyWakefulReceiver.completeWakefulIntent(intent); } }
相關資料:
Managing Device Awake State
Keeping the Device Awake
沒有留言:
張貼留言