http://developer.android.com/training/scheduling/index.html

当静置一个设备的时候,先会屏幕变暗,然后关闭屏幕,最后关闭CPU,以省电。但有的时候有这样的需求: .比如游戏或者电影,需要屏幕一直亮着。 .有些app不要求屏幕亮着,但是要求CPU一直运行,直到完成某项工作。

1.保持屏幕变亮

getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

只能用于activity,不能用于其它组件。

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

或者在activity的 layout文件某个布局或view上设置:android:keepScreenOn="true",会自动给其相关的Window设置上述的属性。

设置这个属性不需要特殊的权限,不需要手动维护和释放。系统会根据当前activity是在后台还是前台来自动切换状态,界面在前台时才会起作用。 若要清除标记,可调用:

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

2.保持CPU唤醒

阻止系统休眠,耗电明显,却有必须的时候才用,而且时间要尽量的短。 一般是后台服务里面用,如果是Activity应该用上面的 FLAG_KEEP_SCREEN_ON.

使用 PowerManager的电源锁需要如下的权限:

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

一定要记得释放,而且要在完成工作后尽快的释放。

//申请电源锁:
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
Wakelock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyWakelockTag");
wakeLock.acquire(); //释放电源锁:
wakelock.release()

3.使用 WakefulBroadcastReceiver

在 support.v4 兼容包中,用来启动一个service(通常是一个IntentService)。因为它维护一个PARTIAL_WAKE_LOCK电源锁,所以需要上面的"android.permission.WAKE_LOCK" 权限。解决在Service启动之前系统就休眠的问题。

有如下方法:

startWakefulService(context, intent);

//它会申请一个电源锁,启动service,并将电源锁通过intent传入到 Service中,在onStart、onStartCommand中接收intent。

completeWakefulIntent(Intent intent);

//如果service中的工作完成了,调用这个方法释放 receiver 中传入的电源锁。 释放成功返回true,失败返回false.

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

4.Alarm

Alarm的运行独立于app进程的生命周期之外。基于AlarmManager。 如果是在app运行期间发生的定时操作,应该用Handler,Timer和Thread,更轻量和易控制。

功能:

.能在特定的时间或以特定频率发出intent 。

可以结合 Receiver 来启动 Service,或者执行其他功能 。

.独立于app进程的生命周期,可以在app没有运行的时候触发事件,即使设备是休眠状态。

.最小化app资源需求,可以定时执行任务而不依赖于Timers或者后台持久的service。

定时重复的alarm相对简单,但是灵活性较小,如果是触发的网络操作,若设计不好可能会很快耗光电量,或者加重服务器的负载。 一个常用的应用场景,是在app退出时和服务器同步数据,可以用重复的alarm实现,但是如果访问数据的服务器是自己的,推荐使用  Google Cloud Messaging(GCM) 结合 sync adapter。

建议:

.对定时重复的alarm,如果是触发网络操作,应该用一个随机的时间点,而不是固定在同一个时间点,以免服务器负载过重。

.将alarm的频率尽量降低 .如非必要不要唤醒设备 。

.不用让alarm触发时间过度的精确,除非有必要 使用setInexactRepeating() 替换 setRepeating(),使用前者,系统会将多个app的alarm同步起来一起发出,以便减少系统被唤醒的总次数,减少耗电。从Android4.4 (API Level 19), 开始,所有的重复alarm都是inexact的。

.尽量不要让alarm基于时钟时间,用 ELAPSED_REALTIME。

重复alarm的构成:

.alarm类型。

.触发的时间,如果时间已经过去了,会立刻触发本alarm。

.重复的间隔。

.Intent,alarm触发时发出,如果重复设置的alarm的intent是一样的,则前一个alarm会被替换掉。

时间的类型:

.elapsed real time       从系统启动作为起始时间,开始计时,和日期的时间无关,不受时区,地区影响。 适用于以固定间隔重复的alarm,比如没半小时触发一次

.real time clock(RTC)  就是手机平时的时钟的时间,用户可以修改,受时区,地区影响. 适用于在一天某个特定的时间点触发的alarm

Alarm的类型:

如果不是唤醒设备的类型,Alarm会在系统下次被唤醒的时候发出.

.ELAPSED_REALTIME                  从系统启动开始计算的时间,包括系统休眠的时间,不会唤醒设备

.ELAPSED_REALTIME_WAKEUP   同上,会唤醒设备

.RTC                                             基于时钟时间,不会唤醒设备

.RTC_WAKEUP                             基于时钟时间,唤醒设备

reboot处理:
默认情况下,所有的alarm在关机后都会被cancel掉。
可以接收 "android.intent.action.BOOT_COMPLETED" 广播,在广播接收器中重设Alarm。

函数原型:

public void setInexactRepeating(int type, long triggerAtTime, long interval,PendingIntent operation) 

public void setRepeating(int type, long triggerAtTime, long interval, PendingIntent operation) 

public void set(int type, long triggerAtTime, PendingIntent operation)

使用setInexactRepeating时,interval参数只能设为指定的几个值,否则和setRepeating是一样的效果。

指定的值为:

AlarmManager.INTERVAL_FIFTEEN_MINUTES,

AlarmManager.INTERVAL_HALF_HOUR,

AlarmManager.INTERVAL_HOUR,

AlarmManager.INTERVAL_HALF_DAY,

AlarmManager.INTERVAL_DAY

实例:

//1. ELAPSED_REALTIME_WAKEUP类型的Alarm,半小时重复一次
// Hopefully your alarm will have a lower frequency than this!
alarmMgr.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
AlarmManager.INTERVAL_HALF_HOUR,
AlarmManager.INTERVAL_HALF_HOUR,
alarmIntent); //2. ELAPSED_REALTIME_WAKEUP类型的Alarm,单次的,一小时后触发
private AlarmManager alarmMgr;
private PendingIntent alarmIntent;
...
alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, AlarmReceiver.class);
alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0); alarmMgr.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,SystemClock.elapsedRealtime() + 60 * 1000, alarmIntent); //3. RTC_WAKEUP类型, 2:00 p.m触发,每天重复:
// Set the alarm to start at approximately 2:00 p.m.
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 14); // With setInexactRepeating(), you have to use one of the AlarmManager interval
// constants--in this case, AlarmManager.INTERVAL_DAY.
alarmMgr.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
AlarmManager.INTERVAL_DAY, alarmIntent); //4. RTC_WAKEUP类型 8:30 a.m.触发, 每隔20分钟重复一次:
private AlarmManager alarmMgr;
private PendingIntent alarmIntent;
...
alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, AlarmReceiver.class);
alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0); // Set the alarm to start at 8:30 a.m.
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 8);
calendar.set(Calendar.MINUTE, 30); // setRepeating() lets you specify a precise custom interval--in this case,
// 20 minutes.
alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
1000 * 60 * 20, alarmIntent); //取消Alarm:
if (alarmMgr!= null) {
alarmMgr.cancel(alarmIntent);
}

Best Practices for Background Jobs_3 Managing Device Awake State之电源锁、Alarm、WakefulBroadcastReceiver的更多相关文章

  1. Android后台处理最佳实践(Best Practices for Background Jobs)

    本课将告诉你如何通过后台加载来加速应用启动和降低应用耗电. 后台跑服务 除非你做了特殊指定,否则在应用中的大部分前台操作都是在一个特殊的UI线程里面进行的.这有可能会导致一些问题,因为长时间运行的操作 ...

  2. 与众不同 windows phone (11) - Background Task(后台任务)之警报(Alarm)和提醒(Reminder)

    原文:与众不同 windows phone (11) - Background Task(后台任务)之警报(Alarm)和提醒(Reminder) [索引页][源码下载] 与众不同 windows p ...

  3. [译]Managing Vue.js State with Vuex

    原文 准备 安装 Vuex, 是Vue官方出的package, 它不是Vue内置的.需要另外安装. npm install vuex --save 然后,需要在应用启动文件启用Vuex. main.j ...

  4. Android Training

    Building Apps with Content Sharing Simple Data --> Intent && ActionProvider 介绍如何让应用程序共享简单 ...

  5. [中英对照]Device Drivers in User Space: A Case for Network Device Driver | 用户态设备驱动: 以网卡驱动为例

    前文初步介绍了Linux用户态设备驱动,本文将介绍一个典型的案例.Again, 如对Linux用户态设备驱动程序开发感兴趣,请阅读本文,否则请飘过. Device Drivers in User Sp ...

  6. Managing remote devices

    A method and apparatus for managing remote devices. In one embodiment of the present invention, ther ...

  7. System and Device power management.

    Advanced Configuration and Power Management Interface(ACPI)是由Intel,Microsoft等厂家订的一套Spec,规范了OS,APP对于电 ...

  8. Android 各版本信息 (维基百科)

    The following tables show the release dates and key features of all Android operating system updates ...

  9. android App Widgets

    http://developer.android.com/guide/practices/ui_guidelines/widget_design.html#design http://develope ...

随机推荐

  1. MVC SSO登陆 的麻烦事~

    前段时间用MVC + Redis 做session搞了个简单的单点登录Web站.真是日了狗的问题多. 今天正好睡不着,做个备忘笔记>_< 实现方法很简单,无非就是从重载个Controlle ...

  2. Reverse-Daily(5)-RE_100

    比较简单的一道题目,主要注意方法一 链接:http://pan.baidu.com/s/1c1U8a4K 密码:cnkq 我用了两种方法 方法一: nop掉几处无关的call指令,然后直接运行程序,但 ...

  3. 球形环境映射之angular与latlong格式互换

    这么做只是纯好奇,因为这种格式互换在实际中是没有意义的,下面映射方式互换的贴图说明了一切. 刚开始打算使用matlab进行贴图映射方式的转换,但许久不用很是生疏,而且生成图片要考虑很多事情,尤其是生成 ...

  4. linux编译c文件

    1.创建.c文件,比如在firstmake文件夹创建了一个a.c文件,那么编译语句为: gcc -o firstmake a.c //格式为文件夹名 文件名 2.然后就会生成一个firstmake.o ...

  5. Appium常用的API函数

    在学习应用一个框架之前,应该了解一下这个框架的整体结构或是相应的API函数.这篇文章还不错:http://blog.sina.com.cn/s/blog_68f262210102vzf9.html,就 ...

  6. tomcat 更新class文件

    在eclipse中写入新代码,debug并没有执行新的代码 原因:部署在tomcat的class文件没有更新,也就是当前的代码没有编译到tomcat的工作目录中 解决方案: project-clean ...

  7. Hello Point——WebGL

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/stri ...

  8. 如何隐藏UITableView中的一项

    我最近工作中的一个iOS App中经常有在不同的场合,隐现菜单列表里某一项的需求.如果初始化的时候就去掉某一项的话,有可能让序号变化, 处理上会比较麻烦容易出错.我采用了初始化列表相同但是隐藏sect ...

  9. Java的数组长度无需编译指定,因为它是对象

    大家可以看从Thinking in Java中摘出来的代码理解一下,甚至.多维数组的子数组无须等长 //: MultiDimArray.java// Creating multidimensional ...

  10. Chp10 10.7

    <Java语言程序设计>P296 本章是关于对象的思考,主要是在研究面向对象的程序设计时类的设计,作业写得比较杂乱,构造方法时没有严格遵守类的流行设计风格,由于是作业,再加上比较简单,没有 ...