/// <summary>
        /// Called when an activity you launched exits, giving you the requestCode you started it with, the
        /// resultCode it returned, and any additional data from it.
        /// </summary>
        /// <param name="requestCode">
        ///   The integer request code originally supplied to startActivityForResult(), allowing you to identify who
        ///   this result came from.
        /// </param>
        /// <param name="resultCode">
        ///   The integer result code returned by the child activity through its setResult().
        /// </param>
        /// <param name="data">
        ///   An Intent, which can return result data to the caller (various data can be attached to Intent "extras").
        /// </param>
        protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
        {
            base.OnActivityResult(requestCode, resultCode, data);

            // If the operation was tasked
            if (this.tasked)
            {
                // Get the media from task result
                var future = resultCode == Result.Canceled
                                 ? MediaPickerActivity.TaskFromResult(new MediaPickedEventArgs(requestCode, true))
                                 : MediaPickerActivity.GetMediaFileAsync(
                    this,
                    requestCode,
                    this.action,
                    this.isPhoto,
                    ref this.path,
                    data?.Data);

                // Finish the current activity
                this.Finish();
                future.ContinueWith(t => MediaPickerActivity.RaiseOnMediaPicked(t.Result));
            }
            else
            {
                // If the task was canceled
                if (resultCode == Result.Canceled)
                {
                    this.SetResult(Result.Canceled);
                }
                else
                {
                    // Return the media resule
                    var resultData = new Intent();
                    resultData.PutExtra(MediaPickerActivity.MediaFileExtraName, data?.Data);
                    resultData.PutExtra(MediaPickerActivity.ExtraPath, this.path);
                    resultData.PutExtra("isPhoto", this.isPhoto);
                    resultData.PutExtra(MediaPickerActivity.ExtraAction, this.action);

                    this.SetResult(Result.Ok, resultData);
                }

                // Finish the current activity
                this.Finish();
            }
        }
        /// <summary>
        /// Gets the media file asynchronous.
        /// </summary>
        /// <param name="context">The execution context.</param>
        /// <param name="requestCode">The request operation code.</param>
        /// <param name="action">The action to perform.</param>
        /// <param name="isPhoto">A value indicating whenter the operation is performed on a photo.</param>
        /// <param name="path">The media path.</param>
        /// <param name="data">The media data URI.</param>
        /// <returns>A <see cref="Task"/> represening the asyncroneous operation.</returns>
        private static Task <MediaPickedEventArgs> GetMediaFileAsync(
            Context context,
            int requestCode,
            string action,
            bool isPhoto,
            ref Uri path,
            Uri data)
        {
            // If requested to take a photo
            Task <Tuple <string, bool> > pathFuture;
            Action <bool> dispose      = null;
            string        originalPath = null;

            if (action != Intent.ActionPick)
            {
                originalPath = path.Path;

                // Not all camera apps respect EXTRA_OUTPUT, some will instead return a content or file uri from data.
                if ((data != null) && (data.Path != originalPath))
                {
                    // Move the camera output
                    originalPath = data.ToString();
                    var currentPath = path.Path;
                    pathFuture =
                        MediaPickerActivity.TryMoveFileAsync(context, data, path, isPhoto)
                        .ContinueWith(t => new Tuple <string, bool>(t.Result ? currentPath : null, false));
                }
                else
                {
                    pathFuture = MediaPickerActivity.TaskFromResult(new Tuple <string, bool>(path.Path, false));
                }
            }
            else if (data != null)
            {
                // Pick the file from  media galery
                originalPath = data.ToString();
                path         = data;
                pathFuture   = MediaPickerActivity.GetFileForUriAsync(context, path, isPhoto);
            }
            else
            {
                // Nothing to perform
                pathFuture = MediaPickerActivity.TaskFromResult <Tuple <string, bool> >(null);
            }

            return(pathFuture.ContinueWith(
                       t =>
            {
                // If selected file exists
                var resultPath = t.Result.Item1;
                if ((resultPath != null) && File.Exists(t.Result.Item1))
                {
                    // Return the selected media
                    if (t.Result.Item2)
                    {
                        dispose = d => File.Delete(resultPath);
                    }

                    var mf = new MediaFile(resultPath, () => File.OpenRead(t.Result.Item1), dispose);
                    return new MediaPickedEventArgs(requestCode, false, mf);
                }

                // Return an error
                return new MediaPickedEventArgs(
                    requestCode,
                    new FileNotFoundException("Media file not found", originalPath));
            }));
        }