I'm developing an application for W10 Mobile (UWP) in Xamarin forms and I have implemented a WebView and I tried to get the URL of this but it is more complicated than I thought at first, I tried to get it through the source property, but not is possible, I would appreciate a help.
You could create an event handler to the navigation completed event.
With that you can check the URL
example:
WebView browser = new WebView();
browser.Navigated += OnNavigatedHandler;
public void OnNavigatedHandler (object sender, WebNavigatedEventArgs args){
Console.WriteLine ("Navigated to: " + args.Url);
}
I'm having trouble getting the URL of the browser in real time, the way you indicate I enter an infinite loop, I have a binding in my WebView on the SourceProperty in the view model called URL, when there is a change in the URL property I detect it thanks to PropertyChanged, the problem is that the event navigated only runs when updating the value of the URL property which causes the infinite loop to load the WebView infinitely. Is there any other way to get the URL?
I have uploaded in Pastebin the classes of the test project I am using:
View: pastebin.com/msyu9dJF
ViewModel: pastebin.com/LaCfC31c
BaseViewModel: pastebin.com/i6GCFbbe
Related
I'm working on a UWP app that hosts a WebView which runs in a separate process.
var webView = new Windows.UI.Xaml.Controls.WebView(WebViewExecutionMode.SeparateProcess)
This results in a behavior that if the WebView has the focus, the containing app can't regain the focus by itself by simply trying to focus on a UI element.
The app supports keyboard shortcuts which may result in different elements getting the focus, but it's not working correctly when the focus is captured by the WebView. The target element seems to be getting the focus but it seems as if the process itself is not activated (as the real focus resides in a different process I suppose...).
I'm currently trying to activate the app programmatically through protocol registration in an attempt to regain focus.
I added a declaration in the app manifest for a custom protocol mycustomprotocol coupled with the following activation overload
protected override void OnActivated(IActivatedEventArgs args)
{
if (eventArgs.Uri.Scheme == "mycustomprotocol")
{ }
}
And the following code to invoke the activation:
var result = await Windows.System.Launcher.LaunchUriAsync(new Uri("mycustomprotocol:"));
Seems to be working only on some computers, on others (not while debugging the app, only when executed unattached) instead of regaining focus the app's taskbar icon just flashes orange.
I've created a sample project showing the problem and the semi working solution here
Any insight on any of this would be great.
I can reproduce your issue. I found that when we switch the focus with the mouse, the focus can be transferred to the TextBlock. So you could solve this question through simulating mouse input.
Please use the following code to instead FocusTarget.Focus(FocusState.Programmatic).
As follows:
InputInjector inputInjector = InputInjector.TryCreate();
var infoDown = new InjectedInputMouseInfo();
// adjust your mouse position to the textbox through changing infoDown.DeltaX,infoDown.DeltaY
infoDown.DeltaX = 10; //change
infoDown.DeltaY = -150; //change
infoDown.MouseOptions = InjectedInputMouseOptions.LeftDown;
var infoUp = new InjectedInputMouseInfo();
infoUp.DeltaX = 0;
infoUp.DeltaY = 0;
infoUp.MouseOptions = InjectedInputMouseOptions.LeftUp;
inputInjector.InjectMouseInput(new[] { infoDown, infoUp });
Note: If you use the input injection APIs, you need to add inputInjectionBrokered Capabilitiy in your Package.appxmanifest.
But this Capabilitiy is a restricted Capabilitiy, you can’t publish this app in store, which can’t pass the verification.
I've been in discussions with a WebView software engineer. The problem is that the separate process still wants to own focus if you try to move the focus away from the webview. His solution is to ask the other process' web engine to give up focus with the following call:
_= webView.InvokeScriptAsync("eval", new string[] { "window.departFocus('up', { originLeft: 0, originTop: 0, originWidth: 0, originHeight: 0 });" });
You can call it before trying to change the focus to your target. I ran various tests and it works consistently.
I have an app that is using a webview to launch an html that loads JWP7 and throws an error Uncaught TypeError :cannot read property 'jwplayer.volume' of null
The same page is loading perfectly on mobile and desktop browsers.
I tried to add in the javascript of the html after the jwplayer.js is being called and before the setup, the following code:
if (typeof jwplayer.volume == "undefined" || typeof jwplayer.volume == null )
jwplayer.volume = 10;
I do see the new volume property using a desktop/mobile browser but it doesn't changes the TypeError in the webview, probably because the TypeError is thrown while running the jwplayer.js script, before it reaches my javascript check.
When i'm Using the JWP6 everything is working perfectly.
Any suggestions on how to fix it?
I inspected the jwplayer.js code.
And saw that it reads the last settings of Volume (jwplayer.volume) and Mute (jwplayer.mute) from the LocalStorage; instead of from cookie.
(Probably JWPlayer 6 was using cookies.)
So, you need to enable LocalStorage access in your WebView; like you do for JavaScript.
Sample code below.
WebView webView = (WebView) findViewById(R.id.webview);
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setDomStorageEnabled(true); // This will allow access
webView.setWebViewClient(new WebViewClient());
/* WebView.setWebContentsDebuggingEnabled(true); // This is to inspect your WebView from desktop Chrome. (>= API 19) You may not want to include this in production. */
webView.loadUrl(url);
JW Player doesn't support using the web player in Android or iOS webview; however, there are native mobile SDKs available to support in-app video: developer.jwplayer.com/android-sdk
Is it possible to return values from Webview in bb 10??
Example: If I load a Webview for online banking in my app and is there a way to get some data (like reference number of the payment) returning from the Webview to the app
At first you have to add a javascript in the html file that return document.documentElement.innerHTML;
After completely loading the webview call evaluateJavaScript (const QString &script, bb::cascades::JavaScriptWorld::Typeworld world) function, this will evaluate the javascript in the webview.
Lastly you should catch the sigal "javaScriptResult" from this signal you can get all the source of html file as qvariant.
For security sake, you cannot access the html content of the webview, except if you have set it yourself as a string.
You can access a redirection url, but without the Post parameter.
I have started developing html applications for mutliple platforms. I recently heard about Cordova 2.0(PhoneGap) and ever since I have been curious to know how the bridge works.
After lot of code walking, i saw that the Exec.js is the code where call from JS -> Native happens
execXhr = execXhr || new XMLHttpRequest();
// Changeing this to a GET will make the XHR reach the URIProtocol on 4.2.
// For some reason it still doesn't work though...
execXhr.open('HEAD', "file:///!gap_exec", true);
execXhr.setRequestHeader('vc', cordova.iOSVCAddr);
if (shouldBundleCommandJson()) {
execXhr.setRequestHeader('cmds', nativecomm());
}
execXhr.send(null);
} else {
execIframe = execIframe || createExecIframe();
execIframe.src = "gap://ready";
But want to understand how that works, what is the concept here, what does file:///!gap_exec or gap://ready do? and how does the call propgate to the lower layers (native code layers)
thanks a bunch in advance.
The trick is easy:
There is a webview. This displays your app. The webview will handle all navigation events.
If the browser navigates to:
file:///!gap_exec
or
gap://
the webview will cancel the navigation. Everything behind these strings is re-used as an identifier, to get the concrete plugin/plugin-method and parameter:
pseudo-url example:
gap://echoplugin/echothistext?Hello World
This will cause phonegap to look for an echoplugin and call the echothistext method to send the text "Hello World" to the (native) plugin.
update
The way back from native to javascript is (or may be) loading a javascript: url into the webview.
The concrete implementation is a little bit more complex, because the javascript has to send a callback-id to native code. There could be more than one native call are running at the same time. But in fact this is no magic at all. Just a number to get the correct JSON to the right javascript-callback.
There are different ways to communicate between the platform and javascript. For Android there are three or four different bridges.
I am trying to figure this out in more detail, too. Basically there are 2 Methods on the iOS side that can help ...
- webView:shouldStartLoadWithRequest:navigationType: and
- stringByEvaluatingJavaScriptFromString:script
From the sources it seems cordova sends a "READY" message using webView:shouldStartLoadWithRequest:... and then picks up results with the second message, but I am not sure.
Cordova Sources iOSExec
There is much to learn there.
Here's the issue:
I have a hook in IE that reacts on WebBrowser.OnNavigateComplete2 event to parse the content of the document for some precise info.
That document contains frames, so I look into the HTMLDocument.frames. For each one, I look into the document.body.outerHTML property to check for the content.
Problem is, the string I'm looking for never shows there, whereas it is displayed in the finale page. So, am I looking in the wrong place? If it is displayed when the page is fully loaded, then it's downloaded at some point, right? But in which object should I look ?
BTW, I Don't know if that is of any importance, but the page I'm searching into comes from a ASP.NET application.
public void OnNavigateComplete2(object pDisp, ref object url)
{
document = (HTMLDocument)webBrowser.Document;
mshtml.FramesCollection frames = document.frames;
for (int i = 0; i < frames.length; i++)
{
object refIdx = i;
IHTMLWindow2 frame = (IHTMLWindow2)frames.item(ref refIdx);
string frameContent = frame.document.body.outerHTML;
}
}
Thank your for your help.
#rams
This event is launched many times for each page, so I figured it was each time a framed is loaded, even if i don't get to catch the one I'm looking for. If not, what would be the event to catch the frames content?
What I want to do is detect some precise info on a precise frame, then save it. later, a web page is loaded triggered by some user action, where I need the info I got from parsing the frame.
Do you know the name/id of the frame you are looking for content? If so, in your navigateComplete2 event, can you get a reference to the frame like
iFrame frm = document.frames(<your frame id>);
int readyState=0;
while(frm.readystate !=4){
// do nothing. be careful to not create an endless loop
}
if(frm.readyState==4){
// get your content now
}
HTH
Are you using some kind of threading? Running the browser in a separate thread really messes up things. Try to execute it in an STAThread and check if you get the correct result.
The reason your string does not show is because of the frame. The web browser control fires the document navigate complete event after it has loaded the main document. At this point, the frames haven't yet requested their sources. After the document is parsed by the web browser control, requests for the frame sources are issues and downloaded.
Can you please describe what you are trying to accomplish?