FCM push notification to reawaken app not effective while device slept - android

I ran into a problem with my flutter app where when it's minimized or the phone is put to sleep for too long (~5+ minutes), the app stops listening to firestore changes. One solution that I came across was to send push notifications to reawaken the device. While it seems to have fixed minimizing problem (the app now responds to changes), however it still suffers from the sleep problem. I noticed that the app still receives the push notifications, but the screen doesn't light up upon receiving them. Could that be why? Is there something that I can do to force the app to connect to the internet? I'm trying to think of a solution like sending a data payload to change the data locally, but I'm not sure if that's the optimal approach (or if it would even work). I'll post my firebase cloud function for sending messages on a doc update:
exports.sendLobbyNotificationTest = functions.firestore
.document("Lobbies/{lobbyCode}")
.onUpdate((change) => {
console.log("Checking for need of push notification...");
// const oldValue = change.before.data() || {};
const newValue = change.after.data() || {};
if (newValue.pushNotification == true) {
console.log("Found a push notification request for: ",
newValue.lobbyCode, "!");
// Set lobby back to false
admin.firestore().collection("Lobbies")
.doc(newValue.lobbyCode).update({
pushNotification: false,
});
return admin.messaging().sendToTopic(newValue.lobbyCode, message)
.then((result) => {
console.log("Message sent successfully: ", result);
// usersRef.where("lobbyCode", "==", newValue.lobbyCode).get()
// .then(function(querySnapshot) {
// querySnapshot.forEach(function(doc){
// })
// })
}).catch((err) => {
console.error("Error sending message: ", err);
});
}
console.log("No message needs to be sent!");
// return dummy value to prevent error
return 0;
});
const message = {
notification: {
title: "Bzzzt!",
body: "You've been buzzed!",
},
};
Is there something I'm missing?
Update: I think it just doesn't work because the phone is locked, once unlocked it begins to function normally.

I think figured out why from reading here: https://developer.android.com/training/monitoring-device-state/doze-standby.html (I had trouble finding this).
Basically if I use the right priority settings for android and ios (priority & content_available) it will bring the app out of idle and listen for changes.

Related

Using react-native-netinfo to detect connection change gets old state

I'm trying to implement a feature in my app. I am using an Android device (not emulator).
Let's say I don't have internet connection an I have an array saved in my Asyncstorage and each time I push a button I insert a new item on that array.
I am using react-native-netinfo to detect when the connection changes, so what I'm trying to do is:
When the NetInfo.addEventListener triggers and if the connection status is true, I want to send that array to my API, the event is triggering well, if I turn off the wifi and cellular data I get connection status false, everything is ok. But when I console.log my array and try to send it to my API is doesn't print the new items into Asyncstorage.
If I restart the app, that same console.log prints the correct information when the connection changes, but again, if I push new items and the connection changes again, it doesn't print the new items added to the Asyncstorage (I know they're there because if I go to another screen, they're there)
This is my code:
useEffect(() => {
const unsubscribe = NetInfo.addEventListener((state) => {
handleConnectionChange(state);
console.log("Connection type", state.type);
console.log("Is connected?", state.isConnected);
});
return () => {
unsubscribe();
};
}, []);
const handleConnectionChange = (state) => {
console.log("Array: ", tickets);
//tickets should be updated with the new tickets but is not, until I refresh the app.
//tickets rendered ok and are printed ok on any other console.log outside of this event.
if (state.isConnected && tickets.length > 0) {
console.log("TRY TO SYNC");
callAPI()
}
setConnectionStatus(state.isConnected);
};
I appreciate any help. Thanks in advance.

React native: requestTechnology called only if the app is brought from background to foreground

I am currently working on a simple app for scanning, reading data from an NFC card (in my case a Mifare NFC card) and displaying in on the screen. I have built it using this example.
The app should work both on Android and iOS, but for the moment, I have tested it only on an android device (an Oppo device with NFC capablities and developer mode activated).
At the launch of the app, everything seems to be working fine, the NfcManager has been successfully started, but there is an issue when the app tries to request the technology for reading the card, namely, I have to bring the app first in the background and then again in the foreground so that the message requestTechnology success is displayed, otherwise, it's simply not called.
After this, the promise NfcManager.getTag() gets rejected with the error message: no reference available.
Here is my code:
componentDidMount() {
NfcManager.start({
onSessionClosedIOS: () => {
alert('ios session closed');
},
}).then(() => console.warn('NfcManager started')) // successfully started
.catch((error) => alert('Error starting NfcManager: ', error));
}
{... componentWillUnmount and render method ...}
_read = async () => {
try {
let tech = Platform.OS === 'ios'
? NfcTech.MifareIOS : [NfcTech.MifareClassic, NfcTech.NfcA, NfcTech.IsoDep, NfcTech.Ndef];
let resp = await NfcManager.requestTechnology(tech, {
alertMessage: 'Ready to do some custom Mifare cmd!'
})
.then((value) => alert('requestTechnology success', value)) // here the value is empty, so no NfcTech
.catch(() => console.warn('reuqestTechnology error'));
const tag = await NfcManager.getTag()
.then((value) => alert('Tag event: ', value))
.catch((err) => console.warn('error getting tag: ', err));
// this part of the code is reached, but not working properly since the tag.id is not correctly retrieved
if (Platform.OS === 'ios') {
resp = await NfcManager.sendMifareCommandIOS([0x30, 0x00]);
} else {
resp = await NfcManager.transceive([0x30, 0x00]);
}
console.warn('Response: ', resp);
this._cleanUp();
} catch (ex) {
console.warn(ex);
this._cleanUp();
}
}
If I scan the card against the device, it makes the sound like it has been scanned, but nothing seems to be displayed.
Does anyone know why does the app needs to be brought to the background so that the technology is requested? And second, does the fail of the getTag() method have anything to do with it?
I hope anyone can help me with this issue, I have been struggling with this problem for quite some time and I haven't found any solution.
May be related to github.com/revtel/react-native-nfc-manager/issues/423 ?? there seems to be a scenario where this package does not correctly configure enableForegroundDispatch and manually pausing and resuming the App by sending it to the background would fix it.

Detect if Appcelerator app was opened from a push notification

I am trying to determine the best way to detect if my app was opened by tapping on a push notification. I have found some different articles online that suggest different way to do this, but none seem to work in a consistent manner across app platforms and states.
Is there an official Appcelerator way to do this?
Yes, there is an official way.
if (Ti.Platform.getOsname() !== 'android') {
// Wait for user settings to be registered before registering for push notifications
Ti.App.iOS.addEventListener('usernotificationsettings', function registerForPush() {
// Remove event listener once registered for push notifications
Ti.App.iOS.removeEventListener('usernotificationsettings', registerForPush);
Ti.Network.registerForPushNotifications({
success: deviceTokenSuccess,
error: deviceTokenError,
callback: receivePush
});
});
// Register notification types to use
Ti.App.iOS.registerUserNotificationSettings({
types: [
Ti.App.iOS.USER_NOTIFICATION_TYPE_ALERT,
Ti.App.iOS.USER_NOTIFICATION_TYPE_SOUND,
Ti.App.iOS.USER_NOTIFICATION_TYPE_BADGE
]
});
}
// For Android
else {
var CloudPush = require('ti.cloudpush');
var deviceToken = null;
// Initialize the module
CloudPush.retrieveDeviceToken({
success: deviceTokenSuccess,
error: deviceTokenError
});
// Process incoming push notifications
CloudPush.addEventListener('callback', function (evt) {
receivePush(evt);
});
}
// Process incoming push notifications
function receivePush(e) {
// alert(e.data);
}

How to get Registration ID with Intel XDK?

For a while now, I have been trying to figure out how to send push notifications. The app I have made is for Android right now, but I want to extend it to other devices once I figure this out. I've looked into various services, such as Amazon SNS, but they all neglect to include how to get the device token. They all assume you know how to do that.
So what I am asking is: how do I get a device token/registration ID for a device?
I tried using this code:
var tokenID = "";
document.addEventListener("deviceready", function(){
//Unregister the previous token because it might have become invalid. Unregister everytime app is started.
window.plugins.pushNotification.unregister(successHandler, errorHandler);
if(intel.xdk.device.platform == "Android")
{
//register the user and get token
window.plugins.pushNotification.register(
successHandler,
errorHandler,
{
//senderID is the project ID
"senderID":"",
//callback function that is executed when phone recieves a notification for this app
"ecb":"onNotification"
});
}
else if(intel.xdk.device.platform == "iOS")
{
//register the user and get token
window.plugins.pushNotification.register(
tokenHandler,
errorHandler,
{
//allow application to change badge number
"badge":"true",
//allow application to play notification sound
"sound":"true",
//register callback
"alert":"true",
//callback function name
"ecb":"onNotificationAPN"
});
}
}, false);
//app given permission to receive and display push messages in Android.
function successHandler (result) {
alert('result = ' + result);
}
//app denied permission to receive and display push messages in Android.
function errorHandler (error) {
alert('error = ' + error);
}
//App given permission to receive and display push messages in iOS
function tokenHandler (result) {
// Your iOS push server needs to know the token before it can push to this device
// here is where you might want to send the token to your server along with user credentials.
alert('device token = ' + result);
tokenID = result;
}
//fired when token is generated, message is received or an error occured.
function onNotification(e)
{
switch( e.event )
{
//app is registered to receive notification
case 'registered':
if(e.regid.length > 0)
{
// Your Android push server needs to know the token before it can push to this device
// here is where you might want to send the token to your server along with user credentials.
alert('registration id = '+e.regid);
tokenID = e.regid;
}
break;
case 'message':
//Do something with the push message. This function is fired when push message is received or if user clicks on the tile.
alert('message = '+e.message+' msgcnt = '+e.msgcnt);
break;
case 'error':
alert('GCM error = '+e.msg);
break;
default:
alert('An unknown GCM event has occurred');
break;
}
}
//callback fired when notification received in iOS
function onNotificationAPN (event)
{
if ( event.alert )
{
//do something with the push message. This function is fired when push message is received or if user clicks on the tile.
alert(event.alert);
}
if ( event.sound )
{
//play notification sound. Ignore when app is in foreground.
var snd = new Media(event.sound);
snd.play();
}
if ( event.badge )
{
//change app icon badge number. If app is in foreground ignore it.
window.plugins.pushNotification.setApplicationIconBadgeNumber(successHandler, errorHandler, event.badge);
}
}
All I get is an alert that says "result = ok". The alerts later on in the code don't happen. I've tried making sense of the code but I'm not getting anywhere. Any suggestions? Is there a tutorial for this I'm not finding?
Those legacy intel.xdk functions are being retired (the will continue to live in an 01.org, see the notice on this page: https://software.intel.com/en-us/node/492826).
I recommend you investigate one of the many push notification Cordova plugins that are available. Use your favorite web search tool to search for something like "cordova phonegap push notification plugin" to find some. The good ones will have examples of how to use.
Note:-
Unregister - Its not strictly necessary to call it.....
Ensure that you have a sender ID for Android (no idea about iOS).
Result OK means that the plugin is installed correctly and has run properly.
Problems could be due to:
Incorrect sender ID
Testing in emulator without adequate setup
Important - Push notifications are intended for real devices. They are not tested for WP8 Emulator. The registration process will fail on the iOS simulator. Notifications can be made to work on the Android Emulator, however doing so requires installation of some helper libraries, as outlined here, under the section titled "Installing helper libraries and setting up the Emulator".
onNotification must be available as a global object. So try attaching it to the window. Refer to this question
Examples of properly initializing PushPlugin in:
Ionic (my answer)

Events and callbacks firing incorrectly in pushwoosh push notifications

I'm using the plugin's registerDevice and unregisterDevice methods and looking at my app's control panel in pushwoosh. My app's preference defaults to accepting push notifications, so I register, that works and my subscriber count increments in pushwoosh control panel. It also fires a push-notification event where the event has the notification property as the guide shows, but it's set to null. This is confusing as I have not yet sent any push notifications from the control panel.
I then set my push preference to false and unregister the the device. It works because my subscriber count decrements in the control panel, but the fail callback is the one that fires, and the only argument it gets is the same push token string that the register success callback got. If I unregister again after that, still only the fail callback fires but this time the only argument is the empty string.
Am I doing something wrong with handling responses from the plugin?
The code I'm testing with:
(function() {
$document.on('push-notification', function(evt) {
var n = evt.originalEvent.notification;
console.log(n);
});
var pushPrefApply = function() {
app.pushPref(function(pushPref) {
console.log('pushPref', pushPref);
if (!pushPref) {
window.plugins.pushNotification.unregisterDevice(
function() {
console.log('unreg ok', arguments);
},
function() {
console.log('unreg fail', arguments);
}
);
return;
}
window.plugins.pushNotification.registerDevice(
{
projectid: '123456789012',
appid : 'F0000-BAAAA'
},
function(pushToken) {
console.log('reg ok', arguments);
},
function(status) {
console.log('reg fail', arguments);
}
);
});
};
//code for changing/initiating push preference goes here
})();
$document is not a typo, it's defined already. app.pushPref is the preference setting/fetching function. window.plugins.pushNotification.onDeviceReady has been done elsewhere on deviceready.
I'm hoping the pushwoosh devs will shed some light on this.
The problem has been fixed and SDK has been updated on Github:
https://github.com/shaders/push-notifications-sdk
and
https://github.com/shaders/phonegap-cordova-push-notifications
Also Android Phonegap sample now includes unregister function:
https://github.com/shaders/push-notifications-sdk/tree/master/SDK%20Sample%20Projects/Android-Phonegap

Categories

Resources