Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[question]: Subscription ID always return as undefined. How do I get my subscription ID? #918

Open
1 task done
daksamedia opened this issue Sep 26, 2023 · 24 comments
Open
1 task done

Comments

@daksamedia
Copy link

daksamedia commented Sep 26, 2023

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

  • Cordova 10.0.0
  • Onesignal Plugin for Cordova 5.0.0

Question :
How do I get subscription ID from every users?

Code of Conduct

  • I agree to follow this project's Code of Conduct
@daksamedia daksamedia changed the title [question]: How do I get my subscription ID? [question]: Subscription ID always return as undefined. How do I get my subscription ID? Sep 26, 2023
@jennantilla
Copy link
Contributor

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!

@nan-li
Copy link
Contributor

nan-li commented Sep 28, 2023

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.

@terreng
Copy link

terreng commented Oct 4, 2023

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.

@brodenbrett
Copy link

brodenbrett commented Nov 3, 2023

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>

@louis123562
Copy link

I can confirm, that using setTimeout or setInterval works... but it is not the nice solution...

@nan-li
Copy link
Contributor

nan-li commented Dec 4, 2023

Hi all, thanks for your responses. I will investigate the push subscription observer not behaving as expected.

@nan-li
Copy link
Contributor

nan-li commented Jan 11, 2024

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?

@nan-li
Copy link
Contributor

nan-li commented Jan 11, 2024

Can you also let us know what devices this is happening on?

I only see one person mention iPhone emulator.

@terreng
Copy link

terreng commented Jan 11, 2024

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:

  1. Fix the underlying problem so that window.plugins.OneSignal.User.pushSubscription.id (and window.plugins.OneSignal.Notifications.hasPermission()) are both immediately available inside Cordova's deviceready event.
  2. Go back to using promises so they can wait to resolve until the values become available.
  3. 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.

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.

@nan-li
Copy link
Contributor

nan-li commented Jan 12, 2024

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.

  1. Fix the underlying problem so that window.plugins.OneSignal.User.pushSubscription.id (and window.plugins.OneSignal.Notifications.hasPermission()) are both immediately available inside Cordova's deviceready 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.

  1. 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.

  1. 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.

@terreng
Copy link

terreng commented Jan 12, 2024

Terrific! Looking forward to a solution. I agree that # 2 makes the most sense.

@louis123562
Copy link

I agree to # 2 !

@EinfachHans
Copy link

Just came across. Option 2 seems the best for me as well. Any plans for implementing that already?

@kpturner
Copy link

kpturner commented Jan 17, 2024

Does this situation explain why OneSignal.User.pushSubscription.optedIn is always false even though notifications are being successfully received?

@kpturner
Copy link

Does this situation explain why OneSignal.User.pushSubscription.optedIn is always false even though notifications are being successfully received?

To answer my own question - yes it does!

@kpturner
Copy link

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?

@nan-li
Copy link
Contributor

nan-li commented Jan 29, 2024

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:

  1. Adding the listener always in initialization code after calling OneSignal.initialize.
  2. If they are looking for data like 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.

@kpturner
Copy link

kpturner commented Jan 29, 2024

With regard to async methods and optIn and optOut can you shed any light on this: #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.

@nan-li
Copy link
Contributor

nan-li commented Mar 8, 2024

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()

@EinfachHans
Copy link

@nan-li these new functions work great! One question: What can be the reason for the push subscription id to be null?

@nan-li
Copy link
Contributor

nan-li commented Apr 1, 2024

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.

@EinfachHans
Copy link

@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.

@nan-li
Copy link
Contributor

nan-li commented Apr 15, 2024

@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.

@qmarcos
Copy link

qmarcos commented Jul 24, 2024

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants