Skip to content

Android doesn't receive push notifications from Parse Server #3654

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

Closed
rferbesa opened this issue Mar 20, 2017 · 55 comments
Closed

Android doesn't receive push notifications from Parse Server #3654

rferbesa opened this issue Mar 20, 2017 · 55 comments

Comments

@rferbesa
Copy link

Hi!
Since I didn't have success asking this in Stackoverflow I'm trying this way.

I've migrated my Android and iOS apps from parse.com to Parse Server. After the migration, everything is working well but the push notifications to Android devices (they are working well to my iOS app).

This is what I've done so far.

1. In my Parse Server code (on Digital Ocean by the way), in /home/parse/index.js I've initialized Parse Server this way:

var api = new ParseServer({  
  databaseURI: databaseUri || '<my mongodb url>',
  cloud: process.env.CLOUD_CODE_MAIN || __dirname + '/cloud/main.js',
  appId: process.env.APP_ID || '<my app ID>',
  masterKey: process.env.MASTER_KEY || '<my master Key>',
  serverURL: process.env.SERVER_URL || 'http://localhost:1337/parse',
  push: {
    android: {
        senderId: '<my GCM sender Id>',
        apiKey: '<my GCM API Key>'
      },
    ios: [{
      pfx: '/home/parse/<my dev P12>',  
      passphrase: '',
      cert: '',
      key: '',
      bundleId: '<my bundle ID>',
      production: false
    },
    {
      pfx: '/home/parse/<my prod P12>',  
      passphrase: '',
      cert: '',
      key: '',
      bundleId: '<my bundle ID>',
      production: true
    }]
  }
});

I’ve taken "my GCM sender ID" from my Google Developer Consoler, it’s the 12 digits number from Settings > Project number.

I’ve tried with 3 different "my GCM API Key", one without app restrictions, one available only for my android/debug.keystore and one available only for my app keystore.

I’ve checked that I have selected this app in my Google Developer console and that my package id is correct in all places.

2. In Android I’m initializing Parse this way:

public static void initParse(Application app) {
    ctxt = app.getApplicationContext();
    Parse.initialize(new Parse.Configuration.Builder(ctxt)
            .applicationId("<my app id>")
            .clientKey(null)
            .server("https://<my new server>/parse/")
            .enableLocalDataStore()
            .build()
    );
    ParseUser.enableRevocableSessionInBackground();
    ParseInstallation.getCurrentInstallation().saveInBackground();
}

3. In Android I’ve added this to my Android Manifest:

<meta-data android:name="com.parse.push.gcm_sender_id"
                   android:value="id:<my GCM sender Id>" />;

The rest of my manifest and my GCM configuration is the same I had before the migration.

4. Setting the GCMSenderId.

Some comments in Stackoverflow pointed that this could be an issue with GCMSenderId. Indeed all my Android users in Parse Server has an undefined GCMSenderId. But if I set manually this value to or even idthe push notification is not sent.

5. And as a summary.

With old parse.com push notifications worked well with Android and iOS.

With new Parse Server and the code described above iOS push notifications are working well.

With new Parse Server and the code described above Android push notifications are not being received.

With my new Parse Dashboard installed in Digital Ocean when sending push notifications both to iOS and to Android Dashboard gives a Saved! what makes me thing it’s a problem with my Android app and not with my Parse Dashboard/Parse Server configuration.

What am I missing here?

@dafinley
Copy link

I think your missing a few steps from this tutorial https://firebase.google.com/docs/android/setup
mainly around your build.gradle and I ended up adding a google-services.json file as well

@rferbesa
Copy link
Author

Hi dafinley!

Yes, when I coded my app with Parse.com Android still used GCM to send push notifications, I don't have anything related to FCM in my code. So then, I have to migrate from GCM to FCM in order to have my push notifications working again?

@jenlai1345
Copy link

I have the exact same problem - followed everything on Parse's instruction to set up Push (not using Firebase).
IOS devices successfully receive push sent from my Parse Cloud Codes, but Android devices didn't.

Any hint or help is great appreciated!

@dafinley
Copy link

I'll know for sure when I finish tomorrow but yea everything is in FCM now and it definitely requires some changes to your Android app. iOS pretty much worked seamlessly

@jenlai1345
Copy link

Thanks for the help.
I signed up for Firebase, created a project, inserted the senderId and serverKey into my ParseServer configuration, also changed the senderId in the Manifest file's meta-data tag.

However, when I did a test Push (via local-hosted dashboard), it shows "0 Push sent" for android devices (IOS devices received the test push).

I'm really scratching my head here.....

@dafinley
Copy link

dafinley commented Mar 22, 2017

What does your index file look like? For the parse server

@dafinley
Copy link

@jenlai1345
Copy link

var api = new ParseServer({
databaseURI: databaseUri || 'mongodb://localhost:27017/dev',
cloud: process.env.CLOUD_CODE_MAIN || __dirname + '/cloud/main.js',
appId: process.env.APP_ID || 'xxxxxxxxxxxxxxxxxxx',
masterKey: process.env.MASTER_KEY || 'xxxxxxxxxxxxxxxxxxx', //Add your master key here. Keep it secret!
serverURL: 'http://lofoparse-env.ap-northeast-1.elasticbeanstalk.com/parse', // Don't forget to change to https if needed
fileKey: 'xxxxxxxxxxxxxxxxxxx',
verifyUserEmails: true,
emailVerifyTokenValidityDuration: 24 * 60 * 60,
preventLoginWithUnverifiedEmail: false, // we check this field ourselves
publicServerURL: 'http://lofoparse-env.ap-northeast-1.elasticbeanstalk.com/parse',
appName: 'LoFo App',
// The email adapter
emailAdapter: {
module: 'parse-server-simple-mailgun-adapter',
options: {
fromAddress: 'LoFo Team [email protected]',
domain: 'lofo.zone',
apiKey: 'key-xxxxxxxxxxxxxxxxxxx',
}
},
filesAdapter: new S3Adapter(
"xxxxxxxxxxxxxxxxxxx",
"xxxxxxxxxxxxxxxxxxx",
"elasticbeanstalk-ap-northeast-1-474885121335",
{region: "ap-northeast-1",
bucketPrefix: "images/",
directAccess: true}
),
push: {
ios: [
{
pfx: __dirname + "/push_certs/lofostore-dev.p12", // Dev PFX or P12
bundleId: 'com.linkross.lofostore',
production: false // Dev
},
{
pfx: __dirname + "/push_certs/lofostore-prd.p12", // Prod PFX or P12
bundleId: 'com.linkross.lofostore',
production: true // Prod
},
{
pfx: __dirname + "/push_certs/lofo-dev.p12", // Prod PFX or P12
bundleId: 'com.linkross.lofo',
production: false // Dev
},
{
pfx: __dirname + "/push_certs/lofo-prd.p12", // Prod PFX or P12
bundleId: 'com.linkross.lofo',
production: true // Prod
}
],
android: {
senderId: 'xxxxxxxxxxxxxxxxxxx',
apiKey: 'xxxxxxxxxxxxxxxxxxx'
}
}
});

@dafinley
Copy link

Have you tried to send a push notification from your FCM console. Its going to look something like this https://console.firebase.google.com/project/**project-id**/notification/compose
If you can successfully send the notifications from the console, then you'll know its your parse server. Otherwise, it's your android application.

@jenlai1345
Copy link

Yes I tried sending push from Firebase console too. It also shows that "0 push sent". So the problem is somewhere in my Android app codes....

@dafinley
Copy link

Did you override FirebaseMessagingService and FirebaseInstanceId?

@jenlai1345
Copy link

No, I used the default gcm settings outlined in the Parse Server wiki.

@dafinley
Copy link

dafinley commented Mar 22, 2017

I was able to receive the fcm push notifications from the firebase console, but I did override the FirebaseMessagingService and FirebaseInstanceId in the Android app. I would work on that part first then come back to the parse server.

DDDFirebaseInstanceIdService.java

public class DDDFirebaseInstanceIDService extends FirebaseInstanceIdService {

    private static final String TAG = "DDDFirebaseInstanceIDService";

    @Override
    public void onTokenRefresh() {
        // Get updated InstanceID token.
        String refreshedToken = FirebaseInstanceId.getInstance().getToken();



        // If you want to send messages to this application instance or
        // manage this apps subscriptions on the server side, send the
        // Instance ID token to your app server.

    }
}

DDDFirebaseMessagingService.java

public class DDDFirebaseMessagingService extends FirebaseMessagingService {


}

AndroidManifest.xml

<service
            android:name=".notifications.DDDFirebaseMessagingService">
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT"/>
            </intent-filter>
        </service>

        <service
            android:name=".notifications.DDDFirebaseInstanceIDService">
            <intent-filter>
                <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
            </intent-filter>
        </service>```

@jenlai1345
Copy link

Thank you so much for your help.

It turned out, it was a really stupid mistake that I made.
I host parse server on aws and I thought I have pushed the updated index.js file containing the Android push settings (senderId, apiKey) to aws using the "eb deploy" command. However, that command grabs the last-committed codes which did not contain the push configuration.

After I did a "git commit" and then "eb deploy" successfully pushed the new settings to aws and push went through successfully.

From AWS --- "If git is installed, EB CLI uses the git archive command to create a .zip file from the contents of the most recent git commit command."

@flovilmart
Copy link
Contributor

@jenlai1345 yeah, however, if git is 'not' installed it will zip it all. Confusing AF!

@rferbesa
Copy link
Author

Hi! Sorry for reopen this but after following all these steps I can't send push notifications to Android. But I think I'm a bit closer.

I've migrated my project from GCM to FCM.
I've updated Parse Server to use the new Server Token and the new senderId (this didn't change by the way which I found it logical).
I've integrated Firebase to my Android Studio project.

The first thing I've seen is that I cannot update Installation.deviceToken from MyFirebaseInstanceIDService:onTokenRefresh because deviceToken is read-only. It's ok.
It's supposed that device token is automatically created by Parse Server each time an Android installation is created, no? But after some tests reinstalling my app the installation is created in Parse Server but the deviceToken is undefined.

Of course, if I send a push notification now from Parse Dashboard to my device the push is not sent, I guess because the device token is not defined.

So, what am I missing here? Do I need to do anything else so Parse Server creates automatically the Android device tokens?

@dafinley
Copy link

Can your Android device receive notifications from the Firebase console?

@rferbesa
Copy link
Author

Yes, I've just tested and after setting the token in the firebase console the push notification is received properly in my Android device. Could this confirm that the problem is that deviceToken is undefined in Parse Server?

@dafinley
Copy link

Set your VERBOSE=1 to see what the output is after you push...it should tell if your having issues.
For example after you execute the push the logs might say

verbose: sending push to 185 installations
verb parse-server-push-adapter GCM sending to 126 devices
verb parse-server-push-adapter GCM GCM Response: {
verb parse-server-push-adapter GCM     "multicast_id": 5475466505354908000,
verb parse-server-push-adapter GCM     "success": 0,
verb parse-server-push-adapter GCM     "failure": 126,
verb parse-server-push-adapter GCM     "canonical_ids": 0,
verb parse-server-push-adapter GCM     "results": [
verb parse-server-push-adapter GCM         {
verb parse-server-push-adapter GCM             "error": "MismatchSenderId"
verb parse-server-push-adapter GCM         },
verb parse-server-push-adapter GCM         {

@rferbesa
Copy link
Author

I'm not sure if I'm doing this well. I've set verbose:true in my index.js file, and I've sent an iOS push (success) and an Android push (fail) but:

  • In Parse dashboard Logs/info it says "no logs in the last 30 days".
  • In the file ./logs/parse-server.info.2017-03-22 there is nothing related to push notifications.

How should I enable and check the logs?

@dafinley
Copy link

dafinley commented Mar 22, 2017

If your on a linux box you can

export VERBOSE=1

But after you finish do

unset VERBOSE

You'll see something like this on startup

verbose: Support key pairs Map {}
parse-server-example running on port 1337.
info: Parse LiveQuery Server starts running

@dafinley
Copy link

If your Installation does not have a deviceToken I dont think the Parse Server will send it a notification

@rferbesa
Copy link
Author

Hi dafinley!

Before your last post I've been testing android push notifications setting manually the firebase token in Installation table with Parse Dashboard, and the push notifications have been received.
Then I've clear again firebase token and the push notification has not been received.
So this confirm that all is well configured but the problem is that devicetoken is empty.
Since Android device cannot update that field (read-only) how could I update it? And maybe more important why Parse is not generating this value automatically with every new installation?

@rferbesa
Copy link
Author

I think our posts have been send at the same time ;-).

Just for summarizing:
Since Android device cannot update that field (read-only) how could I update it? And maybe more important why Parse is not generating this value automatically with every new installation?

@dafinley
Copy link

Honestly, I don't know. My old device installs cause Sender Id Mismatch which makes sense but they also have deviceTokens, but new installs do not have deviceTokens. So I am looking for a solution as well.

@dafinley
Copy link

The short term solution may be to just send an api request to the fcm console from cloud code and only use parse for sending to ios until you get to a 3rd party solution

@rferbesa
Copy link
Author

I'll probably test with this solution: #3099

@dafinley
Copy link

All of my ios installations have the deviceToken field populated

@flovilmart
Copy link
Contributor

If there's an issue with the android SDK for registering deviceToken's probably, you should open an issue on the android SDK repo. @rogerhu what do you think?

Also, you should probably not trust anyone's built SDK's but the official one's

@rferbesa
Copy link
Author

Hi flovimart!

I've checked that iOS SDK has a specific method to update deviceToken. Maybe Android should have another one?
As you say I don't trust too much in non official built SDKs.

@flovilmart
Copy link
Contributor

What's odd is that the android SDK doesn't have a public method to set the deviceToken, whatcha means it gathers it by itself. Maybe a quick look at the source would tell you why it doesn't set it .)

@rogerhu
Copy link
Contributor

rogerhu commented Mar 23, 2017

Take a look at http://guides.codepath.com/android/Push-Notifications-Setup-for-Parse. I've spent many hours dealing with validating Push config setups on Android and trying to explain it to others. I think there are more sane ways going forward but you should run through the checklist there (especially the AndroidManifest.xml file configs_

@rferbesa
Copy link
Author

I've just fixed it! My problem was due to the migration process from GCM to FCM. This process sais to remove all permissions and services related to GCM from AndroidManifest.xml and add those related to FCM.
After enabling verbose level in Android Parse SDK I've seen that the problem was due to missing permissions.
And finally, after some tests, adding again to my AndroidManifest.xml the permissions and services related to GCM (together with the ones related to FCM) device token is set in Parse Server after a new installation and the push notifications are already received properly.

@dafinley
Copy link

Can you post your updated AndroidManifest

@rogerhu
Copy link
Contributor

rogerhu commented Mar 23, 2017

@dafinley
Copy link

I already had those permissions from that link. I'll just check the error logs when I get home

@rferbesa
Copy link
Author

This is my Android manifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.sample.package" >

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <user-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="com.android.vending.BILLING" />

    <!-- FOR PUSH NOTIFICATIONS -->
    <!--<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="com.sample.package.permission.C2D_MESSAGE" />
    <uses-permission android:name="com.sample.package.permission.C2D_MESSAGE" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/launch_ico_1024"
        android:label="@string/app_name"
        android:theme="@style/AppTheme">

        <!-- ACTIVITIES ARE NOT SHOWN --> 

        <!-- FOR PUSH NOTIFICATIONS -->
        <service android:name="com.parse.PushService" />


        <service
            android:name=".services.MyFirebaseInstanceIDService" >
            <intent-filter>
                <action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
            </intent-filter>
        </service>
        <service
            android:name=".services.MyFirebaseMessagingService">
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT" />
            </intent-filter>
        </service>
        <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="com.sample.package" />
            </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:XXXXX" />;
    </application>

</manifest>

@rferbesa
Copy link
Author

I think the services are very important too in this case.

@rogerhu
Copy link
Contributor

rogerhu commented Mar 23, 2017

@flovilmart
Copy link
Contributor

@rogerhu, this guide is 💯.

@dafinley
Copy link

It looks like I have all the services in the Manifest and no errors in the android. @rferbesa are you doing anything inside of your InstanceIdService or MessagingService to handle the deviceToken? Thanks @rogerhu for the article helped get me this far

@rferbesa
Copy link
Author

No, I've created both classes with their methods but everything is empty, they have no functionality.
Do your device receive pushnotifications from Firebase console?

@dafinley
Copy link

Firebase console pushes are successful. So your Installation row in parse server has the deviceToken field populated or your parse server sent the push to the device? My parse server wont even try to send the push if the deviceToken field is empty

@rferbesa
Copy link
Author

In my case, once I re-added to my Manifest all related to GCM and once I make a new installation, the row in PArse Server is created with my device token.
Please, check that (in your android code) once you init Parse you call this:
ParseInstallation.getCurrentInstallation().saveInBackground();

@rferbesa
Copy link
Author

At first sight I don't see anything strange. Have you tried to init Parse with Parse.setLogLevel(Parse.LOG_LEVEL_VERBOSE); and check all logs in your android app? This was what pointed me in the right direction yesterday.

@dafinley
Copy link

@rferbesa That fixed the deviceToken!! This was previous developer's app and the name changed but not the package...so I had a typo in the cd2 message and the category for the GCM broadcast. Good news is that got deviceToken in there. Tricky news is now that parse can push to the device...it throws a 401 error maybe @rogerhu has seen this

verbose: sending push to 26 installations
verb parse-server-push-adapter GCM sending to 1 device
Good Push
{ result: true }
ERR! parse-server-push-adapter GCM send errored: 401
verbose: sent push! 0 success, 1 failures

@dafinley
Copy link

Had to use the right API key from the Google console. That gave me a successful push...but didn't actually display the push on the device :) So definitely getting closer

verbose: sending push to 26 installations
verb parse-server-push-adapter GCM sending to 1 device
Good Push
{ result: true }
verb parse-server-push-adapter GCM GCM Response: {
verb parse-server-push-adapter GCM     "multicast_id": 7347414528335026000,
verb parse-server-push-adapter GCM     "success": 1,
verb parse-server-push-adapter GCM     "failure": 0,
verb parse-server-push-adapter GCM     "canonical_ids": 0,
verb parse-server-push-adapter GCM     "results": [
verb parse-server-push-adapter GCM         {
verb parse-server-push-adapter GCM             "message_id": "0:1490285460326437%3f0b9bb8f9fd7ecd"
verb parse-server-push-adapter GCM         }
verb parse-server-push-adapter GCM     ]
verb parse-server-push-adapter GCM }
verbose: sent push! 1 success, 0 failures

@rogerhu
Copy link
Contributor

rogerhu commented Mar 23, 2017

FYI -- if you are using Gradle you can use {packageName} as mentioned in http://guides.codepath.com/android/Push-Notifications-Setup-for-Parse#add-push-permissions so you don't have to worry about the app name misconfig.

@dafinley
Copy link

Scheduled Push Successfully received from parse server...This was the last step integrating agenda with parse server. Thanks Everybody

@uhw76tgwquerhjbqwnejk
Copy link

Hi everyone, very insightful thread here. I have a similar problem but haven't been able to solve it. I set up a new firebase project just last week, so I never used GCM at all. I am abe to successfully receive push notifications from the Firebase console to my android device. And when I send pushes from the Parse console, it says sent, but they are never actually received by the device.

One diference is that I am not using the parse SDK in my android project--I am just using the Rest API. So I am manually saving user's data via a POST request to my parse backend once I receive the token from firebase. This works to save the PFInstallation. Could this be part of the problem?

As far as I understand, I send pushes to mybackend/parse/push, and then parse sends them to firebase FCM, and then FCM sends them to my device. Since I can receive pushes form the FCM console, I am pretty sure the problem is not client side but rather server side.

My index.js has:

   push: {
    android: {
      senderId: "XXXXX",
      apiKey: "YYYYYY"
      }
}

Sending the push notifications form the parse console says they are successfully sent, but obviously they aren't. Any idea what other connection between the server and FCM I should be doing? I think my problem lies there but not sure what else I can do. Any help is appreciated. Thanks!

@uhw76tgwquerhjbqwnejk
Copy link

Also, when I send pushes from Parse Push console, they do not appear in the firebase push console (which they should if FCM is sending them to the device, right?)

@dafinley
Copy link

dafinley commented Apr 1, 2017

I would put verbose on parse server and see the logs while the parse server attempts to send the push notifications. It will list out every device it tries from your targeting and little bit of information about what happened. You might just try to inspect the latest Android SDK for push notifications to see exactly how their api request is generated.

@keyuls
Copy link

keyuls commented Apr 19, 2017

@dafinley How did you able to display push on device? What changes did you make for it?

@cestum
Copy link

cestum commented May 22, 2017

Looks like Parse server wants deviceToken even for FCM messaging. Once you confirm you can send notification to android using Firebase console, you can use this trick to update device token.

@ogonzalezadell
Copy link

ogonzalezadell commented May 30, 2017

Hi I know this issue is closed but I'm experiencing the same thing as @dafinley, and specifically i'm in the same situation as @JoeyBodnar, as we are using RESTful Services and I can not find a solution.

verbose: sending push to 2 installations verb parse-server-push-adapter GCM sending to 1 device Good Push { result: true } verb parse-server-push-adapter GCM GCM Response: { verb parse-server-push-adapter GCM "multicast_id": xxxxxx verb parse-server-push-adapter GCM "success": 1, verb parse-server-push-adapter GCM "failure": 0, verb parse-server-push-adapter GCM "canonical_ids": 0, verb parse-server-push-adapter GCM "results": [ verb parse-server-push-adapter GCM { verb parse-server-push-adapter GCM "message_id": "xxxxxxx" verb parse-server-push-adapter GCM } verb parse-server-push-adapter GCM ] verb parse-server-push-adapter GCM } verbose: sent push! 1 success, 0 failures

It says push are sent but are not displayed in the application neither the firebase console.

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