android定时器AlarmManager

好久没写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方法,并且记得注销掉广播监听器

是不是特别简单实用啊,如文中有不对的地方,请及时纠正,谢谢大家

另外,文中很多代码可能与实际业务相关,我实在是懒得删除了,大家一看便知,最后提前祝大家腊八节快乐

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值