Exit App develop using IONIC 3 from a specific page using Hardware Back Button - ionic-framework

I try to Exit app from a specific page(HometabsPage) using Hardware Back Button.
I use below code:
var lastTimeBackPress = 0;
var timePeriodToExit = 2000;
platform.registerBackButtonAction(() => {
let view = this.nav.getActive();
if (view.component.name == 'SignInPage' ) {
if (new Date().getTime() - lastTimeBackPress < timePeriodToExit) {
platform.exitApp(); //Exit from app
} else {
this.common.presentToast("Press back again to exit App?", "bottom");
lastTimeBackPress = new Date().getTime();
}
} else {
this.nav.pop({});
}
});
In my application there is two section SignIn and Hometabs. Above code work fine on the SignIn page.
if (view.component.name == 'SignInPage' )
But I try "HometabsPage" instead of "SignInPage" after that in all pages show the toast message.
Please help me.

#Neotrixs After login, set HomeTabsPage as your Root Page. It will prevent your app from going back to LoginPage.
For Hardware Back Button,I did it by Following methods:
/* REGISTERING BACK BUTTON TO HANDLE HARDWARE BUTTON CLICKED */
registerBackButton(){
let backButton = this.platform.registerBackButtonAction(() => {
var stackSize = this.nav.length();
if(stackSize < 1)
this.askForPressAgain();
else
this.nav.pop();
},1);
}
/*ASKING FOR PRESS BACK BUTTON AGAIN*/
askForPressAgain(){
let view = this.nav.getActive();
if (view.component.name == 'ProjectsPage' || view.component.name == 'LoginPage') {
if ((new Date().getTime() - this.lastTimeBackPress) < this.timePeriodToExit) {
this.platform.exitApp(); //Exit from app
} else {
this.toast.showBottomToast(BACK_BTN_MESSAGE);
this.lastTimeBackPress = new Date().getTime();
}
}
}
In the above code, at first I checked the Stack Size, if its less than 1, then showed the Toast for confirmation of leaving the app.
Hope it will help you or someone else.

Ionic latest version 3.xx
app.component.ts file:
import { Platform, Nav, Config, ToastController } from 'ionic-angular';
constructor(public toastCtrl: ToastController, public platform: Platform) {
platform.ready().then(() => {
//back button handle
//Registration of push in Android and Windows Phone
var lastTimeBackPress = 0;
var timePeriodToExit = 2000;
platform.registerBackButtonAction(() => {
// get current active page
let view = this.nav.getActive();
if (view.component.name == "TabsPage") {
//Double check to exit app
if (new Date().getTime() - lastTimeBackPress < timePeriodToExit) {
this.platform.exitApp(); //Exit from app
} else {
let toast = this.toastCtrl.create({
message: 'Press back again to exit App?',
duration: 3000,
position: 'bottom'
});
toast.present();
lastTimeBackPress = new Date().getTime();
}
} else {
// go to previous page
this.nav.pop({});
}
});
});
}

Related

platform.registerBackButtonAction() not working when build --prod

I am working on the project using ionic 3.
ionic cordova run android i use this command to run app.
in this operation platform.registerBackButtonAction() is working fine..
However, if I use the ionic cordova run android --prod option, platform.registerBackButtonAction () is not working.
any help is appreciated.
below is my code for handling hardware back button.
this.platform.registerBackButtonAction(() => {
let view = this.nav.getActive();
if(view.component.name == "NonetworkPage"){
if (!this.showedAlert) {
this.confirmExitApp();
} else {
this.showedAlert = false;
this.confirmAlert.dismiss();
}
}else{
if (view.component.name == "HomePage") {
if (!this.showedAlert) {
this.confirmExitApp();
} else {
this.showedAlert = false;
this.confirmAlert.dismiss();
}
} else if (view.component.name != "HomePage" && view.component.name != "LoginPage") {
if (this.nav.length() == 1) {
this.nav.setRoot(HomePage);
} else if (this.nav.length() > 1) {
this.nav.pop();
}
} else if (view.component.name == "LoginPage") {
this.confirmExitApp();
}
}
});
and below is for confirmation exit popup
confirmExitApp() {
this.showedAlert = true;
this.confirmAlert = this.alertCtrl.create({
title: "Exit App?",
message: "Are you sure you want to exit App?",
enableBackdropDismiss: true,
cssClass: 'confirmCustomCss',
buttons: [
{
text: 'No',
handler: () => {
this.showedAlert = false;
return;
}
},
{
text: 'Yes',
handler: () => {
this.platform.exitApp();
}
}
]
});
this.confirmAlert.present();
}
Because prod flag minify our code and also obfuscate page names but you can fix this problem by using this code may hope it will helps you and it will run on both build --prod and build
platform.registerBackButtonAction(() => {
let view = this.navCtrl.getActive();
let page = view ? this.navCtrl.getActive().instance : null;
if (page && (page instanceof Mypage)
Don't forget to import Mypage into app.component.ts
this.platform.registerBackButtonAction(() => {
let view = this.nav.getActive();
let currentRootPage = view.component;
if(currentRootPage == MyPage)
});
it works for me.
in ionic 3 this gives the name of current page:
const currentActivePage = this.nav.getActive().id;
And it can be compared by
if(currentActivePage == 'LoginPage')

Ionic push view over modal (need to login)

I have a mobile app where the user needs to re-login after some time for security reasons. The thing is that the content that was open in the background needs to stay there, and open after the login. So, even if it was a modal.
What is the best way to do this.
Pushing the login view when a modal is open doesn't help, since the view is put behind the modal.
Thanks in advance!
on the current page
public openLogin() {
let loginModal = this.modalController.create(LoginPage, { modal: true });
loginModal.present();
loginModal.onDidDismiss(data => {
if (data) {
this.profileData = data;
} else {
}
});
};
on loginPage
this.userService.login(username, password)
.subscribe(
data => {
console.log(data);
if (data.success) {
var user = data.result;
this.userService.setSession(user);
if (this.itsModal) {
this.closeModal(data)
}
else {
this.gotoHome();
}
} else {
// error handling
}
},
error => {
console.log(error);
}
);
public closeModal(data: any = null) {
this.viewController.dismiss(data);
}

How to detect whether the gps is enabled after switchToLocationSettings()?

I'm working out on the ionic project. I need to get the items based on current district. To get the current district I tried the below.
cordova.plugins.diagnostic.isLocationEnabled(function(enabled) {
alert("Location is " + (enabled ? "enabled" : "disabled"));
if(!enabled)
cordova.plugins.diagnostic.switchToLocationSettings();
var geocoder = new google.maps.Geocoder();
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(successFunction, errorFunction);
}
function successFunction(position) {
var lat = position.coords.latitude;
var lng = position.coords.longitude;
}
function errorFunction(){
$ionicPopup.alert({
title:"Alert",
content:"Geocoder failed"
});
}
function codeLatLng(lat, lng) {
geocoder.geocode({'latLng': new google.maps.LatLng(lat, lng)}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (results[1]) {
for (var i=0; i<results[0].address_components.length; i++) {
for (var b=0;b<results[0].address_components[i].types.length;b++) {
if (results[0].address_components[i].types[b] == "administrative_area_level_2") {
district= results[0].address_components[i];
}
}
}
alert(distrcit.long_name);
}
else {
alert("No results");
}
}
else {
alert("Geocoder Failed");
}
});
}
}, function(error) {
});
This code is working fine if the GPS is enabled after switching to location settings. I'm getting the problem when the GPS is not enabled and getting back into the app. How can I detect whether it is enabled or not after moving to location settings and getting back to the app? Even though I referred many posts in StackOverflow, I didn't get the solution what I needed actually. So please help me out in solving it.
How can I detect whether it is enabled or not after moving to location settings and getting back to the app?
You can detect when your app is returned to the foreground using the resume event.
function onResume() {
cordova.plugins.diagnostic.isLocationEnabled(function(enabled) {
console.log("Location is " + (enabled ? "enabled" : "disabled"));
// etc.
}, function(error) {});
}
document.addEventListener("resume", onResume, false);

ionic push notification when app is in foreground

I am making a ionic 3 app. I want notifications to appear even when app is in foreground. I have tried using FCM Plugin I'm getting notifications only when app is in background.
Home.ts
import { AngularFireDatabase } from 'angularfire2/database';
import { Component } from '#angular/core';
import { NavController } from 'ionic-angular';
import firebase from 'firebase';
declare var FCMPlugin;
#Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
firestore = firebase.database().ref('/pushtokens');
firemsg = firebase.database().ref('/messages');
constructor(public navCtrl: NavController,public afd:AngularFireDatabase) {
this.tokensetup().then((token)=>{
this.storeToken(token);
})
}
ionViewDidLoad() {
FCMPlugin.onNotification(function (data) {
if (data.wasTapped) {
//Notification was received on device tray and tapped by the user.
alert(JSON.stringify(data));
} else {
//Notification was received in foreground. Maybe the user needs to be notified.
alert(JSON.stringify(data));
}
});
FCMPlugin.onTokenRefresh(function (token) {
alert(token);
});
}
tokensetup(){
var promise = new Promise((resolve,reject)=>{
FCMPlugin.getToken(function(token){
resolve(token);
},(err)=>{
reject(err);
});
})
return promise;
}
storeToken(token){
this.afd.list(this.firestore).push({
uid: firebase.auth().currentUser.uid,
devtoken: token
}).then(()=>{
alert('Token stored')
}).catch(()=>{
alert('Token not stored');
})
// this.afd.list(this.firemsg).push({
// sendername:'adirzoari',
// message: 'hello for checking'
// }).then(()=>{
// alert('Message stored');
// }).catch(()=>{
// alert('message not stored');
// })
}
}
the function cloud for notifications
var functions = require('firebase-functions');
var admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
var wrotedata;
exports.Pushtrigger = functions.database.ref('/messages/{messageId}').onWrite((event) => {
wrotedata = event.data.val();
admin.database().ref('/pushtokens').orderByChild('uid').once('value').then((alltokens) => {
var rawtokens = alltokens.val();
var tokens = [];
processtokens(rawtokens).then((processedtokens) => {
for (var token of processedtokens) {
tokens.push(token.devtoken);
}
var payload = {
"notification":{
"title":"From" + wrotedata.sendername,
"body":"Msg" + wrotedata.message,
"sound":"default",
},
"data":{
"sendername":wrotedata.sendername,
"message":wrotedata.message
}
}
return admin.messaging().sendToDevice(tokens, payload).then((response) => {
console.log('Pushed notifications');
}).catch((err) => {
console.log(err);
})
})
})
})
function processtokens(rawtokens) {
var promise = new Promise((resolve, reject) => {
var processedtokens = []
for (var token in rawtokens) {
processedtokens.push(rawtokens[token]);
}
resolve(processedtokens);
})
return promise;
}
it works only when the app in the background. but when i exit from the app and it's not in the background I don't get any notification.
You need to edit the FCM Plugin files. I found the solution only for android now.
I use https://github.com/fechanique/cordova-plugin-fcm this FCM plugin for android and ios in cordova.
You need to edit file MyFirebaseMessagingService.java line 53(line no be may be differ).
In this file there is a method onMessageReceived at the end of the method there is a line which is commented, this line calling an another method i.e. sendNotification(....).
sendNotification(remoteMessage.getNotification().getTitle(), remoteMessage.getNotification().getBody(), data);
You have to uncomment this line and change last parameter from remoteMessage.getData() to data (data variable is already there in the code).
And comment this line FCMPlugin.sendPushPayload( data );
Now you are good to go. Now you are able to receive notification even when app is opened (foreground), you will receive the banner (floating) notifications.
If you found anything for IOS please let me know!!!
I am using firebase plugin for ionic 3.
There is a check if notification data contain "notification_foreground" or not and save it in variable foregroundNotification.
if(data.containsKey("notification_foreground")){
foregroundNotification = true;
}
then it create showNotification variable which decide if we need to show notification or not and pass this to the sendMessage (show notification function).
if (!TextUtils.isEmpty(body) || !TextUtils.isEmpty(title) || (data != null && !data.isEmpty())) {
boolean showNotification = (FirebasePlugin.inBackground() || !FirebasePlugin.hasNotificationsCallback() || foregroundNotification) && (!TextUtils.isEmpty(body) || !TextUtils.isEmpty(title));
sendMessage(data, messageType, id, title, body, showNotification, sound, vibrate, light, color, icon, channelId, priority, visibility);
}
your payload should contain notification_foreground, notification_title and notification_body.

appcelerator titanium android camera native capture photo

i am working on a cross-platform mobile app using appcelerator titanium alloy. the code below opens the native camera functionality and works fine on apple devices. on android devices, the camera opens but the button to actually take a picture is disabled (greyed out). the buttons for taking video or changing camera settings work fine, just the take picture button is not working. any ideas? thanks in advance
the code below called on click of takePic button to open camera
takePic.addEventListener('click', function(e) {
var win = Titanium.UI.createWindow({ //Open Camera
});
Titanium.Media.showCamera({
success:function(event){
Ti.API.debug('Our type was: '+event.mediaTpe);
if(event.mediaType == Ti.Media.MEDIA_TYPE_PHOTO){
***win = Titanium.UI.currentWindow;
if(osName == "android"){
win.open();
}***
try {
var image_name = "siteing.jpg";
var fileImage = Titanium.Filesystem.getFile(Titanium.Filesystem.applicationDataDirectory, image_name);
fileImage.write(event.media);
Ti.API.log(event.media);
picURL = fileImage;//event.media;
picRaw = event.media; //Raw bytes of picture to save to database
pictureSet = true;
$.videoButton.enabled = false;
$.videoButton.backgroundColor = "#DDDDDD";
//$.audioButton.enabled = false;
format = "Picture";
$.savePic.show();
} catch(e){
alert("An Error:" + e.message);
}
} else {
var alert = createErrorAlert({text:"An error occured getting the media. Please check file size and format and try again."});
$.yesLatLon.add(alert);
alert.show();
}
if(osName == "android"){
win.open();
}
}, cancel:function(){
//called when user cancels taking a picture
if(osName == "android"){
//win.close();
}
}, error:function(error){
//called when there's an error
var a = Titanium.UI.createAlertDialog({title:'Camera'});
if(error.code == Titanium.Media.NO_CAMERA){
a.setMessage('Please run this test on device');
} else {
a.setMessage('Unexpected error: ' + error.code);
}
a.show();
}, saveToPhotoGallery:true,
//allowEditing and mediaTypes are iOS-only settings
allowEditing:true,
mediaTypes:[Ti.Media.MEDIA_TYPE_VIDEO, Ti.Media.MEDIA_TYPE_PHOTO]
});
alert.hide();
$.yesLatLon.removeEventListener('androidback', arguments.callee);
});
screenshot_from_phone
It's been a long time, but I did get this working and thought I'd post my code in case it helps someone else. Fair warning, I now face a different issue with the camera on certain Android devices (Samsung S-series and Google Pixel cannot open camera), which I'm posting in a separate question. However, the original issue with camera button being disabled was successfully resolved last year with the below code.
takePic.addEventListener('click', function(e) {
var win = Titanium.UI.createWindow({//Open Camera
});
Titanium.Media.showCamera({
success : function(event) {
if (event.mediaType == Ti.Media.MEDIA_TYPE_PHOTO) {
win = Titanium.UI.currentWindow;
if (osName == "android") {
var img_view = Titanium.UI.createImageView({
height : '100%',
width : '100%',
});
win.add(img_view);
}
try {
picURL = event.media;
picRaw = event.media;
pictureSet = true;
$.videoButton.enabled = false;
$.videoButton.backgroundColor = "#DDDDDD";
$.savePic.show();
format = "Picture";
} catch(e) {
alert("An Error:" + e.message);
}
} else {
var alert = createErrorAlert({
text : "An error occured getting the media. Please check file size and format and try again."
});
$.yesLatLon.add(alert);
alert.show();
}
},
cancel : function() {
//called when user cancels taking a picture
},
error : function(error) {
//called when there's an error
var a = Titanium.UI.createAlertDialog({
title : 'Camera'
});
if (error.code == Titanium.Media.NO_CAMERA) {
a.setMessage('Please run this test on device');
} else {
a.setMessage('Unexpected error: ' + error.code);
}
a.show();
},
saveToPhotoGallery : true,
allowEditing : false,
autohide : true, //Important!
mediaTypes : [Ti.Media.MEDIA_TYPE_PHOTO]
});
alert.hide();
});