0

I have developed android where I am using GCM to send notification.

I am facing one problem that i will explain by taking an example.

Let's say user A logging in my app. So I generate token for that user let's say that is "AA1" using GCM and storing it our database. But then if user uninstall app and install it again. Then I am generating token again (Lets say AA2) and storing in our server.

If both tokens are same then it will not cause any issue as I am comparing before inserting a token. But as GCM tokens for same device can differ. Right ?

Later, When I want to send a notification to that user. That user will get notification twice as his previous token is still working. I tried to search but found nothing related to this. It may that I am missing something or none have thought like this.

Doesn't matter which but I think there must a way to solve this issue.

Question

Is there a way to check both the notification tokens belongs to same device or not?

Is there a way to remove notification token from our database when user uninstall apps ?

Please guide me.

keen
  • 3,001
  • 4
  • 34
  • 59

5 Answers5

0

What i think is this problem can be solved this way.

When you are storing Token value to application server, you should map it with users device id. therefore when this token is re-generated (with different value), your application server can update the token for that user as in both cases device id was same.

Sunny Garg
  • 1,073
  • 1
  • 6
  • 13
  • But getting deviceId is not 100 % accurate. just because of this it will cause a problem. from this http://stackoverflow.com/questions/2785485/is-there-a-unique-android-device-id – keen Apr 17 '14 at 13:46
  • Kindly see my new answer posted. – Sunny Garg Apr 17 '14 at 15:54
  • abhi's answer seems to be simple and solution of this issue. What do you think about it? Please give your opinion – keen May 20 '14 at 06:10
0

Is there a way to check both the notification tokens belongs to same device or not?

Not in a unique way. You could make an IP comparison when the user registers and store both the GCM id and their IP address, this way when they connect again you can check whether you already have a registration with that IP address and delete the previous. However, this is not a good 100% solution as there are countries that assign the same IP address to several devices. I think the best approach here is implementing a timeout mechanism. In my apps, when the user registers, they have to send a "keepalive" HTTP POST signal every 30 seconds to say "hey, I'm still here". If that keepalive doesn't arrive in a reasonable amount of time, I consider it a timeout and remove it from the database.

This is, however (now I mean unistallation), one of the cases where you should call the GoogleCloudMessaging.unregister() method and send it also to the third-party server.

Is there a way to remove notification token from our database when user uninstall apps ?

Seems that there's not (Perform a task on uninstall in android). But however, with the above approach, you wouldn't have any further issues as this user would stop sending the "keepalive" notifications and he would be timed-out.

Community
  • 1
  • 1
nKn
  • 13,691
  • 9
  • 45
  • 62
  • What happens when the app is not running? Do you keep a background service that sends this "keepalive" every 30 seconds? This seems very battery wasteful. And if you don't, your app remains registered to GCM only while it's running, which is not very useful (since push notifications were specifically created to alert the user and wake the app when it's not running). – Eran Apr 17 '14 at 16:14
  • Nope, once the app closes, the `Service` is also stopped. I know it was designed for this, but in my case the apps I've developed just need those messages when the app is running, if closed there's no need to deliver them. – nKn Apr 17 '14 at 16:18
  • I think other than issue pointed by @Eran , I don't want to add this much of overhead. Because it will can an api every particular time period. – keen Apr 18 '14 at 04:55
  • abhi's answer seems to be simple and solution of this issue. What do you think about it? Please give your opinion. – keen May 20 '14 at 06:08
0

What we do is generate a unique ID (in our server) for each application instance. The application gets that ID by making an API call after first being installed on the device. We store that ID in external storage (that doesn't get wiped when the app is uninstalled). The registration ID of the device is associated in our DB with our unique ID.

This way, when the app is installed again on the same device, we get that identifier from the external storage (if available) and re-use it, and even if the registration ID is changed, we know it belongs to the same device.

In addition to this strategy, your server should handle the following scenarios :

  1. If you get a canonical registration ID in the response from GCM, delete the old registration ID (if the canonical ID already exists in your DB) or change it to the new canonical ID. This would prevent duplicate messages from being sent again to this device.

  2. If you get NotRegistered error in the response from GCM, delete the registration ID you attempted to send from the DB. This means the application was uninstalled. There is no other way to detect that the user uninstalled the app.

Eran
  • 387,369
  • 54
  • 702
  • 768
  • What do you do if the device has no external storage? – nKn Apr 17 '14 at 14:11
  • @nKn Obviously this solution works only for devices with external storage, which are the vast majority of devices in the market. – Eran Apr 17 '14 at 14:45
  • abhi's answer seems to be simple and solution of this issue. What do you think about it? Please give your opinion. – keen May 20 '14 at 06:10
0

Agree with you. But still there is a solution. what you can do is, you can use device IMEI number as device id and use it. This IMEI number will never change even if on factory reset. How to get unique device hardware id in Android?

 TelephonyManager telephonyManager = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
 telephonyManager.getDeviceId();

Also add the below manifest permission.

<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
Community
  • 1
  • 1
Sunny Garg
  • 1,073
  • 1
  • 6
  • 13
  • That assumes that the device is a phone, which is pretty adventurous. – nKn Apr 17 '14 at 15:57
  • Yes i understand. But i don't think there is anything wrong in using IMEI number. – Sunny Garg Apr 17 '14 at 16:00
  • Nope, you don't understand. If the device is not a phone, it doesn't have an IMEI code, so this approach will fail. – nKn Apr 17 '14 at 16:02
  • Ohh you are right. Please see below link http://technet.weblineindia.com/mobile/getting-unique-device-id-of-an-android-smartphone/ as per this link i think WLAN or bluetooth address can be used as almost all devices has bluetooth and wifi card. – Sunny Garg Apr 17 '14 at 16:08
0

One Solution I think would be to send a pushnotification key with every notification. Handle this on your client side by keeping a last pushnotification key used in shared prefs. If you get the same notification key again drop it.

Abhi
  • 11
  • 1
  • This seems to be good idea. Let me get opinion of other people. – keen May 20 '14 at 06:09
  • Giving a little more thought. You also don't have to change server side logic. Just generate a hash out of notification string on client side and save. Drop notifications if hash matches the last hash. – Abhi May 22 '14 at 05:32