Before labeling this as a duplicate:
I've read at least 15 similar threads and each and every one is either using the old Parse code (the now deprecated setDefaultPushCallback) or the problem was a result of calling Parse.initialize(...) in an activity and not in the Application class. But this is not applicable to my case. The official example (which I'm using) is evidently doing it right, so the code is already in the Application class.
I've downloaded the Push Starter example from Parse's official guides and tried it out on an emulator. I receive pushes only while the app is running. The moment's it's closed (removed from the "recent apps" list, not force killed), I no longer get pushes. Which makes the entire feature rather useless... I tried with and without GCM, the behavior is the same.
Any clues what could possible be wrong? All classes are the stock example ones, nothing overridden or added by me (except for the id/key and the ParsePush.subscribeInBackground call which I copied from the guide). Weirdly enough, the example code did not contain ParsePush.subscribeInBackground and the QuickStart does not mention it. It even gives a Test button that supposedly sends a push which I never receive, with or without subscribeInBackground. The only way I've been able to get a push so far was with subscribeInBackground and sending a push manually though the web console, and only so if the app is running. The web console also keeps telling there's 2 registered devices... which is untrue.
Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.parse.starter"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="9" android:targetSdkVersion="21"/>
<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.VIBRATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<!--
IMPORTANT: Change "com.parse.starter.permission.C2D_MESSAGE" in the lines below
to match your app's package name + ".permission.C2D_MESSAGE".
-->
<permission android:protectionLevel="signature"
android:name="com.parse.starter.permission.C2D_MESSAGE" />
<uses-permission android:name="com.parse.starter.permission.C2D_MESSAGE" />
<application
android:name=".ParseApplication"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:allowBackup="true">
<activity
android:name=".ParseStarterProjectActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<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.parse.starter" />
</intent-filter>
</receiver>
</application>
</manifest>
ParseApplication:
package com.parse.starter;
...
public class ParseApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
// Initialize Crash Reporting.
ParseCrashReporting.enable(this);
// Enable Local Datastore.
Parse.enableLocalDatastore(this);
ParseUser.enableAutomaticUser();
// Add your initialization code here
Parse.initialize(this, "***", "***");
ParseACL defaultACL = new ParseACL();
// Optionally enable public read access.
// defaultACL.setPublicReadAccess(true);
ParseACL.setDefaultACL(defaultACL, true);
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);
}
}
});
}
}