Making mono cross platform support for Task/Intent

2019-07-15 02:48发布

问题:

I have a application for WP7 and Android, and this application must have supporthas support for "any" connection type (WiFi, NFC, Bluetooth etc)

I have then created a layered model with MVVMCross https://github.com/slodge/MvvmCross

I have an interface for example Android Bluetooth must implement

interface IConnectionService
{
    List<TargetDevice> FindDevices();
    void Connect(TargetDevice targetDevice);
    void Disconnect();
    byte[] Read();
    void Write(byte[] command);
}

I want to be able to request the user for Bluetooth Access, but I do not want to program my UI specifically to Android Bluetooth, so the view and view-model should not know which intent is used, all this should be handled by the class implementing IConnectionService

The issue is that it should also work for Windows Phone which do not use intents, it uses tasks, so how do I make an interface that allows me to make either a Intent request or a task request without anyone knowing what type of request is needed?

回答1:

This is similar to the way MvvmCross allows users to make phone calls.

When using this pattern:

The ViewModel code consumes a platform independent service via an interface - e.g.:

public interface IMvxPhoneCallTask
{
    void MakePhoneCall(string name, string number);
}

consumed by

    protected void MakePhoneCall(string name, string number)
    {
        var task = this.GetService<IMvxPhoneCallTask>();
        task.MakePhoneCall(name, number);
    }

in https://github.com/slodge/MvvmCross/blob/master/Sample%20-%20CirriousConference/Cirrious.Conference.Core/ViewModels/BaseViewModel.cs

The app setup code injects the platform specific implementation for the interface - e.g:

        RegisterServiceType<IMvxPhoneCallTask, MvxPhoneCallTask>();

In WP7 - this uses the PhoneCallTask - https://github.com/slodge/MvvmCross/blob/master/Cirrious/Cirrious.MvvmCross/WindowsPhone/Platform/Tasks/MvxPhoneCallTask.cs

public class MvxPhoneCallTask : MvxWindowsPhoneTask, IMvxPhoneCallTask
{
    #region IMvxPhoneCallTask Members    

    public void MakePhoneCall(string name, string number)
    {
        var pct = new PhoneCallTask {DisplayName = name, PhoneNumber = number};
        DoWithInvalidOperationProtection(pct.Show);
    }

    #endregion
}

In Droid - it uses the ActionDial Intent - https://github.com/slodge/MvvmCross/blob/master/Cirrious/Cirrious.MvvmCross/Android/Platform/Tasks/MvxPhoneCallTask.cs

public class MvxPhoneCallTask : MvxAndroidTask, IMvxPhoneCallTask
{
    #region IMvxPhoneCallTask Members

    public void MakePhoneCall(string name, string number)
    {
        var phoneNumber = PhoneNumberUtils.FormatNumber(number);
        var newIntent = new Intent(Intent.ActionDial, Uri.Parse("tel:" + phoneNumber));
        StartActivity(newIntent);
    }


    #endregion
}

In Touch - it just uses Urls - https://github.com/slodge/MvvmCross/blob/master/Cirrious/Cirrious.MvvmCross/Touch/Platform/Tasks/MvxPhoneCallTask.cs

public class MvxPhoneCallTask : MvxTouchTask, IMvxPhoneCallTask
{
    #region IMvxPhoneCallTask Members

    public void MakePhoneCall(string name, string number)
    {
        var url = new NSUrl("tel:" + number);
        DoUrlOpen(url);
    }

    #endregion
}

In the vnext version of mvvmcross, this approach is further formalized using plugins - see a brief introduction to these in the 'going portable' presentation at http://slodge.blogspot.co.uk/2012/06/mvvm-mvvmcross-monodroid-monotouch-wp7.html

For example, in vNext the phone call code above is contained in the PhoneCall plugin - https://github.com/slodge/MvvmCross/tree/vnext/Cirrious/Plugins/PhoneCall


One of the challenges of your task may be the word "any" - differences in platform implementation might make it hard to define a cross-platform interface that works across all the platforms for any one of NFC, Bluetooth, etc, let alone all of them.