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

No easy way to stack push notifications #190

Closed
miracle7 opened this issue Mar 3, 2016 · 33 comments
Closed

No easy way to stack push notifications #190

miracle7 opened this issue Mar 3, 2016 · 33 comments

Comments

@miracle7
Copy link

miracle7 commented Mar 3, 2016

Google sent our company an email advising us to combine received push notifications to increase our chances of being featured on the play store, however as far as I can tell the only way to do this is to create a native plugin for unity and create your own custom handler that way.

I asked for assistance on Stack Overflow but no one has answered yet:
http://stackoverflow.com/questions/35738661/stack-android-push-notifications-in-parse-unity

Is this something that can be provided by Parse? If not, what do I need to do to achieve this myself?
As outlined in my Stack Overflow post, my best guess is that I have to basically make my own copy of ParsePushUnityHelper.java, bundle it up as a .jar using Android Studio, which I then add as a Unity Native Plugin, then hook that up in a similar way to PushBehaviour.cs.

Any help would be greatly appreciated, since we may not be able to use the functionality I have been working on for the past month if we can't get this to work.

@richardjrossiii
Copy link
Contributor

No, this is not something we have built into our Unity SDK right now, you will have to roll your own.
We may consider such a feature in the future, but for the meantime we've not seriously looked into it.

You seem to be on the correct track, as that's exactly how you I would handle that situation.
If you have any more concrete questions about hooking this up, feel free to ask.

(I'll close this issue purely for bookkeeping reasons - feel free to continue the discussion here. If you'd like to make this a proper feature request, feel free, but it'd probably be pretty far down the backlog.)

@miracle7
Copy link
Author

miracle7 commented Mar 8, 2016

I have been successful in getting my own custom push notifications to show through the use of a native plugin which contains my subclass of BroadcastReceiver which is a good start, though it doesn't do any of the fancy wakelock stuff you guys are doing or anything.

My next step is to store a list of received parse notifications so I can update the local inbox style notification summary accordingly, but it seems BroadcastReciever is created and destroyed each time a notification comes through, so I can't do it there.

I was thinking the easiest way to do this would be to append received messages to a file when we receive them, then regenerate the summary notification by reading that file.

I think this would work, but that file needs to be cleared whenever the user cancels or clicks the notification. My understanding of all this native android stuff is still quite primitive at this point so I am not sure how to bundle up that cache clearing code as an activity/intent to pass to DeleteIntent, or whether that is even the correct way to go about it.

I hope someone can help point me in the right direction, this is driving me crazy having to do so much work for such a small thing haha

@richardjrossiii
Copy link
Contributor

So, if my native android memory is correct, you could simply have your DeleteIntent your broadcast service with a different action (such as Intent.ACTION_DELETE), and when you get an intent with that action type, you can simply delete the cache file.

Of course, this is all my memory from very early versions of GCM and android, so YMMV, but maybe it will point you on the right trail.

@miracle7
Copy link
Author

miracle7 commented Mar 9, 2016

Okay, thanks for that, the stacking is working now.

I now have a problem where an Installation is not created if I use com.company.MyParseReceiver instead of com.parse.ParsePushBroadcastReceiver in my android manifest xml.

This means that I can only get push notifications if I first install the app using com.parse.ParsePushBroadcastReceiver, and then reinstall using my own broadcast receiver. If I try without doing this first, I get the following error in the web UI:
image

If I forcibly save an installation it does the same thing since the device token is undefined.
image

What do I need to do to fix this?

@miracle7
Copy link
Author

@richardjrossiii Should I make a new issue for this since it is not really related to stacking specifically?

@richardjrossiii
Copy link
Contributor

No, handling the GCM registration ID is something your custom receiver must implement. It should be as straightforward as just taking the implementation from here:

https://github.com/ParsePlatform/Parse-SDK-dotNET/blob/master/ParsePush/Native/src/main/java/com/parse/ParsePushService.java#L153

@miracle7
Copy link
Author

Does that mean I have to implement my own IntentService too?
I am currently only subclassing ParsePushBroadcastReceiver.

@miracle7
Copy link
Author

Maybe I would be better off just grabbing this entire folder and changing the names/functionality as required rather than trying to do my own thing.

I just don't know how much of that is required, and was hoping to avoid adding code that isn't even used.

@miracle7
Copy link
Author

I downloaded the files in this folder and compiled them into my own .jar, and replaced ParsePush.jar in the android sample project with that, but even that doesn't work.

Same behaviour of no install created.

I am totally stumped here, managers are starting to get impatient so prompt response would be greatly appreciated.

@miracle7
Copy link
Author

Okay, the problem when literally copying that folders contents is that it was missing the icon, which was causing it to fail. If I redirect that to somewhere valid in the manifest it works.

Still not sure why it wasn't working using my custom names, but for now I guess this will do.

@richardjrossiii
Copy link
Contributor

Awesome that you got it working! Let me know if there's anything else I can help with.

@miracle7
Copy link
Author

Hey Richard,

This has been working pretty seamlessly since I got it working, however since migrating to Parse Server hosted on Heroku + mLab, Installations no longer seem to have the 'devicetoken' field, and I have no way of knowing how far push notifications are getting since there is no delivery report on the open source dashboard:

image

I have added my GCM sender ID and GCM API key to my application as per the instructions here, as well as change the 'PARSE_GCM_SENDER_ID' variable in my custom 'ParsePushService', and added my new ID to my manifest.

Please help me get push notifications working again on Parse Server, I don't know where to begin troubleshooting something like this.

@richardjrossiii
Copy link
Contributor

Which version of the client SDK are you running with? Its possible there's a client-side bug here...

@miracle7
Copy link
Author

I am running a slightly modified version of 1.7.0 to allow me to specify a custom server in parse initialize behavior.

I went to do this myself but then found this fork where someone needed to do the same thing (including compiling seperate dlls for android and ios):
https://github.com/supersolid/Parse-SDK-dotNET/branches

I found that fork while browsing this issue:
#166

@miracle7
Copy link
Author

Also all other parse functionality appears to be working as far as I can tell.

@richardjrossiii
Copy link
Contributor

Sounds like a back-end bug, then. I'd check on the REST requests being sent by the clients and see if deviceToken is included there. Otherwise, not sure how to test/verify why this would have stopped working....

@miracle7
Copy link
Author

miracle7 commented Apr 19, 2016

Been playing around with this more today, and I found that I am getting the following error in the logs:
http://pastebin.com/9q0eZd1J

I am assuming this is out of date with the manifest info listed here:
https://github.com/ParsePlatform/parse-server/wiki/Push

I have tried various combinations of the two in my manifest but with no luck yet.
Here is what my manifest looks like at the moment. Am I missing something?
http://pastebin.com/zmfRwysL

I am totally stuck here, is there an example of push notifications working with Unity and Parse Server somewhere that I could reverse engineer to work with my parse server?

@miracle7
Copy link
Author

I am wondering whether it has something to do with this?
a63ebd3

@miracle7
Copy link
Author

If I have my manifest like this:
http://pastebin.com/ihhyW2uj

And set PARSE_GCM_SENDER_ID in my custom plugin to my own Sender ID, I get the following messages in adb logcat, the install appears, but still no device token and no push notifications seem to get through.

I/ParsePushService(12481): GCM registration successful. Registration Id: APA91bHHTULJMr18BRXZTIWRXOXnGLo5orHCoyxdgEiTknUuDU7Dg0XLTAhogQ0kRXQtmj__xxAnD7gm3dRVyc6mPBwX68SGVsLNlH9mtxjrEqy_SDo-cp3WAcz0mB_bKY5I3HZX2t4Q

I/ParsePushService(12481): GCM registration is handled while the app is foregrounded.

I really need to get this working, we have been working on this feature for a long time now and my bosses are getting impatient.

@miracle7
Copy link
Author

One more piece of information:

ParseInstallation.CurrentInstallation does appear to have information such as the device token when I log it out, but only certain fields are saved when I call ParseInstallation.CurrentInstallation.SaveAsync() as shown below:

image

@miracle7
Copy link
Author

Okay... Apparently the other columns ARE being saved when I checked my mongodb installation directly, but not being displayed in the new parse dashboard???

image

So in theory I should have everything I need to send push notifications, but sending them through the dashboard has not been working and I have no way to check the status of push notifications that I have already sent. That being said, I no longer trust the self hosted dashboard since it is not showing me the whole picture. No idea what is going on or how to fix it.

@miracle7
Copy link
Author

Sorry for the spam, but just want to keep this updated for anyone else who runs into these problems and to avoid people wasting time on stuff I have already figured out.

I managed to get a push notification to be sent via my server using CURL, but the device isn't displaying it (which is presumably a problem with my custom version of plugin).

Getting this in the logs, looking into it now:

I/ParsePushService(13959): Push notification received. Payload: {"title":"The Shining","alert":"All work and no play makes Jack a dull boy."}

E/art (13959): No implementation found for void com.unity3d.player.UnityPlayer.UnitySendMessage(java.lang.String, java.lang.String, java.lang.String) (tried Java_com_unity3d_player_UnityPlayer_UnitySendMessage and Java_com_unity3d_player_UnityPlayer_UnitySendMessage__Ljava_lang_String_2Ljava_lang_String_2Ljava_lang_String_2)

@miracle7
Copy link
Author

miracle7 commented Apr 20, 2016

I believe this issue was being caused by me not including my icons in Assets\Plugins\Android\res in my unity project, I finally got a push notification to come through! :D

Getting another issue where my Parse Installation won't save in the main app rather than the little test I set up, but I think that is caused due to the application being backgrounded right after parse initialize is called, should be able to figure that one out on my own.

@richardjrossiii
Copy link
Contributor

Spam away! Its awesome to see people passionate about this stuff. Some of the errors you were seeing might be related to #195, which is probably required to make custom GCM senders work (with parse-server).

@miracle7
Copy link
Author

miracle7 commented Apr 20, 2016

Well, I got it working with a test app today at least, but it is still failing in our actual game :(

The installation doesn't seem to be missing any fields, but the saved _PushStatus says it failed.
Do you know if there is a way to get more information as to why it doesn't get through?

The manifest has everything the test app does as well, so I am pretty confused :(

_Installation

{
"_id": "PqwebAszih",
"installationId": "b6d704ae-163c-4c01-9a12-29697b4872e2",
"deviceToken": "APA91bHJmLfBo0MD3Dch5mybAu2pzhqXiHRGd9OqydZN-9FQB_iNb_SicYEmTRxDPq60ikScP4rye94bsC1ylcQIOk15aplMHV6shsDwsFjvtRgI2q9x0tXlU-OG-wRMTynZLz8WL3FG",
"pushType": "gcm",
"deviceType": "android",
"localeIdentifier": "iv",
"parseVersion": "1.7.0.0",
"appVersion": "1.7.1",
"appName": "My Game",
"badge": 0,
"_updated_at": {
"$date": "2016-04-20T07:52:33.876Z"
},
"_created_at": {
"$date": "2016-04-20T07:52:33.876Z"
}
}

_PushStatus

{
"_id": "DsjPpetAiC",
"pushTime": "2016-04-20T07:52:53.639Z",
"_created_at": {
"$date": "2016-04-20T07:52:53.639Z"
},
"query": "{}",
"payload": "{"alert":"last test"}",
"source": "rest",
"status": "succeeded",
"numSent": 0,
"pushHash": "319cd35824c43d35af8714611e44970d",
"_wperm": [],
"_rperm": [],
"numFailed": 1,
"failedPerType": {
"android": 1
}
}

@miracle7
Copy link
Author

It seems as if the device token generated for our actual app is incorrect...

I don't know much about how this stuff works internally, but if I get the device token generated by my test app, and replace that in the actual apps installation, the push notification comes through fine.

The 'failed' result is in the database before the push notification would normally come through as well, so it seems there is some kind of check going on there that can determine whether it is valid or not.

Any ideas on how to fix that?

@richardjrossiii
Copy link
Contributor

Hmm. We upload the deviceToken directly from the results of the GCM callback, which would indicate that there's something wrong with the push registration code. Did you perhaps touch this in the process of your fork?

@miracle7
Copy link
Author

Both the test app and the actual game are using the same modified Parse SDK (to add server field) and custom push handler plugin.

The only thing I changed in terms of registration is that I replaced the value of PARSE_GCM_SENDER_ID in ParsePushService to my own GCM sender id, since I couldn't get it to pass it in through the manifest and there were problems with registering multiple sender ids.

@miracle7
Copy link
Author

Okay, finally figured this out, we have another native java plugin in our app, but last time someone compiled that they accidentally bundled custom notification handler into it as well (which meant using old PARSE_GCM_SENDER_ID), which was being used instead of the new one I compiled.

Such a dumb error, but I was able to figure it out pretty quickly after enabling verbose logs in Heroku, which shows the gcm response and it said 'mismatching id' or something like that.

@richardjrossiii
Copy link
Contributor

Awesome to see that you've figured it out. Let me know if I can help any further.

@miracle7
Copy link
Author

miracle7 commented May 4, 2016

Hey @richardjrossiii, thanks again for your help, for the most part this has been working well and we will be pushing the update live in a few weeks as a result.

I have an issue where you can end up with multiple Installations on parse from the same device by reinstalling the app, which results in them receiving duplicate push notifications. It would be pretty bad for people to get an extra notification for each time they update or otherwise reinstall the application.

My plan was to save the device id to the installation, then delete any installations with a matching id in the installation 'afterSave' callback in cloud code. Problem is, I am not sure how to get that device id for both android and iOS and add that to the installation.

Do you have any suggestions on how to ensure a device does not register for multiple push notifications in a Unity app?

@miracle7
Copy link
Author

miracle7 commented May 5, 2016

It seems in 1.7 the installation is saved as part of ParseInitializeBehaviour (which makes sense I guess).

Since I have to work off a custom build anyway to support self hosted parse server, I suppose I could just add something like: installation["deviceId"] = SystemInfo.deviceUniqueIdentifier; before we save it there, then do what I was saying above on afterSave.

@miracle7
Copy link
Author

miracle7 commented May 5, 2016

The above solution seems to work, though one of the other developers here says that the app will ask for phone call permissions if we ask for this unique identifier which is lame, but I don't have a better solution at this time.

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

2 participants