How to build Xamarin Binding Library for estimote-sdk.aar - c#

I would like to use the Estimote Beacon SDK in an Xamarin for Android Application. Since Xamarin's Estimote SDK [1] is very much outdated, I was thinking of including the official Estimote SDK [2] into the project which provides an estimote-sdk.aar file which I was trying to include and use. The Xamarin documentation suggests creating a Binding Library for that purpose [3].
So I was following those steps, made a Binding Library, added the .aar and set it's Build Action to LibraryProjectZip but I get several errors:
While I can solve the errors like
member names cannot be the same as their enclosing type
by renaming the members via Metadata.xml like so:
<attr path="/api/package[#name='com.estimote.sdk.cloud.model.google']/class[#name='Beacons']/field[#name='beacons']" name="name">BeaconsList</attr>
I don't know how to solve erros like
"Buffer" does not implement interface member "IBufferedSink.Buffer()"
How can this be solved?
What is the best approach to include the Estimote SDK into a Xamarin for Android application?
[1] Estimote SDK for Android by Xamarin Inc. https://components.xamarin.com/view/estimotesdkandroid
[2] Official Estimote SDK for Android https://github.com/Estimote/Android-SDK
[3] Binding an .AAR in Xamarin Developer portal https://developer.xamarin.com/guides/android/advanced_topics/binding-a-java-library/binding-an-aar/

Your best bet to support the Estimote SDK is to do the binding yourself. We do have a components team who tries to stay on top of every release, but as there are so many new releases and new libraries coming out everyday. It can serve quite a challenge.
"Buffer" does not implement interface member "IBufferedSink.Buffer()"
This typically means that the class is not implementing the respective interface member. You have a couple ways to go around this error.
Create a Partial class of your offending class and implement the
interface member.
Look at the api.xml to ensure the class is implementing all
members of the interface. Have a check at all the return types / arguments / etc to ensure they match the proper types. You would then have to change the managedReturn, managedType, or propertyName via Metadata.xml.
As a general reference, I have a small binding guide that you can find here:
https://gist.github.com/JonDouglas/dda6d8ace7d071b0e8cb
Specifically you might be most interested in common metadata fixes: https://gist.github.com/JonDouglas/dda6d8ace7d071b0e8cb#common-metadata-fixes

Related

Sharing generic code between UWP projects

I'm developing an UWP app via C#, that uses IBasicVideoEffect with IDirect3DSurface. As mentioned in documentation, I have created Windows Runtime Component (Universal Windows) project.
But settings of effects are stored in some implementation of IPropertySet (smth like Dictionary<object, object>).
To use high - level operations on this storage, I've introduced IPropertySetExtensions into runtime component, that has for example Get<T>, GetOrDefault<T> methods, which return instance of T (not object) from storage.
Than I realized, that same operations will be needed in main project, but when I changed
internal static class IPropertySetExtensions into public one, I got an error like "winmd components cant contain generic methods".
That's why I duplicated extension class into main project.
How can I avoid this duplicating? Maybe move shared code into NuGet .dll or smth?
Unfortunately, when writing a WinRT Component there are quite a few limitations due to the fact that WinRT Components are usable in C++, C#, VB and JS (yes also JS). The following document covers part of what to watch out for: https://learn.microsoft.com/en-us/windows/uwp/winrt-components/creating-windows-runtime-components-in-csharp-and-visual-basic
In your case, I think creating a "Class Library (Universal Windows)" will solve that problem since you can write C# code as you like without having to watch out for WinRT Component limitations.

How can I list all external classes that implement an interface in Visual Studio

Imagine the following:
You have an external library that you want to use and it isn't documented that well. You know that there is a class "Parent" with a method Add. Add takes an Object of the interface "IChild".
How can I list all classes, especially in that library, that implement this interface?
(By that I mean visually in the editor not in code)
I found some threads about this but none of them really answered my question. All of them were about listing your own implementations of an interface in your namespace (and that works fine for me).
Just to make the problem clearer:
Let me take the ConfigurationBuilder from .Net core. The first thing I found about it in the internet is that I can call new ConfigurationBuilder().Add(IConfigurationSource). Then I wondered how I can get an IConfigurationSource. My next step would be to google for the documentation or some examples on this platform. But I imagine that that's not the completely right way of doing things. I think you should be able to go to IConfigurationSource, and look through classes from the ConfigurationBuilder that implement this interface so that you can find it yourself. Always googling for examples or docs can't be the only way to go.
(I use Visual Studio 2019 Community)

Can't add System.Net.Sockets to a Xamarin PCL project can this be done using "Bait and switch" advanced PCL approach?

I can't add System.Net.Sockets to a Xamarin PCL project can this be done using "Bait and switch" AKA advanced PCL approach?
System.Net.Sockets is available for Xamarin.iOS and Xamarin.Android projects
Explanation of Bait and switch
Yes, this is possible. The approach we use is to make separate iOS and Android Class libraries that will hold non-UI type code that is not accessible from PCL, and have that code implement interfaces that are accessible from the shared PCL layer.
For example:
Create ISocketHandler in Shared PCL project, and it has OpenConnection method.
Create an iOS.Framework class library, and in it create an iOSSocketHandler class that implements ISocketHandler and has platform specific code on using sockets in Xamarin iOS. Do the same for Android.
Then you need dependency injection so that whenever your shared code asks for ISocketHandler, they get the appropriate implementation. We use Unity, and in our Main.cs we will register like so:
IocContainer.GetContainer().RegisterType<ISocketHandler, iOSSocketHandler>();
Then in your shared code you can request the implementation like so:
IocContainer.GetContainer().Resolve<ISocketHandler>();
There are other strategies that can accomplish what you want, but this is what we use in most scenarios.
Also, before trying to do this yourself, you may want to check this out https://github.com/rdavisau/sockets-for-pcl

Portable Class Library Profile 78 missing attribute related methods/properties

In my PCL core project (WP8, Android, iOS, Xamarin, MvvmCross) I use custom attributes. The Type.GetCustomAttributes() extension method lets me examine the attributes used.
Using PCL Profile104 this works well. But because I want to use async/await, I'll need to use PCL Profile78 (and .NET 4.5)
Problem: Seems the GetCustomAttributes() and the Attributes property are not available in Profile78. Why??
Note:
I am looking into the workaround by creating a PCL Profile 104 class library and wrapping the GetCustomAttributes() and then referencing this library from my PCL Profile78 library. However it seems extensionmethods are not supported...
Example Code:
public Pcl78Class()
{
Type t = this.GetType();
var attributes = t.Attributes;
var customAttributes = t.GetCustomAttributes(true);
// another weird thing: Why is VS CodeCompletion telling me it knows CustomAttributeExtensions class and methods?
//System.Reflection.CustomAttributeExtensions.GetCustomAttributes(t);
}
Problem: Seems the GetCustomAttributes() and the Attributes property are not available in Profile78. Why??
Profile78 includes support for Windows Store 8 (as noted on my blog), and Windows Store has a more efficient implementation of Type-based reflection. Essentially, you just have to call Type.GetTypeInfo to get a TypeInfo, and from there it should be pretty straightforward.

Binding a native library in MonoTouch: works, but why strange results when subclassing? Missing NullAllowed attribute?

MonoTouch 5.2.13
I'm using a native ObjectiveC library via MonoTouch bindings. The library exposes a view controller. All is working fine, until I subclass the view controller. Then, I get NULL reference exceptions or part of the UI is not shown.
I have read about the problems with the btouch tool and the "-e" option. But from what I can see, the option is not present:
Tool /Developer/MonoTouch/usr/bin/btouch execution started with
arguments: /d:DEBUG ApiDefinition.cs /s:StructsAndEnums.cs
/tmpdir:obj/Debug/ios/ /sourceonly:obj/Debug/ios//sources.list
The subclass does (in this example) not add any functionality, but using it is enough to break the binding:
// Works.
var contr = new NativeController();
// Fails with various errors. Throws a NULL reference exception about some UIPopoverController being NULL, for instance.
public class SubclassedController : NativeController
{
public SubclassedController() : base()
{
}
}
var contr = new SubclassedController();
I figured out that adding the [NullAllowed] to a property solved the NULL reference exception.
The native controller exposes a property (nonatomic, strong) UIPopoverController *popoverController. This was bound as UIPopoverController PopoveController {get; set;} - adding the NullAllowed here solved the issue.
But now I'm facing issues with images not showing up and there is no obvious exception.
I assume these problems also derive from the fact that something is NULL when using the subclassed version but the native code seems to react on the NULL and handles it gracefully.
This leads to three questions:
Why is the behavior different when using subclassing? What is MonoTouch doing to make this happen? Why do I get a NULL ref in the case I use a derived class? I'm not touching the UIPopoverController an either case.
How can I find out what is wrong and how to fix it if there is no error?
What else has to be taken care of, besides the NullAllowed?
Why is the behavior different when using subclassing?
There can be several reasons, including the instance initializing itself differently based on it's class name. It's not hard to do in C# (very uncommon, inheritance is what's used) or Objective-C (delegates are often used to customize the behavior).
You'll need to refer to the documentation, header files, samples and product support of your native library to understand how subclassing works.
What is MonoTouch doing to make this happen?
I do not think it's MonoTouch related. MonoTouch provides btouch to help you create bindings for Objective-C libraries. This is the same tool that Xamarin uses to make all iOS bindings.
Still unsure ? write a small Objective-C sample that does the same. Compare results with the MonoTouch version.
Different results ? Fill a bug report with both (C# and ObjC) test case and we'll check what's going on (as stated before we have good reasons to ensure that btouch is bug free ;-)
Why do I get a NULL ref in the case I use a derived class? I'm not touching the UIPopoverController an either case.
How can I find out what is wrong and how to fix it if there is no error?
What else has to be taken care of, besides the NullAllowed?
At this stage you're running the native code of the library you binded. The specific rules you'll need to follow are the ones you'll find by:
reading the library documentation;
reading the library source (when available), headers and samples;
for [NullAllowed] you can test (e.g. unit tests) if null is allowed or not (e.g. will it crash);
Also porting existing samples is both a good learning exercise (of the library API) and a quick way to test for bindings bugs (e.g. typos in selectors, wrong parameters...).
This specific issue turned out to be two things:
A missing NullAllowed attribute for a UIPopoverController
A bug in MonoTouch 5.2.13 that is not related to binding but something else that has to do with CocoaTouch. The specific reason is unknown.
Everything is working as expected with MonoTouch 5.3.6

Categories