Xamarin.Forms icon indicating copy to clipboard operation
Xamarin.Forms copied to clipboard

Custom webview not requesting permission

Open vsfeedback opened this issue 3 years ago • 1 comments

This issue has been moved from a ticket on Developer Community.


[severity:Other] I have a custom webview in my Xam.Forms application that creates a Chrome webview and then sets up permissions on the webview for the likes of Javascript etc to work.

The code I'm using in the renderer is this

protected override void OnElementChanged(ElementChangedEventArgs e)
		{
			base.OnElementChanged(e);

			Control.Download += OnDownload;
			Control.Settings.JavaScriptEnabled = true;
			Control.Settings.JavaScriptCanOpenWindowsAutomatically = true;
			
			Control.Settings.SetPluginState(WebSettings.PluginState.On);

			if (e.OldElement == null)
			{
				ResetCookieManagerSettings();

				var chromeClient = new ArenaWebChromeClient((uploadMsg, acceptType, capture) =>
				{
					// The following code is the callback method defined in the ArenaWebChromeClient
					MainActivity.UploadMessage = uploadMsg;

					// Create camera capture image intent and add it to the chooser
					var captureIntent = new Intent(MediaStore.ActionImageCapture);

					var getContentIntent = new Intent(Intent.ActionGetContent);
					getContentIntent.AddCategory(Intent.CategoryOpenable);
					getContentIntent.SetType("image/*");

					var chooserIntent = Intent.CreateChooser(getContentIntent, "Choose image");

					// Ensure that the device's camera is available:
					if (captureIntent.ResolveActivity(currentContext.PackageManager) != null)
					{
						// It is. Create a unique filename for the image that's about to be captured by the camera:
						File image = CreateImageFile();

						// ...and pass a content:// link to that filename to our main activity (see https://developer.android.com/reference/androidx/core/content/FileProvider)
						MainActivity.mCapturedImageURI = GetFileUri(image);

						// ...and to the capture intent, so any image created by the camera will be written to the file we've just created (note, we're also adding permission):
						captureIntent.SetFlags(ActivityFlags.GrantReadUriPermission | ActivityFlags.GrantWriteUriPermission);
						captureIntent.PutExtra(MediaStore.ExtraOutput, MainActivity.mCapturedImageURI);
						chooserIntent.PutExtra(Intent.ExtraInitialIntents, new Intent[] { captureIntent });
					}

					((Activity)currentContext).StartActivityForResult(chooserIntent, FILECHOOSER_RESULTCODE);
				}, currentContext);

				var webViewClient = new ArenaWebViewClient(this);
				if (App.Self.IsConnected)
				{
					Control.SetWebChromeClient(chromeClient);

					webViewClient.PageLoadStarted += RaiseLoadStarted;
					webViewClient.PageLoadFinished += RaiseLoadFinished;

#if DEBUG
					// Ignore SSL errors in our development version
					webViewClient.IgnoreSslErrors = true;
#endif

					Control.SetWebViewClient(webViewClient);
					Control.Settings.SetGeolocationEnabled(true);
					Control.Settings.SetGeolocationDatabasePath(Control.Context.FilesDir.Path);
					Control.Settings.SetSupportZoom(false);
					Control.Settings.SaveFormData = true;
					Control.Settings.AllowFileAccess = true;
					Control.Settings.AllowContentAccess = true;
					Control.Settings.LoadWithOverviewMode = true;
					Control.Settings.CacheMode = CacheModes.NoCache;
				}
				else
                {
					webViewClient.PageLoadStarted -= RaiseLoadStarted;
					webViewClient.PageLoadFinished -= RaiseLoadFinished;
					Task.Run(async () =>
									await Rg.Plugins.Popup.Services.PopupNavigation.Instance.PushAsync
										(new ErrorMessagePopupPage("You don't seem to have a network connection. Please check and try again")));
				}
			}
		}

This works fine. Part of the website the app accesses requires that audio is captured. This is implemented in the Chrome view using the following code

public override async void OnPermissionRequest(PermissionRequest request)
        {
            base.OnPermissionRequest(request);
			if (request != null)
            {
				permissionRequest = request;
				var res = request.GetResources();
				if (res.Length != 0)
				{
					foreach (var r in res)
					{
						if (r.Contains("AUDIO_CAPTURE"))
						{
							try
							{
								if (ContextCompat.CheckSelfPermission(context, r) != Permission.Granted)
								{
									if (ActivityCompat.ShouldShowRequestPermissionRationale(MainActivity.MainActive,
										"android.webkit.resource.AUDIO_CAPTURE"))
									{
										Device.BeginInvokeOnMainThread(async () =>
										await App.Self.MainPage.DisplayAlert("Arena",
										"Arena requires permission to capture audio",
											"OK", "Cancel").ContinueWith((t) =>
											{
												if (t.IsCompleted)
													if (t.Result)
														ActivityCompat.RequestPermissions(MainActivity.MainActive,
															new string[] { "android.webkit.resource.AUDIO_CAPTURE" },
															1001);
											}));
									}
								}
							}
							catch (Exception ex)
							{
								Console.WriteLine($"ex = {ex.Message}");
							}

							var perms = await Permissions.CheckStatusAsync();
							if (perms != PermissionStatus.Granted)
							{
								var req = await Permissions.RequestAsync();
								if (req == PermissionStatus.Granted)
								{
									var mod = await Permissions.CheckStatusAsync();
									if (mod != PermissionStatus.Granted)
									{
										var t = await Permissions.RequestAsync();
									}

#if DEBUG
									Console.WriteLine("Microphone set");
#endif
								}
							}
						}
						else
						{
							var mod = await Permissions.CheckStatusAsync();
							if (mod != PermissionStatus.Granted)
							{
								var t = await Permissions.RequestAsync();

#if DEBUG
								Console.WriteLine("Microphone set");
#endif
							}
						}
					}
				}					
            }
        }

This code is hit when the webview requests it, but the permission is never requested nor set (the receiver in the MainActivity class does receive the request)

My manifest requests the following permissions


	
	
	
	
	
	
	
	
	
	
	
	

Everything looks correct but the permission is not being set correctly.


Original Comments

Feedback Bot on 4/19/2022, 07:31 PM:

(private comment, text removed)


Original Solutions

(no solutions)

vsfeedback avatar Apr 27 '22 22:04 vsfeedback

The empty permissions section in the bug report should read: <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="21" android:maxSdkVersion="29"/> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.MICROPHONE" /> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-feature android:name="android.hardware.audio.low_latency" /> <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.RECEIVE_WAP_PUSH" /> <uses-feature android:name="android.hardware.audio.pro" /> <uses-feature android:name="android.hardware.microphone" />

davidhuggett avatar Sep 09 '22 08:09 davidhuggett