Remove "virtual" keyword in binding Xamarin library by using metadata.xml - android

I'm binding a Xamarin Library from Java and it generates 1 wrong function.
The keyword should be override but currently it is virtual.
// Metadata.xml XPath method reference: path="/api/package[#name='com.mapbox.mapboxsdk.tileprovider']/class[#name='MapTileLayerBase.CacheTask']/method[#name='doInBackground' and count(parameter)=1 and parameter[1][#type='java.lang.Object...']]"
[Register ("doInBackground", "([Ljava/lang/Object;)Ljava/lang/Void;", "GetDoInBackground_arrayLjava_lang_Object_Handler")]
protected virtual unsafe global::Java.Lang.Object DoInBackground
(params global:: Java.Lang.Object[] p0)
I need to change virtual to override but I don't know how to do that.
I found some comments on the internet say that I should try this one:
<attr path="/api/package[#name='com.mapbox.mapboxsdk.tileprovider']/class[#name='MapTileLayerBase.CacheTask']/method[#name='doInBackground']" name="virtual">false</attr>
I tried but it didn't work.
Do you know how to change it?

Try:
<attr path="/api/package[#name='com.mapbox.mapboxsdk.tileprovider']/class[#name='MapTileLayerBase.CacheTask']/method[#name='doInBackground']" name="managedOverride">override</attr>
or more hacky way if previous step doesn't work:
<attr path="/api/package[#name='com.mapbox.mapboxsdk.tileprovider']/class[#name='MapTileLayerBase.CacheTask']/method[#name='doInBackground']" name="final">true</attr>
<attr path="/api/package[#name='com.mapbox.mapboxsdk.tileprovider']/class[#name='MapTileLayerBase.CacheTask']/method[#name='doInBackground']" name="visibility">protected override</attr>

The solution is to set final to true in the Metadata.xml mapping:
<attr
path="/api/package[#name='com.mapbox.mapboxsdk.tileprovider']/class[#name='MapTileLayerBase.CacheTask']/method[#name='doInBackground']"
name="final">true</attr>
This effectively removes the virtual keyword from the method signature, and doesn't add the final keyword either. Strange behavior, but it works.

Are you sure you need this method exposed in your API? You could use approach from this thread http://forums.xamarin.com/discussion/1871/binding-java-library-with-parameter-type-void and just remove this method. Usually methods like this are not explicitly used from the outside.

In
in obj/Debug/generated/src find MCW for that class (com.mapbox.mapboxsdk.tileprovider.cs)
copy that file to Additions/ folder and include it into project.
change BuildAction to Compile if neccessary
change virtual to override
that class from process

Related

Xamarin binding .aar with Metadata.xml doesn't seem to work

I'm trying to bind an android SDK for voice chat (zoom sdk).
They have two .aar files (zoomcoomonlib.aar and zoomsdk.aar)
I know I have to create separate binding project for each .aar and then reference them.
While binding zoomsdk.aar I'm getting the below error
The type `Com.Zipow.Videobox.Onedrive.ErrorEventArgs' already contains a definition for `P0' (CS0102) (B14)
In the .aar file I navigated to the package com.zipow.videobox.onedrive; to the interface IODFoldLoaderListener
And below are the contents of it
So it seems parameter String var1 of method onError is causing the issue.
And xamarin studio generated obj/debug/api.xml confirms it (below screenshot) that onError will have first parameter named p0:
So in this scenario I change the metadata.xml to give this parameter a meaningful name.
Like below screenshot:
But even after doing that I am getting same error. That error didn't resolve.
Moreover now if I see the obj/debug/api/.xml file I see the contents for the class IODFoldLoaderListener remains the same.
So changing the metadata.xml has no effect it seems.
Your definition needs to be changed quite a bit. Here is an example that solves the same problem:
<attr path="/api/package[#name='com.emarsys.mobileengage.inbox']/interface[#name='ResetBadgeCountResultListener']/method[#name='onError' and count(parameter)=1 and parameter[1][#type='java.lang.Exception']]" name="argsType">ResetBadgeCountResultListenerOnErrorArgs</attr>
Please note the /interface and argsType items here as your initial definition is incorrect. You would then change the parameters to strings instead of java.lang.Exception from my example.

Xamarin + Android + Binding YouTube video player compile errors

I'm looking to bind the YouTubeAndroidPlayerApi.jar into my Xamarin Android project. I've added the YouTubeAndroidPlayerApi.jar under my Jars folder, but my project won't compile.
Error: "Do not override object.Finalize. Instead use a destructor."
So I've tried to change the way it compiles by using an:
<attr path="/api/package[#name='Com.Google.Android.Youtube.Player']/class[#name='YouTubeThumbnailView']/method[#name='Finalize']" name="managedName">~YouTubeThumbnailView</attr>
In the Metadata.xml file under Transforms folder... It doesn't seem to change it to a finalizer though... I'm continuing to play around with the syntax here in hopes that I stumble across something that works.
Is this the right approach? Is there something else I could be doing that is a better solution? I'd really like some feedback.
Thanks!
You should just be able to remove this fairly easily. However your issue in your <attr> is the fact that you have the incorrect package name/class name as it should follow Java convention(<lowercase package>.<propercase class>). Simply ensure the case like the example below:
EX:
<remove-node path="/api/package[#name='com.google.android.youtube.player']/class[#name='YouTubeThumbnailView']/method[#name='finalize' and count(parameter)=0]" />
If you add the remove-node, you will remove the finalizer and the code under finalize method will never be called.
If you want to re-use the finalize implementation in the destructor, you can add the following to your Metadata.xml file:
<!--
YouTubeThumbnailView class implemented a Java Finalizer. I have to implement a C# Destructor and call the finalize method.
The C# Destructor is in the partial class under the Addition folder.
-->
<!-- I change the name of the finalizer method to avoid the conflict with java finalizer -->
<attr path="/api/package[#name='com.google.android.youtube.player']/class[#name='YouTubeThumbnailView']/method[#name='finalize' and count(parameter)=0]" name="managedName">InternalFinalize</attr>
<!-- I replace the protected override modifier with the internal modifier -->
<attr path="/api/package[#name='com.google.android.youtube.player']/class[#name='YouTubeThumbnailView']/method[#name='finalize' and count(parameter)=0]" name="visibility">internal</attr>
N.B. the visibility modifier is needed to remove the override modifier.
Then you should add the following class under the folder Additions:
namespace Com.Google.Android.Youtube.Player
{
public partial class YouTubeThumbnailView
{
~YouTubeThumbnailView()
{
this.InternalFinalize();
}
}
}

How to add the global keyword to Metadata.xml for Xamarin jar binding?

I am attempting to bind a jar file to a Xamarin bindings project. For a particular field, the global keyword needs to be used in order to avoid ambiguity between 2 namespaces (com.paypal.android & android.widget).
Error CS0234: The type or namespace name 'Widget' does not exist in the namespace 'Com.Paypal.Android'. Are you missing an assembly reference?
Xamarin is smart enough to include the global keywords within the field's getter and setter; unfortunately, Xamarin isn't smart enough to to include it in the field's type:
public IList<Android.Widget.TextView> C {
When I alter the code itself, it gets overwritten when I rebuild the project. I believe I need to add the global keyword inside the Metadata.xml (although, I'm not quite sure how).
I've attempted to add the following in order to change the return type:
<attr path="/api/package[#name='com.paypal.android.sdk']/class[#name='cD']/field[#name='c']" name="managedReturn"> NOT SURE WHAT GOES HERE </attr>

Binding for AndTinder library

I am trying to create a binding library for android AndTinder library. But I am getting the following error
Error CS0507: 'Com.Andtinder.View.SimpleCardStackAdapter.GetCardView(int, Com.Andtinder.Model.CardModel, Android.Views.View, Android.Views.ViewGroup)': cannot change access modifiers when overriding 'protected' inherited member 'Com.Andtinder.View.CardStackAdapter.GetCardView(int, Com.Andtinder.Model.CardModel, Android.Views.View, Android.Views.ViewGroup)' (CS0507)
To fix the above error , I added the following line to Metadata.xml
<attr path="/api/package[#name='Com.AndTinder.View']/class[#name='CardStackAdapter']/method[#name='GetCardView']" name="visibility">protected</attr>
But this has not fixed. I would appreciate if someone could give me hints on how to fix this error
The base class is protected. So you want to fix this by changing the C# version to protected as well.
Based on the package: package com.andtinder.view;
And the MethodName getCardView: https://github.com/kikoso/Swipeable-Cards/blob/master/AndTinder/src/main/java/com/andtinder/view/CardStackAdapter.java#L69
<attr path="/api/package[#name='com.andtinder.view']/class[#name='CardStackAdapter']/method[#name='getCardView']" name="visibility">protected</attr>
Overall it seems like you just need to ensure your case sensitivity and this should work!

Porting Card.IO to C# Xamarin Studio

I'm having trouble trying to port Card.IO to Xamarin Android. Since I am using C# instead of Java, I don't know what to do with the .so files and the .jar files.
I tried to follow some of the steps posted here : card.io Mono for Android (Xamarin Studio) but I am getting the following two build errors that I don't know how to solve.
Here's What I've done so far
Create a new Android Java Bindings Library Project
Add the .jar and .so files from Card.IO project, with the existing folder structure. So there is four subfolders under the /libs folder, and then a single jar under /libs.
Add the following to Transforms/EnumMethods.xml to resolve a compiler error:
<mapping jni-class="io/card/payment/CardIOActivity">
<method jni-name="onActivityResult" parameter="p1" clr-enum-type="Android.App.Result" />
</mapping>
Add a reference to the above Library in my main application.
And then I am faced with these build errors :
The type or namespace name 'IN' does not exist in the namespace
'IO.Card.Payment' (are you missing an assembly reference?)
'A': member names cannot be the same as their enclosing type
Update
The first error is on this line :
public sealed partial class CardIOActivity : global::Android.App.Activity, global::IO.Card.Payment.IN {
The second error seems to be on this line :
public static global::System.Collections.IList A {
Any help is useful, thanks!
i've spent like 10 hours yday to get card io working with my xamarin application... after long long battles i managed to see what i wanted... i did not see the above error about 2 interfaces, i've had an issue with 'a' field in 'A' class and there as an error telling that "IN" interface does not exist (this is an interface, so no problem with double base class should be shown there, that's odd).
not sure if all my steps are necessary to make it working but (surprise, surprise) i was to tired to clean that up and check which chagnes were really essencial. lots of problems are cause by the code obfuscation of the card io jar.
nevermind, back to the topic:
create new binding project, add the jar as embeded jar, add the .so files as embided native libraries (use the existing structure)
open EnumMethods.xml and add there a mapping:
<mapping jni-class="io/card/payment/CardIOActivity">
<method jni-name="onActivityResult" parameter="p1" clr-enum-type="Android.App.Result" />
</mapping>
(this changes int to enum type used by .net xamarin in the onActivityResult method (which is overloaded by one of the classes in card.io.jar)
3. open Metadata.xml and add below nodes (some might be unnecessary):
<attr path="/api/package[#name='io.card.payment']/class[#name='A']/field[#name='a']" name="managedName">AProp</attr>
<attr path="/api/package[#name='io.card.payment']/class[#name='M']" name="visibility">public</attr>
<attr path="/api/package[#name='io.card.payment']/class[#name='M']" name="name">Mcl</attr>
<attr path="/api/package[#name='io.card.payment']/interface[#name='N']" name="visibility">public</attr>
<attr path="/api/package[#name='io.card.payment']/interface[#name='N']" name="name">Nifc</attr>
<attr path="/api/package[#name='io.card.payment']/class[#name='L']" name="visibility">public</attr>
<attr path="/api/package[#name='io.card.payment']/class[#name='L']/field[#name='a']" name="managedName">aProp</attr>
<attr path="/api/package[#name='io.card.payment']/class[#name='L']/method[#name='a']" name="managedName">aMethod</attr>
<attr path="/api/package[#name='io.card.payment']/class[#name='L']" name="name">Lcl</attr>
above nodes change some visibilities to public (most needed) and change some names of classes or iterfaces (not sure if needed, but it was useful to me at some point)
add reference to the binding project in the main one.
open AndroidManifest.xml in the main project and add there:
<activity android:name="io.card.payment.CardIOActivity" android:configChanges="keyboardHidden|orientation" />
<activity android:name="io.card.payment.DataEntryActivity" android:screenOrientation="portrait"/>
nodes should be added under application node (which is a child of main node - manifest)
now you should be able to invoke the CardIOActivity and use what you want (invoking and using is available and seems to be described well in the examples provided by the creators)
one more hint, nothing big, but when i finally succeeded in getting the library working i missed it... to get result as CreditResult object in OnActivityResult method use java cast:
var scanResult = data.GetParcelableExtra(CardIOActivity.ExtraScanResult).JavaCast();
ordinary c# cast won't work.
if you have any problems let me know, perhaps i missed something (especially that i'm not yet xamarin expert).
good luck!
ps: answer placed #xamarin forum too
EDIT:
Completet solution with binding, checked and working uploded to github:
https://github.com/wiadran/card.io.xamarin.binding.git

Categories

Resources