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

2024-06-22

我在 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()。

In Xamarin 的文档 http://docs.xamarin.com/android/advanced_topics/Java_Integration,我读过有关 Java 到托管互操作的内容,这似乎正是我正在寻找的内容。如果我理解正确的话,当 Mono for Android 应用程序编译时,它会生成称为 Android Callable Wrappers (ACW) 的 Java 类。然后我应该能够从基于 Java 的 Android 应用程序调用这些 ACW 上的方法。

问题是,我到底如何引用编译好的 Mono for Android 应用程序(apk文件)来自基于 Java 的 Android 应用程序?

这就是我现在陷入困境的地方,无法找到任何具体的例子。这里也有类似的问题(this one https://stackoverflow.com/questions/7279012/how-to-call-a-net-class-from-a-java-class-in-mono-from-android and this one https://stackoverflow.com/questions/7467469/monodroid-interop-betwen-java-and-c-sharp)和一些博文,但它们只是归结为“使用 ACW”。但具体如何呢?也许我在这里遗漏了一些明显的东西,因为我不是 Android 人。

我尝试过的是动态加载dex我从 Mono for Android 中提取的文件apk。我只是将其放在存储卡上,然后尝试使用DexClassLoader从基于 Java 的 Android 应用程序加载它(我已经遵循了博客文章 http://android-developers.blogspot.sk/2011/07/custom-class-loading-in-dalvik.html)。找到了 ACW 类,但是当我尝试创建它的实例时,出现以下错误:

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

我想我必须以某种方式将 Mono for Android 运行时包含到基于 Java 的应用程序中,但我不知道如何实现。

EDIT:这是我试图加载的代码dex with:

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();
}

EDIT2:我现在正在读书here https://stackoverflow.com/questions/6814478/using-c-sharp-library-with-mono-for-android-from-java-code应该可以从 Java 直接启动 Mono for Android 编写的活动。我仍然不清楚如何从 Java 引用 Mono for Android,并且谷歌搜索没有产生相关的结果。现在真是难住了。


如果我正确理解你想要做什么,这实际上是不可能的。正如您收到的错误消息所暗示的那样,Mono for Android 应用程序中的 Activity 依赖于 Mono 运行时才能正常运行。在这种情况下,可调用包装器本身并没有什么用处,因为它只是一个调用 Mono 运行时的瘦 Java 包装器类。如果在构建项目后查看 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 运行时实际启动以运行该活动。

Edit

更新以回答您在评论中提出的问题。这ExportAttribute http://androidapi.xamarin.com/?link=T:Java.Interop.ExportAttribute基本上只是让您对 ACW 的生成方式有更多的控制,允许您指定 ACW 中应存在的特定方法或字段以及它应具有的名称。例如,当您想要在布局中使用 android:onClick 属性之类的内容时,这可能很有用,默认情况下 ACW 不包含您想要引用的方法。

在 Mono for Android 应用程序的上下文之外,您无法充分利用 ACW,因为 Mono 运行时不存在。用 C# 编写的代码在 Mono 运行时之上执行,并且不会在编译或类似过程中在幕后转换为 Java。在运行时,有两个并排运行的运行时,Dalvik(Android 的运行时)和 Mono,并且可调用包装器允许两者来回通信。因此,即使是 Mono for Android 类库仍然依赖于 Mono 运行时,因此您不能独立于该运行时使用它。

下图显示了架构的外观以及运行时之间的相互关系:

希望这有助于解决问题!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何从 Android 应用程序中调用 Mono for Android 类? 的相关文章

  • OpenMP 循环数组访问中的错误共享

    我想利用 OpenMP 来并行执行我的任务 我需要将数组的所有元素减去相同的数量并将结果写入另一个向量中 两个数组都是动态分配的malloc第一个填充了文件中的值 每个元素都有类型uint64 t pragma omp parallel f
  • 如何让 PCRE 与 C++ 一起使用?

    这是一个新手问题 但我希望我能尽可能清楚地表达我的问题 我正在尝试用 C 进行模式匹配 我已经从以下位置下载了 PCRE 的 Win32 版本here http gnuwin32 sourceforge net packages pcre
  • 如何在 C++ 中初始化嵌套类的构造函数

    我在初始化嵌套类构造函数时遇到问题 这是我的代码 include
  • 让 DrawerLayout 在 ActionBar 上滑动

    我在活动中有一个滑动抽屉菜单 其中有一个带有一些选项卡的操作栏 我想让滑动抽屉滑过标签 而不是滑过标签下方 这就是现在的样子 关于如何做到这一点有什么想法吗 注意 我知道我可能会在这里打破一些约定和 UI 模式 如果它根本不起作用 我会考虑
  • 嘲笑会员用户

    我目前正在开发一个 asp net mvc 2 应用程序 它使用默认的 SqlMembershipProvider 进行身份验证 我已经实现了一个控制器方法 通过调用读取当前用户的 ProviderUserKeyMembership Get
  • 如何更新 Websphere 7 以使用 EL2.2?

    这就是我所做的 按照此林肯 巴克斯特的帖子 http ocpsoft com java jsf2 java jsf2 how to add the magic of el el2 to jsf 我下载了 el api 2 2 jar 和 e
  • Android Studio - 程序类型已存在:com.google.android.gms.internal.measurement.zzwp

    昨天 我的应用程序运行良好 今天 不知道为什么 重新打开Android Studio后 应用程序就无法编译了 显示的错误是 Program type already present com google android gms intern
  • 除法时的小数舍入误差 (C#)

    我基本上有四个数字 比如 100 200 300 400 我需要计算概率为 100 100 200 300 400 200 100 200 300 400 等等在 当我使用小数数据类型来存储这些概率时 由于舍入问题 它们不会达到 1 在不使
  • 合并大文件的最佳方法是什么?

    我必须合并数千个大文件 每个大约 200MB 我想知道合并这些文件的最佳方法是什么 行将有条件地复制到合并文件中 可以使用 File AppendAllLines 或使用 Stream CopyTo 吗 使用 File AppendAllL
  • JdbcTemplate queryForInt/Long 在 Spring 3.2.2 中已弃用。应该用什么来代替呢?

    JdbcTemplate 中的 queryforInt queryforLong 方法在 Spring 3 2 中已弃用 我无法找出为什么或什么被认为是使用这些方法替换现有代码的最佳实践 典型方法 int rowCount jscoreJd
  • PC 上 XNA 中的信箱和缩放

    有没有一种方法可以让我基本上以 1080p 或 720p 作为默认分辨率来开发 XNA 游戏 然后根据设置的分辨率将游戏中的所有内容缩放到适当的大小 而不必在每个 Sprite 中设置缩放因子Draw 方法 我的想法是 我可以基于 1080
  • Scala 不可变 Map 速度慢

    当我创建地图时 我有一段代码 val map gtfLineArr 8 split map split collect case Array k v gt k v toMap 然后我使用这张地图来创建我的对象 case class MyOb
  • 64 位随机生成器种子

    我目前正在运行一个具有 8 个以上管道 线程 的多线程模拟应用程序 这些管道运行非常复杂的代码 该代码取决于种子生成的随机序列 然后该序列被归结为单个 0 1 我希望在将种子从主线程传递到处理管道后 这种 随机处理 具有 100 的确定性
  • 如何为Android编译最新的FFmpeg库?

    努力将当前 FFmpeg 的工作和一般最佳实践构建在一起 似乎没有最新的文档或教程 现有的内容充满了过时的链接或不起作用的构建脚本 构建独立的 NDK 工具链 下载最新的NDK并运行make standalone toolchain py
  • 具有可导出私钥的证书的“错误密钥”例外

    我正在尝试使用非对称加密来加密然后解密文件 我已经使用 makecert 创建了一个测试证书并将其安装到我的个人本地计算机存储中 将来我必须在多个服务器上安装此证书 这就是为什么我使用 pe 标志创建它 即使用可导出的私钥 证书已成功创建并
  • 从不同的线程访问对象

    我有一个服务器类 它基本上等待来自客户端的连接 在该类中 我创建了一个 NetworkStream 对象 以便能够从客户端接收字节 由于 NetworkStream Read 方法不是异步的 这意味着它将等到从客户端读取字节才能继续执行类似
  • allure2 侦听器在控制台中输出步骤

    我正在使用 Allure2 和 TestNG 我想编写自己的侦听器 在控制台输出中打印 Steps 我在 allure 中看到了 StepLifecycleListener 接口 但我无法在 TestNg 中实现此侦听器 有什么指点吗 Ov
  • Android:Html 锚链接仅在 Web 视图中有效一次

    在使用锚链接加载 html 内容时 我在 webview 中遇到一些奇怪的问题 以下代码非常适合锚标记 但是只有一次 第二次当我按下锚标签时不工作 protected void onCreate Bundle savedInstanceSt
  • 解决SecurityException:权限拒绝:启动意图。我需要什么许可?

    我想从应用程序打开游戏商店 在三星手机上还好 但在一加手机上却失败了 我不知道在哪里alibaba来自 真奇怪 异常 java lang SecurityException 权限拒绝 启动意图 act android intent acti
  • 有关 Endian 性和 .Net 的详细信息?

    我有几个关于字节顺序的问题 这些问题足够相关 我保证将它们作为一个问题提出 1 字节顺序是由 Net还是由硬件决定的 2 如果是由硬件决定的 我怎样才能在C 中找出硬件的字节序 3 字节序是否影响二进制交互 例如 OR AND OR 或移位

随机推荐