项目中遇到一个问题,在视频通话时,有时候页面会异常崩溃,对于Activity是不会走正常的生命周期的,我们的程序必须知道这个Activity是否存在,这期间用了几种方式去实现这个点,结果都不是很好,最终决定使用定时器去做这块:
1.使用一个服务不断检测目标activity是否存在。好了问题来了,这种方式比较消耗资源,主要是你的service一直运行在后台,在配置比较差的android设备上表现不是很好。这个想法直接否定。
2.我自己的想法是使用定时器;在activity启动时,随之在一个已经存在的service中启动一个定时器,这个定时器主要内容是不断检测这个activity是否存在,这中间涉及到3个要点:
- 目标activity在配置文件中的启动方式标注为android:launchMode="singleInstance",也就是这个activity单独开一个Task。这点是为了方便检查,同时还有业务上的考虑
- 由于我们已经存在一个常驻后台的服务,所以在这里就不需要重启一个service,只需要在这个服务中启动一个定时器去轮询检测activity记录,就可以做到这点了
- 最后一点是,定时器独有的属性。就是每个定时器以及任务只能执行一次。再次需要Task时,需要重新new一个对象。
说了这些,下面贴上我的代码
<span style="font-size:18px;"> private final static int DEFAULT_TIME = 3500;
private ConcurrentHashMap<String,Task> guardMap = new ConcurrentHashMap<String, Task>();
class Task extends TimerTask implements Closeable{
private final String CLASSNAME = "需要检查的类名,需要带上包名";
private final int DEFAULT_NUM = 4;
private String id;
private Timer timer;
private ActivityManager am;
// 任务是否关闭
private boolean isClose = false;
public Task(String _id){
this.id = _id;
}
@Override
public void run() {
if(!checkActivityStatus()){
try {
if(!isClose){
// 做一些activity相关变量的维护,标示这个activity是否存在
XXApplication.getPreference().setKeyValue(PrefType.PHONE_CALL_RUNNING, "false");
TvConnectedActivity.isDialService = false;
this.close();
}
} catch (Exception e) {
LogUtil.d(e.getLocalizedMessage());
}
}
}
private boolean checkActivityStatus(){
boolean mark = false;
String className;
if(am == null){am = (ActivityManager)BizServices.this.getSystemService(ACTIVITY_SERVICE);}
List<RunningTaskInfo> appTask = am.getRunningTasks(DEFAULT_NUM);
if (appTask.size() > 0){
for(RunningTaskInfo info :appTask){
className = info.topActivity.getClassName();
if(CLASSNAME.equals(className)){
if(info.numRunning > 0){
mark = true;
}
return mark;
}
}
}
return mark;
}
public void setTimer(Timer timer) {
this.timer = timer;
}
@Override
public void close() throws IOException {
if(isClose){
// 关闭一次
return;
}
isClose = true;
this.cancel();
if(timer != null){
timer.cancel();
timer.purge();
}
if(guardMap.containsKey(id)){
guardMap.remove(id);
}
}
};
private void startInspectorMonitor(boolean isStart) {
if (isStart) {
try {
Thread.sleep(DEFAULT_TIME+500);
} catch (Exception e) {
}
if(guardMap.size() > 0){
return;
}else{
openTask();
}
} else {
Collection<Task> list = guardMap.values();
if(guardMap.size() > 0){
for(Task task :list){
try {
task.close();
} catch (Exception e) {
}
}
}
// 做一些activity相关变量的维护,标示这个activity是否存在
NetPhoneApplication.getPreference().setKeyValue(PrefType.PHONE_CALL_RUNNING, "false");
}
}
private void openTask() {
Timer timer = new Timer();
String key = CommonUtil.getUUID();
Task task = new Task(key);
task.setTimer(timer);
timer.schedule(task, DEFAULT_TIME, DEFAULT_TIME);
guardMap.put(key, task);
}</span>