SERVICE_NOT_AVAILABLE 同时使用 Xamarin for Android 注册 Google Cloud Messaging
Posted
技术标签:
【中文标题】SERVICE_NOT_AVAILABLE 同时使用 Xamarin for Android 注册 Google Cloud Messaging【英文标题】:SERVICE_NOT_AVAILABLE while registering Google Cloud Messaging with Xamarin for Android 【发布时间】:2013-10-15 04:03:29 【问题描述】:我正在创建将 GCM 与 Xamarin 一起使用的 android 应用程序。 我关注了this guide from Xamarin team,然后是this guide from Google team
在我实现了 Gcm 的 Xamarin 版本之后,我的 BroadcaseReceiver.OnReceive 什么也没收到。这是清单和广播接收器
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:installLocation="auto"
package="com.pushtest.droid"
android:versionCode="1"
android:versionName="1">
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="15" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<permission android:name="com.pushtest.droid.permission.C2D_MESSAGE" android:protectionLevel="signature"/>
<uses-permission android:name="com.pushtest.droid.permission.C2D_MESSAGE" />
<application android:label="push droid"/>
</manifest>
广播接收者:
[BroadcastReceiver(Permission = "com.google.android.c2dm.permission.SEND")]
[IntentFilter(new[] "com.google.android.c2dm.intent.RECEIVE", Categories = new[] "com.pushtest.droid")]
[IntentFilter(new[] "com.google.android.c2dm.intent.REGISTRATION", Categories = new[] "com.pushtest.droid")]
[IntentFilter(new[] "com.google.android.gcm.intent.RETRY", Categories = new[] "com.pushtest.droid")]
public class MyGcmBroadcastReceiver : BroadcastReceiver
public override void OnReceive(Context context, Intent intent)
System.Diagnostics.Debug.WriteLine("MyGcmBroadcastReceiver.OnReceive");
if (intent.Action == "com.google.android.c2dm.intent.REGISTRATION")
var registrationId = intent.GetStringExtra("registration_id");
var error = intent.GetStringExtra("error");
var unregistered = intent.GetStringExtra("unregistered");
System.Diagnostics.Debug.WriteLine("!!!! Registration status |R: 0|E: 1|U: 2", registrationId, error, unregistered);
else if (intent.Action == "com.google.android.c2dm.intent.RECEIVE")
System.Diagnostics.Debug.WriteLine("!!!! Push Received: |TBD|");
当我开始意图时,我什么也没得到 - 没有错误,没有调试信息,没有结果:
private void RegisterForGcm(Context context)
const string SenderId = "PROJECT_ID_FROM_GOOGLE_CONSOLE";
var appExtra = PendingIntent.GetBroadcast(context, 0, new Intent(), 0);
var intent = new Intent("com.google.android.c2dm.intent.REGISTER");
intent.PutExtra("app", appExtra);
intent.PutExtra("sender", SenderId);
context.StartService(intent);
然后我以为 Google 的指南终于得到了注册响应 error = "SERVICE_NOT_AVAILABLE":
没有额外的字符串(没有registraion_id)。调试信息: !!!!注册状态 |R: |E: SERVICE_NOT_AVAILABLE|U:
这是我的 Manifest 和 BroadcastReceiver(意图开始是相同的):
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:installLocation="auto"
package="com.pushtest.droid"
android:versionCode="1"
android:versionName="1">
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="15" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<permission android:name="com.pushtest.droid.permission.C2D_MESSAGE" android:protectionLevel="signature"/>
<uses-permission android:name="com.pushtest.droid.permission.C2D_MESSAGE" />
<application android:label="push droid">
<receiver android:name="com.pushtest.droid.MyGcmBroadcastReceiver"
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" />
<action android:name="com.google.android.gcm.intent.RETRY" />
<category android:name="com.pushtest.droid" />
</intent-filter>
</receiver>
</application>
</manifest>
和BroadcastReceiver(没有任何属性)
public class MyGcmBroadcastReceiver : BroadcastReceiver
public override void OnReceive(Context context, Intent intent)
System.Diagnostics.Debug.WriteLine("MyGcmBroadcastReceiver.OnReceive");
if (intent.Action == "com.google.android.c2dm.intent.REGISTRATION")
var registrationId = intent.GetStringExtra("registration_id");
var error = intent.GetStringExtra("error");
var unregistered = intent.GetStringExtra("unregistered");
System.Diagnostics.Debug.WriteLine("!!!! Registration status |R: 0|E: 1|U: 2", registrationId, error, unregistered);
else if (intent.Action == "com.google.android.c2dm.intent.RECEIVE")
System.Diagnostics.Debug.WriteLine("!!!! Push Received: |TBD|");
此处的测试示例: https://dl.dropboxusercontent.com/u/19503836/pushtest-issue.zip
我在我的 Android 2.3.6 设备上尝试此代码 非常感谢任何帮助。
TIA!
【问题讨论】:
你的手机上有谷歌账号吗? 是的,我可以使用此配置的帐户访问 Google Play 商店 您是否已将此应用程序注册到 GCM 以获取 API 访问权限?您也可以将代码发布到您的意图服务吗? 是的,我在 google 控制台注册了我的项目并允许它使用 GCM。刚刚编辑了帖子并添加了源代码 ***.com/questions/17188982/… 是一个密切相关的问题(如果不是重复的话)。 【参考方案1】:您尚未创建 Service [IntentService ] 类。 正在启动服务但尚未创建该服务。BroadCastReceiver 将如下所示:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
namespace hellomultiscreen
public class MyGCMBroadcastReceiver : BroadcastReceiver
const string TAG = "PushHandlerBroadcastReceiver";
public override void OnReceive(Context context, Intent intent)
MyIntentService.RunIntentInService(context, intent);
SetResult(Result.Ok, null, null);
Toast.MakeText(context, "Received Message!", ToastLength.Short).Show();
Intent Service 如下所示
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.Support.V4.App;
using Android.Preferences;
using String = System.String;
namespace hellomultiscreen
[Service]
public class MyIntentService : IntentService
static PowerManager.WakeLock sWakeLock;
static object LOCK = new object();
public static void RunIntentInService(Context context, Intent intent)
lock (LOCK)
if (sWakeLock == null)
// This is called from BroadcastReceiver, there is no init.
var pm = PowerManager.FromContext(context);
sWakeLock = pm.NewWakeLock(
WakeLockFlags.Partial, "My WakeLock Tag");
sWakeLock.Acquire();
intent.SetClass(context, typeof(MyIntentService));
context.StartService(intent);
protected override void OnHandleIntent(Intent intent)
try
Context context = this.ApplicationContext;
string action = intent.Action;
if (action.Equals("com.google.android.c2dm.intent.REGISTRATION"))
HandleRegistration( context,intent);
else if (action.Equals("com.google.android.c2dm.intent.RECEIVE"))
HandleMessage(intent);
finally
lock (LOCK)
//Sanity check for null as this is a public method
if (sWakeLock != null)
sWakeLock.Release();
private void HandleRegistration(Context context, Intent intent)
String registration = intent.GetStringExtra("registration_id");
if (intent.GetStringExtra("error") != null)
// Registration failed, should try again later.
else if (intent.GetStringExtra("unregistered") != null)
// unregistration done, new messages from the authorized sender will be rejected
else if (registration != null)
string score = "Successful Login To Bullseye Account";
long[] vibraPattern = 0, 500, 250, 500 ;
Bundle valuesForActivity = new Bundle();
valuesForActivity.PutString("score", score);
// Create the PendingIntent with the back stack
// When the user clicks the notification, SecondActivity will start up.
Intent resultIntent = new Intent(this, typeof(NotificationDetails));
resultIntent.PutExtras(valuesForActivity); // Pass some values to SecondActivity.
TaskStackBuilder stackBuilder = TaskStackBuilder.Create(this);
stackBuilder.AddParentStack(Java.Lang.Class.FromType(typeof(NotificationDetails)));
stackBuilder.AddNextIntent(resultIntent);
PendingIntent resultPendingIntent = stackBuilder.GetPendingIntent(0, (int)PendingIntentFlags.UpdateCurrent);
// Build the notification
NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
.SetAutoCancel(true) // dismiss the notification from the notification area when the user clicks on it
.SetContentIntent(resultPendingIntent) // start up this activity when the user clicks the intent.
.SetContentTitle(score) // Set the title
.SetNumber(1) // Display the count in the Content Info
.SetSmallIcon(Resource.Drawable.alert) // This is the icon to display
.SetVibrate(vibraPattern)
.SetContentText(score); // the message to display.
// Finally publish the notification
NotificationManager notificationManager = (NotificationManager)GetSystemService(Context.NotificationService);
notificationManager.Notify(1, builder.Build());
private void HandleMessage(Intent intent)
try
string score = intent.GetStringExtra("message");
long[] vibraPattern = 0, 500, 250, 500 ;
Bundle valuesForActivity = new Bundle();
valuesForActivity.PutString("score", score);
// Create the PendingIntent with the back stack
// When the user clicks the notification, SecondActivity will start up.
Intent resultIntent = new Intent(this, typeof(NotificationDetails));
resultIntent.PutExtras(valuesForActivity); // Pass some values to SecondActivity.
TaskStackBuilder stackBuilder = TaskStackBuilder.Create(this);
stackBuilder.AddParentStack(Java.Lang.Class.FromType(typeof(NotificationDetails)));
stackBuilder.AddNextIntent(resultIntent);
PendingIntent resultPendingIntent = stackBuilder.GetPendingIntent(0, (int)PendingIntentFlags.UpdateCurrent);
// Build the notification
NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
.SetAutoCancel(true) // dismiss the notification from the notification area when the user clicks on it
.SetContentIntent(resultPendingIntent) // start up this activity when the user clicks the intent.
.SetContentTitle(score) // Set the title
.SetNumber(1) // Display the count in the Content Info
.SetSmallIcon(Resource.Drawable.alert) // This is the icon to display
.SetContentText(score); // the message to display.
// Finally publish the notification
NotificationManager notificationManager = (NotificationManager)GetSystemService(Context.NotificationService);
notificationManager.Notify(1, builder.Build());
//
catch
【讨论】:
【参考方案2】:我从不费心尝试构建我们自己的推送技术,因为 PushSharp 运行良好。他有带有工作代码的 monodroid 和 monotouch 示例。我们一直在工作中使用它,除了一些已修复的旧错误之外,该库一直很可靠。
我查看了我的应用程序生成的清单,其中包含一些您没有的内容。如果你坚持构建自己的服务,至少看看他的代码,看看他是怎么做的。
Link to GitHub project
【讨论】:
以上是关于SERVICE_NOT_AVAILABLE 同时使用 Xamarin for Android 注册 Google Cloud Messaging的主要内容,如果未能解决你的问题,请参考以下文章
FirebaseInstanceId:令牌检索失败:SERVICE_NOT_AVAILABLE 错误
FirebaseInstanceId:令牌检索失败:SERVICE_NOT_AVAILABLE
解决以下错误:FirebaseInstanceId:令牌检索失败:SERVICE_NOT_AVAILABLE。将重试令牌检索
FirebaseCloudMessaging:FirebaseInstanceId 后台同步失败 - SERVICE_NOT_AVAILABLE
Android 2.2 上的 GCM SERVICE_NOT_AVAILABLE
FirebaseInstanceId.getInstanceId()与连接到iPhone WearOS设备上SERVICE_NOT_AVAILABLE失败