网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
IActivityController mActivityController = new IActivityController.Stub() {
//当调用Activity的onCreate方法(跳转新页面)时回调此方法,
//return false时不会启动Activity;return true时正常启动Activity
//不要在这个方法内做耗时操作
@Override
public boolean activityStarting(Intent intent, String pkg) throws RemoteException {
return true;
}
//当调用Activity的onResume方法(比如dialog消失)时会调用这个方法
@Override
public boolean activityResuming(String pkg) throws RemoteException {
return true;
}
/**
* 有应用在Java层产生异常时回调此方法
* 返回true时,会显示应用crash的弹窗,返回false时会立即kill应用
*/
@Override
public boolean appCrashed(String processName, int pid,
String shortMsg, String longMsg, long timeMillis,
String stackTrace) throws RemoteException {
return false;
}
/**
* 检测到ANR异常时就会回调此方法
*/
@Override
public int appEarlyNotResponding(String s, int i, String s1) throws RemoteException {
return 0;
}
/**
* 应用产生ANR时回调此方法,
* Return 0 时显示 "应用停止响应" 弹窗。
* Return 1 时不做任何操作,等待应用恢复正常;
* Return -1 时结束产生ANR的应用.
*/
@Override
public int appNotResponding(String processName, int pid,
String processStats) throws RemoteException {
return -1;
}
/**
* 系统停止响应时回调此方法,可以在这个方法里面对设备进行些恢复工作
*/
@Override
public int systemNotResponding(String msg) throws RemoteException {
return 0;
}
};
进程变化监听
由于ActivityController服务存在被干扰的情况,我们需要其他服务进行辅助判断,通过ActivityManager注册IProcessObserver可以获取进程变化的回调,特别是在onForegroundActivitiesChanged方法内可以判断是否触发页面切换。
通过IProcessObserver可以实现的功能:
**①. **在onForegroundActivitiesChanged方法内监听页面变化;
**②. **在onProcessStateChanged和onProcessDied方法内可以统计App的线程生命周期;
**③. **可以统计app运行期间创建的线程信息;
**④. **该服务被不同进程注册时,相互间互不影响;
缺点:
**①. **没有直观信息,需要使用uid进行关联,处理复杂;
IProcessObserver mProcessObserver = new IProcessObserver.Stub() {
//与用户交互的Activity发生变化时foregroundActivities为true,否则foregroundActivities为false
//uid产生该活动的应用标识,可以用包信息匹配到具体的应用
//pid 当前活动的线程/进城ID
@Override
public void onForegroundActivitiesChanged(int pid, int uid,
boolean foregroundActivities) throws RemoteException {
if(foregroundActivities) {
//
}
}
//活动状态发生变化时调用,在此方案内实际意义不大
@Override
public void onProcessStateChanged(int pid, int uid, int importance)
throws RemoteException {
}
//结束时调用
@Override
public void onProcessDied(int pid, int uid) throws RemoteException {
}
};
综合应用
上面两种方案各有优劣,我们可以将他们整合在一个流程内实现较为完善的截图机制:
①. 首先我们的服务主要依赖于ActivityController进行页面变化的感知,以便于获取详细的信息和精确控制;
**②. **我们注册IProcessObserver进行辅助验证,当页面发生变化时我们进行截屏,并通过ActivityController最后一次接收事件的时间判断其服务状态,如果服务状态异常,那么我们重新注册ActivityController服务;
**③. **开始监控页面时我们初始化一个定时器,可以定时(2S)截取屏幕,将当前截图Bitmap与上一次的截图Bitmap做图像匹配,如果图片相似度小于0.8,那么可以认定页面发生了变化,如果5S内没有保存过页面信息,那么需要重新初始化ActivityController服务。
Root设备的特殊方案
Android系统是基于Linux系统的移动操作系统。它们可以通过getevent命令输出键盘和屏幕事件,包括响应事件的坐标区域和键盘key值。但是Android系统基于安全考虑,大部分真机系统是没有权限执行getevent命令的,它不会输出任何有效信息,但是华为手机(荣耀20 i)上却可以正常使用。这是一个非常危险的权限,大家自己的手机还是不要开启开发者模式了!
/dev/input/event2: EV_ABS ABS_MT_POSITION_X 0000024b
/dev/input/event2: EV_ABS ABS_MT_POSITION_Y 0000065d
/dev/input/event2: EV_ABS ABS_MT_PRESSURE 000000f5
/dev/input/event2: EV_ABS ABS_MT_TRACKING_ID 00000000
/dev/input/event2: EV_ABS ABS_MT_TOUCH_MAJOR 000000a5
/dev/input/event2: EV_ABS ABS_MT_TOUCH_MINOR 00000087
/dev/input/event2: EV_ABS ABS_MT_ORIENTATION ffffffc6
/dev/input/event2: EV_ABS ABS_MT_BLOB_ID 00000002
/dev/input/event2: EV_SYN SYN_MT_REPORT 00000000
/dev/input/event2: EV_KEY BTN_TOUCH DOWN
/dev/input/event2: EV_SYN SYN_REPORT 00000000
/dev/input/event2: EV_ABS ABS_MT_POSITION_X 0000024b
/dev/input/event2: EV_ABS ABS_MT_POSITION_Y 0000065c
![img](https://img-blog.csdnimg.cn/img_convert/b899dbb88d967ff98bd2ec6ad859cb71.png)
![img](https://img-blog.csdnimg.cn/img_convert/d4349ae09945b88b253274b06ff37acf.png)
**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**[需要这份系统化的资料的朋友,可以戳这里获取](https://bbs.csdn.net/forums/4f45ff00ff254613a03fab5e56a57acb)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
](https://bbs.csdn.net/forums/4f45ff00ff254613a03fab5e56a57acb)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**