我在 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;
}
}
该 Activity 应仅用作概念验证,因此非常简单。现在,我希望能够从“普通的”基于 Java 的 Android 应用程序调用方法 GetString()。
在Xamarin's docs ,我已经阅读了有关 Java 到托管互操作的信息,这似乎正是我正在寻找的。如果我理解正确,当 Mono for Android 应用程序编译时,它会生成称为 Android Callable Wrappers (ACW) 的 Java 类。然后我应该能够从基于 Java 的 Android 应用程序调用这些 ACW 上的方法。
问题是,我如何从基于 Java 的 Android 应用程序(apk 文件)引用已编译的 Mono for Android 应用程序?
这就是我现在遇到的问题,无法找到任何具体示例。在 SO(this one 和 this one)和一些博文中也有类似的问题,但它们归结为“使用 ACW”。 但究竟如何?也许我在这里遗漏了一些明显的东西,因为我不是 Android 专家。
我尝试过的是动态加载从我的 Mono for Android apk 中提取的 dex 文件。我只是将它放在存储卡上,然后尝试使用基于 Java 的 Android 应用程序中的 DexClassLoader 来加载它(我遵循了这个 blog post )。找到了 ACW 类,但是当我尝试创建它的实例时,出现以下错误:
No implementation found for native Lmno/android/Runtime;.register (Ljava/lang/String;Ljava/lang/Class;Ljava/lang/String;)
我想我必须以某种方式将适用于 Android 运行时的 Mono 包含到基于 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: 我现在正在阅读here应该可以从 Java 直接启动用 Mono for Android 编写的 Activity 。我仍然不清楚如何从 Java 引用适用于 Android 的 Mono,谷歌搜索没有产生相关的结果。现在真的很难过。
最佳答案
如果我没有正确理解您要尝试执行的操作,那么这实际上是不可能的。正如您收到的错误消息所暗示的那样,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 应用程序中定义的 Activity ,其方式与您启动外部 Java Activity 的方式相同。当然,这取决于正在安装的两个应用程序,但会导致 Mono for Android 应用程序和 Mono 运行时实际启动以运行该 Activity 。
编辑
更新以回答您在评论中提出的问题。 ExportAttribute基本上只是让您更多地控制 ACW 的生成方式,允许您指定特定的方法或字段应该出现在 ACW 中,以及它应该有什么名称。当您想在布局中使用 android:onClick 属性之类的东西时,这会很有用,例如,默认情况下 ACW 不包含您要引用的方法。
在 Mono for Android 应用程序的上下文之外,您无法充分利用 ACW,因为不存在 Mono 运行时。用 C# 编写的代码在 Mono 运行时之上执行,并且不会在编译或类似的过程中在幕后转换为 Java。在运行时,有两个并排运行的运行时,Dalvik(Android 的运行时)和 Mono,可调用包装器允许两者来回通信。因此,即使是 Mono for Android 类库仍将依赖于 Mono 运行时,因此您不能独立于该运行时使用它。
此图显示了体系结构的外观,以及运行时如何相互关联:
希望这有助于解决问题!
关于c# - 如何从 Android 应用程序中为 Android 类调用 Mono?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12173568/
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t
对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl
我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚
Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack
我想用ruby编写一个小的命令行实用程序并将其作为gem分发。我知道安装后,Guard、Sass和Thor等某些gem可以从命令行自行运行。为了让gem像二进制文件一样可用,我需要在我的gemspec中指定什么。 最佳答案 Gem::Specification.newdo|s|...s.executable='name_of_executable'...endhttp://docs.rubygems.org/read/chapter/20 关于ruby-在Ruby中编写命令行实用程序