Open uj opened 7 years ago
AFAIK, the plugin registers for an event that the internal APIs will trigger whenever a new registrationId
is known, and the registration
event from the plugin API will trigger on cascade from that, so that your application can be notified by it anytime. And for that root event to happen, I'm pretty sure GCM/FCM APIs will keep trying and keep control/state of connection, so that the whole flow works.
So, if you call .init()
and .on('registration')
properly on your app, you should be notified of any updates to the registrationId
as soon as the underlying google API tells the plugin so.
Is that not the case? If you have a scenario that can reproduce a flaw in those expectations, please provide the steps and info so that we can debug it.
If there is no network initially, the registration never happens even after the network comes back. Android 6.0 phonegap-plugin-push version 1.9.2 Cordova version 6.4.0
Steps to reproduce:
ionic start phonegap_sample blank --v2
Add the following to config.xml
<plugin name="phonegap-plugin-push" spec="1.9.2">
<variable name="SENDER_ID" value="xxxxxxxxxxxx"/>
</plugin>
ionic platform add android
app.component.ts:
import { Component } from '@angular/core';
import { Platform } from 'ionic-angular';
import {StatusBar, Push, Splashscreen} from "ionic-native";
import { HomePage } from '../pages/home/home';
@Component({
templateUrl: 'app.html'
})
export class MyApp {
rootPage = HomePage;
constructor(platform: Platform) {
platform.ready().then(() => {
// Okay, so the platform is ready and our plugins are available.
// Here you can do any higher level native things you might need.
StatusBar.styleDefault();
Splashscreen.hide();
var push = Push.init({
android: {
senderID: "xxxxxxxxxxxx"
},
ios: {
alert: "true",
badge: "true",
sound: "true"
},
windows: {}
});
push.on('registration', function(data) {
console.log("registration=" + data.registrationId)
});
push.on('notification', function(data) {
// data.message,
// data.title,
// data.count,
// data.sound,
// data.image,
// data.additionalData
});
push.on('error', function(e) {
console.log("error=" + e.message)
});
});
}
}
TURN ON AIRPLANE MODE ON at the PHONE, to stop all network activity.
ionic run android --prod
Watch the remote log in Chrome.
It shows "error=SERVICE_NOT_AVAILABLE" because of no network.
Turn AIRPLANE MODE off at the phone.
Keep watching log... nothing else happens. A registration ID never arrives.
This class should receive an update whenever the underlying API gets a new value. I'm not sure what is causing your scenario not to be updated whenever connection is available again, so that might indeed be a bug.
@macdonst You mind retesting this?
No, the plugin cannot simply listen for a new value, that will not work. The plugin (or the application) must actively resend the registration request over and over until it gets a different response. The question is: Is this a responsibility of the phonegap plugin? Or do I need to implement that myself?
Below is the official documentation from Google:
https://developers.google.com/android/reference/com/google/android/gms/gcm/GoogleCloudMessaging
Constant Value: "SERVICE_NOT_AVAILABLE" = The device can't read the response, or there was a 500/503 from the server that can be retried later. The application should use exponential back off and retry.
I see. InstanceIDListenerService
has the goal of notifying changes to the registrationId, not the goal of notifying the current registrationId. I think you're right, and we'd need to at least create a listener to a network change event and retry once per app lifecycle, imo, when the first attempt fails.
"Network change event" would only detect if there is a network connection to the phone, correct? If so, that would not account for upstream issues that would prevent the registration from occurring (for example if you have local network access but not access all the way to the google servers).
@uj if you try to register when the device is off line you get a proper error
event it is then up to you as the developer to re-try init
when the network becomes available. You will get an updated registration
even if the app is notified by Google that the registration ID has changed.
@macdonst Thank you for your answer. That is what I am currently doing while waiting to find out officially if this is intended to be a feature of the plugin or not an intended feature.
It seems that your answer contradicts the last "imo" answer given by @fredgalvao.
I could not find anything in the documentation regarding this issue that perhaps many developers never run across during testing because they always have network access during testing, but it could be a major problem with real world users in various situations and create difficult troubleshooting.
I got it wrong indeed, but I wouldn't say it was contradicting, but complementary. I just didn't know that I could call .init()
multiple times to handle that.
I also agree we could put that on the docs.
If .init is called when network is available, my app receives a device token, that is good.
However, if .init is called when network is not available (or the google service is not reachable for whatever reason), then obviously my app will not receive a device token, and I don't think that .init ever retries.
Also, I imagine the same situation would be an issue if google expires the device token, and then the device happens to have no network access when google sends a new device token, it will not receive the new token notification.
Should .init be automatically retrying to get an initial token if there is an error? And, similarly, should it automatically be checking to see if there is a new token available if it missed the new token notification for some reason?
Or should I be periodically calling .init myself to cover such instances?