AlarmManager+BroadcastReceiver+Service实现后台循环定时器

为了判断在线用户数,项目APP要实现一个心跳包的操作。就是在APP运行的时候每隔一段时间发送一个请求到后台,后台根据你发送的信息而得知你是在线用户。
一开始我是使用了Timer定时器来实现这个操作,主要代码如下:

public class TimerMethod {
private static TimerMethod instance = null;
Handler handler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        {
            switch (msg.what) {
                case 1:
                   //执行定时后的对应操作
                    break;
            }
        }
    }
};
private Timer mTimer;
private long count = 900000;
private TimerTask mTimerTask;

private TimerMethod() {
}


public static TimerMethod getInstance() {
    if (instance == null) {
        instance = new TimerMethod();
    }
    return instance;
}

//单例模式调用定时器,根据isTimer判断启动还是关闭定时器。一旦开启后定时器回根据count的时间循环执行
public void exce(boolean isTimer, int count, String token) {

    stopTimer();
    if (isTimer) {
        startTimer(count);
    }

}

//启动定时器
private void startTimer(int count) {
    if (count != -1) {
        this.count = count;
    }
    if (mTimer == null) {
        mTimer = new Timer();
    }
    if (mTimerTask == null) {
        mTimerTask = new TimerTask() {
            @Override
            public void run() {
                Message message = new Message();
                message.what = 1;
                handler.sendMessage(message);
            }
        };

        if (mTimer != null && mTimerTask != null) {
            mTimer.schedule(mTimerTask, this.count, this.count);
        }
    }
}

//停止定时器
private void stopTimer() {
    if (mTimer != null) {
        mTimer.cancel();
        mTimer = null;
    }
    if (mTimerTask != null) {
        mTimerTask.cancel();
        mTimerTask = null;
    }
}

public Timer getTimer() {
    return this.mTimer;
}
}

这样做一眼看上去并没有什么问题,但是实际运用后才发现,当手机锁屏后,定时器会暂停,也就是说不再定时执行任务,直到重新开启屏幕后才会继续执行,这涉及到Android的休眠策略,
这就蛋疼了,所以简单的查了一下资料我就直接抛弃了Timer定时器。准备使用AlarmManager,这是Android中常用的一种系统级别的提示服务,想了解具体可以自行百度。当然,既然要在锁屏后仍然运行,就涉及到后台服务了,所以这里我使用了一个service;当然在使用AlarmManager这个定时器时也有一些小问题,比如在不同版本的休眠策略中,使用AlarmManager会出现定是不准确的问题,还有6.0之后适配的问题。查了不少资料,基本上都解决了以上问题。下面直接上代码:

MainActivity.java
//这里我只是用一个例子,简单的实现启动和关闭定时器
@Override
    public void onClick(View view) {
        switch (view.getId()){
            case R.id.btn_open:
            //启动定时器
                int time = new Integer(editText.getText().toString().trim());
                Log.d("print", "onClick: "+time);
                Intent intent = new Intent(this, LongRunningService.class);
                intent.putExtra("time", time * 60000);  //传入定时时间
                startService(intent);
                break;
            case R.id.btn_close:
            //关闭定时器
                Intent intentService = new Intent(this, LongRunningService.class);
                AlarmManager manager = (AlarmManager) getSystemService(ALARM_SERVICE);
                Intent intent1 = new Intent("ELITOR_CLOCK");
                PendingIntent pi = PendingIntent.getBroadcast(this, 0, intent1, 0);
                manager.cancel(pi);
                stopService(intentService);
                break;
        }
    }

LongRunningService.java
//service主要就是能够后台运行

public class LongRunningService extends Service {
private static int anHour = 60000;
private AlarmManager manager;

@Override
public IBinder onBind(Intent intent) {
    return null;
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    anHour = intent.getIntExtra("time", anHour);
    manager = (AlarmManager) getSystemService(ALARM_SERVICE);
    long triggerAtTime = SystemClock.elapsedRealtime() + anHour;
    Intent intent1 = new Intent("ELITOR_CLOCK");
    PendingIntent pi = PendingIntent.getBroadcast(this, 0, intent1, 0);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        manager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtTime, pi);
    } else {
        manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtTime, pi);
    }
    return super.onStartCommand(intent, flags, startId);
}

}

MyBroadcastReceiver.java
//自定义广播,接收数据,在这里执行定时后要执行的操作
public class MyBroadcastReceiver extends BroadcastReceiver {

private static int ikk = 0;

@Override
public void onReceive(Context context, Intent intent) {
    String action = intent.getAction();
    Log.e("Receiver:", action);
    switch (action) {
        case "ELITOR_CLOCK":
            Log.d("print", "onReceive: 执行成功" + ikk++);
            //执行对应的操作
            //因为定时器是一次性的,在执行操作后重启定时器就可以达到循环执行
            Intent intent1 = new Intent(context, LongRunningService.class);
            context.startService(intent1);
            break;
        default:
            break;
    }
}

}

最后别忘了在AndroidManifest.xml中注册


    
        
            
        
    

通过上面一个简单的后台循环定时器就实现了
有更好的方法欢迎讨论。
居然不能选择免费,要demo可以留言
DeMo

你可能感兴趣的:(Android,定时器)