I need an Android application to work with two push services, GCM and parse. My problem is that I cannot find a way to register Parse correctly, receive parsing notification and GCM notification. I can achieve all these things individually, but never together. My current implementation is as follows:
<service android:name=".GcmIntentService" android:enabled="true"/> <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" /> <receiver android:name=".GcmBroadcastReceiver" android:permission="com.google.android.c2dm.permission.SEND" > <intent-filter android:priority="100"> <action android:name="com.google.android.c2dm.intent.RECEIVE" /> <action android:name="com.twentyLines.GCM_NOTIFICATION_ACTION" /> <category android:name="com.twentyLines.app" /> </intent-filter> </receiver>
This is the broadcast receiver for GCM, and the other below is another receiver for parsing:
<service android:name="com.parse.PushService" /> <receiver android:name="com.parse.GcmBroadcastReceiver" android:permission="com.google.android.c2dm.permission.SEND" > <intent-filter android:priority="0"> <action android:name="com.google.android.c2dm.intent.REGISTRATION" /> <category android:name="com.twentyLines.app" /> </intent-filter> </receiver> <receiver android:name="com.parse.ParseBroadcastReceiver" android:exported="false" > <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> <action android:name="android.intent.action.USER_PRESENT" /> <action android:name="com.twentyLines.PARSE_NOTIFICATION_ACTION" /> </intent-filter> </receiver>
I tried to add a custom broadcast receiver to handle only the parsing of the notification, so I can avoid it to handle GCM. I did it like this:
<receiver android:name="com.twentyLines.app.ParseBroadcastReceiver" android:exported="false" > <intent-filter> <action android:name="com.twentyLines.PARSE_NOTIFICATION_ACTION" /> </intent-filter> </receiver>
This is an implementation of my BroadcastReceiver for GCM that does not display parsing notification.
public class GcmBroadcastReceiver extends WakefulBroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { boolean isFromParse = intent.getExtras().get("action").equals("com.twentyLines.PARSE_NOTIFICATION_ACTION"); if (isFromParse) return;
And this is an implementation of my custom BroadcastReceiver PARSE, which SHOULD avoid GCM readings. I donβt think that a custom parsing receiver is ever called because com.parse.GcmBroadcastReceiver processes the notification itself, rather than passing them. As a result, when I send a notification from my server to the GCM receiver, it is extracted from both and a double notification is displayed. (double is already good, every time I uninstall and reinstall my application, analyze another user .. "UniqueId", which I send to parse every time, is not so UNIQUE for them).
What have i tried? I'm really going crazy, I tried everything.
- I've read all related questions, and no one is good for me; - I've tried to remove the parse receiver, and this cause a parse exception (so doesn't register to parse) - I've tried to set the intent to RESULT_CANCELED, but in some way parse get it before GCM, so isn't working when I use GCM. - I've changed about all using cowboy-coding, and it still not work...
Any help would really be appreciated. Thanks guys!
EDITOR - ADD WORKING MANIFEST
<service android:name=".GcmIntentService" android:enabled="true"/> <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" /> <receiver android:name=".GcmBroadcastReceiver" android:permission="com.google.android.c2dm.permission.SEND" > <intent-filter android:priority="2"> <action android:name="com.google.android.c2dm.intent.RECEIVE" /> <action android:name="com.twentyLines.GCM_NOTIFICATION_ACTION" /> <category android:name="com.twentyLines.app" /> </intent-filter> </receiver> <service android:name="com.parse.PushService" /> <receiver android:name="com.parse.GcmBroadcastReceiver" android:permission="com.google.android.c2dm.permission.SEND" > <intent-filter android:priority="1"> <action android:name="com.google.android.c2dm.intent.RECEIVE" /> <action android:name="com.google.android.c2dm.intent.REGISTRATION" /> <category android:name="com.twentyLines.app" /> </intent-filter> </receiver> <receiver android:name="com.parse.ParseBroadcastReceiver" > <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> <action android:name="android.intent.action.USER_PRESENT" /> <action android:name="com.twentyLines.PARSE_NOTIFICATION_ACTION" /> </intent-filter> </receiver> <receiver android:name="com.twentyLines.app.ParseBroadcastReceiver" android:exported="false" > <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> <action android:name="android.intent.action.USER_PRESENT" /> <action android:name="com.twentyLines.PARSE_NOTIFICATION_ACTION" /> </intent-filter> </receiver>
EDIT 2: HOW DO I REGISTER PARSE and GCM
I register Parse in my application class:
Parse.initialize(this, PARSE_APP_KEY_VALUE, PARSE_CLIENT_KEY_VALUE); PushService.setDefaultPushCallback(getApplicationContext(), MainActivity.class); final ParseInstallation installation = ParseInstallation.getCurrentInstallation(); final String androidId = Settings.Secure.getString(getApplicationContext().getContentResolver(), Settings.Secure.ANDROID_ID); Handler handler = new Handler(); handler.postDelayed(new Runnable() { @Override public void run() { installation.put("UniqueId", androidId); installation.saveInBackground(new SaveCallback() { @Override public void done(ParseException e) { Log.d("Parse installation saved in background", "If operation successfull, 'e' have to be NULL e= " + e); } }); } }, 5000 );
And I get gcm registration_id in my MainActivity:
// Check if there is a saved registration_id in shared_prefs, // or if app version has changed private String getSavedRegistrationId() { final SharedPreferences gcmShared = getGCMSharedPrefss(); String registrationId = gcmShared.getString(Constant.GCM_REGISTRATION_ID_KEY, ""); if (registrationId.isEmpty()) { Log.i("GCM", "Registration not found."); return ""; } int registeredVersion = gcmShared.getInt(Constant.APP_VERSION_KEY, Integer.MIN_VALUE); int currentVersion = getAppVersion(this); if (registeredVersion != currentVersion) { clearSavedGCMRegistrationId(); Log.i("GCM", "App version changed."); return ""; } return registrationId; } // If there isn't, request one private void registerInBackground() { new AsyncTask<Void, Void, String>() { @Override protected String doInBackground(Void... params) { String msg; try { if (_gcm == null) { _gcm = GoogleCloudMessaging.getInstance(MainActivity.this); } String regid = _gcm.register(Constant.GCM_SENDER_ID); msg = "Device registered, registration ID=" + regid; sendRegistrationIdToBackend(regid); storeRegistrationId(regid); // Save reg_id to shared } catch (IOException ex) { msg = "Error :" + ex.getMessage(); // If there is an error, don't just keep trying to register. // Require the startupLoggedUser to click a button again, or perform // exponential back-off. } return msg; } @Override protected void onPostExecute(String msg) { Log.d("GCM registration", msg); } }.execute(null, null, null); }