Android App和Android Library之间的GCM冲突

时间:2015-11-17 13:13:59

标签: android google-cloud-messaging

我正在构建一个使用GCM的库。我正在使用实现GCM的示例应用程序对其进行测试。

我已经对两者使用了相同的实现,除了它们中的每一个都有自己的发送者ID

我为我的示例应用程序编写的内容我正在测试库。我也为图书馆写了同样的东西,但服务名称不同:

<!-- GCM -->
    <receiver
        android:name="com.google.android.gms.gcm.GcmReceiver"
        android:exported="true"
        android:permission="com.google.android.c2dm.permission.SEND">
        <intent-filter>
            <action android:name="com.google.android.c2dm.intent.RECEIVE" />

            <category android:name="com.example.instabug" />
        </intent-filter>
    </receiver>

    <service
        android:name=".SampleInstanceIDListenerService"
        android:exported="false">
        <intent-filter>
            <action android:name="com.google.android.gms.iid.InstanceID" />
        </intent-filter>
    </service>
    <service
        android:name=".SampleGcmRegistrationIntentService"
        android:exported="false"/>
    <service
        android:name=".SampleGcmListenerService"
        android:exported="false">
        <intent-filter>
            <action android:name="com.google.android.c2dm.intent.RECEIVE" />
        </intent-filter>

    </service>

我的问题是每当我向我的库发送推送通知时,App接收器总是抓住它。图书馆接收者什么都不做。

有没有办法解决这个问题?!

2 个答案:

答案 0 :(得分:1)

据我所知,您有两个具有相同意图过滤器的服务。在这种情况下,Android将选择具有更高优先级(前台)的服务。如果优先级相同 - 将随机选择,即只有一个服务将接收意图。

对于您的案例,最佳解决方案是仅使用一项服务,并根据fromonMessageReceived()的{​​{1}}(senderId)参数发送。

答案 1 :(得分:1)

我想办法做到这一点。在我的Android库中,我为GcmListenerService提供了比Android应用程序更高优先级的intent过滤器,以便首先接收和处理库中的GCM消息。

<service
    android:name=".SampleGcmListenerService"
    android:exported="false">
    <intent-filter priority="100">
        <action android:name="com.google.android.c2dm.intent.RECEIVE" />
    </intent-filter>

</service>

当GCM消息到达库的GcmListenerService时,如果它与库无关,则必须转发到Android应用程序。因为我正在创建一个可供将来使用的库。我不知道在哪里可以找到app模块中的GcmListenerService。我所能做的就是使用反射来获取应用程序模块中的所有类,并查看哪个类具有GcmListenerService作为超类,然后启动对该类的唤醒服务。

我在这里做了什么:

@Override
public void onMessageReceived(String from, Bundle data) {

    if (!from.equalsIgnoreCase("51XXXXXXXX")) {
        String[] classes = getClassesOfPackage(getPackageName());
        for (int i = 0; i < classes.length; i++) {
            String sClassName = classes[i];
            try {
                Class classToInvestigate = Class.forName(sClassName);

                String superClassName = classToInvestigate.getSuperclass().getName();
                if (superClassName.equalsIgnoreCase("com.google.android.gms.gcm.GcmListenerService")) {

                    //sending intent to the wakeful app's service
                    forwardGcmToApp(from, data, sClassName);
                }
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    } else {
        //TODO: fire the polling service
        String message = data.getString("message");
    }
}

/**
 * Called to get list of classes included in the current project
 *
 * @param packageName the name of application package
 * @return array of classes' names
 */
private String[] getClassesOfPackage(String packageName) {
    ArrayList<String> classes = new ArrayList<>();
    try {
        String packageCodePath = getPackageCodePath();
        DexFile df = new DexFile(packageCodePath);
        for (Enumeration<String> iter = df.entries(); iter.hasMoreElements(); ) {
            String className = iter.nextElement();
            if (className.contains(packageName)) {
                classes.add(className);
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

    return classes.toArray(new String[classes.size()]);
}

/**
 * Called to forward Gcm content to the App {@link GcmListenerService}
 *
 * @param from Gcm sender ID
 * @param data bundle received from Gcm
 * @param className Class name that extends {@link GcmListenerService}
 */
private void forwardGcmToApp(String from, Bundle data, String className){
    Intent intent = new Intent();
    intent.setAction("com.google.android.c2dm.intent.RECEIVE");

    data.putString("from", from);
    data.putString("message_type", null);

    intent.putExtras(data);
    intent.setComponent(new ComponentName(getPackageName(), className));

    GcmReceiver.startWakefulService(getApplicationContext(), intent);
}