如何修复Google Cloud Messaging注册错误:SERVICE_NOT_AVAILABLE?

我遇到了一个奇怪的问题 – 我一直在我的应用程序中使用GCM相当长的一段时间,一切正常。 但是,在发布到Google Play之前,我将应用程序包名称从com.android.testapp更改为com.android.recognition ,此GCM停止工作之后。 起初,我得到了错误的GCM sender id not set on constructor并通过重写getSenderIds(Context context)修复它,但现在我无法获得注册ID。 以下是来自logcat的消息: 在这里输入图像描述

我该如何解决这个问题? 当我切换到新的软件包时,我将清单文件中的所有内容都更改为新的软件包:

 <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.android.recognition" /> </intent-filter> </receiver> 

那么这背后的问题是什么? 可以重命名应用程序包导致这个还是有另一个原因?

SERVICE_NOT_AVAILABLE错误表示GCM Service在当前不可用。 等一段时间再试。

这很多时候(以我的经验),所以不要担心。


请参阅GCM Lib的GCMConstants类。

 /** * The device can't read the response, or there was a 500/503 from the * server that can be retried later. The application should use exponential * back off and retry. */ public static final String ERROR_SERVICE_NOT_AVAILABLE = "SERVICE_NOT_AVAILABLE"; 

有关更多调查,请参阅GCMBaseIntentService handleRegistration()

 private void handleRegistration(final Context context, Intent intent) { String registrationId = intent.getStringExtra(EXTRA_REGISTRATION_ID); String error = intent.getStringExtra(EXTRA_ERROR); String unregistered = intent.getStringExtra(EXTRA_UNREGISTERED); Log.d(TAG, "handleRegistration: registrationId = " + registrationId + ", error = " + error + ", unregistered = " + unregistered); // registration succeeded if (registrationId != null) { GCMRegistrar.resetBackoff(context); GCMRegistrar.setRegistrationId(context, registrationId); onRegistered(context, registrationId); return; } // unregistration succeeded if (unregistered != null) { // Remember we are unregistered GCMRegistrar.resetBackoff(context); String oldRegistrationId = GCMRegistrar.clearRegistrationId(context); onUnregistered(context, oldRegistrationId); return; } // last operation (registration or unregistration) returned an error; Log.d(TAG, "Registration error: " + error); // Registration failed if (ERROR_SERVICE_NOT_AVAILABLE.equals(error)) { boolean retry = onRecoverableError(context, error); if (retry) { int backoffTimeMs = GCMRegistrar.getBackoff(context); int nextAttempt = backoffTimeMs / 2 + sRandom.nextInt(backoffTimeMs); Log.d(TAG, "Scheduling registration retry, backoff = " + nextAttempt + " (" + backoffTimeMs + ")"); Intent retryIntent = new Intent(INTENT_FROM_GCM_LIBRARY_RETRY); retryIntent.putExtra(EXTRA_TOKEN, TOKEN); PendingIntent retryPendingIntent = PendingIntent .getBroadcast(context, 0, retryIntent, 0); AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); am.set(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + nextAttempt, retryPendingIntent); // Next retry should wait longer. if (backoffTimeMs < MAX_BACKOFF_MS) { GCMRegistrar.setBackoff(context, backoffTimeMs * 2); } } else { Log.d(TAG, "Not retrying failed operation"); } } else { // Unrecoverable error, notify app onError(context, error); } } 

问题得到解答,对我而言,情况稍微复杂一些。

  1. 检查你有一个有效的互联网连接
  2. 检查您的清单中是否有Internet权限
  3. 确保Eran提到的包名是正确的
  4. 设备时间正确设置。 即使一切都是完美的,如果设备时钟设置不正确,它将会失败。

错误的时钟给我造成了问题。 🙂

确保您在清单的权限部分中更改了软件包名称:

 <permission android:name="YOUR_PACKAGE_NAME.permission.C2D_MESSAGE" android:protectionLevel="signature" /> <uses-permission android:name="YOUR_PACKAGE_NAME.permission.C2D_MESSAGE" /> 

我有一个类似的错误,由于在该部分包名不正确。

SERVICE_NOT_AVAILABLE是Google Cloud Messaging最令人沮丧的问题之一。 这是GoogleCloudMessaging.register(SENDER_ID)引发的一个exception,该函数调用为注册推送通知的设备注册并返回一个注册ID。

  1. SERVICE_NOT_AVAILABLE可能意味着用户的设备无法读取注册请求的响应,或者服务器返回500/503错误代码。 开发人员无法解决这个错误,因为它在Google的最后,所以我们可以盲目地build议用户应该在几个小时内再试一次。
  2. 即使注册成功,某些设备上也可能出现SERVICE_NOT_AVAILABLE。 这可以通过实施一个解决方法广播接收器来解决呼叫失败时的令牌。 我实施了这个解决方法,它可能已经解决了一些用户的问题,但我仍然收到许多其他的SERVICE_NOT_AVAILABLE投诉。
  3. 由于设备上的Google Play服务库过时或缺失,可能会发生SERVICE_NOT_AVAILABLE。 在这种情况下,应用程序理论上可以通过打开相应的Google Play应用程序列表来通知用户更新Google Play服务。 但是,应用程序并不知道这就是为什么SERVICE_NOT_AVAILABLE被抛出的原因,所以它不能盲目地将用户redirect到Google Play上的Google Play服务应用程序页面。
  4. 当设备的时钟不与networking同步时,可能发生SERVICE_NOT_AVAILABLE。 同样,开发人员也无法知道这是确切的问题,所以我们可以盲目地build议用户检查他们的系统时钟同步,希望他们是less数几个不同步的时钟之一。
  5. 当有根用户从设备上删除环聊/ GTalk应用时,可能会发生SERVICE_NOT_AVAILABLE(因为他们认为它是英国媒体报道)。 GCM由环聊/ GTalk实施和处理,因此无法使用GCM。
  6. 如果用户正在运行未安装Google API的设备(例如Amazon Kindle),则可能会发生SERVICE_NOT_AVAILABLE。 这里没有什么可以做的,这些用户永远不会收到你的应用程序的推送通知

阅读更多信息: http : //eladnava.com/google-cloud-messaging-extremely-unreliable/

单靠这些问题足以让我开始寻找GCM的替代品。 我会每天或每两天在我的应用程序上获得一星评价,并在包含引发SERVICE_NOT_AVAILABLE时显示的错误消息的注释。 我无法帮助这些用户,因为他们中的大多数都是因为他们无法控制的原因而收到的。

Google Cloud Messaging的另一种select

Pushy( https://pushy.me/ )是一个独立的推送通知网关,完全独立于GCM。 它像GCM一样维护自己的后台套接字连接,以接收推送通知。 基础协议是MQTT,这是一个极轻的pub / sub协议,利用很less的networking带宽和电池。

Pushy的一个巨大优势是发送推送通知(从服务器)到注册设备进行推送通知的代码在GCM和Pushy之间实际上是可以互换的。 这使得在实施GCM之后切换到Pushy非常容易,并且由于其不稳定性而不得不抛弃它。

(完全披露:我为自己的项目创build了Pushy,并意识到许多应用程序将从这样的服务中受益)

对我来说 – 设备时间不正确。 我改变了设备设置使用“自动date和时间”,再次尝试,一切都很好。

干杯

我有同样的问题,但没有上述解决scheme在我的情况下解决了这个问题。 幸运的是,我最近解决了这个问题,我想解释一下,跳过它将会帮助其他人:

在我的情况下,我在一个自定义的应用程序类中注册推送服务(在任何活动之前执行,我认为这是因为有些东西没有被初始化)。 改变主要活动解决了这个问题。

 public class MyCustomApp extends Application { @Override public void onCreate() { super.onCreate(); PushService.register(this); //BAD IDEA, don't register pushes in Application Class } } 

我有一个类似的问题。 在谷歌联盟工作得很好(Android 4.4.2),但不是在三星Galaxy S3(Android 4.1.2)。 我在Samsung上注册了SERVICE_NOT_AVAILABLE。 原来三星的时间已经到了。 它没有设置为使用networking时间自动更新。 一旦我确定GCM的工作就像一个魅力。 谢谢 – Umesh

对我来说有连接问题。 更改networking连接解决了我的问题

对于我来说,我已经通过检查我的Galaxy S4上的“数据使用”选项中的“限制后台数据”来closuresGoogle服务的“后台数据访问”。 只要我把它解决cellarernetworking上的问题。 在无线上,它工作正常。

就我而言,解决scheme是根据https://snowdog.co/blog/dealing-with-service_not_available-google-cloud-messaging/向清单中添加新的意图筛选器操作REGISTRATION

  <receiver android:name=".RemoteNotificationReceiver" android:permission="com.getset.getset.c2dm.permission.SEND" > <intent-filter> <action android:name="com.getset.getset.c2dm.intent.RECEIVE" /> <action android:name="com.getset.getset.c2dm.intent.REGISTRATION" /> <category android:name="com.getset.getset" /> </intent-filter> </receiver> 

我不得不承认,我感到惊讶的是,这是有效的,因为它从教程中缺less,但是把它取出,肯定会把一个成功的注册ID变成一个例外。

注意:使用Nexus 5 API 21(棒棒糖)模拟器。

对我来说,问题是电话没有连接到互联网。 我断开并连接到Wi-Fi,并testing与浏览器的连接并再次testing。 工作就像一个魅力:-)

我已经转向了Google服务的“后台数据访问”。 在数据使用选项取消选中“限制后台数据”它适用于我!

对我来说goolge封锁了我的IP! 我不得不重置我的DSL连接从池中获得一个新的IP,一切工作,idk为什么他们阻止我,也许尝试了很多应用程序? 无论如何正在工作,我希望这可以帮助别人:)

对我来说,SERVICE_NOT_AVAILABLE问题在我的应用程序项目中,因为接收者类。 所以我解决了如下所示的接收器。 <receiver android:name="receiver name" 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="your package"/> </intent-filter> </receiver>我希望会帮助你:-)。

经过漫长的斗争,我设法解决这个问题。 确保Google Play Services应用程序是最新的,并且您的手机上的后台同步function未被禁用。