I'm developing a NativeScript app which involves push notifications.Whenever push notification came I need to store notification contents into database.
For that I have written some code in "onMessageReceived" function.This code is in the page in which GCM registration code is there.
If app is running then every thing working fine. The problem is if app is closed then "onMessageReceived" function is not even executing(I checked with console logs).
So for that I'm trying to place "onMessageReceived" function in app.js so that even app is closed it will execute.For that I'm trying to import the "nativescript-push-notifications" in app.js, but getting error saying "application is null,it's not passed correctly".Below is my app.js code.
app.js
var application = require("application");
var gcm=require("nativescript-push-notifications");
if(gcm.onMessageReceived) {
gcm.onMessageReceived(function callback(data) {
console.log("message received:::: ", "" + JSON.stringify(data));
storeInDatabase(data);// some function to store notification content into db.
});
}
application.mainModule="main-page";
application.start({ moduleName: "main-page" });
Can we import "nativescript-push-notifications" reference in app.js??
Any suggestions will be helpful.Thanks.
Application is null because your app has not started yet try adding the plugin in the application launch event
var application = require("application");
application.start({ moduleName: "main-page" });
application.on(application.launchEvent, function (args) {
if (args.android) {
var gcm = require("nativescript-push-notifications");
gcm.register({ senderID: 'conversate-1148' }, function (data) {
self.set("message", "" + JSON.stringify(data));
}, function () { });
if (gcm.onMessageReceived) {
gcm.onMessageReceived(function callback(data) {
console.log("message received:::: ", "" + JSON.stringify(data));
storeInDatabase(data);// some function to store notification content into db.
});
}
} else if (args.ios !== undefined) {
//Do ios stuff here
}
});
In addition to Osei's code you might want to check out your AndroidManifest.xml file (generated in your platforms/android folder) and make sure the following permissions are set :
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
and also that the plugin is registered as a service in the same AndroidManifest.xml file as follows:
<activity android:name="com.telerik.pushplugin.PushHandlerActivity"/>
<receiver android:name="com.google.android.gms.gcm.GcmReceiver" android:exported="true" android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="com.pushApp.gcm" />
</intent-filter>
</receiver>
<service android:name="com.telerik.pushplugin.PushPlugin" android:exported="false" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>
Related
I am struggling to find the cause for the duplicate notification message on android using Firebase, Unity and sending from nodejs with the help of node-gcm.
Here is all relative code:
Unity3d client side I got:
public class PushServiceManager : MonoBehaviour
{
public string Identifier;
public string SkuId;
public SQSParameters sqsOptions;
private SQSManager sqs;
// Use this for initialization
void Start()
{
sqs = new SQSManager(this.sqsOptions);
sqs.Initialize(this.gameObject);
Firebase.Messaging.FirebaseMessaging.TokenReceived += OnTokenReceived;
Firebase.Messaging.FirebaseMessaging.MessageReceived += OnMessageReceived;
}
public void OnTokenReceived(object sender, Firebase.Messaging.TokenReceivedEventArgs token)
{
Debug.Log("Received Registration Token: " + token.Token);
RegistrationToken t = new RegistrationToken();
t.id_token = token.Token;
// sends token to node server
sqs.SendRegistrationToken(t);
}
public void OnMessageReceived(object sender, Firebase.Messaging.MessageReceivedEventArgs e)
{
Debug.Log(e.Message.Data.ToString());
}
}
Nodejs server side:
pushNotification(pushRequest, tokens, callback) {
// This is an array of firebase tokens
let registrationTokens = tokens.map(function (token) {
return token.token;
});
let message = new gcm.Message({
timeToLive: pushRequest.ttl
});
let note = {
title: 'Message title',
icon: 'none',
sound: 'none',
body: 'message text'
};
message.addNotification(note);
let payload = {
data: {foo: "foo"}
}
message.addData(payload);
this.sender.send(message, {registrationTokens}, callback);
}
Result on device is:
Question:
Why do I get the second empty push notification?
Tapping first one opens up a unity game as expected but tapping that empty one does not.
Where am I going wrong with this?
Thank you!
01.31.17 UPDATE:
Shutout to firebase support team for looking into this issue...
I have the same duplicate notifications issue in my project and below is the solution.
Check your generated AndroidManifest.xml by unity build in [Your unity project folder]\Temp\StagingArea
Look for all receivers that have below line:
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
In my case, I have below that added by the Amazon AWS unity plugin
<receiver android:name="com.amazonaws.unity.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" />
<category android:name="com.amazonaws.unity" />
</intent-filter>
</receiver>
and below from Firebase plugin
<receiver android:exported="true" android:name="com.google.firebase.iid.FirebaseInstanceIdReceiver" 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" />
<category android:name="com.bbbbbttttttgggg.sssssstttt" />
</intent-filter>
</receiver>
The duplicated notification is caused by amazon AWS GCMBroadcastReceiver.
There are two options to fix this.
Remove the receiver if you do not need it.
Add android:exported="false" to the receiver.
Example:
<receiver android:exported="false" android:name="com.amazonaws.unity.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" />
<category android:name="com.amazonaws.unity" />
</intent-filter>
</receiver>
Remember to make the change in the original AndroidManifest.xml that contains the receiver. Not the one in Temp\StagingArea. It should be one of the AndroidManifest.xml file inside [Your unity project folder]\Assets\Plugins\Android or it sub folder.
I am facing the same problem with firebase. I am using Firebase together with Microsoft Azure Notification Hub. If I send a test message via Microsoft Notification Hub I only get one message and that message is handled by my Push Handler. Otherwise if I send push notifications through firebase console I am getting two message like you(also one is empty). One message is handled by my push service and the second one is somehow handled by "no code"! I cannot find in my code where the push notification send by firebase is handled? There must be a OnReceiveMessage method in the background which handles the notification. For me I come with following solution: I just uncommented my push handler and now I am only getting one notification, but this without sound...somehow I have to override that function and implement sound behaviour. Have you found a solution for that? The empty message is caused by your push handler the second full message is handled in the background by firebase.
I also getting two different types of message in my onReceive() method:
Microsoft: Bundle[{google.sent_time=1484748187461, from=230XXXXXXXXXX, google.message_id=0:1484748187469719%8a1048bff9fd7ecd, message=Test through Microsoft, collapse_key=do_not_collapse}]
Firebase: Bundle[{google.c.a.udt=0, google.sent_time=1484748603664, gcm.notification.e=1, google.c.a.c_id=3001008833206773803, google.c.a.ts=1484748604, gcm.n.e=1, from=230XXXXXXXXXXX, google.message_id=0:1484748603943016%8a1048bf8a1048bf, gcm.notification.body=Test through firebase, google.c.a.e=1, collapse_key=com.sub_zero.ipostcard}]
So the message received through firebase is handled one time in the background somewhere maybe in through the firebase lib and the second time I suppose by your handler. That why you getting two of them...Just uncomment your push handler and test it again.
I found what was cause this issue...
I had AWS module included into the project which had it's own manifest file. In it there was a receiver declaration for "GCMBroadcastReceiver" in combination with service declaration for "GCMIntentService".
Removing those solved the issue
I am trying to setup a basic Xamarin app with push notifications for Android. I followed the demo here and all seemed to be going well. The application log shows the registration token received using the following code:
using System;
using Android.App;
using Android.Content;
using Android.Util;
using Android.Gms.Gcm;
using Android.Gms.Gcm.Iid;
namespace HawkProject.Droid {
[Service(Exported = false)]
class RegistrationIntentService : IntentService
{
static object locker = new object();
public RegistrationIntentService() : base("RegistrationIntentService") { }
protected override void OnHandleIntent (Intent intent)
{
try
{
Log.Info ("RegistrationIntentService", "Calling InstanceID.GetToken");
lock (locker)
{
var instanceID = InstanceID.GetInstance (this);
var token = instanceID.GetToken (
"1015213323461", GoogleCloudMessaging.InstanceIdScope, null);
Log.Info ("RegistrationIntentService", "GCM Registration Token: " + token);
//SendRegistrationToAppServer (token);
//Subscribe (token);
}
}
catch (Exception e)
{
Log.Debug("RegistrationIntentService", "Failed to get a registration token");
Log.Debug("RegistrationIntentService", e.Message);
return;
}
}
void SendRegistrationToAppServer (string token)
{
// Add custom implementation here as needed.
}
void Subscribe (string token)
{
var pubSub = GcmPubSub.GetInstance(this);
pubSub.Subscribe(token, "/topics/hawkglobal", null);
}
}
}
Application Log returns:
[RegistrationIntentService] Calling InstanceID.GetToken
[RegistrationIntentService] GCM Registration Token: dz8yxsF61tc:APA91bFpHBPsJuGUN2Yh5Hv9CyuAgyIUP4qthhNE79rJUOvLH__ildlVOaP9Q-X1lBpDk69BDRbnzDl4kdEdJBjyudwiVfRZnVR4trQwcM8JZYIEqMNFiXAy61RSjD2MWnC2kmNLj1Ev
My manifest is as follows:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="auto" package="com.gcs.hawkproject" android:versionCode="1" android:versionName="start">
<uses-sdk android:minSdkVersion="15" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="com.gcs.hawkproject.permission.C2D_MESSAGE" />
<permission android:name="com.gcs.hawkproject.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<application android:label="Hawk" android:icon="#drawable/log"></application>
<application android:label="RemoteNotifications" android:icon="#drawable/Icon">
<receiver android:name="com.google.android.gms.gcm.GcmReceiver"
android:exported="true"
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" />
<category android:name="com.gcs.hawkproject" />
</intent-filter>
</receiver>
<service
android:name="com.gcs.hawkproject.MyGcmListenerService"
android:exported="false" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>
<service
android:name="com.gcs.hawkproject.MyInstanceIDListenerService"
android:exported="false">
<intent-filter>
<action android:name="com.google.android.gms.iid.InstanceID"/>
</intent-filter>
</service>
</application>
</manifest>
All seems to be going well, but when i try to send a message, I get the following results:
POST:
{
"data" : { "message" : "This is a test" },
"to" : "dz8yxsF61tc:APA91bFpHBPsJuGUN2Yh5Hv9CyuAgyIUP4qthhNE79rJUOvLH__ildlVOaP9Q-X1lBpDk69BDRbnzDl4kdEdJBjyudwiVfRZnVR4trQwcM8JZYIEqMNFiXAy61RSjD2MWnC2kmNLj1Ev"
}
RESPONSE
{
"multicast_id":5139152955408512939,
"success":0,"failure":1,"canonical_ids":0,
"results": [{"error":"NotRegistered"}]
}
Any thoughts? I am new to both Xamarin and GCM, so I am fumbling around for hours with no success.
I have other code from the demo as well that i can post if necessary.
Thanks in advance.
Change
using Android.Gms.Gcm.Iid;
to
using Android.Gms.Iid;
I would suggest try the following:
(1) Uninstall and Reinstall the application, get a new notification token from GCM, try push to the new token again.
(2) Double check the Project id "1015213323461", is it possible that the sender_id does not match with the server certificate used to send the notification?
(3) com.gcs.hawkproject is this project id matching the one you registered in Google Developer console?
There is a Xamarin Studio deployment issue that result in those NotRegistered errors, my workaround is detailed here.
Is this is a new GCM project? You should be now using FCM - Firebase Cloud Messaging.
From GCM website:
Firebase Cloud Messaging (FCM) is the new version of GCM. It inherits
the reliable and scalable GCM infrastructure, plus new features! See
the FAQ to learn more. If you are integrating messaging in a new app,
start with FCM. GCM users are strongly recommended to upgrade to FCM,
in order to benefit from new FCM features today and in the future.
I think that your GCM key might not be valid now. You should create your FCM project in here:
https://firebase.google.com/docs/cloud-messaging/
I am trying to use parse for push notification in android, I am registering parse in the Application class like this:
#Override
public void onCreate() {
super.onCreate();
Parse.initialize(this, "***************", "***************");
}
I am subscribing to push like this in the main activity:
#Override
protected void onCreate(Bundle savedInstanceState) {
ParsePush.subscribeInBackground("", new SaveCallback() {
#Override
public void done(ParseException e) {
if (e == null) {
ParseInstallation.getCurrentInstallation().saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
if (e == null) {
String deviceToken = (String) ParseInstallation.getCurrentInstallation().get("deviceToken");
Log.e("MainActivity", "device toekn " + deviceToken);
} else {
Log.e("MainActivity", "failed to subscribe for push " + e.getLocalizedMessage());
}
}
});
} else {
Log.e("MainActivity", "failed to subscribe for push", e);
}
}
});
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
And here is my manifest section the apply to parse:
<service android:name="com.parse.PushService" />
<receiver android:name="com.parse.ParseBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.USER_PRESENT" />
</intent-filter>
</receiver>
<receiver android:name="com.parse.ParsePushBroadcastReceiver"
android:exported="false">
<intent-filter>
<action android:name="com.parse.push.intent.RECEIVE" />
<action android:name="com.parse.push.intent.DELETE" />
<action android:name="com.parse.push.intent.OPEN" />
</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" />
<!--
IMPORTANT: Change "com.parse.starter" to match your app's package name.
-->
<category android:name="com.****" />
</intent-filter>
</receiver>
however, device token returns null most of the times and the device has no device token in the parse dashboard, therefor, my device is not getting the push notifications.
The odd part is that sometimes it does work, i do get deviceToken and the installation object does get the push, has anyone encountered this behavior?
This problem was eventually solved, a simple mistake in the Application name in the tag of the manifest in the tag.
since the code i posted here was "com.***" no one could have helped, i apologize.
I encountered this problem and i solved it by modifying my AndroidManifest file.
It appears that you can configure parse to either use "Parse Push Network" or GCM (Google Cloud Message).
Parse uses its own push network for apps that want to avoid a dependency on the Google Play Store, and for devices (like Kindles) which do not have Play Store support.
Thus it is important to set the below in other to use GCM.
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<permission android:name="YOUR_PACKAGE_NAME.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="YOUR_PACKAGE_NAME.permission.C2D_MESSAGE" />
Replace YOUR_PACKAGE_NAME in the declarations above with your application's package name. Also, make sure that com.parse.GcmBroadcastReceiver and com.parse.PushService are declared as children of the element:
This worked for me, it might as well work for you.
Read this to get a full understanding
I guess you are using version 1.9.3. In version 1.9.4 they have fixed the problem. Check the release notes.
It could be useful to set parse logging to verbose to help debug further:
Parse.setLogLevel(Parse.LOG_LEVEL_VERBOSE);
With that I noticed that I was using the wrong "sender_id" in my manifest:
<meta-data android:name="com.parse.push.gcm_sender_id"
android:value="id:123456789"/>
I'm using my own GCM which your not doing here...but LOG_LEVEL_VERBOSE might help others debug this.
Why are you saving the installation if you're not adding anything to it? ParseSDK does that for you already.
You must pass a valid "channel" parameter into subscribeInBackground:
This is the channel that parse uses to push with; without it you won't get any pushes at all.
https://parse.com/docs/android/api/com/parse/ParsePush.html#subscribeInBackground(java.lang.String,%20com.parse.SaveCallback)
In addition make sure you've added the needed tag in your manifest for parse push to work properly - and the needed just like it explained here:
https://parse.com/docs/android/guide#push-notifications-receiving-pushes
I had a project with Parse in my app, but I've changed the project (and so the keys) and my pushes (test or normal) doesn't get sent from Parse.
When I try to send them I'm notified that it's going to be received by 2 recipients:
My Client push is ENABLED:
Although I think it's not needed, I've got my GCM credentials:
I've tried with a custom ParsePushBroadcastReceiver extended on Android and logging onReceive
I've tried to sign as release and debug.
I've tried with Wi-Fi, 3G and 4G.
I've tried to clear data, uninstall the app, rebooting.
My permissions on AndroidManifest.xml are:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<permission android:protectionLevel="signature"
android:name="taggie.me.permission.C2D_MESSAGE" />
<uses-permission android:name="taggie.me.permission.C2D_MESSAGE" />
My application is:
<application
android:name=".MainApplication"
android:allowBackup="true"
android:icon="#drawable/logo_help"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
which code is:
public class MainApplication extends Application {
#Override
public void onCreate() {
super.onCreate();
Parse.initialize(this, "YBi4ki505TcwKSNEIW7gkFCdWvjHC9yNJmrZHBGR", "APwUw3laazYRhvkSRwZZqpxsROUjH5jWP6QzeHiq");
ParseInstallation.getCurrentInstallation().saveInBackground();
}
}
and the rest of my AndroidManifest.xml is:
<service android:name="com.parse.PushService" />
<receiver android:name="com.parse.ParseBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.USER_PRESENT" />
</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" />
<category android:name="taggie.me" />
</intent-filter>
</receiver>
<receiver android:name="com.parse.ParsePushBroadcastReceiver" android:exported="false">
<intent-filter>
<action android:name="com.parse.push.intent.RECEIVE" />
<action android:name="com.parse.push.intent.DELETE" />
<action android:name="com.parse.push.intent.OPEN" />
</intent-filter>
</receiver>
<meta-data android:name="com.parse.push.gcm_sender_id"
android:value="id:10321_and_the_rest_of_my_number" />;
but THE PROBLEM IS HERE
I don't get notifications, and when I send them I can see this:
Does anyone has a clue before shooting myself? Thank you :)
This is incredible, I've tried to send the apk to one friend of mine... and he gets the push notifications but I don't! why could it be possible?
I've just opened the port 8253 as I've seen some posts reporting this, but it's still not working. :'(
I had a similar issue that was resolved in a strange way, but still - might help:
if you re-install (actually re-deploy, sometimes uninstalling sometimes just running over an existing apk) your application on a device, it might create several entries for device tokens that point to the same actual device (inside the Parse dashboard, go to Core, you can see the full table there), in which case - the system doesn't always know which is the correct physical device.
this might explain:
a. the dashboard telling you it will send more than 1 message (assuming only 1 was supposed to be sent).
b. your friend getting the push (he has only 1 valid device token)
Anyway - the refresh button on the Core page didn't help, but - manualy sending a push from the dashboard would result in the device receiving multiple pushes (for the number of duplicates it had in the table), and then, re-entering the Core table page would automatically clear the duplicates.
from there on - Pushes got back to normal.
you might need another clean, complete removal and re-installation on the device.
Hope this Helps!
Note: GCM Credentials were'nt needed in my case.
The main problem is I was working with Genymotion.
Being a simulator, push notifications should ARRIVE or NOT ARRIVE at all, but they were arriving sometimes. I can't explain why.
In your parseApplication class declare the channel. If you are sending notifications you have to set the channel. See this ParsePush.subscribeInBackground . It is describing the channel .
public class ParseApplication extends Application {
#Override
public void onCreate() {
super.onCreate();
System.out.println("Application");
Parse.initialize(this, "86q5mwgypd1Q2URFV6kJh5MBPmUpuPvoN3lTdeWx", "OhrkrJTuTwtbMprYtiywnQ3f4wnQdr5pitmI7tNt");
ParsePush.subscribeInBackground("temboo", new SaveCallback() {
#Override
public void done(ParseException e) {
if (e == null) {
Log.d("com.parse.push", "successfully subscribed to the broadcast channel.");
} else {
Log.e("com.parse.push", "failed to subscribe for push", e);
Toast.makeText(ParseApplication.this, "Failed to subscribe for push.", Toast.LENGTH_SHORT).show();
}
}
});
This works for me.
Parse.enableLocalDatastore(this);
// Add your initialization code here
Parse.initialize(this, APP_ID, CL_ID);
ParseInstallation.getCurrentInstallation().saveInBackground();
ParseUser.enableAutomaticUser();
ParseACL defaultACL = new ParseACL();
// Optionally enable public read access.
// defaultACL.setPublicReadAccess(true);
ParseACL.setDefaultACL(defaultACL, true);
// IF NEEADED
String topic ="YOUR_TOPIC";
System.out.println(topic);
ParsePush.subscribeInBackground(topic, new SaveCallback() {
#Override
public void done(ParseException e) {
if (e == null) {
Log.d("com.parse.push",
"successfully subscribed ");
} else {
Log.e("com.parse.push", "failed ", e);
}
}
});
This is the situation in my Installation page on Parse Console:
As you see some devices have the "deviceToken" and some do not have the "deviceToken". This is not good because every device should have the deviceToken in order to work.
How is this possible? This is a serious problem because the ones that do not have the deviceToken do not receive push notifications!
I've followed all the instructions on Parse.com and implemented everything as they said, even with the help of their blank project and with the help of various questions on the web. But nothing fixed my problem and now I can't do anything.
The only thing I can think about is that before my application (it is already on the Store) used to use Google Cloud Messaging and then with this new update I've decided to change the system and use Parse removing completely GCM system. Is there maybe a conflict between the two systems?
I need to fix this as you can imagine this is a serious bug and now 3/4 of my users do not receive push notifications.
If you download the app and install it: everything is good, the deviceToken is ok. If you update the app because there already was a version with GCM on the device:
some devices register in Parse good, without any problem
some devices register in Parse but without the deviceToken
For the devices that do not have the deviceToken I've tried a lot of things: inserting a deviceToken manually, uninstall and reinstall the application, delete the specific row on Parse, etc. But nothing good... Still facing this problem.
MY CODE
Application.java
public class Application extends android.app.Application {
public Application() {
}
#Override
public void onCreate() {
super.onCreate();
// Initialize the Parse SDK.
Parse.initialize(this, "x", "x");
// Specify an Activity to handle all pushes by default.
PushService.setDefaultPushCallback(this, MainActivity.class);
}
}
MainActivity.java
In my mainActivity I just concatenate the deviceToken (in my case it is the installationId) into my userAgent: and this work fine: I always have the installationId without any problem! And this is the only thing I am doing in my MainActivity (do I need to do anything else? saveInBackground, callback, etc..?)
deviceToken = ParseInstallation.getCurrentInstallation().getInstallationId();
webSettings.setUserAgentString(userAgent + " ||" + deviceToken);
AndroidManifest.xml
<!-- Gestione del guasto-->
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<!-- Utilizzo di internet -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- Permesso di vibrare per le push notifications -->
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<!-- Mantiene attivo il processore così da poter ricevere in qualsiasi momento le notifiche -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<!-- Consente di impostare l'allarme per l'aggiornamento automatico -->
<uses-permission android:name="com.android.alarm.permission.SET_ALARM"/>
<permission android:name="com.hoxell.hoxellbrowser.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.hoxell.hoxellbrowser.permission.C2D_MESSAGE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<application
android:name="com.hoxell.hoxellbrowser.Application"
android:allowBackup="true"
android:icon="#drawable/ic_launcher_hoxell"
android:label="#string/app_name"
android:theme="#style/AppTheme"
>
<!-- Richiesto per le applicazioni che usano Google Play Services -->
<meta-data android:name="com.google.android.gms.version" android:value="#integer/google_play_services_version" />
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:configChanges="keyboardHidden|orientation|screenSize"
android:windowSoftInputMode="adjustResize"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".SettingsActivity"></activity>
<receiver android:name=".AlarmReceiver"/>
<service android:name="com.parse.PushService" />
<receiver android:name="com.parse.ParseBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.USER_PRESENT" />
</intent-filter>
</receiver>
<receiver android:name="com.hoxell.hoxellbrowser.Receiver"
android:exported="false">
<intent-filter>
<action android:name="com.parse.push.intent.RECEIVE" />
<action android:name="com.parse.push.intent.DELETE" />
<action android:name="com.parse.push.intent.OPEN" />
</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" />
<category android:name="com.hoxell.hoxellbrowser" />
</intent-filter>
</receiver>
</application>
Build.gradle
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
// You must install or update the Support Repository through the SDK manager to use this dependency.
compile 'com.android.support:support-v4:20.+' //support
compile "com.google.android.gms:play-services:5.0.+" //play services
compile 'com.parse.bolts:bolts-android:1.+'
compile fileTree(dir: 'libs', include: 'Parse-*.jar')
}
I don't really know what else to do, that's why I hope that somebody can help me with this.
Thank you.
Are you using 2 user profiles at the same time on the tablet? Because I've had exactly the same problem and from my experience there is a conflict between the profiles. Infact, in my situation one device was registering 2 rows into the Parse database. One with the deviceToken and one with "undefined" deviceToken.
Unfortunately I've never solved this problem, I guess this is a bug from Parse.
It could be useful to set parse logging to verbose to help debug further:
Parse.setLogLevel(Parse.LOG_LEVEL_VERBOSE);
With that I noticed that I was using the wrong "sender_id" in my manifest:
<meta-data android:name="com.parse.push.gcm_sender_id"
android:value="id:123456789"/>
That might not be the exact solution, but LOG_LEVEL_VERBOSE might help debug this.
Some installations do have a GCM Registration Id set up in their deviceToken column, which is a good indication that your setup is correct. Is it definitely possible for an installation to lack a GCM Registration Id:
The device may not have access to Google Services Framework (e.g. Amazon Kindle Fire). If you have set up the non-GCM ParsePush receiver, pushes to these devices should still get delivered.
The app has been deleted from the device, and thus it has been unregistered from GCM. We do not automatically delete installations in this case as that could potentially lead to unintended data loss, given that you're allowed to store arbitrary data in your installation class.
Google Services Framework may have been unavailable when the device attempted to register itself.
In the first two scenarios, this is working as expected and it's not something to generally worry about.
Are those simulator users? From my experience if you are running an installation on your simulator it does not auto setup the device token.
I had been struggling with this problem for a long time until I recently realized what has been going on. Not only does the package name need to match, but you also need to include the build flavor in your declaration.
If you followed the parse tutorial and replace com.parse.starter with your package name, you are done if you have no build flavor, but if you do you need to make sure to include that as such:
com.packagename.build_flavor{debug, release, etc.}
You may create a class and extends Application to initialize your app. Such that initialize ParsePush and updateParseInstallation.
Sample code:
public class YourappApplication extends Application {
#Override
public void onCreate() {
super.onCreate();
Parse.initialize(this,YOU_PARSE_applicationId, YOU_PARSE_clientKey);
ParseInstallation.getCurrentInstallation().saveInBackground();
ParsePush.subscribeInBackground("", new SaveCallback() {
#Override
public void done(ParseException e) {
if (e == null) {
Log.d("com.parse.push", "successfully subscribed to the broadcast channel.");
} else {
Log.e("com.parse.push", "failed to subscribe for push", e);
}
}
});
}
public static void updateParseInstallation(ParseUser user) {
ParseInstallation installation = ParseInstallation.getCurrentInstallation();
installation.put("userId", user.getObjectId());
installation.saveInBackground();
}
}
And then in your LoginActivity: updateParseInstallation
ParseUser.logInInBackground(username, password, new LogInCallback() {
#Override
public void done(ParseUser parseUser, ParseException e) {
setProgressBarIndeterminateVisibility(false);
if(e == null){
YourappApplication.updateParseInstallation(parseUser);
Intent intent = new Intent(LoginActivity.this,
MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
}
}
});
I had similar issue after renaming module.
Try 'Clean Project' followed by 'Rebuild Project'
I had this problem but in a cordova app using the phonegap-parse-plugin. I had to edit the android java code in the plugin to fix, so effectively the same.
Try adding this save BETWEEN the Initialize and the setDefaultPushCallback:
ParseInstallation.getCurrentInstallation().save();
It has to be between them to work.
My problem was that I was missing this permission in the manifest:
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
Also I had to add meta-data just before
<service android:name="com.parse.PushService" />:
<meta-data
android:name="com.parse.APPLICATION_ID"
android:value="YourParseApplicationID" />
<meta-data
android:name="com.parse.CLIENT_KEY"
android:value="YourParseClientKey" />
Now check if you can get the deviceToken. Also check your app dashboard in Parse if everything is ok.
I dont know if tghis helps anyone but I was able to get the device token and notification correctly after removing this line from my Application Class containing parse intalation. here is the code. the commented line (removed line) made everything work properly. Can anyone explain why this works?
package com.test.android.push;
import android.app.Application;
import com.parse.Parse;
import com.parse.ParseInstallation;
import com.parse.ParsePush;
public class FarrApplication extends Application {
#Override
public void onCreate() {
super.onCreate();
Parse.initialize(this, "xxxx", "xxxx");
ParseInstallation.getCurrentInstallation().saveInBackground();
ParsePush.subscribeInBackground("---"); // REMOVED AND WORKS