-
Notifications
You must be signed in to change notification settings - Fork 529
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
UnsatisfiedLinkError when trying to override RegisterReceiver in Application inheritor #9334
Comments
The cause of this crash is straightforward:
needs to be called after
Which would fix this immediate problem. The larger problem is that all virtual [Application]
partial class MyApp : Android.App.Application {
public override Java.IO.File? FilesDir => "/data/local/tmp"; // sure, why not!
} We can't call (Behold the joy of circular dependencies?) We could instead move those I'm not sure what this would do to startup time. JNI invocations are generally slower than invocations from Java. Alternatively, we rework I'm not sure that this is possible, but it certainly should be explored. |
@jonpryor Thank you for investigation! I hope I haven't open any hell portal with that issue. Is there anything I can do to override this method without crashing? Because, from what I read, it looks impossible. |
Yes. Override…in Java. Via the glory that is // java
package kludge;
public class MyIntermediateApp extends android.app.Application {
@Override Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
// …
}
} // C#
public sealed partial class SampleApplication : Kludge.MyIntermediateApp {
// …
} The problem with this idea is that presumably you want to call C# code from |
@jonpryor That might work for this sample, where SampleApplication inherits exactly Android's Application class, but in real app I have already inherited my application class from third-party provided base class (to be precise, MvvmCross). Anything for such case? |
As my college Statics teacher used to say, "it's the same but different." You should still be able to use an intermediary, but instead of having the Java code subclass The problem will be determining the Java name of the C# class. For example, if we create a new MVVM-using app: % dotnet new android -n android-mvx
% cd android-mvx
% git apply --ignore-whitespace <<EOF
diff --git a/android-mvx.csproj b/android-mvx.csproj
index a1999d9..73b8237 100644
--- a/android-mvx.csproj
+++ b/android-mvx.csproj
@@ -10,4 +10,21 @@
<ApplicationVersion>1</ApplicationVersion>
<ApplicationDisplayVersion>1.0</ApplicationDisplayVersion>
</PropertyGroup>
+ <ItemGroup>
+ <PackageReference Include="Microsoft.Extensions.Logging.Abstractions">
+ <Version>5.0.0</Version>
+ </PackageReference>
+ <PackageReference Include="MvvmCross">
+ <Version>8.0.2</Version>
+ </PackageReference>
+ <PackageReference Include="MvvmCross.DroidX.Material">
+ <Version>8.0.2</Version>
+ </PackageReference>
+ <PackageReference Include="Serilog.Extensions.Logging">
+ <Version>3.0.1</Version>
+ </PackageReference>
+ <PackageReference Include="Xamarin.AndroidX.ConstraintLayout">
+ <Version>2.1.1.2</Version>
+ </PackageReference>
+ </ItemGroup>
</Project>
\ No newline at end of file
EOF
% dotnet build The Xamarin MVVX #if DEBUG
[Application(Debuggable = true)]
#else
[Application(Debuggable = false)]
#endif
public class MainApplication : MvxAndroidApplication<Setup, App>
{
public MainApplication(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
{
}
} Once % find obj -iname \*MvxAndroidApplication\*.java
./obj/Debug/net8.0-android/android/src/crc6466d8e86b1ec8bfa8/MvxAndroidApplication.java
./obj/Debug/net8.0-android/android/src/crc6466d8e86b1ec8bfa8/MvxAndroidApplication_2.java The Now that you've figured out the Java Callable Wrapper name, just use it from your Java code: package kludge;
public class MyIntermediateApp extends crc6466d8e86b1ec8bfa8.MvxAndroidApplication {
@Override Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
// …
}
} Then change your C# code from: public partial class MainApplication : MvxAndroidApplication<Setup, App> {
} to public partial class MainApplication : Kludge.MyIntermediateApp {
} You lose generics, but retain the inheritance relationship. |
@jonpryor Many thanks for your help! I tried what you suggest, created .java file in my project, inherited my Java class from MvxAndroidApplication referencing the package from JCW, but it only says "package does not exist" when referencing to package where MvxAndroidApplication is. Am I missing something? |
@jonpryor Here is the build log, and here is the sample I used. updIt looks like a bug. Created new issue #9374. upd2So I was right, generated Java types are not available when AndroidJavaSource binding happens. According to this comment it is not a bug, but expected behavior. So no workaround for now. |
Android framework version
net8.0-android
Affected platform version
.NET 8.0.303
Tried on Android 12 (Samsung) and Android 14 (Pixel)
Description
Not a lot to describe: trying override
RegisterReceiver(BroadcastReceiver? receiver, IntentFilter? filter)
results injava.lang.UnsatisfiedLinkError
.The full message is:
java.lang.UnsatisfiedLinkError: No implementation found for android.content.Intent crc645671ac291747a43a.SampleApplication.n_registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter) (tried Java_crc645671ac291747a43a_SampleApplication_n_1registerReceiver and Java_crc645671ac291747a43a_SampleApplication_n_1registerReceiver__Landroid_content_BroadcastReceiver_2Landroid_content_IntentFilter_2) - is the library loaded, e.g. System.loadLibrary?
Steps to Reproduce
Create new Android application, add Application class inheritor and override
RegisterReceiver(BroadcastReceiver? receiver, IntentFilter? filter)
method.Anyway, you can try the attached sample
Did you find any workaround?
Any workaround would be appreciated.
Relevant log output
The text was updated successfully, but these errors were encountered: