Android:如何使用Parse作为GCM推送通知的替代供应商?[英] Android: How to use Parse as an alternative GCM push notification provider?

本文是小编为大家收集整理的关于Android:如何使用Parse作为GCM推送通知的替代供应商?的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。

问题描述

请参见问题结束时的编辑#2(Google更新了推动的实现方式,因此更容易处理GCM和一起解析)

我已经在应用程序中使用了GCM,我想添加parse作为替代方案.这就是我现在拥有的(所有权限均已正确声明):

<service 
   android:name="com.mypackagename.GCMIntentService" 
   android:enabled="true" />
<receiver 
   android:name="com.google.android.gcm.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.mypackagename.GCMIntentService" />
   </intent-filter>
</receiver>

'gcmintentservice'(从'gcmbaseintentservice'继承)类处理服务器注册和接收消息 - 它可以正常运行,并且收到了所有推送消息.服务器有时会发送自定义数据,因此我自己处理消息并以编程方式创建通知(单击通知时使用的意图有一些从服务器发送的重要附加功能).

我想以某种方式使解析以相同的方式行事,以便能够从Parse网站发送频道推送并创建自己的通知,但是我尝试过的所有内容都失败了(遵循Android Push Tutearial无法正常工作出于我的问题).有没有人尝试过类似的事情?在花费大量时间来调整推送指南/教程之后,我有点不用想法 - 有时我没有收到任何通知;有时,解析和我的接收器都被打电话给我,我会收到双重通知.我还尝试使用Parse REST API进行注册,并自己处理所有内容,但发现在Android上不可能.

因此,我如何处理解析推送和传统的GCM推送(使用我的服务器),以使我可以同时访问通知,并且可以从头开始构建它们(使用所需的Extras创建自己的未决通知)?

编辑#1:

我尝试使用的第一件事是使用解析服务,并有一个广播接收器来处理GCM消息:

androidmaifest.xml:

<service 
    android:name="com.mypackagename.GCMIntentService" 
    android:enabled="true" />
<service android:name="com.parse.PushService"
    android:enabled="true"/>
<receiver 
    android:name="com.google.android.gcm.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.mypackagename.GCMIntentService" />
    </intent-filter>
</receiver>

和解析库需要以下初始化:

Parse.initialize(context, appId, apiKey);
PushService.setDefaultPushCallback(context, MainActivity.class);
// I'm subscribing to channel push because I send channel pushes from the
// parse console
PushService.subscribe(context, MDConstants.PARSE_PUSH_CHANNEL, MainActivity.class);
ParseInstallation.getCurrentInstallation().saveInBackground();

问题是我从其他提供商那里收到通知,但我没有从解析中收到任何东西(所有权限均已声明),并且我从解析库中收到以下错误(当收到错误时,解析注册为做得不好 - 我看不到解析器中的设备):

E/com.parse.ManifestInfo(11677): Cannot use GCM for push because the app manifest is missing some required declarations. Please make sure that these permissions are declared as children of the root <manifest> element:
E/com.parse.ManifestInfo(11677): 
E/com.parse.ManifestInfo(11677): <uses-permission android:name="android.permission.INTERNET" />
E/com.parse.ManifestInfo(11677): <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
E/com.parse.ManifestInfo(11677): <uses-permission android:name="android.permission.VIBRATE" />
E/com.parse.ManifestInfo(11677): <uses-permission android:name="android.permission.WAKE_LOCK" />
E/com.parse.ManifestInfo(11677): <uses-permission android:name="android.permission.GET_ACCOUNTS" />
E/com.parse.ManifestInfo(11677): <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
E/com.parse.ManifestInfo(11677): <permission android:name="com.mypackagename.permission.C2D_MESSAGE" android:protectionLevel="signature" />
E/com.parse.ManifestInfo(11677): <uses-permission android:name="com.mypackagename.permission.C2D_MESSAGE" />
E/com.parse.ManifestInfo(11677): 
E/com.parse.ManifestInfo(11677): Also, please make sure that these services and broadcast receivers are declared as children of the <application> element:
E/com.parse.ManifestInfo(11677): 
E/com.parse.ManifestInfo(11677): <service android:name="com.parse.PushService" />
E/com.parse.ManifestInfo(11677): <receiver android:name="com.parse.GcmBroadcastReceiver" android:permission="com.google.android.c2dm.permission.SEND">
E/com.parse.ManifestInfo(11677):   <intent-filter>
E/com.parse.ManifestInfo(11677):     <action android:name="com.google.android.c2dm.intent.RECEIVE" />
E/com.parse.ManifestInfo(11677):     <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
E/com.parse.ManifestInfo(11677):     <category android:name="com.mypackagename" />
E/com.parse.ManifestInfo(11677):   </intent-filter>
E/com.parse.ManifestInfo(11677): </receiver>
E/com.parse.PushService(11677): Tried to use push, but this app is not configured for push due to: Push is not configured for this app because the app manifest is missing required declarations. Please add the following declarations to your app manifest to support either GCM or PPNS for push (or both). To enable GCM support, please make sure that these permissions are declared as children of the root <manifest> element:
E/com.parse.PushService(11677): 
E/com.parse.PushService(11677): <uses-permission android:name="android.permission.INTERNET" />
E/com.parse.PushService(11677): <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
E/com.parse.PushService(11677): <uses-permission android:name="android.permission.VIBRATE" />
E/com.parse.PushService(11677): <uses-permission android:name="android.permission.WAKE_LOCK" />
E/com.parse.PushService(11677): <uses-permission android:name="android.permission.GET_ACCOUNTS" />
E/com.parse.PushService(11677): <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
E/com.parse.PushService(11677): <permission android:name="com.mypackagename.permission.C2D_MESSAGE" android:protectionLevel="signature" />
E/com.parse.PushService(11677): <uses-permission android:name="com.mypackagename.permission.C2D_MESSAGE" />
E/com.parse.PushService(11677): 
E/com.parse.PushService(11677): Also, please make sure that these services and broadcast receivers are declared as children of the <application> element:
E/com.parse.PushService(11677): 
E/com.parse.PushService(11677): <service android:name="com.parse.PushService" />
E/com.parse.PushService(11677): <receiver android:name="com.parse.GcmBroadcastReceiver" android:permission="com.google.android.c2dm.permission.SEND">
E/com.parse.PushService(11677):   <intent-filter>
E/com.parse.PushService(11677):     <action android:name="com.google.android.c2dm.intent.RECEIVE" />
E/com.parse.PushService(11677):     <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
E/com.parse.PushService(11677):     <category android:name="com.mypackagename" />
E/com.parse.PushService(11677):   </intent-filter>
E/com.parse.PushService(11677): </receiver>
E/com.parse.PushService(11677): To enable PPNS support, please make sure that these permissions are declared as children of the root <manifest> element:
E/com.parse.PushService(11677): 
E/com.parse.PushService(11677): <uses-permission android:name="android.permission.INTERNET" />
E/com.parse.PushService(11677): <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
E/com.parse.PushService(11677): <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
E/com.parse.PushService(11677): <uses-permission android:name="android.permission.VIBRATE" />
E/com.parse.PushService(11677): <uses-permission android:name="android.permission.WAKE_LOCK" />
E/com.parse.PushService(11677): 
E/com.parse.PushService(11677): Also, please make sure that these services and broadcast receivers are declared as children of the <application> element:
E/com.parse.PushService(11677): 
E/com.parse.PushService(11677): <service android:name="com.parse.PushService" />
E/com.parse.PushService(11677): <receiver android:name="com.parse.ParseBroadcastReceiver">
E/com.parse.PushService(11677):   <intent-filter>
E/com.parse.PushService(11677):     <action android:name="android.intent.action.BOOT_COMPLETED" />
E/com.parse.PushService(11677):     <action android:name="android.intent.action.USER_PRESENT" />
E/com.parse.PushService(11677):   </intent-filter>
E/com.parse.PushService(11677): </receiver>

编辑#2:

我更新了基于 Google推送通知开发人员指南.在实施扩展" GCMListenerService"的类时,您现在可以轻松地检查"来自"参数是否与用于注册推送的Google项目ID相同.

public class MyGcmListenerService extends GcmListenerService {
    @Override
    public void onMessageReceived(String from, Bundle data) {
        // only handle gcm messages that come from the same project id used to register
        if (from.equals("Your google project id)) {
            // handle the gcm push
        }
    }
}

另外,解析更新了他们的库(我现在正在使用'1.9.4'),您可以子类" parsepushbroadcastreceiver"来处理您想要的通知.请参阅指南在这里进行基本实施.

在"应用程序"类的" ongreate"方法中解析初始化:

Parse.initialize(this, "your parse app id", "your parse client key");

// subscribing to a channel
ParsePush.subscribeInBackground("your channel name", 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");
        }
    }
});

广播接收器实现:

public class MyParsePushBroadcastReceiver extends ParsePushBroadcastReceiver {
    @Override
    protected void onPushReceive(Context context, Intent intent) {
        // handle the parse push notification
    }
}

解析和GCM的清单声明:

...

<!-- GCM listener service -->
<service
    android:name=".MyGcmListenerService"
    android:exported="false" >
    <intent-filter>
        <action android:name="com.google.android.c2dm.intent.RECEIVE" />
    </intent-filter>
</service>

...

<!-- Parse broadcast receiver -->
<receiver android:name=".MyParsePushBroadcastReceiver" 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>

...

我仅添加了服务和接收器,但是您需要确保遵循GCM指南和Parse推送指南以具有完整的实现(例如,Google还添加了一种处理令牌刷新的方法 - 示例可以找到包含完整的代码样本在这里).

推荐答案

如果我理解正确,您希望代码能够处理所有传入的GCM消息,无论其来源如何(可以是您的服​​务器或解析网站),这意味着您不希望在您的应用程序可以处理它们.

您可以通过在清单中声明单个广播接收器处理com.google.android.c2dm.intent.RECEIVE操作来实现这一目标.那将是您的GCMBroadcastReceiver类,它将处理所有到达的GCM消息.

当您声明两个处理相同操作的广播接收器时,您当前正在经历的行为可能发生.

本文地址:https://www.itbaoku.cn/post/102530.html

问题描述

SEE EDIT#2 at the end of the question (Google updated the way push is implemented so it became easier to handle gcm and parse together)

I already use GCM inside a application and I would like to add parse as an alternative. This is what I have now (all the permissions are correctly declared):

<service 
   android:name="com.mypackagename.GCMIntentService" 
   android:enabled="true" />
<receiver 
   android:name="com.google.android.gcm.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.mypackagename.GCMIntentService" />
   </intent-filter>
</receiver>

The 'GCMIntentService' (inherits from 'GCMBaseIntentService') class handles the server registration and receiving of messages - it works fine and all the push messages are received. The server sometimes sends custom data so I handle the messages myself and create the notifications programmatically (the intent used when the notification is clicked has some important extras sent from the server).

I would like to somehow make parse behave in the same way in order to be able to send channel pushes from the parse website and create my own notifications, but everything I tried failed (following the android push tutorial isn't really working for my problem). Is there anyone who tried a similar thing? I'm kind of out of ideas after spending a lot of time tweaking the push guides/tutorials - sometimes I don't receive any notifications; sometimes both parse and my receiver are called and I get double notifications. I also tried to register using parse REST apis and handle everything myself but found out it isn't possible on Android.

So, how could I handle both parse pushes and the traditional gcm pushes (using my server) in such a way that I have access to both notifications and I can build them from scratch (create my own pending notifications with the required extras)?

EDIT#1:

The first thing I tried was to use the parse service and have a single broadcast receiver to handle the GCM messages:

AndroidMaifest.xml:

<service 
    android:name="com.mypackagename.GCMIntentService" 
    android:enabled="true" />
<service android:name="com.parse.PushService"
    android:enabled="true"/>
<receiver 
    android:name="com.google.android.gcm.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.mypackagename.GCMIntentService" />
    </intent-filter>
</receiver>

And the parse library requires the following initializations:

Parse.initialize(context, appId, apiKey);
PushService.setDefaultPushCallback(context, MainActivity.class);
// I'm subscribing to channel push because I send channel pushes from the
// parse console
PushService.subscribe(context, MDConstants.PARSE_PUSH_CHANNEL, MainActivity.class);
ParseInstallation.getCurrentInstallation().saveInBackground();

The problem is that I receive the notifications from my other provider but I don't receive anything from parse (all the permissions are declared) and I get the following error from the parse library (when receiving the error the parse registration is not properly done - I can't see my device in the parse console):

E/com.parse.ManifestInfo(11677): Cannot use GCM for push because the app manifest is missing some required declarations. Please make sure that these permissions are declared as children of the root <manifest> element:
E/com.parse.ManifestInfo(11677): 
E/com.parse.ManifestInfo(11677): <uses-permission android:name="android.permission.INTERNET" />
E/com.parse.ManifestInfo(11677): <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
E/com.parse.ManifestInfo(11677): <uses-permission android:name="android.permission.VIBRATE" />
E/com.parse.ManifestInfo(11677): <uses-permission android:name="android.permission.WAKE_LOCK" />
E/com.parse.ManifestInfo(11677): <uses-permission android:name="android.permission.GET_ACCOUNTS" />
E/com.parse.ManifestInfo(11677): <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
E/com.parse.ManifestInfo(11677): <permission android:name="com.mypackagename.permission.C2D_MESSAGE" android:protectionLevel="signature" />
E/com.parse.ManifestInfo(11677): <uses-permission android:name="com.mypackagename.permission.C2D_MESSAGE" />
E/com.parse.ManifestInfo(11677): 
E/com.parse.ManifestInfo(11677): Also, please make sure that these services and broadcast receivers are declared as children of the <application> element:
E/com.parse.ManifestInfo(11677): 
E/com.parse.ManifestInfo(11677): <service android:name="com.parse.PushService" />
E/com.parse.ManifestInfo(11677): <receiver android:name="com.parse.GcmBroadcastReceiver" android:permission="com.google.android.c2dm.permission.SEND">
E/com.parse.ManifestInfo(11677):   <intent-filter>
E/com.parse.ManifestInfo(11677):     <action android:name="com.google.android.c2dm.intent.RECEIVE" />
E/com.parse.ManifestInfo(11677):     <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
E/com.parse.ManifestInfo(11677):     <category android:name="com.mypackagename" />
E/com.parse.ManifestInfo(11677):   </intent-filter>
E/com.parse.ManifestInfo(11677): </receiver>
E/com.parse.PushService(11677): Tried to use push, but this app is not configured for push due to: Push is not configured for this app because the app manifest is missing required declarations. Please add the following declarations to your app manifest to support either GCM or PPNS for push (or both). To enable GCM support, please make sure that these permissions are declared as children of the root <manifest> element:
E/com.parse.PushService(11677): 
E/com.parse.PushService(11677): <uses-permission android:name="android.permission.INTERNET" />
E/com.parse.PushService(11677): <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
E/com.parse.PushService(11677): <uses-permission android:name="android.permission.VIBRATE" />
E/com.parse.PushService(11677): <uses-permission android:name="android.permission.WAKE_LOCK" />
E/com.parse.PushService(11677): <uses-permission android:name="android.permission.GET_ACCOUNTS" />
E/com.parse.PushService(11677): <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
E/com.parse.PushService(11677): <permission android:name="com.mypackagename.permission.C2D_MESSAGE" android:protectionLevel="signature" />
E/com.parse.PushService(11677): <uses-permission android:name="com.mypackagename.permission.C2D_MESSAGE" />
E/com.parse.PushService(11677): 
E/com.parse.PushService(11677): Also, please make sure that these services and broadcast receivers are declared as children of the <application> element:
E/com.parse.PushService(11677): 
E/com.parse.PushService(11677): <service android:name="com.parse.PushService" />
E/com.parse.PushService(11677): <receiver android:name="com.parse.GcmBroadcastReceiver" android:permission="com.google.android.c2dm.permission.SEND">
E/com.parse.PushService(11677):   <intent-filter>
E/com.parse.PushService(11677):     <action android:name="com.google.android.c2dm.intent.RECEIVE" />
E/com.parse.PushService(11677):     <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
E/com.parse.PushService(11677):     <category android:name="com.mypackagename" />
E/com.parse.PushService(11677):   </intent-filter>
E/com.parse.PushService(11677): </receiver>
E/com.parse.PushService(11677): To enable PPNS support, please make sure that these permissions are declared as children of the root <manifest> element:
E/com.parse.PushService(11677): 
E/com.parse.PushService(11677): <uses-permission android:name="android.permission.INTERNET" />
E/com.parse.PushService(11677): <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
E/com.parse.PushService(11677): <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
E/com.parse.PushService(11677): <uses-permission android:name="android.permission.VIBRATE" />
E/com.parse.PushService(11677): <uses-permission android:name="android.permission.WAKE_LOCK" />
E/com.parse.PushService(11677): 
E/com.parse.PushService(11677): Also, please make sure that these services and broadcast receivers are declared as children of the <application> element:
E/com.parse.PushService(11677): 
E/com.parse.PushService(11677): <service android:name="com.parse.PushService" />
E/com.parse.PushService(11677): <receiver android:name="com.parse.ParseBroadcastReceiver">
E/com.parse.PushService(11677):   <intent-filter>
E/com.parse.PushService(11677):     <action android:name="android.intent.action.BOOT_COMPLETED" />
E/com.parse.PushService(11677):     <action android:name="android.intent.action.USER_PRESENT" />
E/com.parse.PushService(11677):   </intent-filter>
E/com.parse.PushService(11677): </receiver>

EDIT#2:

I updated the way gcm push was handled based on the google push notification developer guide. While implementing the class that extends 'GcmListenerService', you can now easily check if the 'from' arguments is the same as your google project id used to register for push.

public class MyGcmListenerService extends GcmListenerService {
    @Override
    public void onMessageReceived(String from, Bundle data) {
        // only handle gcm messages that come from the same project id used to register
        if (from.equals("Your google project id)) {
            // handle the gcm push
        }
    }
}

Also, parse updated their libraries (I'm using '1.9.4' right now) and you can subclass the 'ParsePushBroadcastReceiver' to handle the notifications as you'd like. See the guide here for a basic implementation.

Parse initialization in the 'onCreate' method of your 'Application' class:

Parse.initialize(this, "your parse app id", "your parse client key");

// subscribing to a channel
ParsePush.subscribeInBackground("your channel name", 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");
        }
    }
});

The broadcast receiver implementation:

public class MyParsePushBroadcastReceiver extends ParsePushBroadcastReceiver {
    @Override
    protected void onPushReceive(Context context, Intent intent) {
        // handle the parse push notification
    }
}

The manifest declaration for both parse and gcm:

...

<!-- GCM listener service -->
<service
    android:name=".MyGcmListenerService"
    android:exported="false" >
    <intent-filter>
        <action android:name="com.google.android.c2dm.intent.RECEIVE" />
    </intent-filter>
</service>

...

<!-- Parse broadcast receiver -->
<receiver android:name=".MyParsePushBroadcastReceiver" 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>

...

I only added the service and the receiver, but you need to make sure you follow the GCM guide and the Parse push guides to have a full implementation (for example, google also added a way to handle the token refresh - a sample containing full code samples can be found here).

推荐答案

If I understand correctly, you want your code to handle all the incoming GCM messages, regardless of their source (which can be either your server or Parse website), which means you don't want the Parse code in your app do handle them.

You can achieve this by declaring only a single broadcast receiver handling com.google.android.c2dm.intent.RECEIVE action in your manifest. That would be your GCMBroadcastReceiver class, which would handle all the arriving GCM messages.

The behavior you are currently experiencing can happen when you declare two broadcast receivers that handle the same action.