ernestocattaneo
ernestocattaneo

Reputation: 1207

PARSE: Push Notifications "deviceToken" undefined

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:

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.

Upvotes: 22

Views: 10259

Answers (10)

user3078406
user3078406

Reputation: 511

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

Upvotes: 0

mogile_oli
mogile_oli

Reputation: 2188

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.

Upvotes: 2

L.Kovachev
L.Kovachev

Reputation: 1

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.

Upvotes: 0

Paul Hundal
Paul Hundal

Reputation: 11

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

Upvotes: 1

Andy Ballard
Andy Ballard

Reputation: 451

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.

Upvotes: 0

Venkat Kotra
Venkat Kotra

Reputation: 10753

I had similar issue after renaming module.

Try 'Clean Project' followed by 'Rebuild Project'

Upvotes: 0

WiTHS4UC3
WiTHS4UC3

Reputation: 260

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.

Upvotes: 7

Drilem
Drilem

Reputation: 21

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

Upvotes: 1

H&#233;ctor Ramos
H&#233;ctor Ramos

Reputation: 9258

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.

Upvotes: 1

bjiang
bjiang

Reputation: 6078

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);
                            }
                       }
          });

Upvotes: 0

Related Questions