Ionic InAppBrowser on Android doesn't navigate to custom Url Scheme - android

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");
});

Related

Nativescript WebView on Android API 30 yields ERR_ACCESS_DENIED

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);
}

Ionic angular: opening links in (external) mobile browser

I do not want links to open inside my Ionic app, so I'm trying to get the links to open in the mobile browser.
The first example here is working fine. When the URL is inside of the "window.open" command, then the external browser is launched as expected.
<p class="descriptive-class">
<a ng-href="" onclick="window.open('https://stackoverflow.com', '_system', 'location=yes')">
<img src="assets/img/awesome_picture.png" alt="blablabla">
</a>
</p>
The problem lays with this part, where I want to feed a parameter for the URL to the code. I cannot set it directly inside "window.open()", so I have to move it to 'ng-href' and then refer to it via 'this.href'.
Android does not seem to understand this correctly. It shows me the "Complete action using" dialog on Android, and then presents HTML document handler applications. It does not understand the browser link.
How can this be corrected best?
<p class="descriptive-class">
<a href="#" ng-href="item.webURL" onclick="window.open(this.href, '_system', 'location=yes')">
{{ item.webURL }}
</a>
</p>
In this case, the easiest way is to install the In App Browser plugin.
It opens an URL with the installed browser of the device. First add and install the plugin:
*$ ionic cordova plugin add cordova-plugin-inappbrowser*
*$ npm install --save #ionic-native/in-app-browser*
Add it to your app.module.ts
import { InAppBrowser } from '#ionic-native/in-app-browser';
And add it to your providers:
#NgModule({
...
providers: [
...
InAppBrowser
...
]
...
})
Then add on the relevant page:
constructor(private iab: InAppBrowser) { }
openBrowser(){
this.iab.create('https://ionicframework.com/');
}
Call openBrowser() in your (click) method and you're set!
See also: https://ionicframework.com/docs/native/in-app-browser/
As of Feb 2020, this is what works in Ionic 4 & Ionic 5:
1) Install In App Browser plugin. Don't worry, it will open the links externally as you want it. Run the following commands in your project root:
ionic cordova plugin add cordova-plugin-inappbrowser
npm install #ionic-native/in-app-browser
2) In app.module.ts file, add the following code:
Add the import as shown below:
import { InAppBrowser } from '#ionic-native/in-app-browser/ngx';
Add support for InAppBrowser by adding it to the providers array as shown below:
providers: [
StatusBar,
SplashScreen,
InAppBrowser, // ---> Add it here
{provide: RouteReuseStrategy, useClass: IonicRouteStrategy}
],
3) In your desired component TS file or page TS file (example: support.page.ts), add the following code:
Add the import as shown below:
import { InAppBrowser } from '#ionic-native/in-app-browser/ngx';
Add the code in constructor as shown below:
constructor(private iab: InAppBrowser) {}
Add a method that opens the link to your desired webpage as shown below:
openPage(){
this.iab.create('https://stackoverflow.com/'); // --> Change URL here
}
Add click event to your hyperlink as shown below:
{{ item.webURL }}
Result:
Now when you click on the Hyperlink, that should open your desired URL.
NOTE:
If you do not want to hardcode the URL and would rather want to open URLs dynamically, then you can use the following in your HTML page:
{{ item.webURL }}
Add the following in your TS file:
openAnyPage(url){
this.iab.create(url);
}
Result:
Now when you click on any Hyperlink, that should open your desired URL, without the need to hardcode them anywhere.
An update to #Gerben den Boer's answer:
You will run into errors like the following with the import as it is listed.
[ng] ERROR in src/app/components/app-component/app.module.ts(44,5): error TS2322: Type 'InAppBrowserOriginal' is not assignable to type 'Provider'.
[ng] Type 'InAppBrowserOriginal' is not assignable to type 'ClassProvider'.
[ng] Property 'provide' is missing in type 'InAppBrowserOriginal'.
To resolve this use the following import:
import { InAppBrowser } from '#ionic-native/in-app-browser/ngx';
See: https://github.com/ionic-team/ionic-native/issues/2899
Further to #Devner's excellent answer, for a 2021+ (Ionic5) release,
You should do all of the above, but 2 things needed to change for me.
I had multiple variables to pass to it, that suggestion didn't work, but I did overcome the problem with the following:
Open original article.
Also, please note the following that was left off, according to the Cordova Documentation...
A target should be included:
var ref = cordova.InAppBrowser.open(url, target, options);
ref: Reference to the InAppBrowser window when the target is set to '_blank'. (InAppBrowser)
url: The URL to load (String). Call encodeURI() on this if the URL contains Unicode characters.
target: The target in which to load the URL, an optional parameter that defaults to _self. (String)
_system: Opens in the system's web browser.
Therefore, the following code brings it altogether:
openAnyPage(url, wp_id)
{
this.iab.create(url+"index.php?page_id="+wp_id, '_system');
}

Go to a specific page in ionic framework

Im stuck in a problem that i have to open a specific page in ionic framework using the controller.
I have to go to the following page
#/tab/hotel_details/1
when i click ok button in the ionic popup window
$scope.showAlert = function() {
var alertPopup = $ionicPopup.alert({
title: 'Click OK for further details',
});
alertPopup.then(function(res) {
//Go to a specific page
});
};
I cant use $state.go("tab.hotel_details"); , because i have to go to hotel_details/1
I have to get rid of the above problem for further development of my app.
You can pass the id in the second parameter of the call to $state.go :
$state.go("tab.hotel_details", { "id": id })
Then, in your controller, you can retrieve the value from $stateParams :
var id = Number($stateParams.id)
Reference: Angular-ui State
You can still use the $location service if you want to navigate to a particular url instead of navigating by a state.
$location.path('/tab/hotel_details/1');

Update one page with jQuery, in single html file

I've got a single html with 5 pages + navbar. To force a refresh of one page I use this:
$("#page3").on("pagecreate", function(e) {});
It works the first time, but I want it to update every time I visit the page. I know there is .trigger("create"), and "refresh", but I can't get it to work properly...
jQuery Mobile 1.4.0
You need to listen to pageContainer event in order to determine which page is active and accordingly run the functions you want.
The new events can't be attached to a specific page, unlike successor versions of jQuery Mobile. Once an event is occurred, retrieve ActivePage's ID.
$(document).on("pagecontainerbeforeshow", function (e, ui) {
var activePage = $.mobile.pageContainer.pagecontainer("getActivePage")[0].id;
if(activePage == "page3") {
doSomething();
}
});
Demo

Handle Android Back Button on Phonegap InAppBrowser

I would like to disable or override the Android Back button while I am navigating pages on the InAppBrowser. Can I add an event listener that can handle that?
EDIT:
Looking at the answer by #T_D below the solutions provided are the closest I could get to. It does not seem to be possible to override the button in InAppBrowser as all the PhoneGap tweaks stop working while navigating pages on this plugin. I was not able to find any other solution rather than modifying the API library. If there are any PhoneGap guys here and know something more, I 'll be glad to get some comment. Thanks.
The closest I got:
var ref = window.open('http://apache.org', '_blank', 'location=yes');
ref.addEventListener("backbutton", function () { })
According to the documentation the behaviour of the hardware back button can be configured now for the InAppBrowser:
hardwareback: set to yes to use the hardware back button to navigate backwards through the InAppBrowser's history. If there is no previous page, the InAppBrowser will close. The default value is yes, so you must set it to no if you want the back button to simply close the InAppBrowser.
Thanks to Kris Erickson.
So just update your InAppBrowser plugin if the backward navigation is the desired behaviour.
For more details see: https://github.com/apache/cordova-plugin-inappbrowser/pull/86
You can do it quite easily now (as of InAppBrowser version 0.3.3), but you will have to edit the Java files. Go to src/com/org/apache/corodova/inappbrowser directory and edit the InAppBrowserDialog.java:
Change
public void onBackPressed () {
if (this.inAppBrowser == null) {
this.dismiss();
} else {
// better to go through the in inAppBrowser
// because it does a clean up
this.inAppBrowser.closeDialog();
}
}
to
public void onBackPressed () {
if (this.inAppBrowser == null) {
this.dismiss();
} else {
if (this.inAppBrowser.canGoBack()) {
this.inAppBrowser.goBack();
} else {
this.inAppBrowser.closeDialog();
}
}
}
Then go to InAppBrowser and find the goBack function, change:
/**
* Checks to see if it is possible to go back one page in history, then does so.
*/
private void goBack() {
if (this.inAppWebView.canGoBack()) {
this.inAppWebView.goBack();
}
}
to
/**
* Checks to see if it is possible to go back one page in history, then does so.
*/
public void goBack() {
if (this.inAppWebView.canGoBack()) {
this.inAppWebView.goBack();
}
}
public boolean canGoBack() {
return this.inAppWebView.canGoBack();
}
And now the hardware back button will go back until there are no more backs to do. I really think this should be the default behavior in android since the Done button already closes the InAppBrowser window.
This worked for me in PhoneGap 2.7, help came from here, How do I disable Android Back button on one page and change to exit button on every other page
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
document.addEventListener("backbutton", function (e) {
e.preventDefault();
}, false );
}
I was having this same issue and finally got it to work, I'll post the answer here in case it helps someone.
This is the code I use:
window.new_window = window.open(url, '_blank', 'location=no');
window.new_window.addEventListener("exit", function () {
window.new_window.close();
});
So the key basically is to attach the exit event, which gets called when the back button of the device is tapped.
BTW, I used cordova.js, and build my apps locally using the Cordova CLI, I don't know if that makes any difference, I mention it just in case.
EDIT NOTE: As far as I know, it's not possible to override the back-button for the InAppBrowser in PhoneGap. But I did my best searching for possible solutions...
There's an eventListener to override back-button in PhoneGap -doesn't work for InAppBrowser-
function onDeviceReady(){
document.addEventListener("backbutton", onBackKeyDown, false);
}
Alternative eventListener to override back-button -the OP said this didn't work either-
var ref = window.open('http://www.stackoverflow.com', '_blank', 'location=yes');
ref.addEventListener("backbutton", function () {
//logic here
})
Overriding the Back-button in an Activity -this is plain java, obviously didn't work in PhoneGap-
#Override
public void onBackPressed()
{
//logic here
}
Conclusion:
Above solutions didn't work, following links (this answer, this one and a third one) didn't help either. So it's highly possible that overriding the back-button for the InAppBrowser in PhoneGap is not possible. If someone does come up with a solution or if things changed for a new PhoneGap version feel free to let us know...
EDIT:
Installing this plugin may take you to closest solution:
cordova plugin add org.apache.cordova.inappbrowse
What this plugin will do, in WP8, it will overlay back/forward/close button on InAppBrowser whenever you open any link/page in it.
See this image:
Use jQuery mobile:
$(document).on('backbutton',
function(e){
e.preventDefault();
// YOUR CODE GOES HERE
});
Running Cordova 5.1.1 and when i load pages in the inappbroswer i like having the back button work until the inappbrowser exits back to my index.html page because it's blank and just sits there. So i used the following code to fix this. It exits the app when it exits the inappbrowser.
window.open = cordova.InAppBrowser.open;
var ref = window.open(url, '_blank', 'location=no');
ref.addEventListener('exit', function () {
navigator.app.exitApp();
});
As far as I know it's not possible to override or detect the back button from inAppBrowser. When you press the back button, inAppBrowser will hide and return control to the Phonegap page. You can catch this with the focus event on the window, (using jQuery) like
var browser = window.open('http://example.com', '_blank', 'location=no');
$(window).on('focus', function() {
browser.show();
});
to reopen the browser. You could then use browser.executeScript() to signal the webapp loaded in the browser, if you like.
Inspired by this forum post.
I know this question has an answer already but I post my answer for those who any of these answers didn't work for them(such as myself):
so I have a multi page app for android and IOS and I am using cordova 5.x and I added the code below in every page except the page I needed InAppBrowser:
delete window.open;
and then for the rest of the pages I used:
document.addEventListener("backbutton", onBackKeyDown, false);
function onBackKeyDown(event) {
// your code for handling back button comes here
}
for handling back button
note that: delete window.open; base on the documentation
manually restore the default behaviour of 'window.open'
after that InAppBrowser plugin worked great and I handled back button in all pages correctly.
one last thing don't forget to add:<script type="text/javascript" charset="utf-8" src="cordova.js"></script> in pages you need to have InAppBrowser.
hope this help.

Categories

Resources