我试图覆盖Application PackageName属性。但是发生了java.lang.UnsatisfiedLinkError(未找到本机方法)。所以我在谷歌搜索这个问题,我发现一个完全相同问题的问题(https://forums.xamarin.com/discussion/45434/application-packagename-property-override-problem)。但遗憾的是没有答案。我该怎么办?
[Application]
public class TestApplication : Application
{
public override string PackageName
{
get
{
return "com.fake.packagename";
}
}
}
错误日志
07-17 23:06:57.179 E/AndroidRuntime(25801): FATAL EXCEPTION: main
07-17 23:06:57.179 E/AndroidRuntime(25801): Process: TestApp.TestApp, PID: 25801
07-17 23:06:57.179 E/AndroidRuntime(25801): java.lang.UnsatisfiedLinkError: Native method not found: md5cf27010e14af20e69784a5a54418b85f.TestApplication.n_getPackageName:()Ljava/lang/String;
07-17 23:06:57.179 E/AndroidRuntime(25801): at md5cf27010e14af20e69784a5a54418b85f.TestApplication.n_getPackageName(Native Method)
07-17 23:06:57.179 E/AndroidRuntime(25801): at md5cf27010e14af20e69784a5a54418b85f.TestApplication.getPackageName(TestApplication.java:25)
07-17 23:06:57.179 E/AndroidRuntime(25801): at android.app.ActivityThread.installProvider(ActivityThread.java:4855)
07-17 23:06:57.179 E/AndroidRuntime(25801): at android.app.ActivityThread.installContentProviders(ActivityThread.java:4476)
07-17 23:06:57.179 E/AndroidRuntime(25801): at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4413)
07-17 23:06:57.179 E/AndroidRuntime(25801): at android.app.ActivityThread.access$1500(ActivityThread.java:142)
07-17 23:06:57.179 E/AndroidRuntime(25801): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1263)
07-17 23:06:57.179 E/AndroidRuntime(25801): at android.os.Handler.dispatchMessage(Handler.java:102)
07-17 23:06:57.179 E/AndroidRuntime(25801): at android.os.Looper.loop(Looper.java:136)
07-17 23:06:57.179 E/AndroidRuntime(25801): at android.app.ActivityThread.main(ActivityThread.java:5120)
07-17 23:06:57.179 E/AndroidRuntime(25801): at java.lang.reflect.Method.invokeNative(Native Method)
07-17 23:06:57.179 E/AndroidRuntime(25801): at java.lang.reflect.Method.invoke(Method.java:515)
07-17 23:06:57.179 E/AndroidRuntime(25801): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:792)
07-17 23:06:57.179 E/AndroidRuntime(25801): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:608)
07-17 23:06:57.179 E/AndroidRuntime(25801): at dalvik.system.NativeStart.main(Native Method)
答案 0 :(得分:1)
这看起来像MonoAndroid中的限制和错误;发生java.lang.UnsatisfiedLinkError
异常是因为尚未向Mono运行时注册方法n_getPackageName
并且无法解析。简短的回答是:
PackageName
的{{1}}属性。让我们深入研究桥接Java代码,以确定发生这种情况的原因。构建MonoAndroid应用程序时,会在项目的Application
目录中生成一堆Java代码。此源代码是互操作层,允许使用C#构建的应用程序通过Dalvik或ART在Android设备上执行。项目中的每个类都是Android组件([ProjectName]/obj/[Configuration]/android/src
,Application
,Service
,Activity
等),会生成相应的.java源代码文件。
这是Fragment
课程的一部分:
TestApp
这里要注意的重要事项是:
链接到.NET程序集的重写方法的定义:
package md5cf27010e14af20e69784a5a54418b85f;
public class TestApplication
extends mono.android.app.Application
implements
mono.android.IGCUserPeer
{
static final String __md_methods;
static {
__md_methods =
"n_getPackageName:()Ljava/lang/String;:GetGetPackageNameHandler\n" +
"";
}
public TestApplication () throws java.lang.Throwable
{
super ();
}
public java.lang.String getPackageName ()
{
return n_getPackageName ();
}
private native java.lang.String n_getPackageName ();
public void onCreate ()
{
mono.android.Runtime.register ("TestApp.TestApplication, TestApp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", TestApplication.class, __md_methods);
super.onCreate ();
}
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 ();
}
}
static final String __md_methods;
static {
__md_methods =
"n_getPackageName:()Ljava/lang/String;:GetGetPackageNameHandler\n" +
"";
}
媒体资源的链接代码。
PackageName
注册码:
public java.lang.String getPackageName ()
{
return n_getPackageName ();
}
private native java.lang.String n_getPackageName ();
现在,它在public void onCreate ()
{
mono.android.Runtime.register ("TestApp.TestApplication, TestApp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", TestApplication.class, __md_methods);
super.onCreate ();
}
调用时崩溃的最可能原因是因为n_getPackageName()
android.app.Application
方法在之前被称为 getPackageName()
调用
如果您解剖onCreate
和MonoPackageManager
,您会发现问题的原因:
MonoRuntimeProvider.java
MonoRuntimeProvider
MonoPackageManager.java
@Override
public void attachInfo (android.content.Context context, android.content.pm.ProviderInfo info)
{
// Mono Runtime Initialization {{{
android.content.pm.ApplicationInfo apiInfo = null;
String platformPackage = mono.MonoPackageManager.getApiPackageName ();
if (platformPackage != null) {
Throwable t = null;
try {
apiInfo = context.getPackageManager ().getApplicationInfo (platformPackage, 0);
} catch (android.content.pm.PackageManager.NameNotFoundException e) {
// ignore
}
if (apiInfo == null) {
try {
apiInfo = context.getPackageManager ().getApplicationInfo ("Xamarin.Android.Platform", 0);
} catch (android.content.pm.PackageManager.NameNotFoundException e) {
t = e;
}
}
if (apiInfo == null)
throw new RuntimeException ("Unable to find application " + platformPackage + " or Xamarin.Android.Platform!", t);
}
try {
android.content.pm.ApplicationInfo runtimeInfo = context.getPackageManager ().getApplicationInfo ("Mono.Android.DebugRuntime", 0);
mono.MonoPackageManager.LoadApplication (context, runtimeInfo.dataDir,
apiInfo != null
? new String[]{runtimeInfo.sourceDir, apiInfo.sourceDir, context.getApplicationInfo ().sourceDir}
: new String[]{runtimeInfo.sourceDir, context.getApplicationInfo ().sourceDir});
} catch (android.content.pm.PackageManager.NameNotFoundException e) {
throw new RuntimeException ("Unable to find application Mono.Android.DebugRuntime!", e);
}
// }}}
super.attachInfo (context, info);
}
当您完成启动例程时,崩溃的原因变得清晰:
// ...
public static void LoadApplication (Context context, String runtimeDataDir, String[] apks)
{
synchronized (lock) {
if (!initialized) {
System.loadLibrary("monodroid");
Locale locale = Locale.getDefault ();
String language = locale.getLanguage () + "-" + locale.getCountry ();
String filesDir = context.getFilesDir ().getAbsolutePath ();
String cacheDir = context.getCacheDir ().getAbsolutePath ();
String dataDir = context.getApplicationInfo ().dataDir + "/lib";
ClassLoader loader = context.getClassLoader ();
Runtime.init (
language,
apks,
runtimeDataDir,
new String[]{
filesDir,
cacheDir,
dataDir,
},
loader,
new java.io.File (
android.os.Environment.getExternalStorageDirectory (),
"Android/data/" + context.getPackageName () + "/files/.__override__").getAbsolutePath (),
MonoPackageManager_Resources.Assemblies,
context.getPackageName ());
initialized = true;
}
}
}
// ...
类并执行MonoRuntimeProvider
。attachInfo
调用attachInfo
。LoadApplication
次调用使用应用程序上下文LoadApplication
方法。getPackageName()
调用getPackageName()
方法。根据n_getPackageName()
的文档:
public void onCreate()
在应用程序启动时,在创建任何活动,服务或接收方对象(不包括内容提供商)之前调用。实现应尽可能快(例如使用状态的延迟初始化),因为在此函数中花费的时间直接影响在进程中启动第一个活动,服务或接收器的性能。如果重写此方法,请务必调用super.onCreate()。
因为在ContentProviders onCreate之后调用了Applications onCreate,所以本机方法不会被Mono绑定,因此无法解析!因此,android.app.Application
例外存在根本原因。
总而言之,这既是错误又是启动复杂性。