You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
'NoSuchMethodError' calling static interface method on pre-API-24 #6784
The problem occurs when I try to call an initialisation native method from my binding library (.aar). I know that the method exist in my Android Binding Library. Deleting folders bin and obj and rebuilding the project does not help. I also watched the file api.xml this method is there, and and I can refer to it. Removing or adding a method to Metadata.xml also doesn't help.
I also decompiled the .dll file and saw this method there.
method: Start(global::Android.Content.Context context, global::package.name.Configuration configuration)
The error I'm getting
Java.Lang.NoSuchMethodError
no static method "Lpackage/name/SDK;.start(Landroid/content/Context;Lpackage/name/Configuration;)V"
Steps to Reproduce
Create Android Binding library via .arr, which needs to be initialized in MyApplication.cs
Add reference from the Xamarin.Android project to Binding library.
Start the app
This error means the Java compiled method cannot be found. There are a few possible cases to investigate:
The classes.jar from the .aar is not being included in the binding library. Make sure your build action is set to LibraryProjectZip. This will add the .aar as an embedded resource in your binding librarly .dll.
The Java linker is removing the method. You will need to investigate Proguard rules if your method is getting removed from the Java .jar.
You probably don't want to mess with the Metadata for this case. Using the automatically generated one should create the correct mapping to the Java class.
I added proguard rules to the native library, but nothing has changed.
I added proguard rules to the binding project and xamarin.android app but still nothing changed.
the fact is that when initializing my library, one of the parameters is the context.
I tried adding <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
it, but nothing changes either. could this be the cause of the error?
and one more thing I noticed.
the native method takes android.content.context as one of the arguments. on the xamarin app side, I pass this:
@jpobst Thanks for a quick reply.
Everything I have on the Java side @kotlin.jvm.JvmStatic public final fun start(context: android.content.Context, configuration: package.name.Configuration): kotlin.Unit { /* compiled code */ }
Hmm, since the original code is Kotlin, and it's monkeying with how it will actually look in Java, let's see how it looks in Java.
Use a Java decompiler on your .jar file and post how the method actually got compiled into Java. (I use http://java-decompiler.github.io if you don't already have a Java decompiler.)
Additionally, this looks like a static method on an interface, which traditionally isn't supported in C#.
Is this still the exact error message you are getting?
Java.Lang.NoSuchMethodError
no static method "Lpackage/name/SDK;.start(Landroid/content/Context;Lpackage/name/Configuration;)V"
I would expect Lpackage/name/Name;...... There is no type called SDK that I see.
The other thing to check would be to decompile your C# binding assembly and see if it contains the compiled .jar as an embedded resource. The compiled Java code has to make it on to the device as well as the compiled C# code for it to work.
@jpobst Thanks for a qiuck reply. Yes, it's still the same error, SDK and Name are not the real names of packages and interfaces. I'm sorry if this has caused you any inconvenience.
This is from AndroidLibraryProjects.zip and the same I see in classes.jar:
@Metadata(mv = {1, 6, 0}, k = 1, xi = 48, d1 = {"\000\f\n\002\030\002\n\002\020\000\n\002\b\t\bf\030\000 \0042\0020\001:\b\002\003\004\005\006\007\b\t\006\n"}, d2 = {"Lpackage/name/Name;", "", "sdk_release"})
public interface Name {
@NotNull
public static final Companion Companion = Companion.$$INSTANCE;
@JvmStatic
static void start(@NotNull Context context, @NotNull Configuration configuration) {
Companion.start(context, configuration);
}
or did I misunderstand you?
And my build action is set to LibraryProjectZip in my .aar file
@jpobst I've been looking for the root of the problem for a very long time, and apparently I found it. I looked through the classes.dex file and saw there that I don't have a Name type, there is only a Name$-CC type.
Class #0 -
Class descriptor : 'Lpackage/name/Name$-CC;'
Access flags : 0x1011 (PUBLIC FINAL SYNTHETIC)
Superclass : 'Ljava/lang/Object;'
Interfaces -
Static fields -
Instance fields -
Direct methods -
#0 : (in Lpackage/name/Name$-CC;)
name : 'start'
type : '(Landroid/content/Context;Lpackage/name/Name$Configuration;)V'
access : 0x0009 (PUBLIC STATIC)
code -
registers : 3
ins : 2
outs : 3
insns size : 6 16-bit code units
catches : (none)
positions :
locals :
Virtual methods -
source_file_idx : 8937 (Name.kt)
I found workaround for this issue.
I changed the name of the Register from [Register ("package/name/Name", "", "Package.Name.INameInvoker")] to [Register ("package/name/Name$-CC", "", "Package.Name.INameInvoker")].
I also experienced this issue some time last year when I started developing a binding for the Twilio Conversations SDK for Android.
Calling the static interface methods (eg. ConversationsClient.create) always threw a Java.Lang.NoSuchMethodError. I peeked into the SDK package source code & saw that those static interface methods were simply calling through to the implementing class methods, so I worked around the issue by copying the generated C# code for those methods, and changing the class reference to point to the implementing class instead (example).
I recently decided to dig deeper into this issue to find out exactly what the problem was. Here are my findings:
Support for static interface methods in Android was introduced in API 24. To facilitate backward-compatibility for Android projects with Minimum Version or TargetVersion set lower than 24, the Android build tools (d8 maybe?) extract all the static methods of the interface into a separate class (similar to how the Xamarin binding tools generate an additional class for interfaces that contain static methods), whose name is name of the interface + "$-CC", and modifies the calling code to call the static methods in that class instead.
I verified this by creating a JAR containing one interface that has one static method that simply adds 2 integers and returns the result. I then created a binding project for that and added the binding to a blank Xamarin Android project. The app calls the method and displays the result on the screen. You can find those here. The calling code is in MainActivity.cs.
You can observe the issue yourself by cloning the repo and performing the following steps:
Set Minimum Android version < API 24
Clean & Run the app
An error should show on the the screen
Set Minimum Android version >= API 24
Clean & Run the app
The adder result should show on the screen
A possible solution might be to add code in the binding interface to check for the presence of a "InterfaceName$-CC" class and, if it exists, use its handle to invoke the static interface method. If it doesn't exist, then the interface handle can be used instead.
changed the title [-]Java.Lang.NoSuchMethodError: 'No static method' when call method[/-][+]'NoSuchMethodError' calling static interface method on pre-API-24[/+]on Apr 7, 2022
Activity
jpobst commentedon Feb 22, 2022
This error means the Java compiled method cannot be found. There are a few possible cases to investigate:
classes.jarfrom the.aaris not being included in the binding library. Make sure your build action is set toLibraryProjectZip. This will add the.aaras an embedded resource in your binding librarly.dll..jar.You probably don't want to mess with the Metadata for this case. Using the automatically generated one should create the correct mapping to the Java class.
vas1l3nk commentedon Feb 24, 2022
I added proguard rules to the native library, but nothing has changed.
I added proguard rules to the binding project and xamarin.android app but still nothing changed.
vas1l3nk commentedon Feb 24, 2022
after adding proguard rules, I got this error
vas1l3nk commentedon Feb 24, 2022
Hi @jpobst, I found such a thing.


the fact is that when initializing my library, one of the parameters is the context.
I tried adding
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />it, but nothing changes either. could this be the cause of the error?
and one more thing I noticed.

the native method takes
android.content.contextas one of the arguments. on the xamarin app side, I pass this:And before calling this method in "
Application output", I getAttempt to remove non-JNI local reference, dumping threadjpobst commentedon Feb 24, 2022
Can you post:
vas1l3nk commentedon Feb 24, 2022
@jpobst Thanks for a quick reply.
Everything I have on the Java side
@kotlin.jvm.JvmStatic public final fun start(context: android.content.Context, configuration: package.name.Configuration): kotlin.Unit { /* compiled code */ }C# code
jpobst commentedon Feb 24, 2022
Hmm, since the original code is Kotlin, and it's monkeying with how it will actually look in Java, let's see how it looks in Java.
Use a Java decompiler on your
.jarfile and post how the method actually got compiled into Java. (I use http://java-decompiler.github.io if you don't already have a Java decompiler.)Additionally, this looks like a static method on an interface, which traditionally isn't supported in C#.
You can try enabling
<_EnableInterfaceMembers>if you want to support the static method on the C# interface: https://docs.microsoft.com/en-us/xamarin/android/release-notes/10/10.1#c-80-default-interface-members-for-bindings-projects.Alternatively, it looks like this is handled the old way where it has been moved to a class instead.
Please post the C# class signature (including the
[Register]attribute) for the C# type containing theStartmethod.vas1l3nk commentedon Feb 24, 2022
@jpobst Thanks for reply. This is from java decompiler
C# signarure with [Register]:
I have already tried to add :
but nothing has changed
vas1l3nk commentedon Feb 24, 2022
at first there was a class, but after restarting the mac and rebuild, the interface appeared lol
jpobst commentedon Feb 24, 2022
Is this still the exact error message you are getting?
I would expect
Lpackage/name/Name;...... There is no type calledSDKthat I see.The other thing to check would be to decompile your C# binding assembly and see if it contains the compiled
.jaras an embedded resource. The compiled Java code has to make it on to the device as well as the compiled C# code for it to work.vas1l3nk commentedon Feb 24, 2022
@jpobst Thanks for a qiuck reply. Yes, it's still the same error, SDK and Name are not the real names of packages and interfaces. I'm sorry if this has caused you any inconvenience.
This is from AndroidLibraryProjects.zip and the same I see in
classes.jar:or did I misunderstand you?
And my build action is set to
LibraryProjectZipin my.aarfilevas1l3nk commentedon Feb 25, 2022
@jpobst Hello, when I use these group properties
I generate an interface like here:
this is handled the old way where it has been moved to a class instead.
well in two cases I still get an error:
vas1l3nk commentedon Feb 25, 2022
@jpobst I've been looking for the root of the problem for a very long time, and apparently I found it. I looked through the
classes.dexfile and saw there that I don't have aNametype, there is only aName$-CCtype.please tell me what I can do in this case
vas1l3nk commentedon Feb 25, 2022
I found workaround for this issue.
I changed the name of the Register from
[Register ("package/name/Name", "", "Package.Name.INameInvoker")]to[Register ("package/name/Name$-CC", "", "Package.Name.INameInvoker")].but maybe there is some other way?
jpobst commentedon Mar 1, 2022
I guess if that works then it's valid. 🤷♂️
I don't know why the type named
Nameisn't in theclasses.dex.vas1l3nk commentedon Mar 4, 2022
I understand there is no solution to this problem yet?
jpobst commentedon Mar 4, 2022
Unfortunately not. Without a way to reproduce the error there isn't much we can do to investigate or fix it.
jedusei commentedon Apr 7, 2022
Hi @jpobst,
I also experienced this issue some time last year when I started developing a binding for the Twilio Conversations SDK for Android.
Calling the static interface methods (eg. ConversationsClient.create) always threw a Java.Lang.NoSuchMethodError. I peeked into the SDK package source code & saw that those static interface methods were simply calling through to the implementing class methods, so I worked around the issue by copying the generated C# code for those methods, and changing the class reference to point to the implementing class instead (example).
I recently decided to dig deeper into this issue to find out exactly what the problem was. Here are my findings:
Support for static interface methods in Android was introduced in API 24. To facilitate backward-compatibility for Android projects with Minimum Version or TargetVersion set lower than 24, the Android build tools (d8 maybe?) extract all the static methods of the interface into a separate class (similar to how the Xamarin binding tools generate an additional class for interfaces that contain static methods), whose name is
name of the interface + "$-CC", and modifies the calling code to call the static methods in that class instead.I verified this by creating a JAR containing one interface that has one static method that simply adds 2 integers and returns the result. I then created a binding project for that and added the binding to a blank Xamarin Android project. The app calls the method and displays the result on the screen. You can find those here. The calling code is in MainActivity.cs.
You can observe the issue yourself by cloning the repo and performing the following steps:
A possible solution might be to add code in the binding interface to check for the presence of a "InterfaceName$-CC" class and, if it exists, use its handle to invoke the static interface method. If it doesn't exist, then the interface handle can be used instead.
Hope this helps!
jpobst commentedon Apr 7, 2022
Thanks for the investigation! Things like this are never documented anywhere and we generally have to decode and guess what's going on.
[-]Java.Lang.NoSuchMethodError: 'No static method' when call method[/-][+]'NoSuchMethodError' calling static interface method on pre-API-24[/+]sahil2441 commentedon May 6, 2022
I'm noticing the same issue with RxJava 3 upgrade on API < 24.
jpobst commentedon Aug 3, 2023
This should be fixed for .NET 8+ due to dotnet/java-interop#1077.