Every one I am using the parse service for push notification in my app. but it register all time when i re-install the app in one device.Then problem is that,one device receive multiple notifications on each. I have done some code for registration which is shown below. please help me,thanks in advance.
Parse.initialize(this, PARSE_APP_ID, PARSE_CLIENT_KEY);
ParseACL defaultACL = new ParseACL();
defaultACL.setPublicReadAccess(true);
ParseACL.setDefaultACL(defaultACL, true);
PushService.setDefaultPushCallback(this, MainActivity.class);
ParseInstallation.getCurrentInstallation().getInstallationId();
ParseInstallation.getCurrentInstallation().saveInBackground();
And for subscribe:
PushService.subscribe(this, userName, Detail.class);
In Manifest
Above
<permission
android:name="com.example.app.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.example.app.permission.C2D_MESSAGE" />
In application tag:
<receiver android:name="com.parse.ParseBroadcastReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.USER_PRESENT" />
<action android:name="act" />
</intent-filter>
</receiver>
<receiver android:name="com.app.example.PushReceiver" >
<intent-filter>
<action android:name="act" />
</action>
</intent-filter>
</receiver>
<receiver
android:name="com.parse.GcmBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<action android:name="act" />
<category android:name="com.example.app" />
</intent-filter>
</receiver>
And each time when I am Install, it show error which is shown below.
03-10 12:18:48.555: E/ParseCommandCache(12709): Failed to run command.
03-10 12:18:48.555: E/ParseCommandCache(12709): com.parse.ParseException: at least one ID field (installationId,deviceToken) must be specified in this operation
03-10 12:18:48.555: E/ParseCommandCache(12709): at com.parse.ParseCommand$3.then(ParseCommand.java:348)
03-10 12:18:48.555: E/ParseCommandCache(12709): at com.parse.Task$10.run(Task.java:452)
03-10 12:18:48.555: E/ParseCommandCache(12709): at com.parse.Task$1.execute(Task.java:68)
03-10 12:18:48.555: E/ParseCommandCache(12709): at com.parse.Task.completeImmediately(Task.java:448)
03-10 12:18:48.555: E/ParseCommandCache(12709): at com.parse.Task.continueWith(Task.java:322)
03-10 12:18:48.555: E/ParseCommandCache(12709): at com.parse.Task.continueWith(Task.java:333)
03-10 12:18:48.555: E/ParseCommandCache(12709): at com.parse.Task$8.then(Task.java:385)
03-10 12:18:48.555: E/ParseCommandCache(12709): at com.parse.Task$8.then(Task.java:1)
03-10 12:18:48.555: E/ParseCommandCache(12709): at com.parse.Task$11.run(Task.java:485)
03-10 12:18:48.555: E/ParseCommandCache(12709): at com.parse.Task$1.execute(Task.java:68)
03-10 12:18:48.555: E/ParseCommandCache(12709): at com.parse.Task.completeAfterTask(Task.java:481)
03-10 12:18:48.555: E/ParseCommandCache(12709): at com.parse.Task.access$9(Task.java:477)
03-10 12:18:48.555: E/ParseCommandCache(12709): at com.parse.Task$7.then(Task.java:350)
03-10 12:18:48.555: E/ParseCommandCache(12709): at com.parse.Task$7.then(Task.java:1)
03-10 12:18:48.555: E/ParseCommandCache(12709): at com.parse.Task.runContinuations(Task.java:514)
03-10 12:18:48.555: E/ParseCommandCache(12709): at com.parse.Task.access$5(Task.java:510)
03-10 12:18:48.555: E/ParseCommandCache(12709): at com.parse.Task$TaskCompletionSource.trySetResult(Task.java:569)
03-10 12:18:48.555: E/ParseCommandCache(12709): at com.parse.Task$TaskCompletionSource.setResult(Task.java:603)
03-10 12:18:48.555: E/ParseCommandCache(12709): at com.parse.Task$11$1.then(Task.java:497)
03-10 12:18:48.555: E/ParseCommandCache(12709): at com.parse.Task$11$1.then(Task.java:1)
03-10 12:18:48.555: E/ParseCommandCache(12709): at com.parse.Task$10.run(Task.java:452)
03-10 12:18:48.555: E/ParseCommandCache(12709): at com.parse.Task$1.execute(Task.java:68)
03-10 12:18:48.555: E/ParseCommandCache(12709): at com.parse.Task.completeImmediately(Task.java:448)
03-10 12:18:48.555: E/ParseCommandCache(12709): at com.parse.Task.access$8(Task.java:444)
03-10 12:18:48.555: E/ParseCommandCache(12709): at com.parse.Task$6.then(Task.java:315)
03-10 12:18:48.555: E/ParseCommandCache(12709): at com.parse.Task$6.then(Task.java:1)
03-10 12:18:48.555: E/ParseCommandCache(12709): at com.parse.Task.runContinuations(Task.java:514)
03-10 12:18:48.555: E/ParseCommandCache(12709): at com.parse.Task.access$5(Task.java:510)
03-10 12:18:48.555: E/ParseCommandCache(12709): at com.parse.Task$TaskCompletionSource.trySetResult(Task.java:569)
03-10 12:18:48.555: E/ParseCommandCache(12709): at com.parse.Task$TaskCompletionSource.setResult(Task.java:603)
03-10 12:18:48.555: E/ParseCommandCache(12709): at com.parse.Task$11$1.then(Task.java:497)
03-10 12:18:48.555: E/ParseCommandCache(12709): at com.parse.Task$11$1.then(Task.java:1)
03-10 12:18:48.555: E/ParseCommandCache(12709): at com.parse.Task$10.run(Task.java:452)
03-10 12:18:48.555: E/ParseCommandCache(12709): at com.parse.Task$1.execute(Task.java:68)
03-10 12:18:48.555: E/ParseCommandCache(12709): at com.parse.Task.completeImmediately(Task.java:448)
03-10 12:18:48.555: E/ParseCommandCache(12709): at com.parse.Task.continueWith(Task.java:322)
03-10 12:18:48.555: E/ParseCommandCache(12709): at com.parse.Task.continueWith(Task.java:333)
03-10 12:18:48.555: E/ParseCommandCache(12709): at com.parse.Task$11.run(Task.java:489)
03-10 12:18:48.555: E/ParseCommandCache(12709): at com.parse.Task$1.execute(Task.java:68)
03-10 12:18:48.555: E/ParseCommandCache(12709): at com.parse.Task.completeAfterTask(Task.java:481)
03-10 12:18:48.555: E/ParseCommandCache(12709): at com.parse.Task.access$9(Task.java:477)
03-10 12:18:48.555: E/ParseCommandCache(12709): at com.parse.Task$7.then(Task.java:350)
03-10 12:18:48.555: E/ParseCommandCache(12709): at com.parse.Task$7.then(Task.java:1)
03-10 12:18:48.555: E/ParseCommandCache(12709): at com.parse.Task.runContinuations(Task.java:514)
03-10 12:18:48.555: E/ParseCommandCache(12709): at com.parse.Task.access$5(Task.java:510)
03-10 12:18:48.555: E/ParseCommandCache(12709): at com.parse.Task$TaskCompletionSource.trySetResult(Task.java:569)
03-10 12:18:48.555: E/ParseCommandCache(12709): at com.parse.Task$TaskCompletionSource.setResult(Task.java:603)
03-10 12:18:48.555: E/ParseCommandCache(12709): at com.parse.Task$3.run(Task.java:228)
03-10 12:18:48.555: E/ParseCommandCache(12709): at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422)
03-10 12:18:48.555: E/ParseCommandCache(12709): at java.util.concurrent.FutureTask.run(FutureTask.java:237)
03-10 12:18:48.555: E/ParseCommandCache(12709): at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:152)
03-10 12:18:48.555: E/ParseCommandCache(12709): at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:265)
03-10 12:18:48.555: E/ParseCommandCache(12709): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
03-10 12:18:48.555: E/ParseCommandCache(12709): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
03-10 12:18:48.555: E/ParseCommandCache(12709): at java.lang.Thread.run(Thread.java:841)
I want to register only one time for on device. there should be not an issue if app installed multiple time in device.please help me, thanks in advance.
In my case samsung tab 3 registers twice with same UniqueId. Is UniqueId is marked as unique column in parse db? Or we should make it unique? if yes, how?
PushService.subscribe
seems to cache the subscription in local storage, to avoid re-subscribing when you launch the app multiple times.This is what the first parameter of that method is used for :
(quote from here).
However, when you uninstall the app, local storage for that app is wiped from your device, so the new installation will cause
PushService.subscribe
to re-register to Google Cloud Messaging. If the new registration returns a new registration ID, Parse would have two registration IDs that can be used to send push notifications to your app, and both of them would be linked to the same userName you supplied tosubscribe
. Therefore sending a notification to that userName will send it to both registration IDs, causing it to arrive twice.When Parse send the notifications for you, they should get from Google a response with
canonical_registration_id
, which will let them know one of the registration IDs associated with your app on your device is old, and should not be used anymore. Therefore (assuming Parse have a decent implementation of GCM) the next time you send a notification to your device, you should receive it only once.I was also facing this issue. I sort of solved it by calling the below method in my Activity's
onCreate()
Even though it didn't completely solve my problem but now my app doesn't hang and no more ANR's due to this Parse implementation. If i re install an app and run it now then the app creates a new installation record and remove's the last one. The only problem is that the channel_name is not subscribed on this run but on the next run the channel are successfully subscribed.
Create new class and extend it with Application. write code in this way
}
Add entry in
manifest
fileWhat worked for me to get rid of this exception was using
saveEventually()
instead ofsaveInBackground()
.Here you have a link to my answer to a similar question.
I think that
saveEventually()
is a better option because it assures that the installation will always be saved, regardless of the netwwork availability. In contrast, withsaveInBackground()
there is a chance that the save fails due to no network connectivity. Also withsaveEventually()
you don't need to do any error checking, which you should do in aSaveCallback()
withsaveInBackground()
.Regarding the duplicate notifications, this shouldn't occur if you are using the latest Parse SDK (it doesn't happen to me with 1.7.1). There was a bug that has been solved now. See this SO question and this FB bug.
Note that first time the user receives a notification after reinstalling the app, this notification can be delivered twice. It has happened to me, but only happens for the very first notification. (See the FB link for more details.) After that duplicate notification, the old installation will be removed automatically by Parse. This is my experience.
If you are trying to avoid sending duplicate notifications by implementing some logic at the CloudCode (using a beforeSave that triggers when saving a new Installation, check if the app had already been installed into the device and deleting the old installation), don't do that! There is not need. Parse will do it for you: it will delete the old installation :)
I got it after update the table with the send of unique id of the android device.
It will update the raw ,but it doesn't re-register the device .
I think Mukul has provided great cloud code for this issue
here it is
Note that owner is the username or the primary key that you think u can use.
here's the link of the same with better explanation by mukul https://www.parse.com/questions/check-for-duplicate-installations-of-same-user-on-re-installation-of-app