I am using Xcode 11.2.1 and iOS 13.2.2.
I use the method bellow to handle remote notification and it works correctly, but the problem happen when I switch Off the device and switch on again... then insert the pin without opening my app, when I send push, I receive the push but the method bellow not call always, does anybody has the same issue?
this is the payload which I send from server:
{"aps":{"content-available": 1,"alert":"Testing..
(100)","badge":1,"sound":"default"}}
and this is the code when I receive push:
-(void) application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void
(^)(UIBackgroundFetchResult))completionHandler
{
if( [UIApplication sharedApplication].applicationState == UIApplicationStateInactive )
{
NSLog( #"INACTIVE" );
completionHandler( UIBackgroundFetchResultNewData );
}
else if( [UIApplication sharedApplication].applicationState == UIApplicationStateBackground )
{
NSLog( #"BACKGROUND" );
completionHandler( UIBackgroundFetchResultNewData );
}
else
{
NSLog( #"FOREGROUND" );
completionHandler( UIBackgroundFetchResultNewData );
}
}
Related
In my Angular 13 Ionic 6 app I'm using the capacitor/push-notifications with FireBase,
In my service:
import { EventEmitter, Injectable, Output } from '#angular/core';
import {ActionPerformed, PushNotifications, PushNotificationSchema, Token} from '#capacitor/push-notifications';
import { Capacitor } from '#capacitor/core';
import { Dialogs, DialogType } from '../Utilities/dialogs';
import { get, set, remove } from './storage.service';
import { BehaviorSubject } from 'rxjs';
import { App } from '#capacitor/app';
//https://devdactic.com/push-notifications-ionic-capacitor/
#Injectable({
providedIn: 'root'
})
export class FbNotificationsService {
onFCMTokenChanged: BehaviorSubject<string> = new BehaviorSubject('');
tokenProcessed: boolean = false;
constructor(private dialogs: Dialogs) {
}
initPush() {
if (Capacitor.getPlatform() !== 'web') {
this.registerPush()
} else {
console.log('Web platform detected');
this.onFCMTokenChanged.next('web-platform');
}
}
private registerPush() {
PushNotifications.requestPermissions().then((permission) => {
if (permission.receive === 'granted') {
// Register with Apple / Google to receive push via APNS/FCM
console.log('FB Permission granted');
PushNotifications.register(); //Registers app to receive notifications
} else {
// No permission for push granted by user on iOS
console.log('FB NO permissions granted');
}
});
PushNotifications.addListener(
'registration',
(token: Token) => {
if ((token)&&(!this.tokenProcessed)) {
this.tokenProcessed = true;
console.log('My token: ' + JSON.stringify(token));
this.onFCMTokenChanged.next(token.value);
set('device-token', token.value);
}
});
PushNotifications.addListener('registrationError', (error: any) => {
console.log('Registration Error: ' + JSON.stringify(error));
this.dialogs.dialogClose('Network Error','The network signal is not sufficient at this time. Please improve connection and try again');
App.exitApp();
});
PushNotifications.addListener(
'pushNotificationReceived',
async (notification: PushNotificationSchema) => {
console.log('Push received: ' + JSON.stringify(notification));
alert('Push received: ' + JSON.stringify(notification));
//What to do next. Notification received on the device.
}
);
PushNotifications.addListener(
'pushNotificationActionPerformed',
async (notification: ActionPerformed) => {
const data = notification.notification.data;
console.log('Action performed: ' + JSON.stringify(notification.notification));
alert('Push action performed: ' + JSON.stringify(notification));
//What to do next. data holds all payload fields of the notification object
}
);
}
}
The basic guide I followed is here.
When I send a test message from the Firebase console, the alert statement I placed is poping up, meaning, the message is received by the app:
alert('Push received: ' + JSON.stringify(notification)); //WORKING
HOWEVER, there is no notification message popping up by the OS for the user to see. I do get notifications all the time from Whatapp, Emails, etc, and the "Do not disturb" setting is turned off.
This is experienced with TWO Android devices: Xiaomi Rednote 8 and Samsung Galaxy A32.
Am I missing something?
I had a similar problem before, maybe the following information could help you:
When your Android app is in the foreground, PushNotifications won't appear on the screen.
If you absolutely want a visual display of the notification, you can create a local notification when the push notification is received.
I'm working with react native and firebase 6 to send push notifications.
I use the official documentations of the new version :
https://invertase.io/oss/react-native-firebase/v6
I add native code for both android and ios to handle sending and receiving notifications
In my AndroidManifest.xml :
<!-- [START firebase_service] -->
<service
android:name=".java.MyFirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<!-- [END firebase_service] -->
I did not create the MyFirebaseMessagingService .
I AppDelegate.m i add some functions :
// Required for the register event.
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
[FIRMessaging messaging].APNSToken = deviceToken;
[RNCPushNotificationIOS didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
NSLog(#"APNs device token retrieved: %#", deviceToken);
}
// Required for the registrationError event.
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
[RNCPushNotificationIOS didFailToRegisterForRemoteNotificationsWithError:error];
NSLog(#"Unable to register for remote notifications: %#", error);
}
// Required for the localNotification event.
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
[RNCPushNotificationIOS didReceiveLocalNotification:notification];
}
In my Component.js i get the token like this :
// Firebase
import firebase from '#react-native-firebase/app'
import messaging from '#react-native-firebase/messaging'
// ----- COMPONENT DID MOUNT ---- //
async componentDidMount () {
// ====================================================== //
// ====================================================== //
// ====================================================== //
const granted = messaging().requestPermission()
if (granted) {
console.log('User granted messaging permissions!')
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
firebase
.messaging()
.getToken()
.then(fcmToken => {
if (fcmToken) {
// user has a device token
console.log('-------- FCM TOKEN -------')
console.log(fcmToken)
console.log(JSON.stringify(fcmToken))
this._setItem(fcmToken)
} else {
// user doesn't have a device token yet
console.log('error')
}
})
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
} else {
console.log('User declined messaging permissions :(')
}
// ====================================================== //
// ====================================================== //
// ====================================================== //
}
// ----- FIN COMPONENT DID MOUNT ---- //
I send POST request to https://fcm.googleapis.com/fcm/send :
{
"to" : "token",
"notification" : {
"body" : "un nouveau partage",
"title" : "un partage de contact reçu",
"priority" : "high",
"vibration":true,
"sound": "Enabled",
"badge":1,
"requireInteraction": true,
"click_action": "fcm.ACTION.HELLO"
},
"data" : {
"body" : "nouvelle opportunité",
"title" : "un nouveau partage",
"content_available" : true,
"priority" : "high"
}
}
I receive the notification for both android and ios but i can't handle the click action :
I want to redirect to specific route when the user click on the notification .
I haven't used Firebase for notifications, but as you're saying the notifications are working, then the actual issue it seems to me is you want to handle it when your app opens.
So here are the steps you have to follow to get your work done.
Get the data coming in the notification, on the event onNotificationOpened. Check out this link to check if you're getting the notification data.
Next, you want to a specific route on the basis of notification. What I do is, send the type of the screen and id related to that screen to navigate there, ex:
{
"entity": "Place",
"id": "123"
}
So, when I receive the notification, I send the data to a switch case factory that navigate to the screen on the basis of info in that data. Something like that.
function navigateToScreen(entity:string, id:string){
let screenName = "";
let params = {}
switch(entity){
case "Place":
screenName = "placeScreen";
params = {id};
break;
default: return;
}
// Navigation Service = https://reactnavigation.org/docs/navigating-without-navigation-prop/
NavigationService.navigate(screenName, params);
}
Now in case you want to run a specific function on the basis of notification, you can do it on the basis of info received. Like in this example I have to make an API req to get the data of that place by id.
const id = props.match.params['id'];
useEffect(() => {
getThePlaceDetails(id);
}, [id]);
I am struggeling to find a solution for my Cordova Native App.
I am using OneSignal to send out push notifications once a new Article has been published. The push notifications are working fine but the moment I click onto the notification the normal browser opens and not the app.
NB: When I send a test notification through OneSignal and click on it the App opens.
My code just does not want to work with Wordpress articles.
Here's the code which I am using in my index.js
document.addEventListener('deviceready', function () {
// Enable to debug issues.
// window.plugins.OneSignal.setLogLevel({logLevel: 4, visualLevel: 4});
var notificationOpenedCallback = function(jsonData) {
var additionalData = jsonData.notification.payload.additionalData
if (additionalData && additionalData.myKey)
// Not familiar with Cordova, $state may or may not be available here
$state.go('app.post', {'postId': + additionalData.myKey});
};
window.plugins.OneSignal
.startInit("0b8b7e69-1649-4616-XXXXXXX")
.handleNotificationOpened(notificationOpenedCallback)
.endInit();
// Call syncHashedEmail anywhere in your app if you have the user's email.
// This improves the effectiveness of OneSignal's "best-time" notification scheduling feature.
// window.plugins.OneSignal.syncHashedEmail(userEmail);
}, false);
Has anyone any idea what is possibly wrong with my code?
All you need to put all codes under plugin check on device ready function and make sure you parse the data into array object because they sending raw looks like -
if (window.plugins && window.plugins.OneSignal) {
.startInit(your_appid, your_google_project)
.inFocusDisplaying(window.plugins.OneSignal.OSInFocusDisplayOption.Notification)
.handleNotificationOpened(function(jsonData) {
if (device.platform =="Android") {
var addData = JSON.parse(jsonData.result.notification.payload.additionalData);
} else {
var addData = jsonData.result.notification.payload.additionalData;
}
if (addData != undefined) {
if (addData.posts != undefined) {
var postID = Number(addData.posts);
$state.go('app.post', {postId: postID });
}
}
})
.endInit();
}
Note: According to there doc they update the additional data tree to
result.notification.payload.additionalData
Not notification.payload.additionalData
Put this function on your wordpress theme function.php and make sure you have disable the option "Send notifications additionally to iOS & Android platforms". on WordPress plugin page.
add_filter('onesignal_send_notification', 'onesignal_send_notification_filter', 10, 4);
function onesignal_send_notification_filter($fields, $new_status, $old_status, $post)
{
$postID = $post->id;
$fields['isAndroid'] = true;
$fields['isIos'] = true;
$fields['isAnyWeb'] = false;
$fields['isChrome'] = false;
$fields['data'] = array(
"posts" => $postID
);
return $fields;
}
Just leaving this here, in case someone else can make use of it.
add_filter('onesignal_send_notification', 'onesignal_send_notication_filter_push', 10, 4);
function onesignal_send_notication_filter_push($fields, $new_status, $old_status, $post)
{
$fields['isAndroid'] = true;
$fields['isIos'] = true;
$fields['isAnyWeb'] = false;
$fields['isChrome'] = false;
// overwrite http url with app_url so push notifications opens app instead of phone browser.
$fields['url'] = $fields['app_url'];
return $fields;
}
does this get triggered again from the server containing a message?
"ecb":"window.onNotificationGCM"
I have this set up on the server
device_tokens = [], //create array for storing device tokens
retry_times = 4, //the number of times to retry sending the message if it failed
sender = new gcm.Sender('AIzaSyDpA0b2smrKyDUSaP0Cmz9hz4cQ19Rxn7U'), //create a new sender
message = new gcm.Message(); //create a new message
message.addData('title', 'Open Circles');
message.addData('message', req.query.message);
message.addData('sound', 'notification');
message.collapseKey = 'testing'; //grouping messages
message.delayWhileIdle = true; //delay sending while receiving device is offline
message.timeToLive = 3; //the number of seconds to keep the message on the server if the device is offline
device_tokens.push(val.deviceToken);
sender.send(message, device_tokens, retry_times, function(result){
console.log(result);
console.log('push sent to: ' + val.deviceToken);
});
So what I want to know is, once a server call is made will it trigger the notification on the front. What am I missing about this system?
case 'message':
// if this flag is set, this notification happened while we were in the foreground.
// you might want to play a sound to get the user's attention, throw up a dialog, etc.
if (event.foreground) {
console.log('INLINE NOTIFICATION');
var my_media = new Media("/android_asset/www/" + event.soundname);
my_media.play();
} else {
if (event.coldstart) {
console.log('COLDSTART NOTIFICATION');
} else {
console.log('BACKGROUND NOTIFICATION');
}
}
navigator.notification.alert(event.payload.message);
console.log('MESSAGE -> MSG: ' + event.payload.message);
//Only works for GCM
console.log('MESSAGE -> MSGCNT: ' + event.payload.msgcnt);
//Only works on Amazon Fire OS
console.log('MESSAGE -> TIME: ' + event.payload.timeStamp);
break;
case 'error':
console.log('ERROR -> MSG:' + event.msg);
break;
default:
console.log('EVENT -> Unknown, an event was received and we do not know what it is');
break;
}
};
return {
register: function () {
var q = $q.defer();
if(ionic.Platform.isAndroid()){
pushNotification.register(
successHandler,
errorHandler,
{
"senderID":"346007849782",
"ecb":"window.onNotificationGCM"
}
);
}else{
pushNotification.register(
tokenHandler,
errorHandler,
{
"badge":"true",
"sound":"true",
"alert":"true",
"ecb":"window.onNotificationAPN"
}
);
}
return q.promise;
}
}
update. Eventually my server spit back this: TypeError: Cannot read property 'processIncomingMessage' of undefined
It seems my google ID was not working. I created a new one and now it's sending push requests.
I already know how to send push notifications in Titanium with Alloy, the way I do is:
// Require the module
var CloudPush = require('ti.cloudpush');
var deviceToken = null;
// Initialize the module
CloudPush.retrieveDeviceToken({
success: deviceTokenSuccess,
error: deviceTokenError
});
// Enable push notifications for this device
// Save the device token for subsequent API calls
function deviceTokenSuccess(e) {
deviceToken = e.deviceToken;
// alert("--->" + deviceToken);
subscribeToChannel();
}
function deviceTokenError(e) {
alert('Failed to register for push notifications! ' + e.error);
}
// Process incoming push notifications
CloudPush.addEventListener('callback', function (evt) {
alert("Notification received: " + evt.payload);
});
// For this example to work, you need to get the device token. See the previous section.
// You also need an ACS user account.
// Require in the Cloud module
var Cloud = require("ti.cloud");
function loginUser(){
// Log in to ACS
Cloud.Users.login({
login: 'example',
password: 'example'
}, function (e) {
if (e.success) {
alert('Login successful');
} else {
alert('Error:\n' +
((e.error && e.message) || JSON.stringify(e)));
}
});
}
function subscribeToChannel(){
// Subscribe the user and device to the 'test' channel
// Specify the push type as either 'android' for Android or 'ios' for iOS
// Check if logged in:
Cloud.PushNotifications.subscribe({
channel: 'test',
//device_token: 'APA91bHRjGoZLCYKwn-XcCtNLETuf-KRKfT4sMgVE4KgXQgInYfZuYTNrZC7FUMugLs0idzzqtLytrvVJjVzYBzQoc7Q81hEerq0O2vww_tV8mACuUfAi0JRvs7LoufnQZpYLZrb_1rlUsIOEMsPxDs9b_pIRJF5rw',
device_token:deviceToken,
type: Ti.Platform.name == 'android' ? 'android' : 'ios'
}, function (e) {
if (e.success) {
alert('Subscribed');
} else {
alert('Error:\n' +
((e.error && e.message) || JSON.stringify(e)));
}
});
}
function unsubscribeToChannel (){
// Unsubscribes the user and device from the 'test' channel
Cloud.PushNotifications.unsubscribe({
channel: 'test',
device_token: deviceToken
}, function (e) {
if (e.success) {
alert('Unsubscribed');
} else {
alert('Error:\n' +
((e.error && e.message) || JSON.stringify(e)));
}
});
}
loginUser();
However this way is only for sending push notification through https://cloud.appcelerator.com/ such a manually because it is needed you write the alert and push the button in that backend site.
So my question: Is there any way for sending push notification in Titanium from an own server in an "automatically" way?
Thanks in advance for any help.
Yes, it is possible.
How to obtain a device token for push notifications is described in the Titanium docs, here.
To send notifications you have to send the token to your server. The server then sends your notification to Apple Push Notification Services (APNS). See Apple docs. That's not "automatic" but it's a simple task for PHP or any other language - you can find a lot of scripts.
You can also schedule local notifications which might come in handy depending on your case.