我正在构建一个使用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接收器总是抓住它。图书馆接收者什么都不做。
有没有办法解决这个问题?!
答案 0 :(得分:1)
据我所知,您有两个具有相同意图过滤器的服务。在这种情况下,Android将选择具有更高优先级(前台)的服务。如果优先级相同 - 将随机选择,即只有一个服务将接收意图。
对于您的案例,最佳解决方案是仅使用一项服务,并根据from
中onMessageReceived()
的{{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);
}