【问题标题】:Weird behaviour of AndroidJavaObject in Unity, when implemented through C#通过 C# 实现时,Unity 中 AndroidJavaObject 的奇怪行为
【发布时间】:2016-03-06 06:00:59
【问题描述】:

接下来是相当长的帖子。它相当复杂,需要以前使用过 Unity 插件的人(创建它们,而不是使用它们),我不希望因为一些常见的搜索词出现而被否决。所以,请阅读整篇文章。

所以,当我尝试通过 Unity 的 AndroidJavaObject 调用本机函数时,我遇到了一个相当奇怪的问题

我以前构建过本机插件,我试图消除对每次需要更新插件时都必须更新多个 JAR 的依赖。因此,我将很多本地 Java 代码从插件转移到 Unity 本身。

具体来说,有一种方法可以直接从 C# 调用原生 Android 函数(即系统函数),而不是创建插件并在调用原生函数的插件中调用函数。

例如,之前,如果我必须创建一个Toast,我必须用 Java 编写一些本机代码,导出插件,然后调用该函数。这些天来,可以直接从 C# 调用Toast.makeText,如下所示。

这就是我叫 Toast 的方法。

    public static void Toast (string text, int duration) {
        #if UNITY_ANDROID && !UNITY_EDITOR
        CreateActivity();

        activity.Call("runOnUiThread", new AndroidJavaRunnable ( () => {
            new AndroidJavaObject("android.widget.Toast", activity)
                .CallStatic<AndroidJavaObject>("makeText", activity, text, duration)
                    .Call("show");
        }) );
        #endif
    }

这里是 CreateActivity 方法

private static void CreateActivity () {
    #if UNITY_ANDROID && !UNITY_EDITOR
    if(activity == null)
        activity = new AndroidJavaClass("com.unity3d.player.UnityPlayer").
            GetStatic<AndroidJavaObject>("currentActivity");
    #endif

}

这非常有效。但是,当我尝试使用相同的方法创建 AlertDialog 时,我得到一个 androidjavaexception java.lang.classnotfoundexception

这是相关代码

public static void ShowAlert (string title, string message, string buttonText) {

    #if UNITY_ANDROID && !UNITY_EDITOR

    CreateActivity();

    activity.Call("runOnUiThread", new AndroidJavaRunnable ( () => {
        var builder = new AndroidJavaObject("android.app.AlertDialog.Builder", activity);
        ***//Exception happens in the above line***

        builder.Call<AndroidJavaObject>("setMessage", message)  
            .Call<AndroidJavaObject>("setTitle", title)
                .Call<AndroidJavaObject>("setCancelable", false)
                .Call<AndroidJavaObject>("setNeutralButton", buttonText)
                .Call("show");
    }) );
    #endif
}

我尝试过的

  1. 使用 android.support.v7.app.AlertDialog.Builder 而不是 android.app.AlertDialog.Builder
  2. 为 v7 和 v4 添加了支持 JAR(特别是 android-support-v4android-support-v7-appcompat
  3. 尝试为 Unity 的 JNI 创建自己的实现并调用它

以上都失败了。 (第三个,相当壮观)

现在,我也尝试了其他类,它们中的大多数都可以工作(例如ProgressDialog,它是 AlertDialog 的子类),而且这些都可以工作!

在这一点上,我很困惑,我想不出一个有效的理由来让某些功能起作用,而其他功能却失败了。

感谢任何想法。

编辑 1:添加 LogCat

I/Unity: AndroidJavaException: java.lang.ClassNotFoundException: android.app.AlertDialog.Builder
                                            at UnityEngine.AndroidJNISafe.CheckException () [0x00000] in <filename unknown>:0 
                                            at UnityEngine.AndroidJNISafe.CallStaticObjectMethod (IntPtr clazz, IntPtr methodID, UnityEngine.jvalue[] args) [0x00000] in <filename unknown>:0 
                                            at UnityEngine.AndroidJavaObject._CallStatic[AndroidJavaObject] (System.String methodName, System.Object[] args) [0x00000] in <filename unknown>:0 
                                            at UnityEngine.AndroidJavaObject.CallStatic[AndroidJavaObject] (System.String methodName, System.Object[] args) [0x00000] in <filename unknown>:0 
                                            at UnityEngine.AndroidJavaObject.FindClass (System.String name) [0x00000] in <filename unknown>:0 
                                            at UnityEngine.AndroidJavaObject._AndroidJavaObject (System.String className, System.Object[] args) [0x00000] in <filename unknown>:0 
                                            at UnityEngine.AndroidJavaObject..ctor (System.String className, System.Object[] args) [0x00000] in <filename unknown>:0 
                                            at AndroidNative+<ShowAlert>c__AnonSto

【问题讨论】:

  • 有趣的问题!是触发 ClassNotFoundException 的实际 android.app.AlertDialog.Builder 类(即,而不是应用方法调用中使用的隐式类之一)? logcat 摘录可能会提供有用的额外信息。

标签: unity3d unity5


【解决方案1】:

您遇到的问题是,AlertDialog.Builder 是 AlertDialog 的 嵌套类,通过反射创建嵌套类(这是 AndroidJavaObject 试图做的)需要稍微不同的语法在 Java 中:

android.app.AlertDialog$Builder

您的代码中还有其他一些小错误(您无法知道,因为您的构造函数不工作):

  • setNeutralButton 需要回调参数(可以为 null)
  • 必须在 AlertDialog 本身上调用 show,而不是在构建器上调用。

考虑到这些微小的修正,工作代码示例如下所示:

public static void ShowAlert(string title, string message, string buttonText)
{
    CreateActivity();

    activity.Call("runOnUiThread", new AndroidJavaRunnable(() =>
    {
        var builder = new AndroidJavaObject("android.app.AlertDialog$Builder", activity);

        builder.Call<AndroidJavaObject>("setMessage", message)
            .Call<AndroidJavaObject>("setTitle", title)
                .Call<AndroidJavaObject>("setCancelable", false)
                .Call<AndroidJavaObject>("setNeutralButton", buttonText, null)
                .Call<AndroidJavaObject>("create")
                .Call("show");
    }));
}

【讨论】:

  • 如果您无法访问的任何其他类仍然无法使用此方法实例化,请将它们添加到您的问题中(或开始一个新问题),我会看看是否可以想办法。获得更多关于整个 Unity-Android 互操作过程的文档是件好事!
  • 哇。我不知道我是怎么错过的。这不是我第一次使用嵌套类,现在我在嘲笑自己,“哦,你怎么会错过呢?”是的,我知道其余部分存在一些不一致之处,我必须解决。为了这个问题,我取出了一些代码(OnClickListeners)。非常感谢。
猜你喜欢
  • 2013-05-28
  • 2015-07-02
  • 1970-01-01
  • 2019-09-25
  • 2014-11-30
  • 2017-03-10
  • 1970-01-01
  • 1970-01-01
  • 2017-02-10
相关资源
最近更新 更多