/// <summary> /// File picking implementation /// </summary> /// <param name="allowedTypes">list of allowed types; may be null</param> /// <param name="action">Android intent action to use; unused</param> /// <returns>picked file data, or null when picking was cancelled</returns> private Task <FileData> PickFileAsync(string[] allowedTypes, string action) { var id = this.GetRequestId(); var ntcs = new TaskCompletionSource <FileData>(id); if (Interlocked.CompareExchange(ref this.completionSource, ntcs, null) != null) { throw new InvalidOperationException("Only one operation can be active at a time"); } try { var pickerIntent = new Intent(this.context, typeof(FilePickerActivity)); pickerIntent.SetFlags(ActivityFlags.NewTask); pickerIntent.PutExtra(FilePickerActivity.ExtraAllowedTypes, allowedTypes); this.context.StartActivity(pickerIntent); EventHandler <FilePickerEventArgs> handler = null; EventHandler <FilePickerCancelledEventArgs> cancelledHandler = null; handler = (s, e) => { var tcs = Interlocked.Exchange(ref this.completionSource, null); FilePickerActivity.FilePickCancelled -= cancelledHandler; FilePickerActivity.FilePicked -= handler; tcs?.SetResult(new FileData( e.FilePath, e.FileName, () => { if (IOUtil.IsMediaStore(e.FilePath)) { var contentUri = Android.Net.Uri.Parse(e.FilePath); return(Application.Context.ContentResolver.OpenInputStream(contentUri)); } else { return(System.IO.File.OpenRead(e.FilePath)); } })); }; cancelledHandler = (s, e) => { var tcs = Interlocked.Exchange(ref this.completionSource, null); FilePickerActivity.FilePickCancelled -= cancelledHandler; FilePickerActivity.FilePicked -= handler; if (e?.Exception != null) { tcs?.SetException(e.Exception); } else { tcs?.SetResult(null); } }; FilePickerActivity.FilePickCancelled += cancelledHandler; FilePickerActivity.FilePicked += handler; } catch (Exception ex) { // Debug.Write(ex); this.completionSource.SetException(ex); } return(this.completionSource.Task); }