如何在Android应用程序中调用Mono for Android类?

6

我在Mono for Android项目中创建了一个相当简单的Activity:

[Activity(Label = "AndroidApplication1", MainLauncher = true, Icon = "@drawable/icon")]
public class Activity1 : Activity
{
    private string value = "intitial";

    [Export]
    public string GetString()
    {
        return value;
    }

    [Export]
    public void SetString(string newValue)
    {
        value = newValue;
    }
}

该活动仅作为概念验证,因此非常简单。现在,我想能够从基于“正常”的Java的Android应用程序中调用GetString()方法。
Xamarin文档中,我阅读了有关Java到托管互操作性的内容,这似乎正是我要寻找的。如果我理解正确,当Mono for Android应用程序编译时,它会生成称为Android Callable Wrappers(ACW)的Java类。然后,我应该能够从基于Java的Android应用程序中调用这些ACW上的方法。
问题是,我该如何引用已编译的Mono for Android应用程序(apk文件)来自基于Java的Android应用程序?

我现在卡住了,找不到任何具体的例子。这里有一些类似的问题(this onethis one)和一些博客文章,但它们只是简单地说“使用ACWs”。但具体怎么做呢?也许我错过了什么显而易见的东西,因为我不是Android方面的人。

我尝试动态加载我从Mono for Android apk中提取的文件。我将其放在存储卡上,然后尝试使用Java-based Android应用程序中的DexClassLoader加载它(我遵循了这篇博客文章)。找到了ACW类,但当我尝试创建它的实例时,出现了以下错误:

未找到本地Lmno/android/Runtime;.register (Ljava/lang/String;Ljava/lang/Class;Ljava/lang/String;)的实现

我想我需要以某种方式将Mono for Android运行时包含到基于Java的应用程序中,但我不知道该怎么做。
编辑: 这是我正在尝试加载dex的代码:
DexClassLoader cl = new DexClassLoader(dexInternalStoragePath.getAbsolutePath(),
    optimizedDexOutputPath.getAbsolutePath(),
    null,
    getClassLoader());

try {
    Class<?> classActivity1 = cl.loadClass("androidapplication1.Activity1");

    // the following line throws the exception
    Object a = classActivity1.newInstance();

    Method getStringMethod = classActivity1.getMethod("GetString");
    Object result = getStringMethod.invoke(angel);

    result = null;
} catch (Exception e) {
    e.printStackTrace();
}

编辑2: 我现在在这里阅读到,应该可以直接从Java启动使用Mono for Android编写的活动。但我仍然不清楚如何从Java引用Mono for Android,谷歌搜索没有相关结果。现在真的很困惑。

1个回答

5

如果我正确理解你想做的事情,那么这实际上是不可能的。正如你收到的错误信息所暗示的那样,Mono for Android应用程序中的Activity依赖于Mono运行时才能正常工作。在这种情况下,可调用包装器本身并不有用,因为它只是一个薄薄的Java包装类,调用Mono运行时。实际上,如果你在构建项目后查看obj/Debug/android/src文件夹,你可以看到生成的可调用包装器。例如:

package androidapplication9;


public class Activity1
    extends android.app.Activity
    implements
        mono.android.IGCUserPeer
{
    static final String __md_methods;
    static {
        __md_methods = 
            "n_onCreate:(Landroid/os/Bundle;)V:GetOnCreate_Landroid_os_Bundle_Handler\n" +
            "";
        mono.android.Runtime.register ("AndroidApplication9.Activity1, AndroidApplication9, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", Activity1.class, __md_methods);
    }


    public Activity1 ()
    {
        super ();
        if (getClass () == Activity1.class)
            mono.android.TypeManager.Activate ("AndroidApplication9.Activity1, AndroidApplication9, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", "", this, new java.lang.Object[] {  });
    }


    public void onCreate (android.os.Bundle p0)
    {
        n_onCreate (p0);
    }

    private native void n_onCreate (android.os.Bundle p0);

    java.util.ArrayList refList;
    public void monodroidAddReference (java.lang.Object obj)
    {
        if (refList == null)
            refList = new java.util.ArrayList ();
        refList.add (obj);
    }

    public void monodroidClearReferences ()
    {
        if (refList != null)
            refList.clear ();
    }
}

由于Android的工作方式,你可以启动一个由Java应用程序定义的活动,该活动与Mono for Android应用程序相同,就像启动外部Java活动一样。当然,这需要两个应用都已经安装,但结果是Mono for Android应用程序和Mono运行时实际上会启动来运行该活动。
编辑
更新以回答您在评论中提出的问题。ExportAttribute基本上只是为您提供了更多控制如何生成ACW的方法,允许您指定特定方法或字段应存在于ACW中以及它应具有的名称。例如,在布局中使用android:onClick属性时,这可能很有用,默认情况下,ACW不会包含您要引用的方法。
在没有 Mono 运行时的情况下,你无法在 Mono for Android 应用程序之外使用 ACW。C# 编写的代码在 Mono 运行时上执行,而不会在编译期间被翻译成 Java 或其他语言。在运行时,存在两个运行时并行运行,即 Dalvik(Android 的运行时)和 Mono,并且可调用的包装器允许两个运行时相互通信。因此,即使是 Mono for Android 类库仍然依赖于 Mono 运行时,因此你不能独立于该运行时使用它。
以下是体系结构示意图,展示了运行时之间的关系:

Mono for Android architecture

希望这有助于澄清事情!

非常感谢您的回答,终于有东西可以使用了!您所说的很有道理,但是那些链接到我的问题中的Xamarin文档的目的是什么?我什么时候会使用ACWs和“Export”属性?也许最重要的是,有没有任何方法可以使Java应用程序与Mono for Android类“交流”,而不必安装两个单独的应用程序 - 比如拥有一个Mono for Android库并从Java应用程序中引用它?如果您能为我澄清一下这个问题,我将不胜感激。 - Nikola Anusev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接