为了判断在线用户数,项目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