Android Service Alarm 定时广播
Service
最常见的还是执行定时任务,比如轮询,就是每间隔一段时间就请求一次服务器,确认客户端状态或者进行信息更新
Android 提供了两种定时方式 Timer
类与 Alarm
机制
前者不适合于需要长期在后台运行的定时任务,CPU 一旦休眠,Timer 中的定时任务 就无法运行
Alarm
则不存在这种情况,它具有唤醒 CPU
的功能,另外,也要区分 CPU 唤醒与屏幕唤醒
Alarm
Alarm
有一个方法很重要,就是 set()
set(int type,long startTime,PendingIntent pi)
-
type 参数有五个可选值
值 说明 AlarmManager.ELAPSED_REALTIME 闹钟在手机睡眠状态下不可用,该状态下闹钟使用相对时间(相对于系统启动开始),状态值为 3 AlarmManager.ELAPSED_REALTIME_WAKEUP 闹钟在睡眠状态下会唤醒系统并执行提示功能,该状态下闹钟也使用相对时间,状态值为2 AlarmManager.RTC_WAKEUP 表示闹钟在睡眠状态下会唤醒系统并执行提示功能,该状态下闹钟使用绝对时间,状态值为0 AlarmManager.POWER_OFF_WAKEUP 表示闹钟在手机关机状态下也能正常进行提示功能,所以是5个状态中用的最多的状态之一,该状态下闹钟也是用绝对时间,状态值为4
不过本状态好像受SDK版本影响,某些版本并不支持;第一个参数决定第二个参数的类型
-
如果是 REALTIME 的话就用
SystemClock.elapsedRealtime()
方法可以获得系统开机到现在经历的毫秒数 -
如果是 RTC 的就用
System.currentTimeMillis()
可获得从1970-1-1 00:00:00
点到现在做经历的毫秒数
-
-
startTime
闹钟的第一次执行时间,以毫秒为单位,可以自定义时间,不过一般使用当前时间
需要注意的是,本属性与第一个属性(type)密切相关
-
PendingIntent pi
绑定了闹钟的执行动作,比如发送一个广播、给出提示等等
PendingIntent 是 Intent 的封装类
-
如果是通过启动服务来实现闹钟提示的话,
PendingIntent
对象的获取就应该采用Pending.getService(Context c,int i,Intent intent,int j)方法;
-
如果是通过广播来实现闹钟提示的话,
PendingIntent
对象的获取就应该采用PendingIntent.getBroadcast(Context c,int i,Intent intent,int j)方法;
-
如果是采用
Activity
的方式来实现闹钟提示的话,PendingIntent
对象的获取就应该采用PendingIntent.getActivity(Context c,int i,Intent intent,int j)
如果这三种方法错用了的话,虽然不会报错,但是看不到闹钟提示效果。
-
Alarm 使用流程
Alarm
使用方式一般如下
-
获得 Service
AlarmManager manager = (AlarmManager) getSystemService(ALARM_SERVICE);
-
通过 set 方法设置定时任务
int durtime = 2 * 1000; //单位毫秒 long triggerAtTime = SystemClock.elapsedRealtime() + durtime; manager.set(AlarmManager.RTC_WAKEUP,triggerAtTime,pendingIntent);
-
定义一个 Service,在
onStartCommand()
中开辟一条事务线程,用于处理一些定时逻辑 -
定义一个 广播 (
Broadcast
),用于启动 Service -
在
AndroidManifest.xml
注册Service
和Boradcast
Android 4.4+(API 19),Alarm
任务的触发时间可能变得不准确,有可能会延时,是系统
对于耗电性的优化,如果需要准确无误可以调用 setExtra()
方法
范例
先来看看最后的效果图
-
创建一个 空的 Android 项目
cn.twle.android.ServiceAlarm
-
在
MainActivity.java
同一目录下新建文件LongRunningService.java
package cn.twle.android.servicealarm; import android.app.AlarmManager; import android.app.Service; import android.app.PendingIntent; import android.content.Intent; import android.os.IBinder; import android.os.SystemClock; import android.util.Log; import java.util.Date; public class LongRunningService extends Service { @Override public IBinder onBind(Intent intent) { return null; } @Override public int onStartCommand(Intent intent, int flags, int startId) { //这里开辟一条线程,用来执行具体的逻辑操作: new Thread(new Runnable() { @Override public void run() { Log.d("BackService", new Date().toString()); } }).start(); AlarmManager manager = (AlarmManager) getSystemService(ALARM_SERVICE); //这里是定时的,这里设置的是每隔两秒打印一次时间 int durtime = 2 * 1000; long triggerAtTime = SystemClock.elapsedRealtime() + durtime; Intent i = new Intent(this,MsAlarmReceiver.class); PendingIntent pi = PendingIntent.getBroadcast(this, 0, i, 0); manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtTime, pi); return super.onStartCommand(intent, flags, startId); } }
-
在
MainActivity.java
同一目录下新建文件MsAlarmReceiver.java
package cn.twle.android.servicealarm; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; public class MsAlarmReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Intent i = new Intent(context,LongRunningService.class); context.startService(i); } }
-
修改 MainActivity.java
package cn.twle.android.servicealarm; import android.content.Intent; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; public class MainActivity extends AppCompatActivity { MsAlarmReceiver receiver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //创建启动 Service 的 Intent final Intent it = new Intent(this,LongRunningService.class); startService(it); } }
-
修改
AndroidManifest.xml
注册Service
和Broadcast
<!-- 配置 Service 组件,同时配置一个 action --> <service android:name=".LongRunningService"> <intent-filter> <action android:name="cn.twle.android.servicealarm.LongRunningService"/> </intent-filter> </service> <receiver android:name=".MsAlarmReceiver"> <intent-filter> <action android:name="cn.twle.android.servicealarm.MsAlarmReceiver"/> </intent-filter> </receiver>