I have a NativeScript 6.8 JavaScript app that uses WebView to display an html string composed within the app that references local image files. The Google Play Store is forcing me to support API 30, and when I do, the WebView fails with
net::ERR_ACCESS_DENIED(-1)
I found this post that suggests I modify some of the Android WebView's access settings, such that my code now looks like this
AndroidManifest.xml:
<application
...
android:usesCleartextTraffic="true">
xml:
<GridLayout>
<WebView id="annbyday" loadFinished="onLoadFinished" src="{{ htmlsrcForDay }}" />
</GridLayout>
js:
exports.onLoadFinished = function (args) {
if (args.object.android) {
if (!args.error) {
let webView = args.object.android;
webView.getSettings().setAllowFileAccess(true);
webView.getSettings().setAllowContentAccess(true);
console.log("announce-page.onLoadFinished: settings set");
} else {
console.warn("announce-page.onLoadFinished: " + args.error);
}
}
}
When I run this, I get these messages in the console:
JS: announce-page.onLoadFinished: settings set
JS: announce-page.onLoadFinished: net::ERR_ACCESS_DENIED(-1)
JS: announce-page.onLoadFinished: net::ERR_ACCESS_DENIED(-1)
JS: announce-page.onLoadFinished: settings set
On first navigation to the page the android error screens displayed. But, if I re-navigate to the page I get just the "settings set" messages and the html displays correctly.
It's as if the settings work, but they're not being set soon enough. Moving the code to the LoadStarted event has no effect.
I feel like I'm close; I welcome any help.
I moved the code to the page's loaded event handler, and now everything works as expected, and I don't use the WebView's loadStarted or LoadFinished events at all. The final code is,
exports.onLoaded = function (args) {
const page = args.object;
const webView = page.getViewById("<WebView id>");
if (webView.android) {
let setter = webView.android.getSettings();
setter.setAllowFileAccess(true);
setter.setAllowContentAccess(true);
}
Related
I'm using Xamarin Forms using a WebView to display content. To send commands from the webpage to the app, I'm using links with URLs like this:
myapp://command=123&someparam=456
this is then handled in the PCL project like this:
private async void CustomWebView_Navigating(object sender, WebNavigatingEventArgs e) {
if (e.Url.Contains("myapp://")) {
e.Cancel = true;
// Some app logic
}
...
This all worked well up until recently when Android phones began displaying an error page saying:
Webpage not available
ERR_Unknown_URL_Scheme
CustomWebView_Navigating is still being triggered, but how can I prevent the error page from showing?
Note: I have tried overriding ShouldOverrideUrlLoading and returning 'true' - but then CustomWebView_Navigating is no longer triggering in the PCL project.
I load a webpage via the inappbrowser plugin for my Phonegap app.
The app shows a website and a webshop which are both accessible from the web as well.
I cannot add a button 'go back to app' (this wouldn't make sense when visiting the site from PC). So I want a custom navigation (I prefer bootstrap) in the phonegap app so I can navigate between multiple different websites.
Unfortunately the navigation gets hidden by the inappbrowser. Is there a way to show the app html navigation on top of the inappbrowser?
Thanks a lot!
adding absolute position, z-index 999999 and display block with css didn't help
One way you do could this is inject the button into your webpage by generating it in your Cordova app Webview:
var inAppBrowserRef = cordova.InAppBrowser.open("http://www.mypage.com", "_blank");
inAppBrowserRef.addEventListener('loadstop', function(e) {
inAppBrowserRef.executeScript({
code: '\
var body = document.querySelector("body");\
var button = document.createElement("div");\
button.innerHTML = "Return to app";\
button.classList.add("close_button");\
button.onclick = function() {\
webkit.messageHandlers.cordova_iab.postMessage(JSON.stringify({action: "closeIAB"}));\
};\
body.appendChild(button);\
'
});
});
You'd then add a listener for the message that's posted when the button is click which closes the inappbrowser:
inAppBrowserRef.addEventListener("message", function (params){
if(params.data.action === "closeIAB"){
inAppBrowserRef.close();
}
});
You could also inject the styling of the button from within your Cordova app:
inAppBrowserRef.insertCSS({
"code": "\
.close_button {\
position: fixed;\
bottom: 0;\
z-index: 500;\
width: 100%;\
background: white;\
color: black;\
padding: 10px;\
font-size: 20px;\
}"
});
Or if you prefer, add the button styling to the CSS in your webpage (if it's under your control).
Similarly, if you don't like the idea of creating the button HTML dynamically, you could include it as part of your webpage but hide it by default unless a particular class is injected by the app:
inAppBrowserRef.addEventListener('loadstop', function(e) {
inAppBrowserRef.executeScript({
code: '\
var body = document.querySelector("body");\
body.classList.add("is_app");\
'
});
});
And in your website CSS:
body:not(.is_app) .close_button{
display: none;
}
Note that the emulation of the postMessage API that has been added to cordova-plugin-inappbrowser for Android & iOS by this PR is not yet in the latest release version on npm (v3.0.0) so you'll need to install the plugin directly off the Github master branch (v3.1.0-dev):
cordova plugin add https://github.com/apache/cordova-plugin-inappbrowser
I did this long time ago another way. The in app browser opened a website with a additional GET parameter, so the website knows it's opened inside the app. Then in the website I generated a special button, with href containing a custom scheme and some command. (E.g. myapp://close-browser)
Then I configured the app to capture the custom url by using regular app scheme configuration. Once I captured the command in javascript, I closed the in app browser using it's API.
I am having a setup, where I open a url in the plugin InAppBrowser with target '_blank'. The plugin Deeplinks is also installed and configured.
const browser: InAppBrowserObject = this.iab.create(url, '_blank', <InAppBrowserOptions>{
location: "no",
toolbar: "no",
footer: "no"
});
browser.on('loadstart').subscribe((event: InAppBrowserEvent) => {
console.log(event);
if (event.url.indexOf('wflwr://payment/success') > -1) {
browser.close();
}
if (event.url.indexOf('wflwr://payment/cancel') > -1) {
browser.close();
}
if (event.url.indexOf('wflwr://payment/error') > -1) {
browser.close();
}
});
I shortened it to show just the important parts. The url which is opened is https://www.voan.ch/wfl/ (it is just a Mock before the real implementation)
The expected behaviour is, that on a click on each of the links on the url, the browser instance inside the app should close. This works as intended on iOS, but not on Android. The event is just not triggered. If I change one of the urls to e.g. CANCEL, then the Event gets triggered.
the support for this was added in latest pr
to use it you will need 2 things:
for example to allow whatsapp custom scheme and twitter
add new config.xml preference with the custom schemes you want to support:
<preference name="AllowedSchemes" value="whatsapp,twitter" />`
add event listeners customscheme:
inAppBrowserRef.addEventListener('customscheme', function (event) {
//do whatever you want here like:
window.open(event.url, "_system");
});
I want to open page in Cordova WebView and add some styles. I have
function setSize() {
alert('Trying to load styles'); //works
app.insertCSS({code: 'body{width: 100% !important;height: 100% !important;background-color: red !important;}'}, function(){
alert('Styles are loaded!');
});
}
function onDeviceReady() {
var app= window.open('http://example.com','_self','location=no');
app.addEventListener('loadstart', setSize());
}
But it doesn't work. Is there any mistake ?
inAppBrowser is not a page from your application its a web page displays within browser of your app so to apply css into your browser elements you have to load CSS file into page of browser,
So here is an answer I have given in stack overflow before, which is working fine for that OP so try it, may be you will get success in what you wants to do.
TL;DR I need to change the URL of a WebView I previously created in alloy.js inside a new controller but the URL is not changing no matter what I do. How do I do this?
====================================
I've been having problems left and right with Titanium's webview... Require serious assistance ASAP.
I'm using Alloy. What I'm trying to do is to change the URL of a webview that I've previously created in alloy.js.
My alloy.js file first creates a webview:
Alloy.Globals.webview = Titanium.UI.createWebView();
Alloy.Globals.setUserAgent(); //function that just sets the user agent
Alloy.Globals.webview.url = "http://www.google.ca";
Then on index.js, I have a button where when clicked, it creates and opens a new controller (the controller that contains the webview:
var win = $.index;
...
button.addEventListener('click',function(e)
{
var theTest = Alloy.createController('web').getView();
theTest.open();
win.close();
});
On web.js, I add the WebView (from alloy.js) to a view:
$.view_webview.add(Alloy.Globals.webview);
Still on web.js, I have another view (acts as a button) where when I click on it, it tries to change the url of this the webview I made in alloy.js:
view_getpoints.addEventListener('click', function(e){
$.Alloy.Globals.webview.url = "http://www.youtube.com";
$.Alloy.Globals.webview.reload();
});
This did not work, the url did not change. It was still on google.
I also tried setUrl("http://youtube.com"); instead of just url, nothing.
I then figured it might be because I'm trying to change just the variable, where when I really should be directly changing the element object I added to my $.view_webview view. So I tried that:
view_getpoints.addEventListener('click', function(e){
$.view_webview.getChildren(0).url = "http://www.youtube.com";
}
Aw man, "url" is undefined? Maybe I'm getting the child wrong. Let's output $.view_webview.getChildren(0) and see what we get:
view_getpoints.addEventListener('click', function(e){
Ti.API.info("child: " + $.view_webview.getChildren(0));
}
I was expecting this to output "child: undefined" but no...it isn't undefined..It outputs: "child: [object WebView]".
Whoa whoa whoa, hold on back up. It knows it's a WebView object? But...shouldn't I be able to access the url and setUrl() fields from this object then as stated by the docs?
http://docs.appcelerator.com/titanium/3.0/#!/api/Titanium.UI.WebView-property-url
Why can't I change it directly?
I'm out of options.
TL;DR I need to change the URL of a WebView I previously created in alloy.js inside a new controller. How do I do this?