Ionic App 2 Launch Calculator - ionic-framework

I am working on IonicApp 2 and I have a screen in which, when the user clicks the filed we wanted to show the calculator so that the user can perform the calculation.
Is there a way we could do it?
Regards,
Raaj

Install plugins
ionic plugin add cordova-plugin-inappbrowser
ionic plugin add cordova-plugin-appavailability
ionic plugin add cordova-plugin-device
thank import them
import { InAppBrowser, AppAvailability, Device } from 'ionic-native';
now try this
launchExternalApp(iosSchemaName: string, androidPackageName: string, appUrl: string, httpUrl: string, username: string) {
let app: string;
if (Device.device.platform === 'iOS') {
app = iosSchemaName;
} else if (Device.device.platform === 'Android') {
app = androidPackageName;
} else {
let browser = new InAppBrowser(httpUrl + username, '_system');
return;
}
AppAvailability.check(app).then(
(success) => { // success callback
let browser = new InAppBrowser(appUrl + username, '_system');
},
(error) => { // error callback
let browser = new InAppBrowser(httpUrl + username, '_system');
}
);
}
openInstagram(username: string) {
this.launchExternalApp('instagram://', 'com.instagram.android', 'instagram://user?username=', 'https://www.instagram.com/', username);
}
openTwitter(username: string) {
this.launchExternalApp('twitter://', 'com.twitter.android', 'twitter://user?screen_name=', 'https://twitter.com/', username);
}
openFacebook(username: string) {
this.launchExternalApp('fb://', 'com.facebook.katana', 'fb://profile/', 'https://www.facebook.com/', username);
}

Related

Ionic Native BLE plugin not writing

I have a bluetooth printer, this model: SEWOO LK-P400
I'm trying to develop inside my Ionic application this plugin: Ionic Native - BLE
How is the right way to develop that? seeams to have a SDK, how to start? I never develop with a custom SDK, I tryed to use the plugin, the connect and disconnect function it's ok, but the write function don't return any erros, the display of the printer turns ON but don't print anything.
the button print function:
async printTest() {
try {
let value = this.stringToBytes('Hello World');
await this.bluetoothProvider.print(this.deviceId.toUpperCase(), this.serviceUUID, this.characteristicUUID, value)
.then(response => {
console.log(retorno);
})
} catch (error) {
console.log(error);
}
}
stringToBytes(string) {
var array = new Uint8Array(string.length);
for (var i = 0, l = string.length; i < l; i++) {
array[i] = string.charCodeAt(i);
}
return array.buffer;
}
the provider function:
print(
deviceId: string,
serviceUUID: string,
characteristicUUID: string,
value: ArrayBuffer): any
{
return this.ble.write(deviceId, serviceUUID, characteristicUUID, value);
}

Events in Ionic v4

I'm using Ioni v4Beta and I'm traying to update the sidemenu when the user is login.
I search but the usual solution is use Events:
Ionic 3 refresh side menu after login
https://ionicframework.com/docs/api/util/Events/
But in the new version I don't find it, and I don't know how to do it
https://beta.ionicframework.com/docs/api
Thanks a lot, but I finally find how to import it:
import { Events } from '#ionic/angular';
Example on how to do it with subjects:
export const someEvent:Subject = new Subject();
export class ReceivingClass implements OnDestroy, OnInit
{
private someEventSubscription:Subscription;
public OnInit():void{
someEventSubscription = someEvent.subscribe((data) => console.log(data);
}
public onDestroy():void{
someEvent.unsubscribe();
}
}
export class SendingClass implements OnInit
{
public OnInit():void{
setTimeout(() => {
someEvent.next('hi');
}, 500);
}
}
Are you aware that Ionic v4 events will be deprecated soon?
I was also trying to update the sidemenu when a user logs in as well, so i tried using: import { Events } from '#ionic/angular';
However I got a warning referring me to this link https://angular.io/guide/observables#basic-usage-and-terms which I failed to follow because am not that familiar with observables.
After much research I found that I can still use events but I had to import them from angular's router directive.
This was my code before:
/* import was */
import { Events } from '#ionic/angular';
import { Storage } from '#ionic/storage';//ignore this import if doesn't apply to your code
/* inside the class */
constructor(
private events: Events,
private storage: Storage
) {
this.events.subscribe("updateMenu", () => {
this.storage.ready().then(() => {
this.storage.get("userLoginInfo").then((userData) => {
if (userData != null) {
console.log("User logged in.");
let user = userData.user;
console.log(user);
}
else {
console.log("No user found.");
let user = {};
}
}).catch((error)=>{
console.log(error);
});
}).catch((error)=>{
console.log(error);
});
});
}
changes i made that actually got my code working and deprecation warning gone:
/* import is now */
import { Router,RouterEvent } from '#angular/router';
import { Storage } from '#ionic/storage';//ignore this import if it does't apply to your code
Rest of code
constructor(
public router: Router,
public storage: Storage
){
this.router.events.subscribe((event: RouterEvent) => {
this.storage.ready().then(() => {
this.storage.get("userLoginInfo").then((userData) => {
if (userData != null) {
/*console.log("User logged in.");*/
let user = userData.user;
/*console.log(this.user);*/
}
else {
/*console.log("No user found.");*/
let user = {};
}
}).catch((error)=>{
console.log(error);
});
}).catch((error)=>{
console.log(error);
});
});
}
I got the idea after seeing this https://meumobi.github.io/ionic/2018/11/13/side-menu-tabs-login-page-ionic4.html. I hope my answer can be useful.
Steps to resolve the issue
import events in login page and in sidemenu view
In login page, after login success do your logic to publish the events.
for eg:
this.authService.doLogin(payload).subscribe((response) => {
if (response.status) {
this.storage.set('IS_LOGGED_IN', true);
this.events.publish('user:login');
}
}, (error) => {
console.log(error);
});
In sidemenu view, create a listener to watch the events 'user:login'
for eg:
this.menus = [];
// subscribe events
this.events.subscribe('user:login', () => {
// DO YOUR LOGIC TO SET THE SIDE MENU
this.setSidemenu();
});
// check whether the user is logged in or not
checkIsUserloggedIn() {
let isLoggedIn = false;
if (this.storage.get('IS_LOGGED_IN') == '' ||
this.storage.get('IS_LOGGED_IN') == null ||
this.storage.get('IS_LOGGED_IN') == undefined) {
isLoggedIn = false;
} else {
isLoggedIn = true;
}
return isLoggedIn;
}
// to set your sidemenus
setSidemenu() {
let isUserLoggedIn = this.checkIsUserloggedIn();
if(isUserLoggedIn) {
this.menus = ['Home', 'Aboutus', 'Contactus', 'My Profile', 'Logout'];
} else {
this.menus = ['Login', 'Home', 'Aboutus', 'Contactus'];
}
}

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.

one signal additional data in ionic 2/3

I'm trying to work with one signal plugin in my ionic 2 app
I've installed Onesignal and it was working fine,but i don't know how to work with handleNotificationOpened function
there is no document at all (nothing was found)
this is my code:
this.oneSignal.handleNotificationReceived().subscribe((msg) => {
// o something when notification is received
});
but I have no idea how to use msg for getting data.
any help? link?
tank you
Here is how i redirect user to related page when app launch from notification.
app.component.ts
this.oneSignal.handleNotificationOpened().subscribe((data) => {
let payload = data; // getting id and action in additionalData.
this.redirectToPage(payload);
});
redirectToPage(data) {
let type
try {
type = data.notification.payload.additionalData.type;
} catch (e) {
console.warn(e);
}
switch (type) {
case 'Followers': {
this.navController.push(UserProfilePage, { userId: data.notification.payload.additionalData.uid });
break;
} case 'comment': {
this.navController.push(CommentsPage, { id: data.notification.payload.additionalData.pid })
break;
}
}
}
A better solution would be to reset the current nav stack and recreate it. Why?
Lets see this scenario:
TodosPage (rootPage) -> TodoPage (push) -> CommentsPage (push)
If you go directly to CommentsPage the "go back" button won't work as expected (its gone or redirect you to... who knows where :D).
So this is my proposal:
this.oneSignal.handleNotificationOpened().subscribe((data) => {
// Service to create new navigation stack
this.navigationService.createNav(data);
});
navigation.service.ts
import {Injectable} from '#angular/core';
import {App} from 'ionic-angular';
import {TodosPage} from '../pages/todos/todos';
import {TodoPage} from '../pages/todo/todo';
import {CommentsPage} from '../pages/comments/comments';
#Injectable()
export class NavigationService {
pagesToPush: Array<any>;
constructor(public app: App) {
}
// Function to create nav stack
createNav(data: any) {
this.pagesToPush = [];
// Customize for different push notifications
// Setting up navigation for new comments on TodoPage
if (data.notification.payload.additionalData.type === 'NEW_TODO_COMMENT') {
this.pagesToPush.push({
page: TodoPage,
params: {
todoId: data.notification.payload.additionalData.todoId
}
});
this.pagesToPush.push({
page: CommentsPage,
params: {
todoId: data.notification.payload.additionalData.todoId,
}
});
}
// We need to reset current stack
this.app.getRootNav().setRoot(TodosPage).then(() => {
// Inserts an array of components into the nav stack at the specified index
this.app.getRootNav().insertPages(this.app.getRootNav().length(), this.pagesToPush);
});
}
}
I hope it helps :)

Ionic GUI freezes with click event

I'm having som issues with a button in my Ionic app. My button have a click event "loginEvent()" that performs a login for the user. I have two span tags that is supposed to display a loading symbol while the login is performed.
The problem is that the button is not updated with the loading symbol until the loginEvent() returns. The click animation on the button does also not run until the loginEvent() returns.
When the button is clicked both "login" and "/login" is printed before the button updates to a spinner, giving the impression that the GUI freezes. The desired behaviour is that the login-button get the spinner while the login call is being performed.
Any idea why my button behaves like this?
Login button
<button ion-button block (click)="loginEvent();">
<span *ngIf="!isLoading">Logga in</span>
<span *ngIf="isLoading"><ion-spinner></ion-spinner></span>
</button>
loginEvent()
loginEvent() {
console.log("login");
this.isLoading = true;
this.userHandler.login(this.username, this.password, this); //Performa authentication to Amazon Cognito and returns the result via callback function
console.log("/login");
}
EDIT
Adding the code for my UserHandler and AuthenticationService.
UserHandler.ts
#Injectable()
export class UserHandler {
constructor(public authenticationService: AuthenticationService) {
this.observers = new Array<Observer>();
}
public login(username: string, password: string, callback: any) {
this.authenticationService.performLogin(username, password, callback);
}
}
AuthenticationService.ts
public performLogin(username: string, password: string, callback: CognitoCallback) {
username = username .toLowerCase();
var authenticationData = {
Username: username,
Password: password,
};
var authenticationDetails = new AWSCognito.AuthenticationDetails(authenticationData);
var userData = {
Username: username,
Pool: this.getUserPool()
};
let cognitoUser = new AWSCognito.CognitoUser(userData);
cognitoUser.authenticateUser(authenticationDetails, {
onSuccess: function (result: any) {
var loginKey = 'cognito-idp.' + environment.region + '.amazonaws.com/' + environment.userPoolId;
var loginProvider = {};
loginProvider[loginKey] = result.getIdToken().getJwtToken();
var credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: environment.identityPoolId,
Logins: loginProvider
});
credentials.refresh((error: any) => {
if (error) {
console.error(error);
}
});
credentials.get(function (err: any) {
if (!err) {
callback.cognitoCallback(null, result, "FAILED");
} else {
callback.cognitoCallback(err.message, null, "SUCCESS");
}
});
},
onFailure: function (err: any) {
callback.cognitoCallback(err.message, null, "FAILURE");
},
newPasswordRequired: function (userAttributes: any, requiredAttributes: any) {
callback.cognitoCallback("Please set a new password", null, "newPasswordRequired");
}
});
}
I guess 'userHandler.login' is used to call the API for user authentication. As the HTTP requests are asynchronous it returns promise immediately you call them.
Instead of the spinner, you can use ionic loading component, where you can show the loader until the API returns the response.
Please share your userHandler code.