PARSE: Push Notifications "deviceToken" undefined
Asked Answered
S

10

21

This is the situation in my Installation page on Parse Console:

enter image description here

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.

Sweven answered 11/2, 2015 at 8:34 Comment(1)
FYI, the registration id is stored in the deviceToken column, not in installationId.Elamitic
H
7

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.

Headstream answered 17/2, 2015 at 8:11 Comment(5)
Damn, you're right. This is it. I do have 2 profiles in the tablet and I've just tested it: the normal profile does receive the deviceToken but the restricted one (the one I need!) does not receive it. Dammit! And now? Can I do anything?!?Sweven
As I said I did not solve this problem. Because of this, I used only 1 profile for 1 tabletHeadstream
which type of profile u talking , b'coz i m facing same issue.Blarney
was anyone able to solve this problem? I am also stuck at the same place.Creaturely
You can add a new column in the parse installation table called "isActiveUser". An device can't have 2 sessions with different users in the same instant.Ximenez
K
2

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.

Knut answered 19/5, 2016 at 18:8 Comment(0)
V
1

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.

Viewpoint answered 13/2, 2015 at 19:19 Comment(5)
The device has access to the Google Services Framework (galaxy tab 3).. and it is not a problem of unavailability… What I did with a device without the deviceToken was to manually delete and reinstall the application and a new registration has been made: but still without the deviceToken. I’ve tried clearing app cache/data, but same result. I don’t know what else to do… We do not want to leave Parse framework: we think it is amazing. But really.. what else can we do to solve our problem? Please help.. you are the only one that can actually help us.. :)Sweven
I've added my Build.gradle code: is there maybe a problem concerning gms version compiling..?Sweven
I dont understand this answer, you say this is a reasonable behavior, but i don't understand why, i have this problem, no deviceToken and no type, this means my user cannot receive push, how can this be corrected?Viaduct
If the user opted out of push notifications by deleting your app, there's no app to push to. Therefore, it is reasonable behavior :)Elamitic
Similarly, GCM is only supported on devices with access to Google Services. A Kindle device wouldn't be able to obtain a registration token.Elamitic
C
1

Are those simulator users? From my experience if you are running an installation on your simulator it does not auto setup the device token.

Conscious answered 14/2, 2015 at 0:4 Comment(0)
E
1

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.}

Eads answered 1/3, 2016 at 21:31 Comment(0)
M
0

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);
                            }
                       }
          });
Michigan answered 12/2, 2015 at 16:50 Comment(1)
this is not what I've askedSweven
A
0

I had similar issue after renaming module.

Try 'Clean Project' followed by 'Rebuild Project'

Armenia answered 29/12, 2015 at 1:45 Comment(0)
M
0

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.

Made answered 18/1, 2016 at 22:23 Comment(0)
H
0

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.

Hanaper answered 15/3, 2016 at 13:48 Comment(0)
H
0

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
Helve answered 30/8, 2016 at 19:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.