Android Xamarin AAR Binding enclosing type - android

I have an .aar third party library that I want to use in Xamarin Android. So I created a new Android Bindings Library, added the aar-library and changed the Build action of the aar file to LibraryProjectZip like described here: https://learn.microsoft.com/en-us/xamarin/android/platform/binding-java-library/binding-an-aar
Nothing else was changed and I would expect the project to compile and generate a dll file.
Instead I get a lot of errors saying Error CS0542 'xy': member names cannot be the same as their enclosing type.
When I jump to the origin of the error, I find the errors in generated code by Visual Studio with the classes looking something like:
public abstract class Albumin : Java.Lang.Object {
internal Albumin ()
{
}
// (removed for readability)
[Register ("ALBUMIN")]
public const string Albumin = (string) "albumin";
I cannot modify the source code of the library.
What can I do in order to build the Binding Library successfully?

Thank you very much #Leo Zhu for the answer in the comments:
The solution is Renaming Members.
So in my case the Metadata.xml in die Binings Library would look like the following:
<attr path="/api/package[#name='com.company.android.sdk.dataclass']/interface[#name='DataClass.Albumin']/field[#name='ALBUMIN']" name="name">ALBUMIN_Binding</attr>

Related

Android binding library: Type or namespace not found

I developed a Android Binding Library to bind a printer Android AAR file (The AAR has its build action set to LibraryProjectZip), and the project is compiled using Android 7.1, using class-parse android class parser, and AndroidCodeGen Target: XAJavaInterop1. I can provide the simple Project in order to have full access to the code and library.
But I have the following error: 'The type or namespace 'ILibrary' does not exist in the namespace 'Com.Sun.Jna' at Com.Sun.Jna.Native.cs. So I decided to check at the Android library using a decompiler and here is what I found:
The AAR file contains an interface 'Library' (not ILibrary), and the Native.class file contains a method whose signature is the following and is the source of the error and which requires a Library object as input
public static Library synchronizeLibrary(final Library library){...}
The C# generated code contains a Com.Sun.Jna.ILibrary.cs file which contains a public abstract class 'Library':
[Register ("com/sun/jna/Library", DoNotGenerateAcw=true)] public abstract class Library : Java.Lang.Object {...}
but the generated Native.cs file has the counterpart method SynchronizeLibrary :
// Metadata.xml XPath method reference: [Register ("synchronizedLibrary", "(Lcom/sun/jna/Library;)Lcom/sun/jna/Library;", "")] public static unsafe global::Com.Sun.Jna.ILibrary SynchronizedLibrary(global::Com.Sun.Jna.ILibrary library) {...}
I do not understand why the C# generated method SynchronizedLibrary demands an ILibrary and not the Library.
I tried to modify the Metadata.xml file to rename the class Library to ILibrary but with no success. Moreover I have a warning saying that:
class-parse: warning: could not load .jar entry 'libjnidispatch.jnilib': System.Argument.OutOfRangeException,
I tried to change the name of the interface from Library to ILibrary using <attr path="/api/package[#name='com.sun.jna']/class[#name='Library']" name="managedName">ILibrary</attr> but the definition of the interface does not change. It is strange that I have a reference path for the members of the interface but not the interface itself
[Register ("com/sun/jna/Library", DoNotGenerateAcw=true)]
public abstract class Library : Java.Lang.Object {
internal Library ()
{
}
// Metadata.xml XPath field reference: path="/api/package[#name='com.sun.jna']/interface[#name='Library']/field[#name='OPTION_ALLOW_OBJECTS']"
[Register ("OPTION_ALLOW_OBJECTS")]
public const string OptionAllowObjects = (string) "allow-objects";,
and I do not know if it is related to the prior problem.
Thank you for any suggestion
Finally, I found the way to correct the error by modifying the name of the interfaces by adding the following lines to the Metadata file:
<attr path="/api/package[#name='com.sun.jna']/interface[#name='Library']" name="name">ILibrary</attr>
But now I have errors telling me that JNIENv does not contain method like NewString. And I am wondering if it is related to the warning i have telling me that It cannot load .jar entry libjnidispatch.jnilib
Any ideas, thanks

Why an unresolved reference on attempting to access constant values?

The app defines constants in a Kotlin singleton object:
#file:JvmName("APIConstants")
package com.myapp.api
object APIConstants {
const val HTTP_RESPONSE_CODE_NOT_AUTHORIZED = 401
etc....
}
They are then used in another class:
import com.myapp.api.APIConstants.HTTP_RESPONSE_CODE_NOT_AUTHORIZED
etc ...
class API {
private fun returnBadResponse(response: Response<*>, callback: ApiAuthListener<*>) {
if (response.code() == HTTP_RESPONSE_CODE_NOT_AUTHORIZED) {
callback.onBadAuthToken()
} else {
callback.onFailure(response.message(), getServerError(response))
}
}
In this class Android Studio (3.0 beta) provided a hint to add the import for the constant, and it does not give any indication of a problem (no red underlines etc, and the constant reference in the method is shown in purple italic text indicating it has been resolved) but when I build the project I get this:
Error: Unresolved reference: HTTP_RESPONSE_CODE_NOT_AUTHORIZED
I've tried clearing the IDE cache and restarting it, and doing a clean build, which make no difference. I've tried removing the #JvmName annotation and even placing the const values in the root of the file with no containing object but neither allows a build.
Why is the class failing to reference the constant, especially when the IDE strongly suggests it can resolve it?
And the solution is.... to make very sure all Kotlin source files have a .kt file extension! In this case the APIConstants file was called "APIConstants" and not "APIConstants.kt" which appears to mean the IDE was able to resolve references based on the content of the file, but the build tools could not. Confusingly Android Studio showed a Kotlin K icon on the filename despite the lack of a .kt extension.

Scala reflection java.rmi dependency, can it work on Android?

I would like to use the Scala (2.11) reflection package's runtime mirror in a Scala application compiled for android which is being build using Scala on android.
I was able to fiddle with ProGuard options in order to make it include the required Scala classes. However when I try to get a mirror instance:
universe.runtimeMirror(this.getClass.getClassLoader)
(Indeed it fails during the lazy computation of universe)
The application crashes in run time:
java.lang.NoClassDefFoundError: Failed resolution of: Ljava/rmi/Remote;
at scala.reflect.internal.Definitions$DefinitionsClass.RemoteInterfaceClass$lzycompute(Definitions.scala:370)
at scala.reflect.internal.Definitions$DefinitionsClass.RemoteInterfaceClass(D efinitions.scala:370)
at scala.reflect.runtime.JavaUniverseForce$class.force(JavaUniverseForce.scal a:255)
at scala.reflect.runtime.JavaUniverse.force(JavaUniverse.scala:16)
at scala.reflect.runtime.JavaUniverse.init(JavaUniverse.scala:147)
at scala.reflect.runtime.JavaUniverse.<init>(JavaUniverse.scala:78)
at scala.reflect.runtime.package$.universe$lzycompute(package.scala:17)
at scala.reflect.runtime.package$.universe(package.scala:17)
This crash is for me as expected as it isn't:
It is expected as java.rmi is not part of the Android API and I should expect any code trying to load its classes to crash.
It is unexpected as I didn't know that Scala's reflect package used java.rmi
I have traced the code to were rmi is required, that is to JavaUniverse (a trait mixed in JavaUniverse class) force method:
...
definitions.RemoteInterfaceClass
...
Which leads to DefinitionsClass:
lazy val RemoteInterfaceClass = requiredClass[java.rmi.Remote]
Am I wrong to think that this is a no-go for Scala reflection in Android?
If I am, what could be a workaround to this problem?
To summarize your solution and a related solution, it is sufficient to add two files, and modify build.sbt to include:
dexAdditionalParams in Android += "--core-library"
Add java/rmi/Remote.java to your project with the content:
package java.rmi;
public interface Remote {}
Add java/rmi/RemoteException.java to your project with the content:
package java.rmi;
public interface RemoteException {}

Monodroid issue with jar binding zubhium sdk

Iam trying to bind a jar(zubhium sdk jar) file to my mono droid project. I have followed their guide on xamarins website and created a new binding project which I reference I my mono droid project.
I am having some issues with package names. I get the following error:
Error 3 package com.zubhium.interfaces does not exist
com.zubhium.interfaces.ZubhiumListener
C:\Users\jbp\Desktop\ny\CmsApp.Droid\obj\Debug\android\src\mono\com\zubhium\interfaces\ZubhiumListenerImplementor.java 8 25 CmsApp.Droid
from the genrated source:
package mono.com.zubhium.interfaces;
public class ZubhiumListenerImplementor
extends java.lang.Object
implements
mono.android.IGCUserPeer,
com.zubhium.interfaces.ZubhiumListener
And that is because when the project is wrapped it automaticly adds mono(.com.zubhium....) to the package name. I cant find how to remove this mono or if i can set a rule to add this part.
I tried to put <attr path="/api/package[#name='com.zubhium.interfaces']" name="managedName">mono.com.zubhium.interfaces</attr>
in the xmldata.xml file but that did not work.
Do you guys have any sugestions?
Regards
package com.zubhium.interfaces does not exist
When you bind a .jar library and reference the binding project from another project, you need to also add the .jar to your Application project and set its Build action to AndroidJavaLibrary.
Failure to do so means that the .jar won't be added to the javac $CLASSPATH, resulting in javac compilation errors when compiling the Android Callable Wrapper (as you saw), and that the .jar won't included into your final .apk. Both of these are Badâ„¢.
And that is because when the project is wrapped it automaticly adds mono(.com.zubhium....) to the package name.
That's for an "Implementor" type; you can ignore it. It's used as part of the implementation of events. If you look at the generated C# code, there should be:
[global::Android.Runtime.Register ("mono/com/zubhium/interfaces/ZubhiumListenerImplementor")]
internal sealed class ZubhiumListenerImplementor : Java.Lang.Object, IZubhiumListener {
// ...
}
The mono.com.zubhium.interfaces.ZubhiumListenerImplementor is the ACW for the internal ZubhiumListenerImplementor type.
You can't rename this type; it's an internal construct that isn't controlled via metadata.

Android Annotations framework doesn't seem to generate anything

I'm trying to use Android annotations framework because it seems quite powerful. I'm quite stuck to configuring my first project based on it.
I followed every step of the wiki but it doesn't generate any file after a build.
So when I ask for a generated class from the manifest:
<activity android:name=".MyActivity_"
android:label="#string/app_name">
I get an exception:
java.lang.ClassNotFoundException
My activity is exactly the same one as in the wiki:
#EActivity(R.layout.main)
public class MyActivity extends Activity {
#ViewById
EditText myInput;
#ViewById(R.id.myTextView)
TextView textView;
#Click
void myButton() {
String name = myInput.getText().toString();
textView.setText("Hello "+name);
}
}
Any ideas?
EDIT: Just found out a directory ".apt_generated" is made but it's empty after the build.
This seems to be an AndroidAnnotations bug, and should be reported on the dedicated bug tracker, here : http://code.google.com/p/androidannotations/issues/entry . You could also use the AndroidAnnotations mailing list, http://groups.google.com/group/androidannotations
First, I have a few questions :
Which IDE do you use : Eclipse, Netbeans, IntelliJ ? Which version ?
Do you use Maven, Ant, or only your IDE to build the project ?
Your problem may be due to a few things : annotation processing not triggered, a bug in AA, or the files generated in a folder not part of the classpath.
In Eclipse, you may get more information from the "Window > Show View > Error Log" view. If annotation processing is triggered, you should see some messages about AndroidAnnotations.
For other people who are running into this and the leading answer doesn't work, run a build and then search for the file androidannotations.log somewhere in the project. This log file is generated and may hint at what is wrong.
For me, it had a warning message that it could not locate AndroidManifest.xml. Though this seemed like just a warning, it was actually the cause of the error... Not finding my AndroidManifest.xml file resulted in it not generating some of the classes it should have.
Check if you have the xml file. If not, the solution is obvious. If you do have it, the typical reason AA cannot find the file is because it is in a non-standard location -- AA recursively checks the parent directories above where it generates files for this xml file and will fail if it's not there. In my case, my AndroidManifest.xml was located in [project root]/app/src/main which is not a direct ancestor folder so that was the problem.
You can specify where your xml file is in your project build.gradle:
android {
defaultConfig {
javaCompileOptions {
annotationProcessorOptions {
arguments = ["androidManifestFile": "specify_location_of_AndroidManifest.xml_here"]
}
}
}
}

Categories

Resources