zoukankan      html  css  js  c++  java
  • Unity中AndroidJavaProxy方法参数为null的坑

    AndroidJavaProxy是个好东西,可以让安卓原生代码直接调用Unity的代码,而不用通过SendMessage的方式。

    今天在使用的过程中发现一个问题,Android调用Unity的方法时报错:

    No such proxy method: xxxx(AndroidJavaObject)
    

    经过各种尝试和Google以后发现了最终的原因:

    首先贴出代码

    Java代码IListener.java

    package com.company.test;
    
    public interface IListener {
        public void onComplete(String error);
    }
    

    Java代码:Test.java

    package com.company.test;
    
    public class Test {
        
        private IListener listener;
        
        public void setListener(IListener listener) {
            this.listener = listener;
        }
        
        public void doTask() {
            listener.onComplete(null);
        }
        
        public static Test create() {
            return new Test();
        }
    }
    

    Unity代码:Test.cs

    using UnityEngine;

    public class Test : MonoBehaviour
    {
    private AndroidJavaObject nativeJavaObject;

    class Listener : AndroidJavaProxy
    {
    public Listener() : base("com.company.test.IListener")
    {

    }

    void onComplete(string error)
    {
    Debug.Log($"onComplete:{error}");
    }
    }
    // Start is called before the first frame update
    void Start()
    {
    AndroidJavaClass javaClass = new AndroidJavaClass("com.company.test.Test");
    nativeJavaObject = javaClass.CallStatic<AndroidJavaObject>("create");
    nativeJavaObject.Call("setListener", new Listener());
    nativeJavaObject.Call("doTask");
    }
    }

      Unity场景中把Test.cs脚本挂到GameObject上打包在真机运行会报以下错误:

    No such proxy method: Test+Listener.onComplete(UnityEngine.AndroidJavaObject)
    

    问题出现的是在UnityEngine.AndroidJavaProxy.Invoke的实现中

    public virtual AndroidJavaObject Invoke(string methodName, object[] args)
        {
          Exception inner = (Exception) null;
          BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
          System.Type[] types = new System.Type[args.Length];
          for (int index = 0; index < args.Length; ++index)
            // 如果参数为null则将类型设置为AndroidJavaObject
            types[index] = args[index] == null ? typeof (AndroidJavaObject) : args[index].GetType();
          try
          {
            MethodInfo method = this.GetType().GetMethod(methodName, bindingAttr, (Binder) null, types, (ParameterModifier[]) null);
            if (method != null)
              return _AndroidJNIHelper.Box(method.Invoke((object) this, args));
          }
          catch (TargetInvocationException ex)
          {
            inner = ex.InnerException;
          }
          catch (Exception ex)
          {
            inner = ex;
          }
          string[] strArray = new string[args.Length];
          for (int index = 0; index < types.Length; ++index)
            strArray[index] = types[index].ToString();
          if (inner != null)
            throw new TargetInvocationException(this.GetType().ToString() + "." + methodName + "(" + string.Join(",", strArray) + ")", inner);
          AndroidReflection.SetNativeExceptionOnProxy(this.GetRawProxy(), new Exception("No such proxy method: " + (object) this.GetType() + "." + methodName + "(" + string.Join(",", strArray) + ")"), true);
          return (AndroidJavaObject) null;
        }
    

    当Java调用Unity方法传递过来的值为null时,AndroidJavaProxy会按照参数类型为AndroidJavaObject的方式去查找方法(见上面第8行代码),自然就找不到。然后就报错了

    解决方法也很简单,重写Invoke方法避免查找Method失败就可以了

    public override AndroidJavaObject Invoke(string methodName, object[] args)
            {
                if (methodName == "onComplete")
                {
                    onComplete(args[0] as string);
                    return null;
                }
                return base.Invoke(methodName, args);
            }
    

    再次打包程序运行就不会报错,能正常输出日志了.

       PS:上面的修复代码只是测试使用,正式项目中请自行补全错误处理,参数转换以及多方法的支持等代码

  • 相关阅读:
    android开发之socket通信 向PC机发信息
    android:screenOrientation的说明
    java环境变量配置
    maven-webapp项目pom.xml配置
    maven设置本地仓库及配置阿里云镜像
    zxing生成二维码
    jQuery日期获取月和星期
    jquery实现导航栏分级切换
    servlet监听器统计在线人数
    xml配置utf-8编码过滤器
  • 原文地址:https://www.cnblogs.com/hyamw/p/15532650.html
Copyright © 2011-2022 走看看