GCM 和 Parse 通知冲突 [英] GCM and Parse notification conflict

查看:27
本文介绍了GCM 和 Parse 通知冲突的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要我的 android 应用程序与两个推送服务一起工作,GCM 和解析.我的问题是我找不到正确注册到 Parse、获取解析通知和 GCM 通知的方法.我可以单独完成所有这些事情,但永远不会一起完成.我当前的实现是这样的:

I need my android app to work with two push services, GCM and parse. My problem is that I can't find a way for register correctly to Parse, get parse notification and GCM notification too. I can reach all these things individually, but never together. My current implementation looks this way:

<!-- 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>

这是GCM的broadcastReceiver,下面是解析的另一个接收器:

This is the broadcastReceiver for GCM, and the one below is the other receiver for parse:

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

我尝试添加一个自定义广播接收器来处理解析通知,因此我也可以避免它处理 GCM.我是这样做的:

I've tried to add a custom broadcast receiver to handle just parse notification, so I can avoid it to handle GCM too. I've done 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>

这是我的 BroadcastReceiver for GCM 的实现,可避免显示解析通知.

This is the implementation of my BroadcastReceiver for GCM, that avoid parse notification to be displayed.

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

这是我的 PARSE 自定义 BroadcastReceiver 的实现,应该避免显示 GCM.解析自定义接收器永远不会被调用,我认为是因为 com.parse.GcmBroadcastReceiver 处理通知本身而不是传递它们.结果是,当我从我的服务器向 GCM 接收器发送通知时,这会从两者中检索,并显示双重通知.(double 已经很好了,每次我卸载并重新安装我的应用程序时,Parse 都会注册另一个用户.我每次发送来解析的UniqueId"对他们来说并不是那么独特).

And this is the implementation for my PARSE custom BroadcastReceiver that SHOULD avoid GCM to be showed. The parse custom receiver is never invoked, I think because the com.parse.GcmBroadcastReceiver handle the notification itself instead of pass them. The result is that, when I send a notification from my server to GCM receiver, this is retrieved from both, and double notification is showed. (double is already good, every time I uninstall and reinstall my app Parse register another user.. the "UniqueId" I send to parse every time is not so UNIQUE for them).

我尝试了什么?我真的快疯了,我什么都试过了.

What have I tried? I'm really getting crazy, I've tried about 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 will be really welcome. Thank you guys!

编辑 - 添加工作清单

<!-- 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>

编辑 2:我如何注册解析和 GCM

我在我的应用程序类中注册了 Parse:

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

我在 MainActivity 中得到了 gcm registration_id:

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

推荐答案

我们这里有两个广播接收器来监听c2dm意图

We have two broadcast receivers here to listen c2dm intent

  1. .GcmBroadcastReceiver :让我们将其称为 GCM 接收器...解析推送永远不会到达此接收器.
  2. com.parse.GcmBroadcastReceiver :我们称之为解析接收器

由于您给 GCM 接收器赋予了更高的优先级,广播将首先到达 GCM 接收器,然后到达解析接收器.这并不能保证 Broadcast 不会进入 Parse 接收器.您需要添加 abortBroadcast();作为 onReceive 方法的最后一行,以确保在 GCM 接收器工作时不会触发 Parse 接收器.

As you have given higher priority to GCM receiver, broadcast will come to GCM receiver first and then to Parse receiver. This does not guarantee that Broadcast will not go to Parse receiver. You need to add abortBroadcast(); as last line in onReceive method to make sure that Parse receiver is not triggered when we have GCM receiver working.

根据 Parse Push 通知指南,接收带有特定意图操作的 Push.数据被发送到使用该操作注册的广播接收器.在您的情况下,如果通过操作com.twentyLines.PARSE_NOTIFICATION_ACTION"接收推送,您可以使用自定义广播接收器来收听此操作.在该广播接收器中,您可以通过以下代码获取数据,

As per Parse Push notification guidelines, Push is received with a specific intent action. Data is sent to broadcast receiver registered with that action. In your case, if push is received with action "com.twentyLines.PARSE_NOTIFICATION_ACTION", you can have a custom broadcast receiver to listen to this action. In that broadcast receiver you can fetch data by below 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());
    }

当有 GCM 推送时,这个自定义接收器永远不会得到广播事件,因为 C2DM 广播在 GCM 接收器(.GcmBroadcastReceiver")中被中止

When there is GCM push, this custom receiver will never get broadcast event as the C2DM broadcast is being aborted in GCM receiver (".GcmBroadcastReceiver")

希望这有帮助!

这篇关于GCM 和 Parse 通知冲突的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆