iOS Xamarin WKWebView Not Showing Popups - xamarin.ios

I've been trying to show this KYC webpage on WKWebView by calling the below method:
private void KYCLink(string obj)
{
WKWebView webView = new WKWebView(new CGRect(0, 0, this.MainWebView.Frame.Width,
this.MainWebView.Frame.Height), new WKWebViewConfiguration());
webView.ContentMode = UIViewContentMode.ScaleToFill;
webView.NavigationDelegate = new WK_KYCWebViewDelegate();
webView.ScrollView.Bounces = false;
NSUrl Link = new NSUrl(new System.Uri(obj).AbsoluteUri);
webView.LoadRequest(new NSUrlRequest(Link));
this.MainWebView.AddSubview(webView);
}
public class WK_KYCWebViewDelegate : WKNavigationDelegate
{
//empty
}
which doesn't shows popup to access FaceID camera, where as if i open the link in Safari browser it shows the popup (Am not familiar with swift).
Would really appreciate some help.
Thanks All.

Related

Downloads with JavaFX WebView

my web application offers a download. Javascript creats at the click the url (it depends on the user input) and the browser should open it, so that the page isn't reloaded.
For that, I think I have to alternatives:
// Alt1:
window.open(pathToFile);
// Alt2:
var downloadFrame = document.getElementById('downloads');
if (downloadFrame === null) {
downloadFrame = document.createElement('iframe');
downloadFrame.id = 'downloads';
downloadFrame.style.display = 'none';
document.body.appendChild(downloadFrame);
}
downloadFrame.src = pathToFile;
Both works under Firefox. Problem with open new window method: If the creation of the file at the server needs more time, the new empty tab will be closed late.
Problem with iframe: If there is an error at the server, no feedback is given.
I think at firefox the iframe is the better solution. But the web application must run with an JavaFX WebView, too. JavaFX haven't a download feature, I have to write it. One possible way is to listen on the location property:
final WebView webView = new WebView();
webView.getEngine().locationProperty().addListener(new ChangeListener<String>() {
#Override public void changed(ObservableValue<? extends String> observableValue, String oldLoc, String newLoc) {
if (newLoc.cotains("/download")) {
FileChooser chooser = new FileChooser();
chooser.setTitle("Save " + newLoc);
File saveFile = chooser.showSaveDialog(webView.getEngine().getScene().getWindow());
if (saveFile != null) {
BufferedInputStream is = null;
BufferedOutputStream os = null;
try {
is = new BufferedInputStream(new URL(newLoc).openStream());
os = new BufferedOutputStream(new FileOutputStream(saveFile));
while ((readBytes = is.read()) != -1) {
os.write(b);
}
} finally {
try { if (is != null) is.close(); } catch (IOException e) {}
try { if (os != null) os.close(); } catch (IOException e) {}
}
}
}
}
}
There are some problems:
The download start depends on a part of the url, because JafaFX supports no access to the http headers (that is bearable)
If the user starts the download with the same url two times, only the first download works (the change event only fires, if the url is new). I can crate unique urls (with #1, #2 and so on at the end). But this is ugly.
Only the "window.open(pathToFile);" method works. Loading an iframe don't fire the change location event of the website. That is expectable but I haven't found the right Listener.
Can someone help me to solve 2. or 3.?
Thank you!
PS: Sorry for my bad english.
edit:
For 2. I found a way. I don't know if it is a good one, if it is performant, if the new webview is deleted or is in the cache after download, ....
And the user don't get an feedback, when some a problem is raised:
webView.getEngine().setCreatePopupHandler(new Callback<PopupFeatures, WebEngine>() {
#Override public WebEngine call(PopupFeatures config) {
final WebView downloader = new WebView();
downloader.getEngine().locationProperty().addListener(/* The Listener from above */);
return downloader.getEngine();
}
}
I think you may just need to use copyURLtoFile to get the file...call that when the location changes or just call that using a registered java class. Something like this:
org.apache.commons.io.FileUtils.copyURLToFile(new URL(newLoc), new File(System.getProperty("user.home")+filename));
Using copyURLToFile the current page doesn't have to serve the file. I think registering the class is probably the easiest way to go... something like this:
PHP Code:
Download $filename
Java (in-line class in your javafx class/window... in this case my javafx window is inside of a jframe):
public class JavaApp {
JFrame cloudFrameREF;
JavaApp(JFrame cloudFrameREF)
{
this.cloudFrameREF = cloudFrameREF;
}
public void getfile(String filename) {
String newLoc = "http://your_web_site.com/send_file.php?filename=" + filename;
org.apache.commons.io.FileUtils.copyURLToFile(new URL(newLoc), new File(System.getProperty("user.home")+filename));
}
}
This part would go in the main javafx class:
Platform.runLater(new Runnable() {
#Override
public void run() {
browser2 = new WebView();
webEngine = browser2.getEngine();
appREF = new JavaApp(cloudFrame);
webEngine.getLoadWorker().stateProperty().addListener(
new ChangeListener<State>() {
#Override public void changed(ObservableValue ov, State oldState, State newState) {
if (newState == Worker.State.SUCCEEDED) {
JSObject win
= (JSObject) webEngine.executeScript("window");
// this next line registers the JavaApp class with the page... you can then call it from javascript using "app.method_name".
win.setMember("app", appREF);
}
}
});
You may not need the frame reference... I was hacking some of my own code to test this out and the ref was useful for other things...

Codenameone Webbrowser issue

I am trying to display a webpage from codenameone application. It works fine in Iphone but not in andriod mobile.
public void showLoginForm()
{
final Form loginForm = new Form("Login");
loginForm.setUIID("Form1");
loginForm.setLayout(new BorderLayout());
loginForm.setScrollable(false);
try
{
WebBrowser browser = new WebBrowser()
{
//Overrides onStart and onLoad methods to load progress bars for page transitions.
};
browser.setURL(appsGlobalSettings.get(URL_KEY));
loginForm.addComponent(BorderLayout.CENTER,browser);
loginForm.show();
}
catch(Exception e)
{
e.printStackTrace();
}
}
Check your URL. I suggest removing the override code and placing Google.com hardcoded as a URL and proceeding from there. Since it doesn't work in the simulator either make sure you are using Java 7 with JavaFX enabled, with that case it should show a browser and should work for a proper web address.
Shai...It took some time to collect device logs.
But even that is intriguing.
I tried in two ways
No overridden methods in WebBrowser class and http://www.google.co.in as URL.
public void showLoginForm()
{
InfiniteProgress inf = new InfiniteProgress();
Dialog progress = inf.showInifiniteBlocking();
final Form loginForm = new Form("Login");
loginForm.setUIID("Form1");
loginForm.setLayout(new BorderLayout());
try
{
//Log.p("Inside showLoginForm method");
WebBrowser browser = new WebBrowser()
{
};
//browser.setURL(appsGlobalSettings.get(URL_KEY));
browser.setURL("http://www.google.co.in");
//Log.p("Set Broswer url");
loginForm.addComponent(BorderLayout.CENTER,browser);
//Log.sendLog();
loginForm.show();
}
catch(Exception e)
{
e.printStackTrace();
//Log.p(e.toString());
}
}
Result - the same blank screen.
Same code with added Log.p and Log.send() statements.
Result - it works fine
Is this due to some race condition?

Issue with Game Center on Monotouch

I'm trying to implement Game Center into my game but i have problems with it.
Here is my Main.cs code :
namespace iosgame
{
public class Application
{
[Register ("AppDelegate")]
public partial class AppDelegate : IOSApplication {
MainViewController mainViewController;
public AppDelegate(): base(new Game(new StaticsDatabase(),new StoreDatabase(),new InappPurchase(),new Social(),new MissionsDatabase()), getConfig()) {
}
internal static IOSApplicationConfiguration getConfig() {
IOSApplicationConfiguration config = new IOSApplicationConfiguration();
config.orientationLandscape = true;
config.orientationPortrait = false;
config.useAccelerometer = false;
config.useMonotouchOpenTK = true;
config.useObjectAL = true;
return config;
}
//
// This method is invoked when the application has loaded and is ready to run. In this
// method you should instantiate the window, load the UI into it and then make the window
// visible.
//
// You have 17 seconds to return from this method, or iOS will terminate your application.
//
public override bool FinishedLaunching (UIApplication app, NSDictionary options)
{
base.FinishedLaunching(app,options);
UIViewController controller = ((IOSApplication)Gdx.app).getUIViewController();
mainViewController = new MainViewController();
controller.View.Add(mainViewController.View);
return true;
}
private bool isGameCenterAPIAvailable()
{
return UIDevice.CurrentDevice.CheckSystemVersion (4, 1);
}
}
static void Main (string[] args)
{
UIApplication.Main (args, null, "AppDelegate");
}
}
}
And here is the superclass of that Main.cs : https://github.com/libgdx/libgdx/blob/master/backends/gdx-backend-iosmonotouch/src/com/badlogic/gdx/backends/ios/IOSApplication.java
I'm trying to use this https://github.com/xamarin/monotouch-samples/blob/master/GameCenterSample/GameCenterSample/MainViewController.cs example but i can't see any authenticate window in my game.I can see "Welcome back ,name" notification but after i log out from gamecenter app and reopen my game but i can't see any authentication window.
How can i fix it?
Thanks in advance
Just call this in FinishedLaunching:
if (!GKLocalPlayer.LocalPlayer.Authenticated) {
GKLocalPlayer.LocalPlayer.Authenticate (error => {
if (error != null)
Console.WriteLine("Error: " + error.LocalizedDescription);
});
}
This should display a Game Center "toast" saying "Welcome back, Player 1".
Here are some ideas if this doesn't work:
Make sure you have setup a new bundle id in the developer portal, and declare it in your Info.plist
Start filling out your app details in iTunes connect (Minimum is description, keywords, icon, 1 screenshot), and make sure to enable Game Center and add your new game to a group
Login with a test iTunes user in Game Center (create in ITC), or the login associated with your developer account
PS - I wouldn't worry about checking for iOS 4.1, just target iOS 5.0 and higher these days.

Playing YouTube video in iPhone only app - loss of controls

The code below is used to put a small WebView on a View so that the user can tap it and the video opens in full screen mode and plays. All that works, but after 4 seconds of play the controls disappear and will not reappear (tapping, rotating...). Once the video finishes, the controls reappear and the 'Done' button becomes available. However once the WebView is disposed of and a new view loaded, that new view is unresponsive for up to 6 minutes.
[Preserve (AllMembers=true)]
public class YouTubeViewer : UIWebView
{
public static AppDelegate appDelegate = (AppDelegate) UIApplication.SharedApplication.Delegate;
public YouTubeViewer(string url, RectangleF frame)
{
Log.WriteLog("loading YouTubeView");
appDelegate.firstViewing = true;
this.UserInteractionEnabled = true;
this.BackgroundColor = UIColor.Clear;
this.Frame = frame;
string youTubeVideoHTML = #"<object width=""{1}"" height=""{2}""><param name=""movie""
value=""{0}""></param><embed
src=""{0}"" type=""application/x-shockwave-flash""
width=""{1}"" height=""{2}""</embed></object>";
string html = string.Format(youTubeVideoHTML, url, frame.Size.Width, frame.Size.Height);
this.LoadHtmlString(html, null);
}
}
Here is how the WebView is disposed of:
public void RemoveWebView(UIWebView inView)
{
try
{
Log.WriteLog("RemoveWebView");
NSUrlCache.SharedCache.RemoveAllCachedResponses();
NSUrlCache.SharedCache.DiskCapacity = 0;
NSUrlCache.SharedCache.MemoryCapacity = 0;
inView.LoadHtmlString("",null);
inView.EvaluateJavascript("var body=document.getElementsByTagName('body')[0];body.style.backgroundColor=(body.style.backgroundColor=='')?'white':'';");
inView.EvaluateJavascript("document.open();document.close()");
inView.StopLoading();
inView.Delegate = null;
inView.RemoveFromSuperview();
inView.Dispose();
}
catch(Exception ex)
{
Log.LogError("RemoveWebView",ex);
}
}
Thanks,
Rick
I talked to Xamarin and they suggested removing the override for orientation management in the AppDelegate.
public override UIInterfaceOrientationMask GetSupportedInterfaceOrientations(UIApplication application, UIWindow forWindow)
{ /*... code ...*/ }
After I removed this override my application worked as expected when loading YouTube videos.
This resolved the issue for me. You can still control supported orientations via individual ViewController overrides and globally via the Info.plist file.
https://github.com/nishanil/YouTubePlayeriOS
Hope this sample helps you. It worked well for me.

Outlook add in , text box , delete\backspace not working

I developed an outlook add in (custom task pane), with web browser in the user control.
All the things working well beside the backspace or the delete button when I am writing something in text box in the web browser, I can't use those keys, am I missing something?
I am a few years late to the party but I managed to fix this. The easiest way to fix this is to ensure proper focus is given to the input fields, so you will need to be able to run your own javascript on whatever page is being loaded.
The javascript I run on the page is as follows (using jQuery):
$(document).on("click", function (e) {
// first let the add-in give focus to our CustomTaskPane
window.external.focus();
// then in our web browser give focus to whatever element was clicked on
$(e.target).focus();
});
the window.external variable contains code run from the plugin (c# or VB I assume) which is exposed so we can interact from web page back to the add-in.
In the add-in code for the custom taskpane set the context of window.external:
// event when webBrowser is finished loading document
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
// sets context of window.external to functions defined on this context
webBrowser1.ObjectForScripting = this;
}
And a public method for focusing:
// can be called by the web browser as window.external.focus()
public void focus()
{
this.Focus();
}
This worked for me, and I hope it helps others. Although do note that this probably doesn't work if the user keyboard navigates using tab, but you can either extend this code for that use case, or safely assume that the average outlook user will have his hand glued to the mouse.
Ok I solved the problem ,
The problem is that the custom task pane in not always gets fucos from the outlook.
So, I raised an event every time that there is "onclick" for all the pane, and then forced the pane to be in focus.
spent a lot of time trying to get this working in Outlook v16.0.13801.20288 the above did not work for me. I ended up with this working code.
Create a user control and add your webbrowser control to it then customize the .cs as below
private void CreateTaskPane() {
MyWinFormUserControl webBrowser = new MyWinFormUserControl();
webBrowser.webBrowser3.Url = new Uri("https://google.com");
webBrowser.webBrowser3.Width = 500;
webBrowser.webBrowser3.Dock = DockStyle.Fill;
webBrowser.webBrowser3.Visible = true;
webBrowser.Width = 500;
webBrowser.Dock = DockStyle.Fill;
webBrowser.Visible = true;
this.CRMTaskPaneControl = CustomTaskPanes.Add(webBrowser, "My App");
//Components.WebViewContainerWPFUserControl webView = (Components.WebViewContainerWPFUserControl)_eh.Child;
//webView.webview.Source = new Uri("https://localhost:3000");
this.CRMTaskPaneControl.Width = 500;
System.Windows.Forms.Application.DoEvents();
this.CRMTaskPaneControl.Control.Focus();
this.CRMTaskPane.Visible = true;
}
public partial class MyWinFormUserControl : UserControl
{
public WebBrowser webBrowser3;
public System.Windows.Forms.WebBrowser webBrowser1;
public MyWinFormUserControl()
{
InitializeComponent();
}
private void InitializeComponent()
{
this.webBrowser3 = new System.Windows.Forms.WebBrowser();
this.SuspendLayout();
//
// webBrowser3
//
this.webBrowser3.Dock = System.Windows.Forms.DockStyle.Fill;
this.webBrowser3.Location = new System.Drawing.Point(0, 0);
this.webBrowser3.MinimumSize = new System.Drawing.Size(20, 20);
this.webBrowser3.Name = "webBrowser3";
this.webBrowser3.Size = new System.Drawing.Size(500, 749);
this.webBrowser3.TabIndex = 0;
this.webBrowser3.DocumentCompleted += new System.Windows.Forms.WebBrowserDocumentCompletedEventHandler(this.webBrowser3_DocumentCompleted);
//
// MyWinFormUserControl
//
this.Controls.Add(this.webBrowser3);
this.Name = "MyWinFormUserControl";
this.Size = new System.Drawing.Size(500, 749);
this.Load += new System.EventHandler(this.MyWinFormUserControl_Load);
this.ResumeLayout(false);
}
void webBrowser3_DocumentCompleted(object sender, System.Windows.Forms.WebBrowserDocumentCompletedEventArgs e)
{
HtmlDocument doc;
doc = webBrowser3.Document;
doc.Click += doc_Click;
}
void doc_Click(object sender, HtmlElementEventArgs e)
{
this.Focus(); // force user control to have the focus
HtmlElement elem = webBrowser3.Document.GetElementFromPoint(e.ClientMousePosition);
elem.Focus(); // then let the clicked control to have focus
}
private void MyWinFormUserControl_Load(object sender, EventArgs e)
{
//Control loaded
}
Turns out this is an easy issue to fix.
Just write
class MyBrowser : WebBrowser {}
Then use MyBrowser instead of the .NET one.

Resources