我在我的应用程序执行的GCM通知。 因为我用我的代码来生成大量的应用程序具有不同的包名的我无法使用标准mypackage.GCMIntentService名。 当生成应用程序我只是做我的R类别的清单和变化的进口变化。 所以我impelented我自己的BroadcastReceiver
public class GCMReceiver extends GCMBroadcastReceiver {
@Override
protected String getGCMIntentServiceClassName(Context context) {
return GCMIntentService.class.getName();
}
}
返回GCMIntentService的名字不管包的名字。
这里是我的清单:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<permission
android:name="org.rferl.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="org.rferl.permission.C2D_MESSAGE" />
<service
android:name="org.rferl.service.GCMIntentService"
android:enabled="true" />
<receiver
android:name="org.rferl.GCMReceiver"
android:enabled="true"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<!-- Receives the actual messages. -->
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<!-- Receives the registration id. -->
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="org.rferl" />
</intent-filter>
</receiver>
一切工作正常,我可以注册,注销,接收消息。 但是,当应用程序没有运行过程中出现不GCMIntentService.onMessage不叫。 我失去了我的表现的东西吗? 为什么系统没有启动的服务?
为应用/改变包/类名GCMIntentService
/ GCMBroadcastReceiver
为Android GCM(使用Eclipse ADT)
注 : 建议您验证是否可以做以下修改之前通过GCM接收消息。 为了实现在使用应用程序的默认的包名 Android应用GCM,请参阅GCM:入门 。
包裹名字
要更改您的应用程序(例如,新包的名字=的包名com.example.newpackage
)
- 在Package Explorer中,右键单击该项目的Android→工具→重命名应用程序包。
这种自动更新方便包的名称。 在AndroidManifest.xml
,在更新软件包名称permission
和uses-permission
的C2D_MESSAGE
:
<permission android:name="com.example.newpackage.permission.C2D_MESSAGE" android:protectionLevel="signature" /> <uses-permission android:name="com.example.newpackage.permission.C2D_MESSAGE" />
在AndroidManifest.xml
,在更新软件包名称category
中的receiver
:
<receiver android:name="com.example.oldpackage.GCMBroadcastReceiver" android:permission="com.google.android.c2dm.permission.SEND" > <!-- Not this one!! --> <intent-filter> <action android:name="com.google.android.c2dm.intent.RECEIVE" /> <action android:name="com.google.android.c2dm.intent.REGISTRATION" /> <category android:name="com.example.newpackage" /> <!-- This one!! --> </intent-filter> </receiver>
名称GCMIntentService
如果你的应用程序的软件包名称com.example.newpackage
,您GCMIntentService
必须调用com.example.newpackage.GCMIntentService
。 如果不,
创建一个新的类extends
GCMBroadcastReceiver
和覆盖getGCMIntentServiceClassName()
public class MyBroadcastReceiver extends GCMBroadcastReceiver { @Override protected String getGCMIntentServiceClassName(Context context) { return MyIntentService.class.getName(); // Don't hard-code like "com.example.oldpackage.MyIntentService", see http://stackoverflow.com/a/936696/1402846 } }
这是基于谷歌的GCMBroadcastReceiver文档 :
默认情况下, GCMBaseIntentService
类属于应用程序主包,被命名为DEFAULT_INTENT_SERVICE_CLASS_NAME
。 要使用新的类,在getGCMIntentServiceClassName(Context)
必须重写。
在AndroidManifest.xml
,更新的名称receiver
:
<receiver android:name="com.example.oldpackage.MyBroadcastReceiver" ... > </receiver>
在AndroidManifest.xml
,更新的名称service
:
<service android:name="com.example.oldpackage.MyIntentService" />
名称GCMBroadcastReceiver
如果你改变的包/类名GCMBroadcastReceiver
:
故障排除
验证在AndroidManifest.xml
,包名应该出现至少4次:
在manifest
:
<manifest ... package="com.example.newpackage" ...
在permission
:
<permission android:name="com.example.newpackage.permission.C2D_MESSAGE" android:protectionLevel="signature" />
在uses-permission
:
<uses-permission android:name="com.example.newpackage.permission.C2D_MESSAGE" />
在category
中的intent-filter
内的receiver
的GCM广播接收器:
<category android:name="com.example.newpackage" />
如果你改变了你的包名,卸载在测试之前您的设备/仿真器的旧的应用程序。
- 如果你改变了你的包名,发现注册ID(即您在收到
onRegistered()
已经改变。 如果您在收到您的注册ID onRegistered()
你应该看到在logcat中(标签像这样GCMBroadcastReceiver
):
GCMBroadcastReceiver onReceive: com.google.android.c2dm.intent.REGISTRATION GCMBroadcastReceiver GCM IntentService class: com.example.oldpackage.MyIntentService
验证意图服务的包/类名是正确的。
如果重写getGCMIntentServiceClassName(Context)
在自己的GCMBroadcastReceiver
,你应该看到的logcat(标签像这样GCMRegistrar
):
GCMRegistrar Setting the name of retry receiver class to com.example.oldpackage.MyBroadcastReceiver
验证广播接收机的包/类名是正确的。
- 当你的服务器发送消息给GCM服务器,检查HTTP状态代码和错误的HTTP响应。
- 如果你感到绝望:
- 检查logcat的错误。
- 请尝试重新启动您的设备/模拟器。
- 尝试在设备/仿真器卸载您的应用程序。
- 请尝试重新启动Eclipse的。
- 尝试清洁并重新构建项目。
- 尝试更新ADT(下拉菜单→窗口→Android SDK中管理器→安装包)。
- 尝试更新的Eclipse(下拉菜单→帮助→检查更新)。
- 请尝试重新启动您的计算机。
- 获得良好的睡眠,或祈祷。
你应该把GCMIntentService类到根应用程序包。 这里org.rferl
<service
android:name=".GCMIntentService"
android:enabled="true" />
和接收器
<receiver
android:name="com.google.android.gcm.GCMBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<!-- Receives the actual messages. -->
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<!-- Receives the registration id. -->
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.EgoSecure.ma" />
</intent-filter>
</receiver>
因为我用我的代码来生成大量的应用程序具有不同的包名的我无法使用标准mypackage.GCMIntentService名。
我不知道你是否要求运行时或生成时的解决方案。 其他答案是运行时的解决方案,所以我想我在编译的时候加上possibilites一些信息。
在AndroidManifest,你可以使用变量$PACKAGE_NAME
(默认情况下可用),这将是指您在属性指定的包名package
在manifest
根元素。
此的值package
属性不需要是硬编码的字符串,但也可以经由资源引用动态地设置,如下所示:
<manifest package="@string/app_package" ...>
...
<service
android:name="$PACKAGE_NAME.service.GCMIntentService"
android:enabled="true" />
...
</manifest>
注.service
仅仅是我包括向您展示如何指定这些子包。 当然,如果你的应用程序遵循一般规律,即把服务类在此解决方案只会工作.service
分装。
还要注意,你其实可以留下根包完全关闭。 它将搭载Android扩展:
<manifest package="@string/app_package" ...>
...
<service
android:name=".service.GCMIntentService"
android:enabled="true" />
...
</manifest>
在效果上,与上述相同。
如果你正在寻找一种更灵活的方式在AndroidManifest(或不同文件)来替换值,你可能想看看Ant的替换任务( http://ant.apache.org/manual/Tasks/replace。 HTML )或资源过滤( http://maven.apache.org/plugins/maven-resources-plugin/examples/filter.html )与Maven。
该GCM广播接收器(GCMBroadcastReceiver.class)调用从应用程序根目录意图服务类(GCMIntentService.class)。 不能使用“org.rferl.service.GCMIntentService”现在。 你应该覆盖从GCMBroadcastReceiver getGCMIntentServiceClassName方法,返回你的GCMIntentService类的名称。 如何做到这一点, 在这里