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中注册

<service android:name=".LongRunningService"/>
    <receiver
        android:name=".MyBroadcastReceiver"
        android:enabled="true">
        <intent-filter>
            <action android:name="ELITOR_CLOCK"/>
        </intent-filter>
    </receiver>

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

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
安卓的BroadcastReceiver可以被用来接收系统发送的广播消息,而AlarmManager则可以用来触发在特定时间触发的定时任务。然而,在某些情况下,我们可能会遇到AlarmManager无法将广播发送给BroadcastReceiver的问题。 出现这种情况的原因可能有多个。一种可能性是未正确注册BroadcastReceiver。在AndroidManifest.xml文件中,需要添加正确的intent-filter来指定BroadcastReceiver接收的广播类型。如果没有正确添加intent-filter,那么AlarmManager发送的广播就无法被BroadcastReceiver接收到。 另一种可能性是未正确设置AlarmManager的PendingIntent。在设置AlarmManager时,我们需要为PendingIntent指定BroadcastReceiver的类。如果未正确设置PendingIntent,那么AlarmManager发送的广播就无法正确地被指定的BroadcastReceiver接收到。 此外,还有可能是由于权限问题导致BroadcastReceiver无法接收AlarmManager发送的广播。当AlarmManager发送广播时,需要确保应用程序具有相应的权限。如果没有正确配置权限,那么BroadcastReceiver将无法接收到AlarmManager发送的广播。 解决这个问题的步骤包括: 1. 在AndroidManifest.xml文件中确保正确注册BroadcastReceiver,并添加正确的intent-filter。 2. 在设置AlarmManager时,确保为PendingIntent正确指定BroadcastReceiver的类。 3. 确认应用程序具有相应的权限来接收AlarmManager发送的广播。 通过以上步骤的检查和调整,应该能够解决AndroidBroadcastReceiver收不到AlarmManager发送的广播的问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值