GCM and Parse conflict

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:

<!-- GCM BradcastReceiver & Service --> <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"> <!-- higher priority to GCM messages --> <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.RECEIVE" />--> <action android:name="com.google.android.c2dm.intent.REGISTRATION" /> <category android:name="com.twentyLines.app" /> </intent-filter> </receiver> <!-- Can remove this if application is already registered for GCM --> <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; // Explicitly specify that GcmIntentService will handle the intent. ComponentName comp = new ComponentName(context.getPackageName(), GcmIntentService.class.getName()); // Start the service, keeping the device awake while it is launching. startWakefulService(context, (intent.setComponent(comp))); setResultCode(Activity.RESULT_CANCELED); } } 

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

 <!-- GCM BradcastReceiver & Service --> <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"> <!-- higher priority to GCM messages --> <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> <!-- Parse service broacastReceiver and 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> <!-- Can remove this if application is already registered for GCM --> <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); } 
+5
source share
1 answer

We have two broadcast receivers to listen to c2dm intention

  • .GcmBroadcastReceiver: lets call it a GCM receiver ... Parse Push will never come to this receiver.
  • com.parse.GcmBroadcastReceiver: lets call it like a Parse receiver

Since you have a higher priority for the GCM receiver, the broadcast will first go to the GCM receiver and then to the Parse receiver. This does not guarantee that Broadcast will not go to the Parse receiver. You need to add abortBroadcast (); as the last line in the onReceive method, to make sure that the Parse receiver does not start when the GCM receiver is working with us.

Following the instructions for notifying Parse Push, Push receives a specific action. Data is sent to the broadcast recipient registered with this action. In your case, if the push is received with the action "com.twentyLines.PARSE_NOTIFICATION_ACTION", you may have a custom broadcast receiver to listen to this action. In this broadcast receiver you can receive data by code,

 try { String action = intent.getAction(); String channel = intent.getExtras().getString("com.parse.Channel"); JSONObject json = new JSONObject(intent.getExtras().getString("com.parse.Data")); Log.d(TAG, "got action " + action + " on channel " + channel + " with:"); Iterator itr = json.keys(); while (itr.hasNext()) { String key = (String) itr.next(); Log.d(TAG, "..." + key + " => " + json.getString(key)); } } catch (JSONException e) { Log.d(TAG, "JSONException: " + e.getMessage()); } 

When there is a GCM push signal, this user receiver will never receive a broadcast event since C2DM broadcast is interrupted at the GCM receiver (".GcmBroadcastReceiver")

Hope this helps!

+4
source

Source: https://habr.com/ru/post/1200719/


All Articles