Android StartActivityForResult and Xamarin Forms

In this post I demonstrate a technique for using getting the results from Android activities in Xamarin Forms apps. The code for this example is available here.

The Problem

In a standard Android app you can use the StartActivityForResult method on your current activity to start a child activity. When the child activity completes the OnActivityResult is called on the parent activity.

In a Xamarin Forms app you don’t really have a parent activity – you have the Forms.Context object but if you use that all results will go to the main activity which is messy. If you are making a library you can’t even do that.

The Solution

The example app prompts the user to select a contact, then displays the name of the selected contact.

The magic takes place in the Phonebook class.

    public class Phonebook : IPhonebook
    {
        public Task<string> GetContactName()
        {
            var intent = new Intent(Forms.Context, typeof(PhonebookActivity));
            Forms.Context.StartActivity(intent);

            var tcs = new TaskCompletionSource<string>();
            EventHandler handler = null;

            handler = (sender, args) =>
            {
                PhonebookActivity.ContactResultHandler -= handler;
                tcs.SetResult(((PhonebookActivity)sender).ContactName);
            };

            PhonebookActivity.ContactResultHandler += handler;

            return tcs.Task;
        }
    }

Although it’s short, its doing a fair bit of work. The GetContactName method starts starts the PhonebookActivity from the app’s main activity.It then uses a TaskCompletionSource to wait for an event from the PhoneBookActivity. It returns a Task so it can be called asynchronously.

There’s more magic in the PhonebookActivity class. The main reason for using this activity is to give us somewhere to call StartActivityForResult from. When the activity starts it creates and starts an Intent to prompt the user to select a contact. When that activity finishes it takes the result and raises an event back to the Phonebook class. The PhonebookActivity is never actually displayed on screen – really it’s just a wrapper for the select contact activity.

    [Activity(Label = "PhonebookActivity")]
    public class PhonebookActivity : Activity
    {
        private const int RequestCodeSelectContact = 1;

        public string ContactName { get; private set; }

        public static EventHandler ContactResultHandler;

        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);

            if (bundle == null)
            {
                var intent = new Intent(Intent.ActionPick, ContactsContract.Contacts.ContentUri);

                if (intent.ResolveActivity(PackageManager) != null)
                {
                    StartActivityForResult(intent, RequestCodeSelectContact);
                }
            }
        }

        protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
        {
            ContactName = string.Empty;

            if (requestCode == RequestCodeSelectContact && resultCode == Result.Ok)
            {
                var uri = data.Data;

                string[] projection = new string[] { ContactsContract.ContactNameColumns.DisplayNamePrimary };

                var cursor = ContentResolver.Query(uri, projection, null, null, null);

                if (cursor.MoveToFirst())
                {
                    int columnIndex = cursor.GetColumnIndexOrThrow(ContactsContract.ContactNameColumns.DisplayNamePrimary);
                    ContactName = cursor.GetString(columnIndex);
                }
            }

            ContactResultHandler?.Invoke(this, new EventArgs());
            Finish();
        }
    }
Advertisements
Android StartActivityForResult and Xamarin Forms

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s