阅读 1485

Android上随意修改第三方库源码

以arouter为例

  • 如何给一个类/接口增加方法/属性,且能在编码时调用此新增方法?
  • 如何修改一个方法的内容?

arouter-api-onActivitResult

这里有两个需求:

给ARouter的回调NavigationCallback增加一个onActivityResult方法

通过

ARouter.getInstance().navigation(mContext, this, requestCode, callback)
复制代码

直接在回调里收到onActivityResult的结果.

前提: 已有工具库:

通过api 'com.github.hss01248.StartActivityResult:activityresult:1.0.2'库,可一行代码实现activity回调:

StartActivityUtil.startActivity(activity, null, intent, requestCode != 0
                    , new TheActivityListener<Activity>() {
                        @Override
                        public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
                            super.onActivityResult(requestCode, resultCode, data);
                            if (callback != null) {
                                callback.onActivityResult(requestCode, resultCode, data);
                            }
                        }

                        @Override
                        public void onActivityNotFound(Throwable e) {
                            super.onActivityNotFound(e);
                            if (callback != null) {
                                callback.onLost(postcard);
                            }

                        }
                    });
复制代码

关键在于,如何给com.alibaba:arouter-api 库里的NavigationCallback增加一个原先不存在的onActivityResult方法,且使其起作用.

1.增加方法:

写一个同包名同路径的接口类,新增onActivityResult方法

使用classpath "com.github.skyNet2017:JarFilterPlugin:2.5.5"插件,打包时排除掉arouter-api库里的NavigationCallback,从而让我们自己写的这个多了方法的NavigationCallback生效.

2. 让回调生效:

找到arouter-api 里startActivityForReuslt的代码,使用aspectjx进行切入,替换掉整个方法的实现:

@Aspect
public class ARouterAspect {

    @Around("execution(* com.alibaba.android.arouter.launcher._ARouter.startActivity(..))")
    public Object weaveJoinPoint(ProceedingJoinPoint joinPoint) throws Throwable {
        Object[] args = joinPoint.getArgs();
        Object result = null;
        
        final int requestCode = (int) args[0];
        Context currentContext = (Context) args[1];
        Intent intent = (Intent) args[2];
        final Postcard postcard = (Postcard) args[3];
        final NavigationCallback callback = (NavigationCallback) args[4];

        if (currentContext instanceof FragmentActivity) {
            FragmentActivity activity = (FragmentActivity) currentContext;
            StartActivityUtil.startActivity(activity, null, intent, requestCode != 0
                    , new TheActivityListener<Activity>() {
                        @Override
                        public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
                            super.onActivityResult(requestCode, resultCode, data);
                            if (callback != null) {
                                callback.onActivityResult(requestCode, resultCode, data);
                            }
                        }

                        @Override
                        public void onActivityNotFound(Throwable e) {
                            super.onActivityNotFound(e);
                            if (callback != null) {
                                callback.onLost(postcard);
                            }

                        }
                    });
        } else {
            ActivityCompat.startActivity(currentContext, intent, postcard.getOptionsBundle());
        }

        if ((-1 != postcard.getEnterAnim() && -1 != postcard.getExitAnim()) && currentContext instanceof Activity) {    // Old version.
            ((Activity) currentContext).overridePendingTransition(postcard.getEnterAnim(), postcard.getExitAnim());
        }

        if (null != callback) { // Navigation over.
            callback.onArrival(postcard);
        }

        return result;
    }

}
复制代码

注意增加混淆规则,以及aspecjx的include配置

给arouter的关键步骤增加log日志,乃至记录到数据库,以便debug

找到切入点,aspectj切入. callback为接口,使用动态代理注入替换即可

@Aspect
public class ArouterLogAspect {

    @Around("execution(* com.alibaba.android.arouter.launcher.ARouter.navigation(..))")
    public Object callbackProxy(ProceedingJoinPoint joinPoint) throws Throwable {
        Object[] args = joinPoint.getArgs();
        if(args.length != 4){
            return joinPoint.proceed(args);
        }
        NavigationCallback callback = (NavigationCallback) args[3];
        args[3] = LogProxy.getProxy(callback);
        return joinPoint.proceed(args);
    }
    
    @Around("execution(* com.alibaba.android.arouter.facade.Postcard.setProvider(..))")
    public Object providerProxy(ProceedingJoinPoint joinPoint) throws Throwable {
        Object[] args = joinPoint.getArgs();
        IProvider provider = (IProvider) args[0];
        args[0] = LogProxy.getProxy(provider);
        return joinPoint.proceed(args);
    }
}
复制代码
文章分类
Android
文章标签