Android Service,AlarmManager组合实现定时任务踩的坑
来源:互联网 发布:win10安装tensorflow 编辑:程序博客网 时间:2024/06/05 03:30
做项目时遇到一个场景:app需要定时访问后台,感知获取登录用户有没有最新的消息。
我采用了定义一个Service,在onStartCommand()方法中请求后台获取最新消息,接着创建一个AlarmManager来延时发送广播,再定义一个广播接收器,接收到一个广播后,接收器触发startService( ),这时service的onStartCommand再次被触发,就再次请求获取最新消息,继续发送广播,如此往复。
用户名userId是登录成功后就能得到的。在登录成功进入主界面后,并立即启动MyNewTaskService
MyNewTaskService的主要业务逻辑代码如下:
public int onStartCommand(Intent intent, int flags, int startId) { mRealm = Realm.getDefaultInstance(); mUserDao = new UserDao(mRealm);//获取当前登录用户id mTaskTimeDao = new TaskTimeDao(mRealm); if(intent!=null){ userId = intent.getStringExtra("userId"); }else{ userId = mUserDao.getUserInfo().getUserId();//realm也保存了用户信息,但不一定每次都能获取到 } if(null!=userId){ //...做一些事情,比如访问网络获取最新消息 //设置定时操作 AlarmManager am= (AlarmManager)getSystemService(ALARM_SERVICE); //1分钟请求一次更新 int elapseTime = 1*60*1000; long interval = SystemClock.elapsedRealtime()+elapseTime; //传递userId参数给MyNewTaskReceiver,为了到时候回传回来 Intent i = new Intent(this,MyNewTaskReceiver.class); i.putExtra("userId",userId); PendingIntent pi = PendingIntent.getBroadcast(this,0,i,0); am.set(AlarmManager.ELAPSED_REALTIME,interval,pi); } return super.onStartCommand(intent, flags, startId); }
下面是MyNewTaskReceiver类
public class MyNewTaskReceiver extends BroadcastReceiver{ @Override public void onReceive(Context context, Intent intent) { Intent i= new Intent(context, MyNewTaskService.class); i.putExtra("userId",intent.getStringExtra("userId")); Log.i("user",intent.getStringExtra("userId")); context.startService(i); //每1分钟将接收到一次广播,这时触发service的onStartCommand()执行需要的重复操作 }}
但是app测试时发现,当第一次登录进去后,例如此时用户名是 ‘zs’ ,这是后台可以每1分钟接收到’zs’的最新的消息。然而,现在’zs’退出登录,用’ls’账号登录,这时后台返回的消息仍然还是’zs’的,而不是’ls’的。
后来发现,每次第一个登录的用户登陆后,后面不管任何其他用户再次登录同一台手机,后台返回的都是第一个用户的信息。因为App设计的时第一次登录成功后,Service会一直在后台执行。所以怀疑第一次创建Service后,Service所持有的userId并没有更新。
经过调试,发现,MyNewTaskReceiver接收的Intent中获取的userId全都是第一次登录用户的id。猜想可能发送广播时传入的参数有问题。
经过查阅安卓API发现,定时器AlarmManager初始化时传入的PendingIntent的构造函数的第四个参数需要一个Flag常量。
之前我传入的是0。没有作用。
当改为 FLAG_UPDATE_CURRENT 时,每次发送的广播传递的Intent就能更新了。
将onStartCommand()方法的这一行改为
PendingIntent pi = PendingIntent.getBroadcast(this,0,i,0);
PendingIntent pi = PendingIntent.getBroadcast(this,0,i,FLAG_UPDATE_CURRENT);
这时不管那个用户登录,后台都可以定时返回当前用户的消息了。
总结&注意:
1 该示例的后台Service在用户关闭app后并没有stop。如果stop,相信不会有这种Bug产生。因为定时任务是依附于Service存在的。
2 曾经尝试在主Activity的onDestory()中调用StopService()方法让app关闭后service也结束运行,没有成功。如果service在app关闭后也停止运行,相信不会有这种bug产生。
3 app经过多方面测试才能完善。
- Android Service,AlarmManager组合实现定时任务踩的坑
- android Service重启问题,结合AlarmManager实现定时任务
- Service+AlarmManager 定时任务
- Android,定时任务AlarmManager
- AlarmManager实现精准定时任务
- AlarmManager实现精准定时任务
- 使用AlarmManager实现Android应用每天定时执行任务
- android使用AlarmManager实现应用每天定时执行任务
- PendingIntent和AlarmManager实现定时(重复)任务 Android
- 利用pendingintent 和AlarmManager实现定时任务的一些分析
- android 后台定时提醒(Service,AlarmManager的使用)
- 谈谈对Android定时任务中AlarmManager的理解
- 8.4 AlarmManager实现精准定时任务
- 使用AlarmManager实现精确定时任务
- 使用Android AlarmManager类定时执行任务
- Android利用AlarmManager执行定时任务
- AlarmManager详解:android中的定时任务
- 【AlarmManager】使用AlarmManager定时任务
- 互联网应用开发技术的发展对网游的影响
- Flutter实战一Flutter聊天应用(二十)
- 获取模块路径
- jquery可见性过滤选择器:hidden、:visible
- LintCode 合并两个排序链表
- Android Service,AlarmManager组合实现定时任务踩的坑
- 【Python】Python3 List remove()方法
- winform多线程
- windows平台使用eclipse搭建android开发环境
- JavaWeb——文件上传和下载
- IAR 编译不过performing Post-Build Action的问题
- 并发编程1:全面认识 Thread
- Python Numpy的数组array和矩阵matrix
- Tp自定义分页