How to handle the result of StartActivityForResult in Forms

AntaoAlmadaAntaoAlmada Antao AlmadaPTMember ✭✭

In the Android specific code of my Xamarin.Forms project, I use the following code to request the user to turn Bluetooth on:

const int RequestEnableBt = 2;
var context = Forms.Context;
var activity = (Activity)context;
var intent = new Intent(BluetoothAdapter.ActionRequestEnable);
activity.StartActivityForResult(intent, RequestEnableBt);

The user can either accept or deny the request.
In Xamarin.Android the result is handled in Activity.OnActivityResult().
Is there a way to handle this in Xamarin.Forms?

Posts

  • MarkFeldmanMarkFeldman Mark Feldman USMember ✭✭
    edited October 2016

    I'm not aware of any Android.Forms support myself so I add an event to my main activity that other parts of my Android app can subscribe to:

        public event Action<int, Result, Intent> ActivityResult;
    
        protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
        {
            if (this.ActivityResult != null)
                this.ActivityResult(requestCode, resultCode, data);
        }
    

    I then provide a service that registers itself with the main activity and passes the result back via a Task:

    // interface is declared in a common PCL
    public interface IBluetoothService
    {
        Task<bool> RequestBluetooth();
    }
    
    // implementations are in platform projects
    public class BluetoothService : IBluetoothService
    {
        public Task<bool> RequestBluetooth()
        {
            var activity = (MainActivity)Forms.Context;
            var listener = new ActivityResultListener(activity);
    
            const int RequestEnableBt = 2;
            var intent = new Intent(BluetoothAdapter.ActionRequestEnable);
            activity.StartActivityForResult(intent, RequestEnableBt);
    
            return listener.Task;
        }
    
        private class ActivityResultListener
        {
            private TaskCompletionSource<bool> Complete = new TaskCompletionSource<bool>();
            public Task<bool> Task { get { return this.Complete.Task; } }
    
            public ActivityResultListener(MainActivity activity)
            {
                // subscribe to activity results
                activity.ActivityResult += OnActivityResult;
            }
    
            private void OnActivityResult(int requestCode, Result resultCode, Intent data)
            {
                // unsubscribe from activity results
                var context = Forms.Context;
                var activity = (MainActivity)context;
                activity.ActivityResult -= OnActivityResult;
    
                // process result
                if (resultCode != Result.Ok)
                    this.Complete.TrySetResult(false);
                else
                    this.Complete.TrySetResult(true);
            }
        }
    };
    

    This service is then injected into my shared code and called asynchronously where needed:

        // request bluetooth
        private async Task OnEnableBluetooth()
        {
            var result = await this.BluetoothService.RequestBluetooth();
            this.PopupService.ShowMessage(result ? "Bluetooth is on" : "Bluetooth is off");
        }
    
  • AntaoAlmadaAntaoAlmada Antao Almada PTMember ✭✭

    It works! Thanks a lot for the tip.

  • manishchoudharymanishchoudhary manish choudhary USMember ✭✭

    Thanks @MarkFeldman

Sign In or Register to comment.