背景
一、因工信部整改要求,现编写检测工具如下功能:
- 1、禁止在用户未点击同意前,获取用户手机设备信息。
- 2、禁止在用户未点击同意前,发起网络接口请求
- 3、禁止在用户点击同意前,初始化第三方SDK,防止上报隐私信息;
- 4、禁止调用获取软件安装列表等敏感android api接口;
二、集成步骤
1、在根项目的build.gradle中添加以下内容:
arduino
dependencies {
classpath 'com.hujiang.aspectjx:gradle-android-plugin-aspectjx:2.0.8'
}
2、在需要使用module的build.gradle中添加(app则不用)
bash
plugins {
id 'android-aspectjx'
}
3、添加依赖
arduino
dependencies {
implementation "com.meiyou.aspectj:aspectj:1.2.0" //具体请参照update.md使用最新版本
}
4、注意(重要重要重要!!!!!!!!!!!!!!!)
必须实现IPrivacyPolicyStub中的方法:
kotlin
@Protocol("PrivacyPolicyStub")
public class PrivacyPolicyStub {
/**
* 是否同意过首次进入app的隐私协议
*/
public boolean isAcceptFirstStartApp() {
return MainActivity.isAccepted;
}
}
依赖包中会实时去获取isAcceptFirstStartApp()的值,当用户同意首次进入app的隐私协议后,需要及时改变返回的值。
5、确认主工程app/build.gradle有应用插件:
arduino
apply plugin: 'android-aspectjx'
aspectjx {
exclude 'com.alipay', 'com/alipay'
}
scss
支付宝SDK必须exclude(不exclude会导致支付出现ClassNotFound),采用此种全局扫描,避免遗漏
6、如果原本自己的app有集成AspectjFix用于整改,对比一下这个库里边的AspectjUtil类,有重复的话,app里需要进行删除,避免重复hook造成的问题,因为这个库全局公用(重要重要重要!!!!!!!!!!!!!!!!!!!!)
三、测试方法
1、面向安全人员和产品的测试方法:
- 1、下载fbflipper.com 工具,并打开,等待手机连接;
- 2、安装美柚Test版本或者Debug版本(这两个版本有日志),手机USB连接电脑,连接成功后,Flippe软件会输出app的logcat日志
- 3、在Flipper软件上过滤 "SAFE"字样
- 4、操作APP,查看日志是否有异常即可,比如:
2、面向测试和开发人员的测试方法:
-
可参考测试方法1或者按如下步骤
-
1、编译Test或者Debug包(有日志就行)手机挂上Charles代理;
-
2、操作以下过程:卸载重装app,打开app,停留隐私弹窗界面,点击隐私链接,然后返回停留在隐私弹窗界面。
-
3、查看是否有触发 不符合安全整改 的问题(测试人员)
-
查看对应项目的crash缺陷列表:
- 出现"未接受隐私弹窗就初始化SDK"相关的字样的bug,需要进行修正,禁止在未同意前初始化第三方SDK
- 出现 "获取了软件安装列表"相关的字样的bug,需要进行修正,禁止获取设备软件安装列表;
- 出现 "用户未同意隐私协议,主线程获取设备信息:"相关的字样的bug,需要进行修正,用户未统一前,禁止获取设备信息
- 出现 ""主线程接口请求""相关的字样的bug,需要进行修正,禁止在主线程进行网络请求
- 出现 "application接口请求"相关的字样的bug,不一定需要进行修正,由开发进一步确认即可。
- 若用户未点击同意前,代理出现http请求,请反馈开发进行修改,说明有遗漏拦截的地方
- 若无以上问题,说明验证通过。
-
-
4、查看是否有触发 不符合安全整改 的问题(开发人员)
-
查看logcat信息日志,过滤"Aspect"字样:
- 出现 "未接受隐私弹窗就初始化SDK"相关的字样的bug,需要进行修正,禁止在未同意前初始化第三方SDK
- 出现 "获取了软件安装列表"相关的字样的bug,需要进行修正,禁止获取设备软件安装列表;
- 出现 "用户未同意隐私协议,主线程获取设备信息:"相关的字样的bug,需要进行修正,用户未统一前,禁止获取设备信息
- 出现 ""主线程接口请求""相关的字样的bug,需要进行修正,禁止在主线程进行网络请求
- 出现 "application接口请求"相关的字样的bug,不一定需要进行修正,由开发进一步确认即可。
- 若用户未点击同意前,代理出现http请求,需要进行修改,说明有遗漏拦截的地方
- 若无以上问题,说明验证通过。
-
-
5、 核心hook api如下:
`package com.meiyou.app.aspectj;
@Aspect public class AspectjUtil {
java
public static final String TAG = "AspectjUtil";
/**
* 第三方SDK包含:
* 友盟、bugly、QQ、微博、微信、支付宝、
* 淘宝百川、七鱼、腾讯IM、
* 阿里云播放器、穿山甲、腾讯X5、
* 阿里云、高德地图、OPPO PUSH、VIVIO PUSH、J PUSH、HUAWEI PUSH、MI PUSH、
* 腾讯短视频;
* 美摄SDK
* @param joinPoint
* @return
* @throws Throwable
*/
@Around("(call(* com.baichuan.nb_trade.core.AlibcTradeSDK.asyncInit(..))) || " + //百川sdk
"(call(* com.tencent.smtt.sdk.QbSdk.initX5Environment(..))) || " + //X5
"(call(* com.meiyou.framework.ui.widgets.pulltorefreshview.CustomWebView.init(..))) || " + //X5 webview
"(call(* com.tencent.bugly.crashreport.CrashReport.initCrashReport(..))) || " + //Bugly
"(call(* com.umeng.commonsdk.UMConfigure.init(..))) || " + //友盟SDK
"(call(* com.meiyou.framework.share.SocialService.prepare(..))) || " + //分享SDK
"(call(* com.qiyukf.unicorn.api.Unicorn.init(..))) || " + //七鱼SDK
"(call(* com.bytedance.sdk.openadsdk.TTAdSdk.init(..))) || " + //穿山甲SDK
"(call(* com.tencent.imsdk.TIMManager.init(..))) || " + //腾讯IM SDK
"(call(* com.amap.api.location.AMapLocationClient.startLocation(..))) || " + //高德SDK
"(call(* com.meiyou.pushsdk.PushSDK.init(..))) || " +
"(call(* com.tencent.ugc.TXUGCBase.setLicence(..))) || " + //腾讯视频SDK
"(call(* com.meicam.sdk.NvsStreamingContext.init(..))) " )
public Object handleSDKInit(ProceedingJoinPoint joinPoint) throws Throwable {
try {
if (!AspectjController.INSTANCE.isAcceptFirstStartApp()) {
if(isTest()){
//上报tapd,用于测试记录
String line="",className="",methodName="";
try {
line = joinPoint.getSourceLocation().toString(); //BbjInit:83
className = joinPoint.getSignature().getDeclaringType().getSimpleName();// TTTBASE
methodName = joinPoint.getSignature().getName(); //setLicence
}catch (Exception ex){
ex.printStackTrace();
}
String message = "严重警告:未接受隐私弹窗就初始化SDK:"+line+"->"+className+"->"+methodName;
LogUtils.e(TAG, message);
ToastUtils.showToast(MeetyouFramework.getContext(), message);
sendToTapd(message,3);
if(isTest() && joinPoint.getTarget()!=null && joinPoint.getSignature()!=null){
//打印logcat,用于后台埋点
String name = joinPoint.getSignature().getName();
String classSimpleName = joinPoint.getTarget().getClass().getSimpleName();
AspectjLogController.INSTANCE.handleThirdSDKReport(
classSimpleName,name,"");
}
}
}
} catch (Exception e) {
}
return joinPoint.proceed();
}
@Around("(call(* android.content.pm.PackageManager.getInstalledPackages(..))) || "+
"(call(* android.content.pm.PackageManager.getInstalledPackagesAsUser(..))) || " +
"(call(* android.content.pm.PackageManager.getInstalledApplications(..)))")
public Object handleGlobalGetInstalledPackages(ProceedingJoinPoint joinPoint) throws Throwable {
try {
//上报tapd,用于测试记录
if(isTest()){
String line="",className="",methodName="";
try {
line = joinPoint.getSourceLocation().toString(); //BbjInit:83
className = joinPoint.getSignature().getDeclaringType().getSimpleName();// TTTBASE
methodName = joinPoint.getSignature().getName(); //setLicence
}catch (Exception ex){
ex.printStackTrace();
}
String message = "严重警告:获取了软件安装列表:"+line+"->"+className+"->"+methodName;
LogUtils.e(TAG, message);
ToastUtils.showToast(MeetyouFramework.getContext(), message);
sendToTapd(message,3);
}
//打印logcat,用于后台埋点
try {
if(isTest()&& joinPoint.getTarget()!=null && joinPoint.getSignature()!=null){
String name = joinPoint.getSignature().getName();
String classSimpleName = joinPoint.getTarget().getClass().getSimpleName();
AspectjLogController.INSTANCE.handleLogReport(classSimpleName,name,"");
}
}catch (Exception ex){
ex.printStackTrace();
}
return joinPoint.proceed();
} catch (Exception e) {
}
return null;
}
@Around("call(* android.content.Context.getSystemService(..))")
public Object location(ProceedingJoinPoint joinPoint) throws Throwable {
try {
Object[] args = joinPoint.getArgs();
if(args!=null && isTest()){
for (Object arg : args) {
if (StringUtils.equalsIgnoreCase("location",arg.toString())) {
LogUtils.d(TAG, "arg = " + arg.toString());
String className = joinPoint.getSignature().getName();
LogUtils.e(TAG, "className = " + className);
LogUtils.e(TAG, "获取了用户的位置信息");
String message = Log.getStackTraceString(new Throwable());
AspectjLogController.INSTANCE.handleLocationReport(className,className,message);
LogUtils.d(TAG,message);
}
}
}
return joinPoint.proceed();//joinPoint.proceed();
} catch (Exception e) {
//e.printStackTrace();
}
return null;
}
@Around("(call(* com.amap.api.location.AMapLocationClient.startLocation(..))) ")
public Object handleGlobalLocation(ProceedingJoinPoint joinPoint) throws Throwable {
try {
//打印logcat,用于后台埋点
if(isTest()&& joinPoint.getTarget()!=null && joinPoint.getSignature()!=null){
String name = joinPoint.getSignature().getName();
String classSimpleName = joinPoint.getTarget().getClass().getSimpleName();
AspectjLogController.INSTANCE.handleLocationReport(classSimpleName,name,"");
}
}catch (Exception ex){
ex.printStackTrace();
}
return joinPoint.proceed();
}
@Around("(call(* android.content.ContentResolver.query(..))) ")
public Object handleGlobalContentResolver(ProceedingJoinPoint joinPoint) throws Throwable {
try {
try {
if(isTest()&& joinPoint.getTarget()!=null && joinPoint.getSignature()!=null){
String arg0 = null;
if(joinPoint.getArgs()!=null && joinPoint.getArgs().length>0){
arg0 = joinPoint.getArgs()[0].toString();//content://call_log/calls
}
String name = joinPoint.getSignature().getName();
String classSimpleName = joinPoint.getTarget().getClass().getSimpleName();
AspectjLogController.INSTANCE.handleContentProviderReport(arg0,classSimpleName,name,"");
}
}catch (Exception ex){
ex.printStackTrace();
}
return joinPoint.proceed();
} catch (Exception e) {
}
return null;
}
/**
* 禁止百川SDK获取应用列表
* @param joinPoint
* @return
* @throws Throwable
*/
@Around("call(* com.alibaba.alibclinkpartner.smartlink.manager.ALSLAppCheckManager.getInstallAppList(..))")
public Object handleBaichuanGetInstalledPacakges(ProceedingJoinPoint joinPoint) throws Throwable {
try {
LogUtils.e(TAG,"捕获到百川获取应用列表,拦截它并反馈new ArrayList()");
return new ArrayList<>();
} catch (Exception e) {
}
return null;
}
//@Around("call(* android.app.ActivityManager.getRunningAppProcesses(..))")
@Around("execution(* com.alibaba.analytics.a.a.c())")
public Object handleAlibabaGetRunningAppProcess(ProceedingJoinPoint joinPoint) {
try {
//禁用百川定频获取,强制返回前后台标识;
/*
if(isHitForbiddenMethod(joinPoint,"getRunningAppProcesses","ActivityManager","com.alibaba.analytics")){
return null;
}
return joinPoint.proceed();*/
return MeetyouWatcher.getInstance().getAppFrontBackWatcher().isAppAtBg();
}catch (Exception ex){
ex.printStackTrace();
} catch (Throwable throwable) {
//throwable.printStackTrace();
}
return false;
}
private boolean isAppAtBg(){
if(MeetyouWatcher.getInstance().getAppFrontBackWatcher()!=null
&& MeetyouWatcher.getInstance().getAppFrontBackWatcher().isAppAtBgMemory()){
return true;
}
return false;
}
/**
* AndroidQ适配
* 修复友盟android 10 因为权限无法上报的问题;
* <p>
* 以及 工信部整改需求:未点击同意前,不允许获取设备信息
* * https://www.tapd.cn/21039721/prong/stories/view/1121039721001042893
* * @param joinPoint
*
* @param joinPoint
* @return
* @throws Throwable
*/
@Around("(call(* android.telephony.TelephonyManager.*(..))) || " +
"(call(* android.net.wifi.WifiInfo.*(..))) || " +
"(call(* java.net.NetworkInterface.getHardwareAddress*(..))) || " +
"(call(* com.meiyou.sdk.core.UniqueIdUtils.getDeviceInfo(..))) || " +
"(call(* com.meiyou.sdk.core.DeviceUtils.getProvidersIMSI(..))) || " +
"(call(* com.meiyou.sdk.core.DeviceUtils.getPhoneOnlyKey(..))) || " +
"(call(* com.meiyou.detector.functionlality.Telephony.getImei(..))) || " +
"(call(* com.meiyou.detector.functionlality.Telephony.getImeiX(..))) || " +
"(call(* com.meiyou.detector.functionlality.Telephony.getImsi(..))) || " +
"(call(* com.meiyou.detector.functionlality.Telephony.getNetworkOperator(..))) || " +
"(call(* com.meiyou.detector.functionlality.Telephony.getSimStatus(..))) || " +
"(call(* com.meiyou.detector.functionlality.Telephony.getPhoneNumber(..))) || " +
"(call(* com.umeng.commonsdk.statistics.common.DeviceConfig.getAndroidId(..))) || " +
"(call(* com.umeng.commonsdk.statistics.common.DeviceConfig.getCPU(..))) || " +
"(call(* com.umeng.commonsdk.statistics.common.DeviceConfig.getDeviceIdForGeneral(..))) || " +
"(call(* com.umeng.commonsdk.statistics.common.DeviceConfig.getDeviceIdForBox(..))) || " +
"(call(* com.umeng.commonsdk.statistics.common.DeviceConfig.getGPU(..))) || " +
"(call(* com.umeng.commonsdk.statistics.common.DeviceConfig.getImei(..))) || " +
"(call(* com.umeng.commonsdk.statistics.common.DeviceConfig.getIMEI(..))) || " +
"(call(* com.umeng.commonsdk.statistics.common.DeviceConfig.getImeiNew(..))) || " +
"(call(* com.umeng.commonsdk.statistics.common.DeviceConfig.getImsi(..))) || " +
"(call(* com.umeng.commonsdk.statistics.common.DeviceConfig.getMacBySystemInterface(..))) || " +
"(call(* com.umeng.commonsdk.statistics.common.DeviceConfig.getMacByJavaAPI(..))) || " +
"(call(* com.umeng.commonsdk.statistics.common.DeviceConfig.getMacShell(..))) || " +
"(call(* com.meiyou.common.apm.controller.ApmAgent.start(..))) || " +
"(call(* com.meiyou.detector.DetectorManager.getDetectionInfoWithSign(..))) || " +
"(call(* com.meiyou.framework.util.ChannelUtil.getStatisticInfo(..)))")
public Object handleGlobalGetDeviceInfo(ProceedingJoinPoint joinPoint) {
try {
//android 10无法获取imei
if(Build.VERSION.SDK_INT >= 29 ){
if(isHitForbiddenMethod(joinPoint,"getDeviceId","TelephonyManager","")){
return null;
}
}
//禁止小米SDK在后台的时候获取SSID
if(isHitForbiddenMethodWhenBg(joinPoint,"getSSID","WifiInfo","com.xiaomi.push")){
return null;
}
//禁止七鱼SDK在后台的时候获取IMEI
if(isHitForbiddenMethodWhenBg(joinPoint,"getDeviceId","TelephonyManager","com.qiyukf")){
return null;
}
if (!AspectjController.INSTANCE.isAcceptFirstStartApp()) {
if (Thread.currentThread() != Looper.getMainLooper().getThread()) {
LogUtils.e(TAG, "线程中获取设备信息,因用户未同意隐私协议,已被拦截等待");
while (true) {
Thread.sleep(50);
if (AspectjController.INSTANCE.isAcceptFirstStartApp()) {
break;
}
}
LogUtils.e(TAG, "线程中用户已同意隐私协议,释放拦截");
} else {
if (joinPoint.getSourceLocation().toString().contains("AppUtil")) {
return null;
}
try {
if (isTest()) {
String line="",className="",methodName="";
try {
line = joinPoint.getSourceLocation().toString(); //BbjInit:83
className = joinPoint.getSignature().getDeclaringType().getSimpleName();// TTTBASE
methodName = joinPoint.getSignature().getName(); //setLicence
}catch (Exception ex){
ex.printStackTrace();
}
String message = "严重警告:用户未同意隐私协议,主线程获取设备信息:"+line+"->"+className+"->"+methodName;
LogUtils.e(TAG, message);
ToastUtils.showToast(MeetyouFramework.getContext(), message);
sendToTapd(message,3);
}
}catch (Exception ex){
ex.printStackTrace();
}
try {
if(isTest() && joinPoint.getTarget()!=null && joinPoint.getSignature()!=null){
String name = joinPoint.getSignature().getName();
String classSimpleName = joinPoint.getTarget().getClass().getSimpleName();
AspectjLogController.INSTANCE.handleLogReport(classSimpleName,name,"");
}
}catch (Exception ex){
ex.printStackTrace();
}
}
} else {
LogUtils.i(TAG, "用户已同意隐私协议,可正常获取设备信息");
try {
if(isAppAtBg() && joinPoint.getSignature()!=null){
String name = joinPoint.getSignature().getName();
String classSimpleName = "";
if(joinPoint.getTarget()!=null){
classSimpleName = joinPoint.getTarget().getClass().getSimpleName();
}
if(AspectjLogController.INSTANCE.isHitDeviceInfo(name+"",classSimpleName+"")){
LogUtils.i(TAG,"后台命中获取设备信息methodname:"+name+" className:"+classSimpleName+" 返回null");
return null;
}
}
if(isTest() && joinPoint.getTarget()!=null && joinPoint.getSignature()!=null){
String name = joinPoint.getSignature().getName();
String classSimpleName = joinPoint.getTarget().getClass().getSimpleName();
AspectjLogController.INSTANCE.handleLogReport(classSimpleName,name,"");
}
}catch (Exception ex){
ex.printStackTrace();
}
}
return joinPoint.proceed();
} catch (Exception e) {
//e.printStackTrace();
} catch (Throwable throwable) {
//throwable.printStackTrace();
}
return null;
}
private boolean isHitForbiddenMethod(ProceedingJoinPoint joinPoint,String methodName,String classsimpleName,String stack){
try {
try {
if(joinPoint.getTarget()!=null && joinPoint.getSignature()!=null){
String name = joinPoint.getSignature().getName();
String classSimpleName = joinPoint.getTarget().getClass().getSimpleName();
if(StringUtils.isNull(methodName)){
if((classsimpleName.equalsIgnoreCase(classSimpleName))){
if(StringUtils.isNull(stack)){
return true;
}
if(getStackLog().contains(stack)){
LogUtils.e(TAG,"禁用"+stack+"获取获取设备信息:"+methodName+" 直接return "+classSimpleName);
return true;
}
}
}else{
if((methodName.equalsIgnoreCase(name) && classsimpleName.equalsIgnoreCase(classSimpleName))){
if(StringUtils.isNull(stack)){
return true;
}
if(getStackLog().contains(stack)){
LogUtils.e(TAG,"禁用"+stack+"获取获取设备信息:"+methodName+" 直接return "+classSimpleName);
return true;
}
}
}
}
}catch (Exception ex){
ex.printStackTrace();
}
}catch (Exception ex){
ex.printStackTrace();
}
return false;
}
private boolean isHitForbiddenMethodWhenBg(ProceedingJoinPoint joinPoint,String methodName,String classsimpleName,String stack){
try {
try {
if(MeetyouWatcher.getInstance().getAppFrontBackWatcher()!=null
&& MeetyouWatcher.getInstance().getAppFrontBackWatcher().isAppAtBgMemory()
&& joinPoint.getTarget()!=null && joinPoint.getSignature()!=null){
String name = joinPoint.getSignature().getName();
String classSimpleName = joinPoint.getTarget().getClass().getSimpleName();
if(StringUtils.isNull(methodName)){
if((classsimpleName.equalsIgnoreCase(classSimpleName))){
if(getStackLog().contains(stack)){
LogUtils.e(TAG,"在后台时,禁用"+stack+"获取获取设备信息:"+methodName+" 直接return "+classSimpleName);
return true;
}
}
}else{
if((methodName.equalsIgnoreCase(name) && classsimpleName.equalsIgnoreCase(classSimpleName))){
if(getStackLog().contains(stack)){
LogUtils.e(TAG,"在后台时,禁用"+stack+"获取获取设备信息:"+methodName+" 直接return "+classSimpleName);
return true;
}
}
}
}
}catch (Exception ex){
ex.printStackTrace();
}
}catch (Exception ex){
ex.printStackTrace();
}
return false;
}
@Around("(execution(* com.tencent.smtt.utils.b.d(..))) || " +
"(execution(* com.tencent.smtt.utils.b.f(..))) || " +
"(execution(* com.tencent.smtt.utils.b.e(..))) || " +
"(execution(* com.tencent.smtt.utils.b.g(..)))")
public Object handleX5GetDeviceInfo(ProceedingJoinPoint joinPoint) throws Throwable {
try {
if (!AspectjController.INSTANCE.isAcceptFirstStartApp()) {
LogUtils.e(TAG, "用户未同意隐私协议,禁止com.tencent.smtt等方法执行获取设备信息");
return null;
} else {
return joinPoint.proceed();
}
} catch (Exception ex) {
ex.printStackTrace();
}
return joinPoint.proceed();
}
/**
* 工信部整改需求:未同意前,不允许请求网络
* https://www.tapd.cn/21039721/prong/stories/view/1121039721001042893
*
* @param joinPoint
* @throws Throwable
*/
@Around("(call(* okhttp3.OkHttpClient.newCall(..))) || (call(* okhttp3.Call.execute(..)))")
public Object handleOkHttp(ProceedingJoinPoint joinPoint) throws Throwable {
try {
if (!AspectjController.INSTANCE.isAcceptFirstStartApp()) {
if (Thread.currentThread() != Looper.getMainLooper().getThread()) {
LogUtils.e(TAG, "线程中触发接口,因用户未同意隐私协议,已被拦截等待");
while (true) {
Thread.sleep(50);
if (AspectjController.INSTANCE.isAcceptFirstStartApp()) {
break;
}
}
LogUtils.e(TAG, "用户已同意隐私协议,释放拦截接口等待");
}
} else {
LogUtils.i(TAG, "用户已同意隐私协议,可正常进行网络请求");
}
//不是正式包,但是正式环境
if(!AspectjController.INSTANCE.isProductApk()){
if(isTest()){
String url = getRequestUrl(joinPoint);
if(!StringUtils.isNull(url) && url.contains("test-") || url.contains("yf-")){
//正式环境请求了test-
try {
AspectjLogController.INSTANCE.handleHttpWrongReport("","",url);
}catch (Exception ex){
ex.printStackTrace();
}
}
}
}
if(isTest()){
final String url = getRequestUrl(joinPoint);
try {
AspectjLogController.INSTANCE.handleHttpReport("","",url);
}catch (Exception ex){
ex.printStackTrace();
}
//检测主线程http请求
/*if (Thread.currentThread() == Looper.getMainLooper().getThread()) {
if (!AspectjController.INSTANCE.isWhiteUrl(url)
&& !url.contains("doraemon.xiaojukeji.com")) {
// 解析请求地址
if (!StringUtils.isNull(url)) {
Uri uri = Uri.parse(url);
String message = uri.getPath()+ ":主线程接口请求:"+url;
LogUtils.e(TAG, message);
ToastUtils.showToast(MeetyouFramework.getContext(), message);
sendToTapd(message,3);
}
}
}*/
//检测application 里的网络请求
if(AspectjController.INSTANCE.isReportApplicationHttp()){
if (!AspectjController.INSTANCE.isWhiteUrl(url)&& !url.contains("doraemon.xiaojukeji.com")) {
if (MeetyouWatcher.getInstance().getActvityWatcher()!=null
&& MeetyouWatcher.getInstance().getActvityWatcher().getTopActivity()==null) {
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
@Override
public void run() {
if (MeetyouWatcher.getInstance().getActvityWatcher()!=null && MeetyouWatcher.getInstance().getActvityWatcher().getTopActivity()==null) {
if (!StringUtils.isNull(url)) {
Uri uri = Uri.parse(url);
String urlLog = uri.getScheme()+"://"+uri.getHost()+uri.getPath();//放服务端虑重,移除query
String message = uri.getPath()+ ":application接口请求:"+urlLog;
sendToTapd(message, 3);
}
}
}
},1000);
}
}
}
}
return joinPoint.proceed();
} catch (Exception e) {
// e.printStackTrace();
} catch (Throwable throwable) {
// throwable.printStackTrace();
}
return null;
}
/**
* 解析获取请求地址
*/
public String getRequestUrl(ProceedingJoinPoint joinPoint) {
String url = "";
try {
if (joinPoint != null && joinPoint.getTarget() != null) {
if (joinPoint.getTarget() instanceof Call) {
Call call = (Call) joinPoint.getTarget();
url = call.request().url().toString();
LogUtils.i(TAG, "Call url=" + url);
}
if (joinPoint.getTarget() instanceof OkHttpClient) {
if (joinPoint.getArgs() != null
&& joinPoint.getArgs().length > 0
&& joinPoint.getArgs()[0] instanceof Request) {
url = ((Request) joinPoint.getArgs()[0]).url().toString();
LogUtils.i(TAG, "OkHttpClient url=" + url);
}
}
}
} catch (Exception e) {
}
return url;
}
/**
* 发送到tapd
*/
public void sendToTapd(String errorMsg, int infoType) {
try {
JSONObject jsonObject = new JSONObject();
jsonObject.put("errorMsg", errorMsg);
jsonObject.put("stack", getStackLog());
AspectjController.INSTANCE.sendToTapd(jsonObject.toString(), infoType);
} catch (Exception e) {
}
}
private String getStackLog(){
try {
String str = Log.getStackTraceString(new Throwable());
if(str.length()>800){
return str.substring(0,800);
}else{
return str;
}
}catch (Exception ex){
ex.printStackTrace();
}
return "";
}
private boolean isTest() {
return ConfigManager.from(MeetyouFramework.getContext()).isDebug()
|| ConfigManager.from(MeetyouFramework.getContext()).isTest();
}
} `