android之保持设备唤醒

来源:互联网 发布:讨鬼传极pc版优化问题 编辑:程序博客网 时间:2024/05/23 20:41

     为了避免消耗电池,一个空闲的设备很快就会进入休眠,但是有的时候需要应用保持屏幕或CPU唤醒来完成一些工作。

      实现的方法取决于你的APP的要求,一般是采取最轻量级的方法,以减少你的APP对系统资源的影响。下面讲述如何处理设备默认的休眠行为和应用需求之间的矛盾。


1.保持屏幕亮起

     某些APP需要保持屏幕一直亮起,如游戏和看电影。最好的方法就是在Activity(只是Activity,而不是services或其他App的组件)中使用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);
  }

      和wakelock(下面会讨论到)比较,这个方法好处就是不需要申请权限,平台就能正确地管理移动于应用之间的用户,也不需要你的APP去考虑无用资源的释放。

      另一个方法去实现设备亮起就是在应用的布局文件中使用 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标志,关闭屏幕。

      注意:正常情况下,你是不需要清除 FLAG_KEEP_SCREEN_ON标志的,除非你不想屏幕在应用还运行时保持亮起(比如程序有一段时间都没有发生活动,你想把屏幕关闭)。当你的APP跑到后台或恢复前台时,Window manager会进行相应的设置。但是如果你想显式地进行清除这个标志,关闭屏幕,可以使用clearFlag():

getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON).


2.保持CPU运行

     有时候为了在设备休眠之前能完成一些工作,必须保持CPU运行。你可以使用一个PowerManager系统服务特性——WakeLock实现。Wakelock允许APP控制设备的电源状态。

     创建并持有Wakelock对设备电池寿命有很大影响。所以你应该在确实很必要的时候才使用,且使用时间尽可能少。比如在Acitivity中就没必要用了,如前面所述,可以使用FLAG_KEEP_SCREEN_ON标志。

     使用WakeLock一个合适的例子就是,当屏幕关闭的时候,后台服务中需要持有WakeLock来保持CPU运行,以继续完成工作。但还是那句话,应尽量避免WakeLock的使用,否则会影响电池寿命。

     使用WakeLock的第一步就是在应用的manifest文件中添加WAKE_LOCK权限

<uses-permission android:name="android.permission.WAKE_LOCK" />

      如果你的APP包含有broadcast Receiver,且在broadcast Receiver中开启了服务去完成一些工作,那么可以通过 WakefulBroadcastReceiver来管理WakeLock,下面将会讲述,这是我们推荐的方法,如果你的APP不符合这个模式,下面是直接设置WakeLock的方法:

PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
Wakelock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
        "MyWakelockTag");
wakeLock.acquire();

      调用wakelock.release()来释放WakeLock,这会释放CPU。当你的APP执行完成时不要忘了释放WakeLock,这样能避免消耗电池。


3.使用WakefulBroadcastReceiver

      使用Broadcast Receiver和service能让你很好地管理后台任务的生命周期。

      WakefulBroadcastReceiver是BroadcastReceiver的一种特例。它会为你的APP创建和管理一个PARTIAL_WAKE_LOCK 类型的WakeLock。WakefulBroadcastReceiver把工作交接给service(通常是IntentService),并保证交接过程中设备不会进入休眠状态。如果不持有WakeLock,设备很容易在任务未执行完前休眠。最终结果是你的应用不知道会在什么时候能把工作完成,相信这不是你想要的。

      像其他BroadcastReceiver使用WakefulBroadcastReceiver的第一步就是把它加到manifest中:

<receiver android:name=".MyWakefulReceiver"></receiver>


      下面的代码通过startWakefulService()开启MyIntentService,该方法和 startService()相似,不同之处在于WakefulBroadcastReceiver会在服务开启的时候持有一个WakeLock。startWakefulService传递的intent封装了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传来的intent:

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);
    }
}

0 0