好久没写Blog了,一是最近项目比较忙,二也是最近家里的事也比较多
好了,寒暄到此为止,貌似有些短暂 ?
最近项目有一些位置信息需要实时去上传,也有好长一段时间没用过心跳服务了,一直都在用激光推动啊,阿里的MQTT啊
也是借此机会复习一下这个简单的Service
那么这里用的定时器就是Google推荐的Alarm
下面简单介绍一下这个AlarmManager
一. AlarmManager的常用方法有三个:
1.set(int type,long startTime,PendingIntent pi);
该方法用于设置一次性闹钟,第一个参数表示闹钟类型,第二个参数表示闹钟执行时间,第三个参数表示闹钟响应动作。
2.setRepeating(int type,long startTime,long intervalTime,PendingIntent pi);
该方法用于设置重复闹钟,第一个参数表示闹钟类型,第二个参数表示闹钟首次执行时间,第三个参数表示闹钟两次执行的间隔时间,第三个参数表示闹钟响应动作。
3.setInexactRepeating(int type,long startTime,long intervalTime,PendingIntent pi);
该方法也用于设置重复闹钟,与第二个方法相似,不过其两个闹钟执行的间隔时间不是固定的而已。
二. 参数详解:
**1.**int type: 闹钟的类型,常用的有5个值:AlarmManager.ELAPSED_REALTIME、 AlarmManager.ELAPSED_REALTIME_WAKEUP、AlarmManager.RTC、 AlarmManager.RTC_WAKEUP、AlarmManager.POWER_OFF_WAKEUP。
AlarmManager.ELAPSED_REALTIME表示闹钟在手机睡眠状态下不可用,该状态下闹钟使用相对时间(相对于系统启动开始),状态值为3;
AlarmManager.ELAPSED_REALTIME_WAKEUP表示闹钟在睡眠状态下会唤醒系统并执行提示功能,该状态下闹钟也使用相对时间,状态值为2;
AlarmManager.RTC表示闹钟在睡眠状态下不可用,该状态下闹钟使用绝对时间,即当前系统时间,状态值为1;
AlarmManager.RTC_WAKEUP表示闹钟在睡眠状态下会唤醒系统并执行提示功能,该状态下闹钟使用绝对时间,状态值为0;
AlarmManager.POWER_OFF_WAKEUP表示闹钟在手机关机状态下也能正常进行提示功能,所以是5个状态中用的最多的状态之一,该状态下闹钟也是用绝对时间,状态值为4;不过本状态好像受SDK版本影响,某些版本并不支持;
2. long startTime: 闹钟的第一次执行时间,以毫秒为单位,可以自定义时间,不过一般使用当前时间。需要注意的是,本属性与第一个属性(type)密切相关,
3. long intervalTime:对于后两个方法来说,存在本属性,表示两次闹钟执行的间隔时间,也是以毫秒为单位。
4. 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)方法。如果这三种方法错用了的话,虽然不会报错,但是看不到闹钟提示效果。
接下来 也是直接上代码吧
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import android.support.annotation.Nullable;
import com.bohan.ems.mdm.MdmManage;
import com.bohan.ems.mdm.utils.Constant;
import com.bohan.icexpressapp.business.base.ViewCallback;
import com.bohan.icexpressapp.core.MainApplication;
import com.bohan.icexpressapp.core.log.SLog;
import com.bohan.icexpressapp.network.base.BaseReq;
import com.bohan.icexpressapp.network.networkserver.handoverserver.entity.BeanRespEmpty;
import org.apache.commons.lang3.StringUtils;
/**
* @author The sky seems to be raining
* @class 主线程心跳服务
*/
public class HeartBeatService extends Service {
// 心跳间隔
// 以前为final static的,但是服务器要求修改间隔时间,则去掉
//心跳间隔时间 默认毫秒
public static final int DEFAULT_INTERVAL = 3 * 60 * 1000;
//心跳间隔时间 默认毫秒
public static int HEART_SPE = DEFAULT_INTERVAL;
public static final String ACTION_ALARM_HEARTBEAT = "ACTION_ALARM_HEARTBEAT";
private PendingIntent heartbeatPi = null;
private AlarmManager heartbeatAlarm;
private MainService mMainService;
private int shark = 0;
private ScreenControlAlarmReceiver screenControlAlarmReceiver;
/**
* 初始化窗口
*/
@Override
public void onCreate() {
super.onCreate();
System.out.println("### N1GHeartService onCreate");
initData();
initReceiver();
}
private void initData() {
mMainService = new MainService(MainApplication.getInstance());
heartbeatAlarm = (AlarmManager) getSystemService(ALARM_SERVICE);
}
/**
* 初始化接收对象
*/
private void initReceiver() {
screenControlAlarmReceiver = new ScreenControlAlarmReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ACTION_ALARM_HEARTBEAT);
registerReceiver(screenControlAlarmReceiver, intentFilter);
}
/**
* 释放资源
*/
@Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(screenControlAlarmReceiver);
endTimer();
}
// 每次启动Servcie时都会调用该方法
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
System.out.println("--onStartCommand()--");
shark = intent.getIntExtra("SHARK", DEFAULT_INTERVAL);
startTimer(shark * 1000 + "");
return super.onStartCommand(intent, flags, startId);
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
/**
* 更新心跳间隔,并启动心跳
*
* @param timeString 心跳间隔 单位:毫秒
*/
private void startTimer(String timeString) {
HEART_SPE = DEFAULT_INTERVAL;
int tempTime = 0;
if (StringUtils.isEmpty(timeString) || "null".equals(timeString)) {
//如果登录认证就失败了,也需要启动timer
tempTime = HEART_SPE;
} else {
try {
tempTime = Integer.parseInt(timeString);
} catch (NumberFormatException e) {
tempTime = HEART_SPE;
e.printStackTrace();
}
}
if (tempTime == HEART_SPE && heartbeatPi != null) {
//间隔时间和原来一致,并且启动过timer,不重启timer
return;
} else {
//间隔时间和原来不一致,重启timer
HEART_SPE = tempTime;
endTimer();
Intent alarmIntent = new Intent(ACTION_ALARM_HEARTBEAT);
heartbeatPi = PendingIntent.getBroadcast(HeartBeatService.this, 0, alarmIntent, 0);//通过广播接收
heartbeatAlarm.setRepeating(AlarmManager.RTC, 0, HEART_SPE, heartbeatPi);//INTERVAL毫秒后触发
SLog.Console("心跳间隔:" + HEART_SPE + "");
heartBeat();
}
}
public class ScreenControlAlarmReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//你的逻辑处理
//如果需要实现间隔定时器功能,在重新执行1的发送步骤,实现间隔定时,间隔时间为INTERVAL
heartBeat();
}
}
/**
* 停止心跳
*/
private void endTimer() {
if (heartbeatAlarm != null && heartbeatPi != null) {
heartbeatAlarm.cancel(heartbeatPi);
heartbeatPi = null;
}
}
/**
* 心跳上传数据
*/
private void heartBeat() {
BeanRespEmpty req = new BeanRespEmpty();
mMainService.heartbeat(new BaseReq<>(req), new ViewCallback() {
@Override
public void returnResult(boolean result, Object... objects) {
if (result) {
SLog.Console("心跳上传位置信息成功" +
Constant.LOCATION + ":" + MdmManage.getInstance().getLongiTude() + "," +
MdmManage.getInstance().getLatiTude() + "," + MdmManage.getInstance().getLastAlt());
} else {
SLog.Console("心跳上传位置信息失败" +
Constant.LOCATION + ":" + MdmManage.getInstance().getLongiTude() + "," +
MdmManage.getInstance().getLatiTude() + "," + MdmManage.getInstance().getLastAlt());
}
}
});
}
}
看完代码,总结一下使用步骤吧
AlarmManager的使用步骤
1)初始化ALarmManager实例 ALarmManager am=(ALarmManager)getSystemService(ALARM_SERVICE);
2)定义一个PendingIntent发出广播
3)调用ALarmManager方法,设置定时或重复提醒
4)取消提醒:
我这直接用的cancle方法,并且记得注销掉广播监听器
是不是特别简单实用啊,如文中有不对的地方,请及时纠正,谢谢大家
另外,文中很多代码可能与实际业务相关,我实在是懒得删除了,大家一看便知,最后提前祝大家腊八节快乐