我是靠谱客的博主 细腻哈密瓜,最近开发中收集的这篇文章主要介绍Kotlin书写动态代理method.invoke(iam, *args) must not be null,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

文章目录

    • 问题
      • 1.动态代理使用Kotlin书写报错
        • 描述
        • 思考
        • 解决

问题

1.动态代理使用Kotlin书写报错

描述

    Process: com.y.hookdemo, PID: 24014
    java.lang.IllegalArgumentException: method android.app.IActivityManager$Stub$Proxy.getActivityDisplayId argument 1 has type android.os.IBinder, got java.lang.Object[]
        at java.lang.reflect.Method.invoke(Native Method)
        at com.y.hookdemo.HookUtil$HookInvocationHandler.invoke(HookUtil.kt:121)
  • kotlin书写:
    private class HookInvocationHandler(private val iam: Any): InvocationHandler {

        @Throws(Throwable::class)
        override fun invoke(proxy: Any, method: Method, args: Array<Any>): Any {
            if (method.name.contains("startActivity")) {
                Log.e("Hook", "IActivityManager动态代理的invoke方法,伪装intent")
                for (i in args.indices) {
                    if (args[i] is Intent) {
                        val intent = args[i] as Intent
                        val proxyIntent = Intent(mContext, ProxyActivity::class.java)
                        proxyIntent.putExtra("intent", intent)
                        args[i] = proxyIntent
                        break
                    }
                }
            }
            return method.invoke(iam, args)
        }
    }

报错在 return method.invoke(iam, args) 这一行,用java写正常执行

  • java书写:
        private class HookInvocationHandler implements InvocationHandler {

        private Object iam;

        private HookInvocationHandler(Object iam) {
            this.iam = iam;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            if (method.getName().contains("startActivity")) {
                Log.e("Hook", "IActivityManager动态代理的invoke方法,伪装intent");
                for (int i = 0; i < args.length; i++) {
                    if (args[i] instanceof Intent) {
                        Intent intent = (Intent) args[i];
                        Intent proxyIntent = new Intent(mContext, ProxyActivity.class);
                        proxyIntent.putExtra("intent", intent);
                        args[i] = proxyIntent;
                        break;
                    }
                }
            }
            return method.invoke(iam, args);
        }
    }

将java通过as转为kotlin,这行变为

return method.invoke(iam, *args)

第二个参数变为*args,依旧报错

com.y.hookdemo E/AndroidRuntime: Error reporting crash
    java.lang.IllegalStateException: method.invoke(iam, *args) must not be null
        at com.y.hookdemo.HookUtil$HookInvocationHandler.invoke(HookUtil.kt:121)
        at java.lang.reflect.Proxy.invoke(Proxy.java:913)

思考

    @CallerSensitive
    // Android-changed: invoke(Object, Object...) implemented natively.
    @FastNative
    public native Object invoke(Object obj, Object... args)
            throws IllegalAccessException, IllegalArgumentException, InvocationTargetException;

反射api中Method的invoke方法接收可变长参数,在java中允许数组赋值给可变长参数Object… args,Kotlin中,数组是array,可变长参数类型是vararg,类型不一致,所以method.invoke(iam, args),是两个参数,第二个参数是数组,实际方法需要多个参数,第二个参数是IBinder,所以报第一个错。
Kotlin中数组转为可变长参数,是通过前面加*,所以as把java转为kotlin后,变为method.invoke(iam, *args),参数正确,但依旧报第二个错.

???

解决

解决毛,谷歌吹个毛的java和kotlin可以一起用,改用java写了

kotlin书写时,返回值是Any,方法可能是没有返回值的,所以修改为Any?,然后修改

private class HookInvocationHandler(private val iam: Any): InvocationHandler {

        @Throws(Throwable::class)
        override fun invoke(proxy: Any, method: Method, args: Array<Any>): Any? {
            if (method.name.contains("startActivity")) {
                Log.e("Hook", "IActivityManager动态代理的invoke方法,伪装intent")
                for (i in args.indices) {
                    if (args[i] is Intent) {
                        val intent = args[i] as Intent
                        val proxyIntent = Intent(mContext, ProxyActivity::class.java)
                        proxyIntent.putExtra("intent", intent)
                        args[i] = proxyIntent
                        break
                    }
                }
            }
            val res = method.invoke(iam, *args)
            Log.e("------a1:${method.name}",args.size.toString())
            Log.e("res = ",res?.toString() + "--")
            Log.e("returnType:",method.genericReturnType.typeName)
            return if("void" == method.genericReturnType.typeName) Unit else res
        }
    }

正常运行

  • 新的问题
    java书写时返回值为Object,执行没有返回值的method时,为什么可以

最后

以上就是细腻哈密瓜为你收集整理的Kotlin书写动态代理method.invoke(iam, *args) must not be null的全部内容,希望文章能够帮你解决Kotlin书写动态代理method.invoke(iam, *args) must not be null所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(37)

评论列表共有 0 条评论

立即
投稿
返回
顶部