Dialer App Example

→ Specific PlatformService implementation

 

The latest version of all the official Flutnet samples can be found in the official GitHub repository: https://github.com/flutnet/samples/

 

Overview

This example is simple, but very powerfull, because will see some of the potential about a flutnet application. In particural this example will open the system dialer on the smartphone, calling it from Flutter and implementig in two different way the PlatformService, based on the corrisponding platform (Android or iOS).

 

We will define a PlatformService called DialerService that will provide one PlatformOperation:

  1. public void OpenDialer ( string number ) → Flutter request to open the dialer with specific number.

 

This example rely on the fact that we have some experience developing both Android and iOS Platform: we know that Android can open the dialer using an Intent, and in iOS we can  rely on App Extensions, that will handle the task about opening the dialer.

 


Create the project

Create a project named "FlutnetDialer" using the Flutnet Console.

The generated project structure will contain the Visual Studio solution (FlutnetDialer.sln) and a set of Xamarin and Flutter projects:

  • Xamarin
    • FlutnetDialer.Android (Xamarin.Android application)
    • FlutnetDialer.iOS (Xamarin.iOS application)
    • FlutnetDialer.ServiceLibrary (.NET Standard class library)
  • Flutter
    • flutnet_dialer (Flutter module → it's the main Flutter project where you develop the UI)
    • flutnet_dialer_bridge (Flutter package → it will contain auto-generated Dart code that defines the communication layer between Flutter and Xamarin).

Define the ServiceLibrary (PlatformService, PlatformOperations, etc.)

In the *.ServiceLibrary project we need to define the IDialerService as an Interface, because we will implement the specific platform code: in Flutter not matter the platform code (because it is handled by xamarin).

IDialerService.cs

using Flutnet.ServiceModel;

namespace FlutnetDialer.ServiceLibrary
{

    // This service class will be exposed to Flutter
    [PlatformService]
    public interface IDialerService
    {

        [PlatformOperation]
        public int OpenDialer();       
    }
}

 

The code will be implemented in the specific not shared project.

 


Implement a specific PlatformService for Android and iOS

We just implement the IDialerService declared in the ServiceLibrary project.

Xamarin Android

DialerServiceDroid.cs

public class DialerServiceDroid : IDialerService
    {
        private readonly Context _appContext;

        public DialerServiceDroid(Context appContext)
        {
            this._appContext = appContext;
        }
        // Open Android dialer using Intent
        public void OpenDialer(string phoneNumber)
        {

            // Use format with "tel:" and phoneNumber received from Flutter. 
            Uri uri = Uri.Parse("tel:" + phoneNumber);

            // Create the intent and set the data for the  
            // intent as the phone number. 

            Intent i = new Intent(Intent.ActionDial, uri);
            i.AddFlags(ActivityFlags.NewTask);

            _appContext.StartActivity(i);

        }
    }

 

Xamarin iOS

In iOS the OpenUrl call must me done on the UI thread, so we need to override the default configuration for the PlatformOperation. To do so  we need to re-declare the Platform attribute in this class.

DialerServiceIOS

PlatformService ]
public class DialerServiceIOS : IDialerService
    {
        [ PlatformOperation ( IosMainThreadRequired = true ) ]
        public void OpenDialer(string phoneNumber)
        {
            NSUrl uri = NSUrl.FromString($"tel://{phoneNumber}");

            if (UIApplication.SharedApplication.CanOpenUrl(uri))
            {
                // Open the dialer 
                UIApplication.SharedApplication.OpenUrl(uri);
            }
        }
    }


Build ServiceLibrary project

By default the ServiceLibrary project is configured to execute the $ flutnet pack command in the post-build event.

The procedure will update the "flutnet_dialer_bridge" package with all the required Dart code for managing the communication between Flutter and Xamarin.


Configure the FlutnetBridge Mode

Depending on your development preferences, you could use a specific FlutnetBridge mode:

In order to set the FlutnetBridge mode, just edit the following methods:

  • App.cs → ConfigureFlutnetBridge(FlutterEngine) in Xamarin.Android app
  • ViewController → ViewDidAppear(bool) in Xamarin.iOS app
  • main.dartmain() in Flutter module

Xamarin.Android

App.cs → ConfigureFlutnetBridge(FlutterEngine)

#if (DEBUG)
  _bridge = new FlutnetBridge(flutterEngine, AppContext, FlutnetBridgeMode.PlatformChannel);
#else
  ...
#endif

 

Xamarin.iOS

ViewController.cs → ViewDidAppear(bool)

#if (DEBUG)
  _bridge = new FlutnetBridge(this.Engine, FlutnetBridgeMode.PlatformChannel);
#else
  ...
#endif

 

Flutter

main.dart 

 

import 'package:flutter/material.dart';

import 'package:flutnet_dialer_bridge/flutnet_bridge.dart';

 

void main() {

  // Configure the bridge mode for debug

  FlutnetBridgeConfig.mode = FlutnetBridgeMode.PlatformChannel;

  runApp(MyApp());

}


Develop your user interface in Flutter

// Import the counter service

import 'package:flutnet_dialer_bridge/flutnet_dialer/service_library/i_dialer_service.dart';

....

 

class _MyHomePageState extends State<MyHomePage> {

 

  // Reference to the xamarin dialer service interface

  // NOTE: we reference the service as an interface because we don't care about the implementation.

  final IDialerService _dialerService IDialerService("dialer_service");

 

  String _phoneNumber = "+39-123-456-789";

 

@override

  Widget build(BuildContext context) {

    ......

            FloatingActionButton(

              backgroundColor: Colors.green,

              child: Icon(Icons.phone),

              // We open the dialer using the service

              onPressed: () =>

                  _dialerService.openDialer(phoneNumber: _phoneNumber),

            ),

   ......

  }

....


Build the Flutter project

Before running the Xamarin app, you need to build the Flutter module project ("flutnet_dialer" in this case).

In order to do this, open the terminal from Visual Studio Code and run the following commands:

  • $ flutter build aar --no-profile
  • $ flutter build ios-framework --no-profile (only if you're on macOS)

Once the build is finished, you should be able to run your Xamarin app with Flutter as user interface.


Register the PlatformServices

In order to expose the platform-specific services to Flutter, you need to register an instance of these services on the FlutnetRuntime by specifying a proper, unique name ("dialer_service" in this case).

The registration must be done before the FlutnetBridge initialization. This occurs in the following methods:

  • App → ConfigureFlutnetRuntime() in Xamarin.Android app
  • ViewController → ViewDidAppear(bool) in Xamarin.iOS app

Xamarin.Android

// Initialize the Flutnet environment by providing a proper app key
// (see App keys in Flutnet Console)
FlutnetRuntime.Init("TRIAL-APP-KEY");

// Register the service
FlutnetRuntime.RegisterPlatformService(new DialerServiceDroid(AppContext), "counter_service");

...

Xamarin.iOS

// Initialize the Flutnet environment by providing a proper app key
// (see App keys in Flutnet Console)
FlutnetRuntime.Init("TRIAL-APP-KEY");

// Register the service
FlutnetRuntime.RegisterPlatformService(new DialerServiceIOS(), "counter_service");

...