Browser also asks camera permission in ios webview - ios

I am having a Xamarin.Forms Prism application. It is using a WKWebView in ios Project to display a web page. In that page, other than the permission from the iOS, a permission popup from browser is also being displayed. Can anybody please help me with this? This is happening only in iOS.

https://learn.microsoft.com/en-us/answers/questions/1167987/how-to-fix-double-permission-popup-in-xamarin-ios
This thread helped me to solve this problem. Implement a class which is inherited from WKUIDelegate.
public class CustomWebViewDelegate : WKUIDelegate
{
[Export("webView:decideMediaCapturePermissionsForOrigin:initiatedByFrame:type:decisionHandler:")]
public override void RequestMediaCapturePermission(WKWebView webView, WKSecurityOrigin origin, WKFrameInfo frame, WKMediaCaptureType type, Action decisionHandler)
{
try
{
decisionHandler(WKPermissionDecision.Grant);
base.RequestMediaCapturePermission(webView, origin, frame, type, decisionHandler);
}
catch (Exception e)
{ }
}
}
Add this statement in the Renderer class.
webView.UIDelegate = new CustomWebViewDelegate();

Related

Xamarin forms Stop screen shot and record in ios

I have xamarin forms app and need to prevent user from take screen shot or record screen
these implemented for android using these:
Window.SetFlags(WindowManagerFlags.Secure, WindowManagerFlags.Secure);
is there any we to do these for ios
Thanks
Like Jason said, you could find more information in Google. You could try the code below for ios to blur or hide the screenshot taken, to hide sensitive information. I hope this would be helpful for you.
A easy way is to set a blur when the AppDelegate calls OnResignActivation.
UIVisualEffectView _blurWindow = null;
public override void OnActivated(UIApplication application)
{
base.OnActivated(application);
_blurWindow?.RemoveFromSuperview();
_blurWindow?.Dispose();
_blurWindow = null;
}
public override void OnResignActivation(UIApplication application)
{
base.OnResignActivation(application);
using (var blurEffect = UIBlurEffect.FromStyle(UIBlurEffectStyle.Dark))
{
_blurWindow = new UIVisualEffectView(blurEffect)
{
Frame = UIApplication.SharedApplication.KeyWindow.RootViewController.View.Bounds
};
UIApplication.SharedApplication.KeyWindow.RootViewController.View.AddSubview(_blurWindow);
}
}
I use Dark here. You could change the blur effect to Light, Regular or any of the other options listed.

How to exit the App in Xamarin Forms?

My project is built with master-detail navigation.
There are totally three pages in the list named as Resources, Contacts, and Login.
Everything works fine in iOS, but when the user presses the Droid/WinPhone devices hardware back button, the app should exit.
Is there any app-exit mechanism for Xamarin Forms which will work on all the devices.? (I mean native code not platform dependent)
Thanks in advance.
I did that on this way
In xamarin forms I added interface
public interface INativeHelper
{
void CloseApp();
}
In android project I made implementation of INativeHelper
public class NativeHelper : INativeHelper
{
public void CloseApp()
{
Android.OS.Process.KillProcess(Android.OS.Process.MyPid());
}
}
Implementation of INativeHelper in IOS
public class NativeHelper : INativeHelper
{
public void CloseApp()
{
Process.GetCurrentProcess().CloseMainWindow();
Process.GetCurrentProcess().Close();
}
}
And then just override method OnBackButtonPressed in page in Xamarin.Forms project
protected override bool OnBackButtonPressed()
{
INativeHelper nativeHelper = null;
nativeHelper = DependencyService.Get<INativeHelper>();
if (nativeHelper != null)
{
nativeHelper.CloseApp();
}
return base.OnBackButtonPressed();
}
I didn't made implementation for WinPhone, but it should be similar.
You can use a DepedencyService for closing an app when your physical back button is pressed:
In your UI (PCL), do the following:
protected override bool OnBackButtonPressed()
{
if (Device.OS == TargetPlatform.Android)
DependencyService.Get<IAndroidMethods>().CloseApp();
return base.OnBackButtonPressed();
}
Now implement the Android-specific logic in your Android project:
[assembly: Xamarin.Forms.Dependency(typeof(AndroidMethods))]
namespace Your.Namespace
{
public class AndroidMethods : IAndroidMethods
{
public void CloseApp()
{
Android.OS.Process.KillProcess(Android.OS.Process.MyPid());
}
}
}
Also create an Interface (in your UI PCL):
public interface IAndroidMethods
{
void CloseApp();
}
As far as I know there is no native way to exit the app in Xamarin application.
The only way is to use dependency service. Override OnBackButtonPressed function in your ContentPage and check it is the last page:
protected override bool OnBackButtonPressed()
{
if(navigation.NavigationStack.Count == 1)//navigation is MainPage.Navigation
DependencyService.Get<YourDependencyInterface>().CloseApp();
}
For Android in YourAndroidDependency class:
public void CloseApp()
{
(Xamarin.Forms.Forms.Context as Activity).Finish();
}
As for WinPhone I'm not sure but I believe it can be done in same way - dependency service.
Having experimented with all the above, I found that none of the above worked on a Google Pixel 3a, with latest version of Android
The command that came closest was
Android.OS.Process.KillProcess(Android.OS.Process.MyPid());
However it left the remains of the app still visible in the background.
The following worked for me when called from the Android Main Activity
public void ExitApp()
{
this.FinishAndRemoveTask();
Android.OS.Process.KillProcess(Android.OS.Process.MyPid());
}
The first line FinishAndRemoveTask removes the app from both the foreground and the background, however the Application process is still active, hence the need for the second command.
This is the more easy way found:
public void QuitApp(object sender, EventArgs args)
{
Process.GetCurrentProcess().CloseMainWindow();
Process.GetCurrentProcess().Close();
}
PS: Tested in android
You can use Environment.Exit(0);

Custom Webview renderer in Xamarin for Windows RT not working

I'm writing Webview renderer in Xamarin for Windows Desktop project by following guide in Xamarin HybridWebView
[assembly: ExportRenderer(typeof(Xamarin.Forms.WebView), typeof(ProApp.Windows.Helpers.CustomWebViewRenderer))]
namespace ProApp.Windows.Helpers
{
public class CustomWebViewRenderer : ViewRenderer<Xamarin.Forms.WebView, global::Windows.UI.Xaml.Controls.WebView>
{
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.WebView> e)
{ //Debug Point
base.OnElementChanged(e);
if (this.Control == null)
{
}
}
}
}
I've similarly defined WebView Renderer in Android also. I'm running a Xamarin.Form Content page with WebView. The android WebView renderer is getting executed/debug but I'm not getting any debugger for Windows and code in Xamarin.Forms is running.
I also tried to add var t = new Windows.Helpers.CustomWebViewRenderer(); in App.xaml.cs to avoid any non-inclusion after build (to have some reference to class), but didn't work. Is there anything I'm missing?
The easier way to do it is to let the XF framework implement its webview code. Inherit from WebViewRenderer instead.
[assembly: ExportRenderer(typeof(WebView), typeof(CustomWebViewRenderer))]
namespace Mobile.WinRT.Renderers
{
public class CustomWebViewRenderer: WebViewRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
{
base.OnElementChanged(e);
if (Control != null)
{
}
}
}
}
Also I recommend just creating a simple control in your XF project called something like CustomWebView that just inherits from WebView. Then you can render for this instead of every possible WebView in the app.

GWT Window.confirm() triggered by onchange of ValueListBox crashing Safari on iPad iOS 7.0.6

I recently received a support ticket that some of our web app's functionality is crashing safari on the iPad. This functionality had no problems prior to the latest iOS 7.0.6 update. We have a few GWT ValueListBoxes that change the DOM when their values are changed. Prior to making the changes, we present the user with a Window.confirm() message to inform them of the effects the changes will have and ask whether or not they would still like to proceed. Since the update, the confirm choices do nothing and Safari crashes. This is only happening on the iPad. The functionality works fine on the desktop browsers (IE, Chrome, Firefox, Safari and the Chrome mobile emulator), but crashes safari on the iPad. Is anyone else having this issue?
Here's a screenshot of the crash:
And here's a sample of the code:
this._view.isPrimaryFoodGen().addValueChangeHandler(new ValueChangeHandler<Boolean>()
{
#Override
public void onValueChange(final ValueChangeEvent<Boolean> event)
{
#SuppressWarnings("unchecked")
ValueListBoxWithOldValue<Boolean> vlb = (ValueListBoxWithOldValue<Boolean>)event.getSource();
if (confirmQuestionChange() ){
changeGroupAndQuestions(CONSTANTS.PRIMARY_FOOD, event.getValue());
}
else {
vlb.setValue(vlb.getOldValue());
}
}
});
public boolean confirmQuestionChange()
{
if (!this._view.isImageCriteriaQuestionsVisible())
{ //questions aren't currently visible
return true;
}
boolean confirmed = Window.confirm("Changing this response will delete image data already collected. Do you wish to proceed?");
return confirmed;
}
Any help on a solution for preventing the crash on the iPad would be greatly appreciated. I have tried focusing on another element prior to calling Window.confirm() in hopes that the overlay and the ValueListBox choices would be removed to stop any JS conflicts, but it hasn't worked.
Am I at the mercy of Apple until the next update fixes this?
Or is there a viable solution?
OK, so it turns out that since I couldn't find a fix to continue using Window.confirm(), I had to implement a solution by changing the onValueChange() and confirmQuestionChange() methods to use a manually created DialogBox instead of Window.confirm(). It isn't the optimal solution, but Safari does not crash on the iPad anymore and users can get their work done. Here are the code changes:
this._view.isPrimaryFoodGen().addValueChangeHandler(new ValueChangeHandler<Boolean>()
{
#Override
public void onValueChange(final ValueChangeEvent<Boolean> event)
{
confirmQuestionChange(CONSTANTS.PRIMARY_FOOD, event);
}
});
public void confirmQuestionChange(final String question, ValueChangeEvent<Boolean> event)
{
final ValueListBoxWithOldValue<Boolean> vlb = (ValueListBoxWithOldValue<Boolean>)event.getSource();
if (!this._view.isImageCriteriaQuestionsVisible()) //questions aren't currently visible, can change them no problem
{
changeGroupAndQuestions(question, vlb.getValue());
}
else{
//the following fix was put in place for issues with Safari on the iPad OPS-76
final DialogBox dialogBox = new DialogBox();
dialogBox.setHTML("<center>Changing this response will delete<br />image data already collected.<br />Do you wish to proceed?</center>");
dialogBox.setAnimationEnabled(true);
Button yesButton = new Button("YES");
Button noButton = new Button("NO");
HorizontalPanel dialogHPanel = new HorizontalPanel();
dialogHPanel.setWidth("100%");
dialogHPanel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
dialogHPanel.add(noButton);
dialogHPanel.add(yesButton);
noButton.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
vlb.setValue(vlb.getOldValue());
dialogBox.hide();
}
});
yesButton.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
changeGroupAndQuestions(question, vlb.getValue());
dialogBox.hide();
}
});
// Set the contents of the Widget
dialogBox.setWidget(dialogHPanel);
dialogBox.setPopupPosition(180, 425);
dialogBox.show();
}
}
Here's a screenshot:
As you can see, the ValueListBox options close before the DialogBox appears and the screen no longer locks.

Loading screen inside handleNavigationRequest in Browserfield Blackberry

Inside my application, I'm displaying a website using BrowserField. And when each link inside the site is selected, I need to show loading screen so that the user won't feel blank.
I was able to add the loading screen inside this method
public void documentCreated(BrowserField browserField,
ScriptEngine scriptEngine, Document document)
But the problem is only when connection is established, this method will be called and so there will be a delay before the loading screen is displayed.
So I tried implementing the ProtocolController and adding the loading screen inside this method
public void handleNavigationRequest(BrowserFieldRequest request)
But still, the loading screen is displayed after a small delay (same as when it was under documentCreated method)
This is my code snippet
public void handleNavigationRequest(BrowserFieldRequest request)
throws Exception {
if (!NetworkUtil.isNetworkAvailable()) {
Dialog.inform(Strings.NETWORK_ERROR);
} else {
UiApplication.getUiApplication().invokeAndWait(new Runnable() {
public void run() {
BaseScreen.showLoadingProgress(Strings.LOADING);
}
});
InputConnection ic = handleResourceRequest(request);
browserField.displayContent(ic, request.getURL());
}
}
I tried this outside the thread as well....Still the same is happening. For testing, I added a dialog inside this method and it was coming on the same time I'm clicking any link inside the site. Only this loading screen takes time to load.
Is there any way to make this happen ?
Also, the browser field is taking a bit longer to load the website compared to the native browser.
Am I missing something here ! Please help
I have tried the documentUnloading method as you suggested. But it is not getting triggered. Given below is the code snippet, could you please check what I'm doing wrong here...!!
protected void onUiEngineAttached(boolean attached) {
if (attached) {
BaseScreen.showLoadingProgress(Strings.LOADING);
}
super.onUiEngineAttached(attached);
}
try {
listener = new BrowserFieldListener() {
// Page starts loading...
public void documentCreated(BrowserField browserField,
ScriptEngine scriptEngine, Document document)
{
// show the loading screen
//showLoadingProgress(Strings.LOADING);
}
public void documentError(BrowserField browserField,
Document document) {
hideLoadingProgress();
Dialog.inform(Strings.NETWORK_ERROR);
}
public void documentAborted(BrowserField browserField,
Document document) {
hideLoadingProgress();
Dialog.inform(Strings.NETWORK_ERROR);
}
public void documentUnloading(BrowserField browserField,
Document document) {
BaseScreen.showLoadingProgress(Strings.LOADING);
}
// Page loaded
public void documentLoaded(BrowserField browserField,
Document document) {
// the document has loaded, hide loading popup ...
BaseScreen.hideLoadingProgress();
}
};
} catch (Exception ex) {
Dialog.inform(Strings.NETWORK_ERROR);
}
browserField.addListener(listener);
// add the browser field to a ui manager or screen
add(browserField);
// request the content
browserField.requestContent(URL);
I do this using the BrowserFieldListener (see BrowserFieldListener.html). It is slightly counter intuitive, but I display the loading screen in documentUnloading(), and remove it in documentLoaded(). When I first populate the BrowserField I also push the loading screen, and when the screen with the BrowserField is closed, I make sure the loading screen is popped too. So not a pretty solution, but it works for me.
And yes, in general, the BrowserField is slower than the Browser. I have not found a way round it. However one significant aspect is caching. Look for information on creating your own cache for the BrowserField - there is Thread on here and a KB article on the BB Web site. Sorry can't find them atm, will update when I do.
Update
As found by the OP, the caching article is here.
Further Update
Just to clarify two things:
You must associate the Listener with the BrowserField, using the addListener method.
Assuming you do the usual requestContent() for the initial load of your BrowserField, you will need to push the loading screen yourself because the first method in listener that will be invoked (assuming it has worked of course), will be documentLoaded().
A sample demonstrating how to use the Listener is included here:
listener sample

Resources