寒炽-----AlarmManager为定时而生的绝杀技能

很多时候,我们需要在 android 程序中 制造一个不被杀死的 轮询 监听机制,很容易想到的就是:

1. 线程中while 循环 ,然后 sleep

2. Timer 定时器


对于以上两个方式的做法,对于 线程而言,sleep 并不一定能得到准确的 时间 间隔,所以 1  对于有严格时间间隔要求来说,直接放弃使用

对于 2. 而言 时间间隔可以得到有效保证,但 它和 1 都要一个致命问题,那就是 手机 一旦 黑屏,循环 监听就不会工作


因此,今天我们要讲的就是 android中特有的 定时器  AlarmManager。

下面附上 AlarmManager 的 使用,

public class Polling {
  
	private static final long RECYCLE_TIME=1000 * 60 *1;//循环时间间隔
	private static final String ACTION_TAG="com.ishangbin.shop.heartbeat.Polling";
	
	private AlarmManager manager;
	private Intent mIntent;
	private PendingIntent mPendingIntent;
	
	@SuppressLint("NewApi")
	public void start() {
		cancel();
		// 获取AlarmManager系统服务
		manager = (AlarmManager) BaseApplication.getInstance().getSystemService(Context.ALARM_SERVICE);
		// 包装需要执行Service的Intent
		mIntent = new Intent(BaseApplication.getInstance(), HeartService.class);
		mIntent.setAction(ACTION_TAG);
		mPendingIntent = PendingIntent.getService(BaseApplication.getInstance(), 0, mIntent,PendingIntent.FLAG_UPDATE_CURRENT);
		
	    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){
	    	manager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()+RECYCLE_TIME, mPendingIntent);
	    }else{
	    	manager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), RECYCLE_TIME, mPendingIntent);
	    }
	}
	
	public void cancel() {
		// 取消正在执行的服务
		if(manager!=null&&mPendingIntent!=null){
		   manager.cancel(mPendingIntent);
		}
	}
}

此处 HeartService 为 服务,当 AlarmManager 启动的是服务时,调用的是 

mPendingIntent = PendingIntent.getService(BaseApplication.getInstance(), 0, mIntent,PendingIntent.FLAG_UPDATE_CURRENT);
若 启动的是 广播 则为

mPendingIntent = PendingIntent.getBroadcast(BaseApplication.getInstance(), 0, mIntent,PendingIntent.FLAG_UPDATE_CURRENT);

然后是 AlarmManager 有两种计时标准 ,分别是 ELAPSED 计时方式(相对时间)和 RTC (自1970年开始计时)的方式,设置 AlarmManager 要注意,当你使用一种计时方式时,就只用这一种,不可两种混用

AlarmManager .set ( , , , ,) 中第一个参数有不同设置,此处设置的是  

AlarmManager.RTC_WAKEUP
表示 手机在,黑屏,锁屏时,定时器依然工作,即 cpu唤醒,屏幕唤醒工作。

最后需要注意的是 start 闹钟的 PendingIntent 要和 cancel 的 PendingIntent 保持一致,才能 cancel 掉对应的 AlarmManager

oh,no!android api 19 以后  AlarmManager  的 setRepeating 方法失效,那么我们只有通过 不断的 重复设置  AlarmManager .set ( , , , ,) 方法来实现轮询

OK,讲了这些,回到主题,我们要实现 闹钟的 轮询,再看看 HeartService 服务中的 处理

	@Override
	protected void onHandleIntent(Intent intent) {
		//获取app开启状态
		boolean isAlive=Cacher.getInstance().getAppStateTag();
		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT&&isAlive) {
			mPolling.start();
		}
		if(!isAlive){
			mPolling.cancel();
		}
		L.i("===+++= 执行一次心跳 =+++===" + DateUtil.getNowTime());
		if (!NetUtil.isNetConnected()) {
			L.i("======心跳  网络异常=====" + DateUtil.getNowTime());
			return;
		} else {
			L.i("======心跳  网络正常=====" + DateUtil.getNowTime());
		}
		//......执行后续逻辑
	}

HeartService 继承的 是 IntentService,然后在  
onHandleIntent
方法中,首先判断 当前 api 是否 大于 19,若大于则再次执行一次 set 方法,到此实现了一个轮询机制。

好的,再看下 在 activity 中的调用

	private AlarmReceiver mAlarmReceiver;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		initView();
		initData();
		setListener();
	}


	private void initView() {
		mButton=(Button) findViewById(R.id.button1);
		mImageView=(ImageView) findViewById(R.id.imv_head);
		mTvUserName=(TextView) findViewById(R.id.tv_user_name);
	}

	private void initData() {
		mAlarmReceiver=new AlarmReceiver();
	}

	private void setListener() {
		mButton.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				Log.i("","====咳嗽ihi======"+DateUtil.getNowTime());
				
				mAlarmReceiver.start(MainActivity.this);
			}
		});
	}
	

	@Override
	protected void onDestroy(){
		mAlarmReceiver.cancel();
		super.onDestroy();
	}

在 MainActivity 中 的 button 中开启定时器,然后在退出时 cancel 掉

当然,最后不能在 mainfast。xml 中忘记 服务的注册:

 <!-- 心跳服务 -->
 <service android:name="com.ishangbin.shop.heartbeat.HeartService" />

对于  AlarmManager  的 一些基本用法,今天就讲到这里吧








package com.bdvcd.utils; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.TimeZone; /** * 文件名:DateUtils.java 日期处理相关工具类 * 版本信息:V1.0 * 日期:2013-03-11 * Copyright BDVCD Corporation 2013 * 版权所有 http://www.bdvcd.com */ public class DateUtils { /**定义常量**/ public static final String DATE_JFP_STR="yyyyMM"; public static final String DATE_FULL_STR = "yyyy-MM-dd HH:mm:ss"; public static final String DATE_SMALL_STR = "yyyy-MM-dd"; public static final String DATE_KEY_STR = "yyMMddHHmmss"; /** * 使用预设格式提取字符串日期 * @param strDate 日期字符串 * @return */ public static Date parse(String strDate) { return parse(strDate,DATE_FULL_STR); } /** * 使用用户格式提取字符串日期 * @param strDate 日期字符串 * @param pattern 日期格式 * @return */ public static Date parse(String strDate, String pattern) { SimpleDateFormat df = new SimpleDateFormat(pattern); try { return df.parse(strDate); } catch (ParseException e) { e.printStackTrace(); return null; } } /** * 两个时间比较 * @param date * @return */ public static int compareDateWithNow(Date date1){ Date date2 = new Date(); int rnum =date1.compareTo(date2); return rnum; } /** * 两个时间比较(时间戳比较) * @param date * @return */ public static int compareDateWithNow(long date1){ long date2 = dateToUnixTimestamp(); if(date1>date2){ return 1; }else if(date1<date2){ return -1; }else{ return 0; } } /** * 获取系统当前时间 * @return */ public static String getNowTime() { SimpleDateFormat df = new SimpleDateFormat(DATE_FULL_STR); return df.format(new Date()); } /** * 获取系统当前时间 * @return */ public static String getNowTime(String type) { SimpleDateFormat df = new SimpleDateFormat(type); return df.format(new Date()); } /** * 获取系统当前计费期 * @return */ public static String getJFPTime() { SimpleDateFormat df = new SimpleDateFormat(DATE_JFP_STR); return df.format(new Date()); } /** * 将指定的日期转换成Unix时间戳 * @param String date 需要转换的日期 yyyy-MM-dd HH:mm:ss * @return long 时间戳 */ public static long dateToUnixTimestamp(String date) { long timestamp = 0; try { timestamp = new SimpleDateFormat(DATE_FULL_STR).parse(date).getTime(); } catch (ParseException e) { e.printStackTrace(); } return timestamp; } /** * 将指定的日期转换成Unix时间戳 * @param String date 需要转换的日期 yyyy-MM-dd * @return long 时间戳 */ public static long dateToUnixTimestamp(String date, String dateFormat) { long timestamp = 0; try { timestamp = new SimpleDateFormat(dateFormat).parse(date).getTime(); } catch (ParseException e) { e.printStackTrace(); } return timestamp; } /** * 将当前日期转换成Unix时间戳 * @return long 时间戳 */ public static long dateToUnixTimestamp() { long timestamp = new Date().getTime(); return timestamp; } /** * 将Unix时间戳转换成日期 * @param long timestamp 时间戳 * @return String 日期字符串 */ public static String unixTimestampToDate(long timestamp) { SimpleDateFormat sd = new SimpleDateFormat(DATE_FULL_STR); sd.setTimeZone(TimeZone.getTimeZone("GMT+8")); return sd.format(new Date(timestamp)); } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值