Open daksamedia opened 1 year ago
Hello @daksamedia thanks for reaching out! Would you be able to send over the logs from your device so we can take a closer look? Thanks!
It may also not be available yet if you ask for the subscription ID immediately after initialization.
Try waiting to see if you receive it later. Another way is to use the push subscription listener to find out when it becomes available.
I'm having the same issue. The subscription ID takes a moment to become available. This could be fixed by making a function to access it that returns a promise instead.
Try waiting to see if you receive it later. Another way is to use the push subscription listener to find out when it becomes available.
This doesn't work. The listener doesn't get called when the subscription ID switches from being undefined to being the string.
Try waiting to see if you receive it later. Another way is to use the push subscription listener to find out when it becomes available.
@nan-li I can confirm with @terreng that this does not work as described, at least on an iPhone Emulator (iOS 17.0.1) using Xcode. When I initialize OneSignal, the push subscription listener is not triggered. I was able to get the listener to trigger when I leave the app, change my notification settings, and go back into that app.
The only way I can get my Subscription ID after calling OneSignal.initialize()
is to set an interval that continuously checks the variable. Definitely not ideal, I'm hoping for a better solution.
let start = +(new Date());
OneSignal.initialize(appID);
let interval = setInterval(() => {
let now = +(new Date());
console.log(`${(now-start)}ms timeout: `, OneSignal.User.pushSubscription.id);
if (OneSignal.User.pushSubscription.id) {
clearInterval(interval);
}
// Do work...
}, 100);
// Output in Xcode:
//⚡️ [log] - 100ms timeout: <SUBSCRIPTION_ID>
I can confirm, that using setTimeout or setInterval works... but it is not the nice solution...
Hi all, thanks for your responses. I will investigate the push subscription observer not behaving as expected.
Hi everyone, Thanks for your patience and continuing to give us information.
Can you let me know when do you add the push subscription event listener?
Can you also let us know what devices this is happening on?
I only see one person mention iPhone emulator.
Hi Nan,
There are two potential issues at play here.
The primary issue is that window.plugins.OneSignal.User.pushSubscription.id
is always initially undefined
. I have tested this on a real iPhone running the latest everything. I'm running this inside the Cordova deviceready
event. I have tried putting it both before and after window.plugins.OneSignal.initialize
, but it doesn't make a difference.
Note that there's the exact same problem with window.plugins.OneSignal.Notifications.hasPermission()
. It always initially returns false
. See #925.
The workaround for both of these issues is to use a setInterval
to wait until the values become available/accurate.
Both of these things used to be functions that returned promises in the older version of the OneSignal Cordova SDK before it was recently changed in the new release.
I can see three possible ways to fix this problem:
window.plugins.OneSignal.User.pushSubscription.id
(and window.plugins.OneSignal.Notifications.hasPermission()
) are both immediately available inside Cordova's deviceready
event.The secondary issue is that the push subscription listener (OneSignal.User.pushSubscription.addEventListener("change", listener)
) doesn't get called when window.plugins.OneSignal.User.pushSubscription.id
goes from being undefined
to being the ID as a string.
However, this issue would be eliminated by solving the first problem. This is only really a problem because you suggested it as a workaround to the first issue. If everything returned properly when called immediately, then the push subscription listener wouldn't need to be called unless something actually changed.
I hope this is helpful in laying everything out and establishing what the actual issue is.
Hi @terreng,
I see, thanks for your feedback, and I understand the issues here better.
The crux of the problem is that on cold starts, the SDK defaults OneSignal.User.pushSubscription.id
to undefined
and OneSignal.Notifications.hasPermission()
to false
, before it goes over the native bridge to get these values after OneSignal.initialize()
is called. So, there is the delay in their availability after the SDK is initialized. Then, these values may be set, or they may not be set if the push subscription ID is truly still not yet available.
- Fix the underlying problem so that
window.plugins.OneSignal.User.pushSubscription.id
(andwindow.plugins.OneSignal.Notifications.hasPermission()
) are both immediately available inside Cordova'sdeviceready
event.
This is not a solution the SDK can implement. The SDK should only start operating after it is initialized by the app developer and should not hold up the deviceready
event. On the first app installation, the SDK makes requests after initialization and the push subscription ID is generated and returned by the server. This can be delayed for many reasons.
- Go back to using promises so they can wait to resolve until the values become available.
This is probably the best option for the SDK to implement, and resolve these promises after going over the native bridge to retrieve these values. If the push subscription ID is not yet available, the promise will resolve with null
and the push subscription listener will trigger in this case. See below.
We removed promises for hasPermission
and pushSubscription.id
to simplify the API but you point out the flaw in this implementation.
- Leave them in their weird broken state, but fix the push subscription listener so that we can be notified when they become available. And add this to the documentation.
I understand the reported issue with the push subscription listener now. It will fire from the native SDK when there is truly a change in values. This means it will fire on the first app installation when the push subscription ID is generated and received by the SDK. But on subsequent cold starts, it will not fire as there is no change in values in the native OneSignal SDK. However, the OneSignal Cordova SDK does have a change in value from undefined
to a string, but this is not due to values themselves changing but from retrieving the value over the native bridge.
We will consider a solution, and it is likely to be # 2 above.
Terrific! Looking forward to a solution. I agree that # 2 makes the most sense.
I agree to # 2 !
Just came across. Option 2 seems the best for me as well. Any plans for implementing that already?
Does this situation explain why OneSignal.User.pushSubscription.optedIn
is always false
even though notifications are being successfully received?
Does this situation explain why
OneSignal.User.pushSubscription.optedIn
is alwaysfalse
even though notifications are being successfully received?
To answer my own question - yes it does!
Can you let me know when do you add the push subscription event listener?
It might be easier if you tell us (or point to the documentation that tells us) when the correct time is to add the listener?
Hi @kpturner thanks for your question,
It might be easier if you tell us (or point to the documentation that tells us) when the correct time is to add the listener?
There isn't one universal recommendation. Here are some scenarios that SDK users can adopt:
OneSignal.initialize
.OneSignal.User.pushSubscription.id
and it returns null
, undefined
, or empty string, then add the listener to be notified of changes.We will be adding async methods to get token, subscription ID, and optedIn status, so these values should return the actual value more consistently instead of undefined
.
With regard to async methods and optIn
and optOut
can you shed any light on this: https://github.com/OneSignal/OneSignal-Cordova-SDK/issues/967 ?
That aside, in our own code we add the change
listener after having run initialize
but it cannot be relied upon to tell us when the subscription id is available because it doesn't fire unless something specific in the subscription changes (as discussed earlier in this issue). The only way to get the subscription id after initialize
is to create your own timer/loop until it returns something.
Hi everyone, the latest release Release 5.1.0 contains 4 new async getters that will return accurate data. It is recommended to replace your older non-async getters with these new ones:
await OneSignal.Notifications.getPermissionAsync()
await OneSignal.User.pushSubscription.getIdAsync()
await OneSignal.User.pushSubscription.getTokenAsync()
await OneSignal.User.pushSubscription.getOptedInAsync()
@nan-li these new functions work great! One question: What can be the reason for the push subscription id to be null?
Hi @EinfachHans,
One question: What can be the reason for the push subscription id to be null?
The push subscription ID can typically be null
on new app installs where the SDK has not been able to make the successful request to the server yet to create a user. This can happen when there is no network connection or other rare reasons. Eventually, when the ID is received, the SDK will fire the push subscription observer to notify you.
It can also be null
if the user or subscription has been deleted.
@nan-li i experienced sone errors in my app, because the id is null.
This happens for example every time on the first app start after an app deinstallation and re-installation. But: While the subscription is null in the sdk, it is shown in the dashboard. And after a re-open of the app it exists as well.
Any thoughts about this? Feels like a bug in the sdk to me.
@EinfachHans This can be as expected depending on when you get the subscription ID.
On the first app open of a new installation or re-installation, there is no local SDK data to get the ID from, and a network request must be made to register the device. If you get the ID too early, it will be null
.
Are you checking the dashboard at the exact time you are calling the getter, or only after calling the getter? If it is available in the dashboard and then you call the subscription ID getter, it should not return null
. Can you confirm this?
You can use the Push Subscription Listener to be notified when the ID is available on new installs.
I was trying to work with the new available async methods using promises instead await
and it seems not to work properly, this code doesn't work for me:
OneSignal.User.pushSubscription.getIdAsync().then((userId) => {
console.log(userId); // value is not available here
});
The same code using await
works:
const userId = await OneSignal.User.pushSubscription.getIdAsync();
console.log(userId); // this works
I've reviewed the docs, but those methods are not included on them: https://documentation.onesignal.com/docs/mobile-sdk-reference
How can we help?
Hello there, I am new on using this version (5.0.0). I did initialisation on my but I can't get subscription ID.
What we did on loading page
window.plugins.OneSignal.initialize(my_app_id) let id = window.plugins.OneSignal.User.pushSubscription.id; console.log(id);
What I get ?
undefined
And it always undefined,What I'm using now
Question : How do I get subscription ID from every users?
Code of Conduct