Android Xamarin中的PackageName属性重写错误
[附件项目文件:] 我试图覆盖应用程序PackageName属性。但发生了java.lang.UnsatisfiedLinkError(未找到本机方法)。所以我在谷歌搜索这个问题,我发现了一个关于完全相同的问题()。但不幸的是,没有答案。我能做些什么来解决这个问题Android Xamarin中的PackageName属性重写错误,android,xamarin,xamarin.android,Android,Xamarin,Xamarin.android,[附件项目文件:] 我试图覆盖应用程序PackageName属性。但发生了java.lang.UnsatisfiedLinkError(未找到本机方法)。所以我在谷歌搜索这个问题,我发现了一个关于完全相同的问题()。但不幸的是,没有答案。我能做些什么来解决这个问题 [Application] public class TestApplication : Application { public override string PackageName { get
[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)
这看起来像是MonoAndroid中的一个限制和一个bug;发生
java.lang.UnsatifiedLinkError
异常,因为方法n_getPackageName
尚未在Mono运行时注册,并且无法解析。简单的回答是:
- 由于MonoAndroids启动序列的复杂性,可能无法覆盖
应用程序的
属性PackageName
- 向Xamarin提交错误报告。这是MonoAndroid启动例程中的一个bug(如下所述)李>
[ProjectName]/obj/[Configuration]/android/src
目录中生成一组Java代码。这段源代码是互操作层,它允许用C#构建的应用程序通过Dalvik或ART在Android设备上执行。项目中作为Android组件的每个类(应用程序
,服务
,活动
,片段
等)都将生成相应的.java源代码文件
这是您的TestApp
类的一个:
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 ();
}
}
这里需要注意的重要事项是:
- 链接到.NET程序集的重写方法的定义:
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\u getPackageName()
调用时崩溃的最可能原因是android.app.Application
sgetPackageName()
方法在onCreate
调用之前被调用
然后,如果仔细分析MonoPackageManager
和MonoRuntimeProvider
,就会找到问题的原因:
MonoRuntimeProvider.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);
}
MonoPackageManager.java
// ...
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;
}
}
}
// ...
当您完成启动例程时,崩溃的原因就会变得很清楚:
- Android加载
类并执行MonoRuntimeProvider
attachInfo
调用attachInfo
LoadApplication
调用使用应用程序上下文LoadApplication
方法getPackageName()
调用getPackageName()
方法n\u getPackageName()
java.lang.UnsatifiedLinkError
异常的根本原因就在这里
总而言之,这既是一个bug,也是一个启动复杂性。在Activity案例中,注册码在静态构造函数中调用,继承的PackageName属性运行良好。若我修改apk文件以调用静态构造函数类活动的注册码,那个么就并没有错误了?不用担心,我喜欢解决一个好问题;这个比我原来想的要复杂得多;)不要修改apk;这通常不是好的做法。为什么需要更改
PackageName
的返回值?我希望这样。答案是在应用程序中重写getPackageName。正如我所希望的那样,它在Java中运行良好。