android binding : Map java interface based callback to modern C# - xamarin

I'm fine-tuning a library written in java for android that deals with bluetooth, that I will use in a Xamarin project with native binding.
Since it deal with I/O, most of the api contains async method and, cause we don't have access to the good stuff yet (lambdas), those async calls are dealt using callbacks (an interface to be implemented by the client). ie :
void connect(BluetoothPeripheral target, IConnectionCompletion handler);
Of course in C#, there are much better way to deal with async stuff : Action instead of creating a whole new class, or even better the Task with async/await.
My question is : What do I need to do to map those Callback based java methods to C# methods that will return Task or take and Action instead of the callback?

Related

Xamarin Forms - calling a shared code method from the platform project

I have read the two other questions on SO regarding this and I wanted to know if there is a good solution for that now / best practice.
Long story short, we use an SDK which is written natively and we've wrapped it so that it works on Xamarin.Android and Xamarin.iOS. It has asynchronous callback methods. I need to call a method in the shared code when a callback is received in the Android project for instance.
There's a lot of info for doing the opposite - using DependencyService. How about in my scenario? Does anyone have experience with an app like this and what's the best approach to keep code clean and do this using MVVM?
The options I know are:
Using a static App instance - this is what we currently do.
MessagingCenter
Anything else?
Actually I've never seen anyone recommend usage of MessagingCenter for anything else than communication between ViewModels so I am not sure it is recommended here. Also, I need to know the sender object type so I need a reference to the class in the platform specific project.
I would recommend you to use messagingCenter to pass data or call method between shared project and platform project. You can just send a new object instead of the class in the platform specific project.
Also, have a look at using eventhandler as I mentioned in this answer may help someone who want to call from the shared project into the platform specific one.
BTW, I mean you can even pass an object as TSender if it is not necessary to use:
MessagingCenter.Send<Object>(new object(), "Hi");
MessagingCenter.Subscribe<Object>(new object(), "Hi", (sender) =>
{
// Do something whenever the "Hi" message is received
});

Call method on specific platform only

I know I can call a platform-specific method by using:
DependencyService.Get<ISomething>();
But I have a method I need to call only on one platform (Android). Instead of creating an interface and implementing it on one platform only, is there a way of calling a method in one platform?
I'm asking because creating an interface makes sense when there will be more than one implementation. But when there will be only one - I would expect there to be a simpler way of doing it.
Have you tried using Xamarin.Forms built in RuntimePlatform? For example, if you needed to do something specifically for Android only:
if (Device.RuntimePlatform == Device.Android)
{
//Call your method
}

Reverse Dependency Service

I have a Xamarin Forms Project. I have used Dependency Service to call the Platform specific method to fire a local notification on Android and a Alert on iOS.
My problem is now, how to handle an action on both notification(android) and alert(iOS). Is it possible to call a method of the shared project from the android or iOS project?
Do I need another approach? Does someone know what I have to do?
Just for clarification, I know how the ordinary dependency services works i.e. Call a method on android or iOS from the shared project!
I believe I had a similar scenario on my app. If you want to push something from your platform methods to your PCL you would need to make use of call backs and event delegates.
In Interface PCL:
event OnMessageHandlerCallback OnMessageEvent;
event OnErrorHandlerCallBack OnErrorEvent;
In Platform specific Class inheriting interface:
private OnMessageHandlerCallback callback = null;
private OnErrorHandlerCallBack errorCallBack = null;
public event OnMessageHandlerCallback OnMessageEvent;
public event OnErrorHandlerCallBack OnErrorEvent;
Have you tried just calling the method from your native project...? No special patterns necessary. The native iOS and Android projects have a direct reference to your shared project, so it can call the method directly.

How to integrate WinRT asynchronous tasks into existing synchronous libraries?

We have a long established, greatly multiplatform codebase that is currently being ported to WinRT. One of the challenges we're facing is how to handle WinRT's asynchronous style.
For example, we are unsure how to handle WinRT's async file operations. Unsurprisingly, our codebase's API is synchronous. A typical example is our File::Open function which attempts to open a file and return with success or failure. How can we call WinRT functions and yet keep the behavior of our functions the same?
Note that we are unfortunately constrained by legacy: we cannot simply go and change the API to become asynchronous.
Thanks!
I assume you wish to reimplement the library to support WinRT apps while not changin the definitions of the APIs so that existing applications remain compatible.
I think that if you don't include the await keyword when calling an async method you will not do an async operation, it should execute in a synchronous way. But it really doesn't work if the method returns a value (in my experience).
I've been using this code to make a file operation synchronous:
IAsyncOperation<string> contentAsync = FileIO.ReadTextAsync(file);
contentAsync.AsTask().Wait();
string content = contentAsync.GetResults();
If you want to share your code with a platform that does not support async/await - you are probably better off having a different API for the old platform and the new one with switches like
#if SILVERLIGHT
#elif NETFX_CORE
#elif WPF
#endif
Eventually the async APIs are likely to show up in older platforms and you could actually wrap the non-async calls into Tasks to make them async if they don't. Forcing async method to work synchronously is bound to bite you back rather quickly. Your WinRT app might become unresponsive for a few seconds for example and get killed by the OS. Or you could get deadlocks waiting for tasks to complete and blocking the thread they try to complete on.

Why are events defined as delegates

I have started working with ASP.NET controls and there appeared a question:
"why events in ASP controls are defined as delegates, and not as methods"?
Because an event must point to the function that it fires somehow and in C# this mechanism is achieved by delegates.
In response to the comment:
Then, why is such not a case with Java that uses only methods to fire
events?
Because Java uses the old traditional event pattern (like in C++). C# delegates are easier to use and also allow you to point to a static function rather than forcing the use of a class method.

Resources