Android 应用程序和 Android 库之间的 GCM 冲突

GCM conflict between Android App and Android Library

我正在构建一个使用 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>

我的问题是,每当我向我的图书馆发送推送通知时,应用程序接收器总是会捕获它。图书馆接收者什么都不做。

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

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

对于您的情况,最佳解决方案是仅使用一项服务并根据 GcmListenerService.

onMessageReceived()from (senderId) 参数进行调度

我想出了办法做到这一点。在我的 Android 库中,我为 GcmListenerService 的意图过滤器赋予了比 Android 应用程序中更高的优先级,以便库首先接收和处理 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 应用程序。因为我正在制作一个将来任何人都可以使用的库。我不知道在哪里可以找到应用程序模块中的 GcmListenerService。我所能做的就是使用反射来获取应用程序模块中的所有 classes 并查看哪个具有 GcmListenerService 作为超级 class 然后为那个 [=25] 启动唤醒服务=].

这是我所做的:

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