private Android.Net.Uri GetFileForBrowser(Android.Net.Uri dataFromActivityResult) { try { string TempfileName = Guid.NewGuid().ToString("N") + ".file"; string outputFolder = FileCachingHelper.GetFileCacheFolder(); if (!System.IO.Directory.Exists(outputFolder)) { System.IO.Directory.CreateDirectory(outputFolder); } var backingFile = System.IO.Path.Combine(outputFolder, TempfileName); using (var output = System.IO.File.Create(backingFile)) { using (System.IO.Stream inputStream = BlazorWebViewService.GetCurrentActivity().ContentResolver.OpenInputStream(dataFromActivityResult)) { inputStream.CopyTo(output); } } return(Android.Net.Uri.Parse("file://" + backingFile)); } catch (System.Exception e) { ConsoleHelper.WriteException(e); throw; } }
protected override void OnElementChanged(ElementChangedEventArgs <GeckoViewForms> e) { base.OnElementChanged(e); if (keyboardHelper == null) { keyboardHelper = new KeyboardUtil(BlazorWebViewService.GetCurrentActivity(), Control); } }
private void GetContentCompatibleIntents(int type, out List <IntentMetadata> intentList, out List <ResolveInfo> info) { Intent camIntent = new Intent("android.media.action.IMAGE_CAPTURE"); Intent getActionIntents = new Intent(Intent.ActionGetContent); getActionIntents.SetType("*/*"); getActionIntents.AddCategory(Intent.CategoryOpenable); //We must manage multiple file selection too if (type == FilePromptType.MULTIPLE) { getActionIntents.PutExtra(Intent.ExtraAllowMultiple, true); } // look for available intents info = new List <ResolveInfo>(); intentList = new List <IntentMetadata>(); PackageManager packageManager = BlazorWebViewService.GetCurrentActivity().PackageManager; List <ResolveInfo> listCam = packageManager.QueryIntentActivities(camIntent, 0).ToList(); //Required permissions for camera intents string[] permissionsForCamera = new string[] { Android.Manifest.Permission.WriteExternalStorage, Android.Manifest.Permission.Camera }; //Required permissions for read content intents string[] permissionsForGetContent = new string[] { Android.Manifest.Permission.ReadExternalStorage }; foreach (ResolveInfo res in listCam) { Intent finalIntent = new Intent(camIntent); finalIntent.SetComponent(new ComponentName(res.ActivityInfo.PackageName, res.ActivityInfo.Name)); intentList.Add(new IntentMetadata(finalIntent, permissionsForCamera)); info.Add(res); } List <ResolveInfo> listGall = packageManager.QueryIntentActivities(getActionIntents, 0).ToList(); foreach (ResolveInfo res in listGall) { Intent finalIntent = new Intent(getActionIntents); finalIntent.SetComponent(new ComponentName(res.ActivityInfo.PackageName, res.ActivityInfo.Name)); intentList.Add(new IntentMetadata(finalIntent, permissionsForGetContent)); info.Add(res); } }
public override Android.Views.View GetView(int position, Android.Views.View convertView, ViewGroup parent) { Android.Views.View view = base.GetView(position, convertView, parent); ResolveInfo res = ActivitiesInfo.ElementAt(position); ImageView image = (ImageView)view.FindViewById( BlazorWebViewService.GetResourceId("intent_listview_icon", AndroidResourceType.Identifier) ); image.SetImageDrawable(res.LoadIcon(BlazorWebViewService.GetCurrentActivity().PackageManager)); TextView textview = (TextView)view.FindViewById( BlazorWebViewService.GetResourceId("intent_listview_title", AndroidResourceType.Identifier) ); textview.Text = res.LoadLabel(BlazorWebViewService.GetCurrentActivity().PackageManager); return(view); }
/// <summary> /// Check for a permission available in <seealso cref="Android.Manifest.Permission"/> namespace /// </summary> /// <param name="permission"></param> /// public static void CheckForPermission(string[] permission, System.Action onGranted, System.Action onDenied) { string[] needAdditionalPermissions = permission.Where(p => BlazorWebViewService.GetCurrentActivity().CheckSelfPermission(p) != Android.Content.PM.Permission.Granted).ToArray(); if (Build.VERSION.SdkInt >= BuildVersionCodes.M && needAdditionalPermissions != null && needAdditionalPermissions.Length > 0) { BlazorWebViewService.GetCurrentActivity().RequestPermissions(needAdditionalPermissions, BLAZORMOBILE_REQUESTCODE); //TODO: We must forward event directly from an async result OR at least show a toast in order to ask to repeat the action again //We must dismiss the result, and the user have to retry after validating the permission onDenied?.Invoke(); } else { //We already have the permission onGranted?.Invoke(); } }
public virtual void OnFilePrompt(GeckoSession session, string title, int type, string[] mimeTypes, GeckoSession.PromptDelegateClassFileCallback callback) { var currentActivity = BlazorWebViewService.GetCurrentActivity(); AlertDialog _futureDialog = null; //Workaround dismiss method not available on AlertDialog.Builder before Show(); bool shouldDismiss = true; var dialogBuilder = new Android.App.AlertDialog.Builder(_renderer.Context); BlazorFileDialogDismissListener onDismissEvent = new BlazorFileDialogDismissListener(); onDismissEvent.SetDismissHandler(() => { if (shouldDismiss) { callback.Dismiss(); } dialogBuilder.Dispose(); }); dialogBuilder.SetOnDismissListener(onDismissEvent); GetContentCompatibleIntents(type, out List <IntentMetadata> intentList, out List <ResolveInfo> activitiesInfo); dialogBuilder.SetAdapter(BuilderAdapter(currentActivity, activitiesInfo), (sender, e) => { //On Intent click shouldDismiss = false; IntentMetadata selectedIntent = intentList.ElementAt(e.Which); //Check for Android permissions for intents RequestPermissionHelper.CheckForPermission(selectedIntent.RequiredPermissions, () => { //On Intent permission availables //We must manage multiple file selection too //TODO: Even by adding this intent //this seem to not working yet. Not sure if possible through launching external intents if (type == FilePromptType.MULTIPLE) { selectedIntent.Intent.PutExtra(Intent.ExtraAllowMultiple, true); } currentActivity.StartActivityForResult(selectedIntent.Intent, 1, (int requestCode, Result resultCode, Intent data) => { if (resultCode != Result.Ok) { //Do nothing as the user is still now on the Intent dialog box chooser //As on Permission not granted, see comment below => //We should reset this value to true if denied, as the user may don't click on Cancel but use a back button instead //As the back button will call the Dialog dismiss internally, we should emulate the cancel behavior (see SetNeutralButton code) shouldDismiss = true; } else { try { callback.Confirm(currentActivity, GetFileForBrowser(data.Data)); } catch (System.Exception e) { ConsoleHelper.WriteException(e); callback.Dismiss(); } _futureDialog.Dismiss(); } }); }, () => { //On Intent permission unavailable //We should reset this value to true if denied, as the user may don't click on Cancel but use a back button instead //As the back button will call the Dialog dismiss internally, we should emulate the cancel behavior (see SetNeutralButton code) shouldDismiss = true; }); }); dialogBuilder.SetNeutralButton(currentActivity.Resources.GetString(Android.Resource.String.Cancel), (sender, e) => { shouldDismiss = true; _futureDialog.Dismiss(); }); shouldDismiss = true; _futureDialog = dialogBuilder.Show(); }
public virtual void OnChoicePrompt(GeckoSession session, string title, string msg, int type, GeckoSession.romptDelegateClassChoice[] choices, GeckoSession.PromptDelegateClassChoiceCallback prompt) { //This code is highly inspired of https://github.com/mozilla-mobile/focus-android/blob/f5b22ff78fca22765b8b873b4f70693943ae559a/app/src/main/java/org/mozilla/focus/gecko/GeckoViewPrompt.java#L265 var currentActivity = BlazorWebViewService.GetCurrentActivity(); if (currentActivity == null) { prompt.Dismiss(); return; } var builder = new Android.App.AlertDialog.Builder(currentActivity); AddStandardLayout(builder, title, msg); Android.Widget.ListView list = new Android.Widget.ListView(builder.Context); if (type == GeckoSession.romptDelegateClassChoice.ChoiceTypeMultiple) { list.ChoiceMode = ChoiceMode.Multiple; } ModifiableChoiceArrayAdapter <ModifiableChoice> adapter = new ModifiableChoiceArrayAdapter <ModifiableChoice>(builder.Context, Android.Resource.Layout.SimpleListItem1, type, builder, list); AddChoiceItems(type, adapter, choices, /* indent */ null); list.SetAdapter(adapter); builder.SetView(list); AlertDialog dialog; if (type == GeckoSession.romptDelegateClassChoice.ChoiceTypeSingle || type == GeckoSession.romptDelegateClassChoice.ChoiceTypeMenu) { dialog = CreateStandardDialog(builder, prompt); list.ItemClick += (sender, e) => { ModifiableChoice item = adapter.GetItem(e.Position); if (type == GeckoSession.romptDelegateClassChoice.ChoiceTypeMenu) { GeckoSession.romptDelegateClassChoice[] children = item.Choice.Items?.ToArray(); if (children != null) { // Show sub-menu. dialog.SetOnDismissListener(null); dialog.Dismiss(); OnChoicePrompt(session, item.ModifiableLabel, /* msg */ null, type, children, prompt); return; } } prompt.Confirm(item.Choice); dialog.Dismiss(); }; } else if (type == GeckoSession.romptDelegateClassChoice.ChoiceTypeMultiple) { list.ItemClick += (sender, e) => { ModifiableChoice item = adapter.GetItem(e.Position); item.ModifiableSelected = ((CheckedTextView)e.View).Checked; }; builder .SetNegativeButton(Android.Resource.String.Cancel, /* listener */ (IDialogInterfaceOnClickListener)null) .SetPositiveButton(Android.Resource.String.Ok, (sender, e) => { int len = adapter.Count; List <string> items = new List <string>(len); for (int i = 0; i < len; i++) { ModifiableChoice item = adapter.GetItem(i); if (item.ModifiableSelected) { items.Add(item.Choice.Id); } } prompt.Confirm(items.ToArray()); }); dialog = CreateStandardDialog(builder, prompt); } else { throw new UnsupportedOperationException(); } dialog.Show(); //TODO: Don't forget to Dispose dialogbuilder }
public override Android.Views.View GetView(int position, Android.Views.View view, ViewGroup parent) { var context = BlazorWebViewService.GetCurrentActivity(); int itemType = GetItemViewType(position); int layoutId; if (itemType == TYPE_SEPARATOR) { if (mSeparator == null) { mSeparator = new Android.Views.View(context); mSeparator.LayoutParameters = new Android.Widget.ListView.LayoutParams(ViewGroup.LayoutParams.MatchParent, 2, itemType); TypedArray attr = context.ObtainStyledAttributes( new int[] { Android.Resource.Attribute.ListDivider }); mSeparator.SetBackgroundResource(attr.GetResourceId(0, 0)); attr.Recycle(); } return(mSeparator); } else if (itemType == TYPE_MENU_ITEM) { layoutId = Android.Resource.Layout.SimpleListItem1; } else if (itemType == TYPE_MENU_CHECK) { layoutId = Android.Resource.Layout.SimpleListItemChecked; } else if (itemType == TYPE_GROUP) { layoutId = Android.Resource.Layout.PreferenceCategory; } else if (itemType == TYPE_SINGLE) { layoutId = Android.Resource.Layout.SimpleListItemSingleChoice; } else if (itemType == TYPE_MULTIPLE) { layoutId = Android.Resource.Layout.SimpleListItemMultipleChoice; } else { throw new UnsupportedOperationException(); } if (view == null) { if (mInflater == null) { mInflater = LayoutInflater.From(_builder.Context); } view = mInflater.Inflate(layoutId, parent, false); } ModifiableChoice item = GetItem(position); TextView text = (TextView)view; text.Enabled = !item.Choice.Disabled; text.Text = item.ModifiableLabel; if (view is CheckedTextView) { bool selected = item.ModifiableSelected; if (itemType == TYPE_MULTIPLE) { _list.SetItemChecked(position, selected); } else { ((CheckedTextView)view).Checked = selected; } } return(view); }