Android 定时操作方法AlarmManager,Timer,Handler
2015-10-27 17:33
501 查看
AlarmManager
Timer有一个明显的短板,它并不太适用于那些需要长期在后台运行的定时任务。我们都知道,为了能让电池更加耐用,每种手机都会有自己的休眠策略,Android 手机就会在长时间不操作的情况下自动让 CPU 进入到睡眠状态,这就有可能导致 Timer 中的定时任务无法正常运行。另一方面,其实也可以通过handler的poseDelay方法来实现定时操作,也是不靠谱的,因为默认handler依赖于线程(main线程或者子线程),所以只要进程被杀死,所有相关的线程都被杀死,所以handler中的定时操作就无效了。timer也一样,因为timer实际上是另启一个子线程,进程被杀了,子线程当然也被杀了,所以time失效。。。。而Alarm 机制则不存在这种情况,它通过pendingintent具有唤醒 未启动的进程 的功能,即可以保证每次需要执行定时任务的时候 CPU 都能正常工作。但是闹钟当设备关机和重启后,闹钟将会被清除。一张图总结一下区别
ELAPSED_REALTIME 表示让定时任务的触发时间从系统开机开始算起,但不会唤醒 CPU
AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
long triggerAtTime = SystemClock.elapsedRealtime() + 10 * 1000;
//10s执行一次pendingIntent
manager.set(AlarmManager.ELAPSED_REALTIME, triggerAtTime, pendingIntent);
RTC 表示让定时任务的触发时间从 1970 年 1月 1 日 0 点开始算起,但不会唤醒 CPU
long triggerAtTime = System.currentTimeMillis() + 10 * 1000;
//10s执行一次pendingIntent
manager.set(AlarmManager.RTC, triggerAtTime, pendingIntent);
SystemClock.elapsedRealtime()方法可以获取到系统开机至今所经历时间的毫秒数
System.currentTimeMillis()方法可以获取到1970年1月1日0点至今所经历时间的毫秒数
long repeat = 10000;
//从当前时间开始,10s中执行一次PendingIntent
mAlarmManager.setRepeating(AlarmManager.RTC, System.currentTimeMillis(), repeat, pendingIntent);
PendingIntent
Intent 更加倾向于去立即执行某个动作,而 PendingIntent 更加倾向于在某个合适的时机去执行某个动作。所以,也可以把 PendingIntent 简单地理解为延迟执行的 Intent。getActivity()方法、getBroadcast()方法、getService()方法
Notification
sdk16以后可以这样使用,点击该通知后启动NextActivityIntent acIntent = new Intent(this, NextActivity.class); NotificationManager nm = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE); PendingIntent pi = PendingIntent.getActivity(this, 0, acIntent, 0); Notification notify = new Notification.Builder(this) .setSmallIcon(R.mipmap.ic_launcher) .setTicker("TickerText:" + "您有新短消息,请注意查收!") .setContentTitle("Notification Title") .setContentText("This is the notification message") .setContentIntent(pi).build(); notify.flags |= Notification.FLAG_AUTO_CANCEL; // FLAG_AUTO_CANCEL表明当通知被用户点击时,通知将被清除。 nm.notify(NotiID, notify);
如果要支持老的sdk,点击该通知后启动HtmlNavActivity
Intent intent = new Intent(); intent.setClass(mContext, HtmlNavActivity.class); final PendingIntent pi = PendingIntent.getActivity(mContext, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT); //创建一个通知 Notification n = new Notification(R.drawable.icon, obj.optString("LocalNotifyTitle"), System.currentTimeMillis()); // 为通知添加数据 n.flags |= Notification.FLAG_AUTO_CANCEL; n.setLatestEventInfo(mContext, "LocalNotifyTitle", "LocalNotifyContent", pi); // 发送通知 NotificationManager nm = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE); nm.notify(NotiID, n);
notify.flags |= Notification.FLAG_AUTO_CANCEL; //表明点击后,通知自动消失
也可以通过NotificationManager.cancel(NofiID); 手动取消通知
以下为通知设置震动,响铃,还有其它用法就不举例
long[] vibrates = {0, 1000, 1000, 1000};
notification.vibrate = vibrates;
Uri soundUri = Uri.fromFile(new File("/system/media/audio/ringtones/
Basic_tone.ogg"));
notification.sound = soundUri;
注意:
通知一到,如果该应用已经启动了进程,那么使用当前进程。如果没有启动进程,那么就会启动进程,可以看到会调用application的oncreate方法。从ddms也可以看出,通知一到,如果没有进程就启动该应用的进程
Date
Date date = new Date(System.currentTimeMillis()); SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒"); Log.d("LiaBin", "current: " + dateFormat.format(date));2. yyyy:年
3. MM:月
4. dd:日
5. hh:1~12小时制(1-12)
6. HH:24小时制(0-23)
7. mm:分
8. ss:秒
Calendar
推荐使用Calendar类进行时间和日期处理Calendar checkInCal = Calendar.getInstance(); checkInCal.setTimeInMillis(System.currentTimeMillis()); checkInCal.add(Calendar.DATE, 2); checkInCal.set(Calendar.HOUR_OF_DAY, 8); if (checkInCal.getTimeInMillis() > System.currentTimeMillis()) { }getTime方法 该方法的作用是将Calendar类型的对象转换为对应的Date类对象
getTimeInMillis 转换为相对于1970.1.1时间
after方法 该方法的作用是判断当前日期对象是否在when对象的后面,如果在when对象的后面则返回true,否则返回false
Calendar.YEAR——年份
Calendar.MONTH——月份
Calendar.DATE——日期
Calendar.DAY_OF_MONTH——日期,和上面的字段完全相同
Calendar.HOUR——12小时制的小时数
Calendar.HOUR_OF_DAY——24小时制的小时数
Calendar.MINUTE——分钟
Calendar.SECOND——秒
Calendar.DAY_OF_WEEK——星期几
案例
实际项目中经常会需要在某个时间点弹出通知,或者重复在某个时间点弹出通知,下面是代码实现。由于手机关机或者重启,闹钟就失效,所以在application中开启服务,service的oncreate方法中开启闹钟,所以每次启动进程,都会重新设定闹钟。
public class BaseApplication extends Application { @Override public void onCreate() { super.onCreate(); startService(new Intent(this, MyService.class)); Log.d("LiaBin","application oncreate"); } }
public class MyService extends Service { private final static String ACTION_NOTIFICATION = "ACTION_NOTIFICATION"; @Override public void onCreate() { super.onCreate(); initAlarm(ACTION_NOTIFICATION); } @Override public void onStart(Intent intent, int startId) { super.onStart(intent, startId); if (intent != null) { String action = intent.getAction(); if (ACTION_NOTIFICATION.equals(action)) { Intent acIntent = new Intent(this, NextActivity.class); NotificationManager nm = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE); PendingIntent pi = PendingIntent.getActivity(this, 0, acIntent, 0); Notification notify = new Notification.Builder(this) .setSmallIcon(R.mipmap.ic_launcher) .setTicker("TickerText:" + "您有新短消息,请注意查收!") .setContentTitle("Notification Title") .setContentText("This is the notification message") .setContentIntent(pi).build(); notify.flags |= Notification.FLAG_AUTO_CANCEL; // FLAG_AUTO_CANCEL表明当通知被用户点击时,通知将被清除。 nm.notify(1000, notify); } } } @Override public IBinder onBind(Intent intent) { return null; } private void initAlarm(String action) { AlarmManager mAlarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); Intent serviceIntent = new Intent(this, MyService.class); serviceIntent.setAction(action); PendingIntent pi = PendingIntent.getService(this, 0, serviceIntent, 0); mAlarmManager.cancel(pi); Calendar checkInCal = Calendar.getInstance(); checkInCal.setTimeInMillis(System.currentTimeMillis()); checkInCal.add(Calendar.SECOND, 5); long repeat = 10000; mAlarmManager.setRepeating(AlarmManager.RTC, checkInCal.getTimeInMillis(), repeat, pi); } }
开启进程就启动service,oncreate方法中开启闹钟,注意设置闹钟前必须把以前设置的闹钟取消,mAlarmManager.cancel(pi);很关键。
此时设置一个重复性闹钟,5秒后开始执行,之后10s重复一次。然后pendingintent还是该service,这样就不必额外写一个broadcast了,如果该service
内存中已经存在一个实例,那么只会调用onstart方法,然后判断action,显示notification通知即可。
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories