Can a Xamarin Android bindings library behave like 'compileOnly' in gradle? - xamarin

I am trying to write a Xamarin Android binding library for a library that is loaded in the app during runtime. When using this library in a normal Android project, you would use "compileOnly".
compileOnly 'de.robv.android.xposed:api:82'
compileOnly 'de.robv.android.xposed:api:82:sources'
From my understanding, "compileOnly" makes the code from the library available for compilation but does not add it to the resulting apk. Meaning it needs to be provided in runtime for the app to work.
When reading the Xamarin binding Build Action docs, "compileOnly" sounds very similar to "InputJar".
Does not embed the .jar into the resulting Bindings Library .DLL. Your Bindings Library .DLL will have a dependency on this .jar at runtime. Use this option when you do not want to include the .jar in your Bindings Library (for example, for licensing reasons). If you use this option, you must ensure that the input .jar is available on the device that runs your app.
However, when compiling my application while using methods provided by the runtime library, I get errors from the generated java code that the packages do not exist.
javac.exe error : error: package de.robv.android.xposed does not exist
javac.exe error : de.robv.android.xposed.IXposedHookLoadPackage
javac.exe error : error: package de.robv.android.xposed.callbacks.XC_LoadPackage does not exist
javac.exe error : public void handleLoadPackage (de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam p0)
error : error: package de.robv.android.xposed.callbacks.XC_LoadPackage does not exist
error : private native void n_handleLoadPackage (de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam p0);
Meaning that the code was not made available during compilation. How can I make sure the code is made available during compilation but not embedded into application?

See my answer at https://stackoverflow.com/a/64973909/4374462
Either using AndroidExternalJavaLibrary or [assembly: Java.Interop.DoNotPackage("ref.jar")].

Related

Xamarin Binding Library - missing Java references

We have a couple of ELO touch tablets and status lights and a jar file ("eloperipherallib.jar") to change the color of the status light. Though we are not Java developers, we were able to create an .apk (with Android Studio) and change the color of the status light using this jar.
We now want to do the same in .NET, using Xamarin. We therefore created an "Android Bindings Library (Xamarin)" and added the jar (following the instructions here: https://learn.microsoft.com/en-us/xamarin/android/platform/binding-java-library/binding-a-jar). When building the bindings library we get the following warnings:
warning BG8605: The Java type 'android.elo.peripheral.ELOPeripheralEventListener' could not be found (are you missing a Java reference jar/aar or a Java binding library NuGet?)
warning BG8605: The Java type 'android.elo.peripheral.ELOPeripheralManager' could not be found (are you missing a Java reference jar/aar or a Java binding library NuGet?)
warning BG8606: Some types or members could not be bound because referenced Java types could not be found. See the 'java-resolution-report.log' file for details.
And at runtime we get a similar exception when "ELOPeripheralManager" is used.
Now, we do not have this problem in the .apk created with Android Studio, so I guess the jar file contains everything that is needed. We just can't figure out what the Xamarin project is missing, if that what's missing is in the jar file anywhere and/or how we can get it out of the jar file and put it in the Xamarin project so it'll build…
Can someone point us in the right direction?

Xamarin binding library combination of InputJar and ReferenceJar?

I am trying to use https://github.com/Redth/Xamarin.Android.Xposed in Xamarin but the final result is rejected by Xposed, saying: "cannot load module" .. "the xposed api classes are compiled into the module's apk". The xposed-api.jar file is currently a EmbeddedJar, which is what causes that error. The xposed-api.jar file is made available during run-time by Xposed already.
From the xamarin docs.
InputJar – Does not embed the .jar into the resulting Bindings Library .DLL. Your Bindings Library .DLL will have a dependency on this .jar at runtime.
InputJar seems like it will solve my issue with it being compiled into the resulting apk. However, it can't compile into an apk at all. It gives me errors in the generated java file such as.
JAVAC0000: error: package de.robv.android.xposed does not exist
de.robv.android.xposed.IXposedHookLoadPackage 0
Then for ReferenceJar..
ReferenceJar – Specifies a reference .jar: a reference .jar is a .jar that one of your bound .jar or .AAR files depends on. This reference .jar is used only to satisfy compile-time dependencies. When you use this build action, C# bindings are not created for the reference .jar and it is not embedded in the resulting Bindings Library .DLL.
Great, it will provide it during compile-time.. however, no bindings will be generated so I can't use it.
I also tried combining these by creating 2 identical libraries with one having InputJar and the other ReferenceJar, but that did not work at all.
How can I achieve what I am trying to do?
To sum it up, I need to add xposed-api.jar as a library just like how android.jar of the Android framework is added. You can use the classes and compile properly, without the classes being compiled into the apk.
OK, The trick is actually "AndroidExternalJavaLibrary".
Imagine you have a Jar binding project XPosedAPI, and an Android project XposedSample.
The structure would be:
XPosedAPI
|-- Jar
|-- api-82.jar (InputJar)
XposedSample
|-- Jar
|-- api-82.jar (AndroidExternalJavaLibrary)
You see, the trick is you have to put the same jar file for each project.
For the Jar binding project, it has to be "InputJar" - that's used to generate the C# binding dll.
For the project that using the Jar bindng dll, the jar has to be "AndroidExternalJavaLibrary". This ensures the javac compile process.
There was an easier way, the Java.Interop.DoNotPackageAttribute.
You just put the below line on one of these projects (just put it on XPosedAPI project would be enough), and it works:
[assembly: Java.Interop.DoNotPackage("api-82.jar")]
However, this attribute is marked as "deprecated", although it's easier.
I figured out this, because I'm trying to do the same thing - write a xposed module in C#.
The Xamarin.Android.Xposed project looks nice, but in fact it won't work, and there are much more problems to be fixed besides the jar binding issue.
I think I'm getting closer, and I may publish it in a few days if I can fix all the bugs remained.
If you're interested, watch my project: https://github.com/UlyssesWu/XamarinPosed

Xamarin binding for AWS SDK

Summary
When binding a JAR/AAR built on top of aws-java-sdk, do you have to EmbeddedReferenceJar all the libraries below your JAR, down to and including the aws-java-sdk, when down at that low level the AWS SDK for .NET has the functionality.
Are there any Xamarin packages (Xamarin.Forms or Xamarin.Android) that give an out-of-the box authentication UI with Sign-In/Sign-Up buttons for AWS user pools, Google+, Facebook authentication providers ?
Context
I would like to use SignInUI from aws-android-sdk-auth-ui in a Xamarin.Android app, which gives you an out-of-the-box UI for authentication to AWS. I've got the AWS UserPool and AWS IdentityPool setup already.
Unfortunately, the AWS SDK for .NET does not expose the equivalent aws-android-sdk-auth-ui a java package built on top of aws-android-sdk-auth-core (also unavailable in .NET), which is built on top of aws-android-sdk-core and finally aws-java-sdk.
I thought about binding a java library. I would create a Xamarin binding project for aws-android-sdk-auth-ui.aar downloaded from maven Central. I followed the Binding an .AAR tutorial. It builds, but the generated aws-android-sdk-auth-ui.dll file is missing some classes. I opened the dll with Ildasm.exe and in the Com.Amazonaws.Mobile.Auth.UI namespace I only found AuthUIConfiguration and BuildConfig, clearly missing the SignInUI class.
Is it expected that when you build a binding project for an .aar file that references other .jar, the build succeeds but silently does not produce wrapper classes for java classes who reference missing jars? I would have guessed building would succeed AND would include a wrapper for all classes, but a failure would occur at runtime in codepaths that require the missing jar.
Alright, so I added aws-android-sdk-auth-core.jar, aws-android-sdk-core.jar to the bindings project, as EmbeddedReferencedJar. That did not help, the generated dll is also missing the same classes. The build output pasted below does point in the direction of misssing reference jars. See below.
How far do I need to go though, do I also need to embed all the way down to the 80MB aws-java-sdk.jar?
I have the following build output:
1>JARTOXML : warning J2X9001: Couldn't load class com/amazonaws/mobile/auth/ui/SignInActivity : java.lang.NoClassDefFoundError: android/support/v7/app/AppCompatActivity
1>JARTOXML : warning J2X9001: Couldn't load class com/amazonaws/mobile/auth/ui/SignInUI$1 : java.lang.NoClassDefFoundError: com/amazonaws/mobile/auth/core/DefaultSignInResultHandler
1>JARTOXML : warning J2X9001: Couldn't load class com/amazonaws/mobile/auth/ui/SignInActivity$SignInProviderResultHandlerImpl : java.lang.NoClassDefFoundError: com/amazonaws/mobile/auth/core/signin/SignInProviderResultHandler
android/support/v7/app/AppCompatActivity indicates that com.android.support:appcompat isn't found. How are those supposed to bind? In Xamarin.Android these classes are in
Xamarin.Android.Support.v7.AppCompat Nuget package. But the jar does not know it's running in Xamarin.Android. Does that mean I also need to EmbedReferenceJar all the native Android stuff as well? That's a deep rabbit hole...
com/amazonaws/mobile/auth/core/DefaultSignInResultHandler: that one should not error, I did embed aws-android-sdk-auth-core.jar with EmbbededRefenceJar
Update:
Someone referred me to Xamarin.GradleBindings. I haven't tested this yet, but thought I'd share in hopes this can be useful to other readers.

Xamarin iOS binding, symbol not found in library

I needed a sketch/painting control for my Xamarin.iOS project, and while I couldn't seem to find one compatible with C# I did find a good component available written in Objective C. https://github.com/acerbetti/ACEDrawingView
I've done Xamarin bindings before, so I had hoped that the process would be fairly simple, but unfortunately I've hit a few roadblocks along the way.
I started off creating my static library and used an ant build script to make a FAT binary to cover devices and the simulator:
snippet of my ant script
AceDrawingViewSDK.a: libAceDrawingView-i386.a libAceDrawingView-armv7.a libAceDrawingView-armv7s.a libAceDrawingView-arm64.a xcrun -sdk iphoneos lipo -create -output $# $^
Next, I ran
sharpie bind --sdk=iphoneos10.1 *.h
on the header files to get my ApiDefinitions and Structs and Enum files.
I checked and removed a the Verify attributes. (They all looked fine.) But this is where some of my other issues started.
The type ACEDrawingLabelViewTransform' already contains a definition forTransform' (CS0102) (AceDrawingViewBinding).
For the sake of just trying to move on and get something working, I just commented out this reference.
I then got multiple problems similar to this:
The type or namespace name `IACEDrawingTool' could not be found. Are you missing an assembly reference? (CS0246) (AceDrawingViewBinding)
I figured it related to this:
// #interface ACEDrawingPenTool : UIBezierPath
[BaseType(typeof(UIBezierPath))]
interface ACEDrawingPenTool : IACEDrawingTool
and this:
// #protocol ACEDrawingTool
[Protocol, Model]
[BaseType(typeof(NSObject))]
interface ACEDrawingTool
I tried to fix this my making the interface name consistent (I tried both IACEDrawingTool and ACEDrawingTool.) Doing this got past this error and allowed me to compile
One of my enums came out as
[Native]
public enum ACEDrawingMode : nuint
{
Scale,
OriginalSize
}
I couldn't find how to handle [Native] in this case (so once again, for testing sake I removed it.) I tried using removing the nuint from the enum and using uint. Either approach seemed to fix the error.
So with those errors fixed I was able to generate the .dll from my binding project and add it to my main project.
Now, I am getting 2 more issues.
If I build and deploy to the simulator I am able to run my app up until the point that I try to create a new instance of the ACEDrawingView from the binding. I get:
Could not create an native instance of the type 'ACEDrawingView': the native class hasn't been loaded.
It is possible to ignore this condition by setting ObjCRuntime.Class.ThrowOnInitFailure to false.
If I try to build and deploy to my phone I get different errors in the build phase which prevents it from launching on the device at all:
MTOUCH: error MT5211: Native linking failed, undefined Objective-C class: ACEDrawingArrowTool. The symbol 'OBJC_CLASS$ACEDrawingArrowTool' could not be found in any of the libraries or frameworks linked with your application.
MTOUCH: error MT5211: Native linking failed, undefined Objective-C class: ACEDrawingDraggableTextTool. The symbol '_OBJC_CLASS$ACEDrawingDraggableTextTool' could not be found in any of the libraries or frameworks linked with your application.
MTOUCH: error MT5211: Native linking failed, undefined Objective-C class: ACEDrawingEllipseTool. The symbol '_OBJC_CLASS$_ACEDrawingEllipseTool' could not be found in any of the libraries or frameworks linked with your application.
...and so on.
I've tried going back, rereading and redoing steps and have tried to reuse some of the scripts and settings from my previous successful bindings with no luck.
Does anyone have suggestions for what might fix these issues?
The type or namespace name `IACEDrawingTool' could not be found.
Add a new interface, like this interface IACEDrawingTool{ }
public enum ACEDrawingMode : nuint
Change the nuint to ulong

Adding Xamarin.Google.iOS.SignIn results in a native linking error (MT5209)

I wanted to replace the Google.Plus library from an existing app with the Xamarin.Google.iOS.SignIn library using the Google Sign-In for iOS component (https://components.xamarin.com/view/googleiossignin).
However... when adding it and replacing the old code with the new (slightly different code) it results in a compile error:
/projectdir/MTOUCH: Error MT5209: Native linking error: file not found: /projectdir/obj/iPhoneSimulator/Debug/mtouch-cache/libOpenInChrome.a (MT5209) (Immo.Vlan.Touch)
/projectdir/MTOUCH: Error MT5202: Native linking failed. Please review the build log. (MT5202) (Immo.Vlan.Touch)
Here is the relevant part from the build log:
MTOUCH: warning MT1302: Could not extract the native library 'libOpenInChrome.a' from '/projectdir/obj/iPhoneSimulator/Debug/mtouch-cache/libOpenInChrome.a'. Please ensure the native library was properly embedded in the managed assembly (if the assembly was built using a binding project, the native library must be included in the project, and its Build Action must be 'ObjcBindingNativeLibrary').
MTOUCH: warning MT1302: Could not extract the native library 'libGTMOAuth2_external.a' from '/projectdir/obj/iPhoneSimulator/Debug/mtouch-cache/libGTMOAuth2_external.a'. Please ensure the native library was properly embedded in the managed assembly (if the assembly was built using a binding project, the native library must be included in the project, and its Build Action must be 'ObjcBindingNativeLibrary').
MTOUCH: warning MT1302: Could not extract the native library 'libGTMOAuth2_internal.a' from '/projectdir/obj/iPhoneSimulator/Debug/mtouch-cache/libGTMOAuth2_internal.a'. Please ensure the native library was properly embedded in the managed assembly (if the assembly was built using a binding project, the native library must be included in the project, and its Build Action must be 'ObjcBindingNativeLibrary').
MTOUCH: warning MT1302: Could not extract the native library 'libSignIn.a' from '/projectdir/obj/iPhoneSimulator/Debug/mtouch-cache/libSignIn.a'. Please ensure the native library was properly embedded in the managed assembly (if the assembly was built using a binding project, the native library must be included in the project, and its Build Action must be 'ObjcBindingNativeLibrary').
MTOUCH: warning MT1302: Could not extract the native library 'libGIPNSURL+FIFE.a' from '/projectdir/obj/iPhoneSimulator/Debug/mtouch-cache/libGIPNSURL+FIFE.a'. Please ensure the native library was properly embedded in the managed assembly (if the assembly was built using a binding project, the native library must be included in the project, and its Build Action must be 'ObjcBindingNativeLibrary').
MTOUCH: warning MT1302: Could not extract the native library 'libGTM_AddressBook.a' from '/projectdir/obj/iPhoneSimulator/Debug/mtouch-cache/libGTM_AddressBook.a'. Please ensure the native library was properly embedded in the managed assembly (if the assembly was built using a binding project, the native library must be included in the project, and its Build Action must be 'ObjcBindingNativeLibrary').
MTOUCH: warning MT1302: Could not extract the native library 'libGTM_core.a' from '/projectdir/obj/iPhoneSimulator/Debug/mtouch-cache/libGTM_core.a'. Please ensure the native library was properly embedded in the managed assembly (if the assembly was built using a binding project, the native library must be included in the project, and its Build Action must be 'ObjcBindingNativeLibrary').
MTOUCH: warning MT1302: Could not extract the native library 'libGTM_DebugUtils.a' from '/projectdir/obj/iPhoneSimulator/Debug/mtouch-cache/libGTM_DebugUtils.a'. Please ensure the native library was properly embedded in the managed assembly (if the assembly was built using a binding project, the native library must be included in the project, and its Build Action must be 'ObjcBindingNativeLibrary').
MTOUCH: warning MT1302: Could not extract the native library 'libGTM_GTMURLBuilder.a' from '/projectdir/obj/iPhoneSimulator/Debug/mtouch-cache/libGTM_GTMURLBuilder.a'. Please ensure the native library was properly embedded in the managed assembly (if the assembly was built using a binding project, the native library must be included in the project, and its Build Action must be 'ObjcBindingNativeLibrary').
MTOUCH: warning MT1302: Could not extract the native library 'libGTM_iPhone.a' from '/projectdir/obj/iPhoneSimulator/Debug/mtouch-cache/libGTM_iPhone.a'. Please ensure the native library was properly embedded in the managed assembly (if the assembly was built using a binding project, the native library must be included in the project, and its Build Action must be 'ObjcBindingNativeLibrary').
MTOUCH: warning MT1302: Could not extract the native library 'libGTM_KVO.a' from '/projectdir/obj/iPhoneSimulator/Debug/mtouch-cache/libGTM_KVO.a'. Please ensure the native library was properly embedded in the managed assembly (if the assembly was built using a binding project, the native library must be included in the project, and its Build Action must be 'ObjcBindingNativeLibrary').
MTOUCH: warning MT1302: Could not extract the native library 'libGTM_NSData+zlib.a' from '/projectdir/obj/iPhoneSimulator/Debug/mtouch-cache/libGTM_NSData+zlib.a'. Please ensure the native library was properly embedded in the managed assembly (if the assembly was built using a binding project, the native library must be included in the project, and its Build Action must be 'ObjcBindingNativeLibrary').
MTOUCH: warning MT1302: Could not extract the native library 'libGTM_NSDictionary+URLArguments.a' from '/projectdir/obj/iPhoneSimulator/Debug/mtouch-cache/libGTM_NSDictionary+URLArguments.a'. Please ensure the native library was properly embedded in the managed assembly (if the assembly was built using a binding project, the native library must be included in the project, and its Build Action must be 'ObjcBindingNativeLibrary').
Any suggestions on how to tackle this?
Niels
These dlls no longer have the native libraries embedded. The addition of the native libraries is now handled in an additional build task that is added to the app project when the NuGet is added to the app project.
Be sure to add the NuGet or Component to the app project as well.
Some are experiencing the problem when the Microsoft.Bcl.Build NuGet is added to the project as well. We intend to release a patch for this issue soon. Look for version 0.2.1 of the Xamarin.Build.Download NuGet.
To work around the issue you will need to edit the targets file packages/Xamarin.Build.Download.0.2.0/build/Xamarin.Build.Download.targets
Add a AfterTargets="AssignProjectConfiguration" attribute to the _XamarinBuildDownload target.
<Target
Name="_XamarinBuildDownload"
DependsOnTargets="_XamarinBuildDownloadCore;_XamarinBuildAddDownloadedItems"
AfterTargets="AssignProjectConfiguration"
Condition="'#(XamarinBuildDownload)'!=''"
/>
I've solved the same problem with Google Analytics on Xamarin iOS installing Xamarin.Build.Download 0.2.2-beta1
I hope this will become as soon as possible the stable version.
After additional research I think the problem is that the native libraries referenced are not included in the DLL. If I open the DLL for the current version of Google.Core (v1.3.2.1) there's no Resources entry. If I open v1.1.0beta-3 I can see a resources entry that contains all the libraries referenced.
So solution is to have them rebuild it properly.
I'm not 100% confident that this is the answer. For some reason my project will compile fine on simulator but not on device. But the fact that it's referencing the missing names I think is very suggestive.

Resources