1

Xamarin で GCM を使用する Android アプリを作成しています。Xamarin チームこのガイドと、Google チームのこのガイドに従いました。

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のガイドが最終的にエラー= "SERVICE_NOT_AVAILABLE"で登録応答を取得したと考えました:

余分な文字列はありませんでした (registration_id はありません)。デバッグ情報: !!!!登録状況 |R: |E: SERVICE_NOT_AVAILABLE|U:

これが私のマニフェストと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 デバイスでこのコードを試していました。

ティア!

4

2 に答える 2

1

サービス [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();
        }
    }
}

インテントサービスは以下のようになります

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 
            {

            }
        }
    }
}
于 2013-12-09T13:12:55.560 に答える
0

PushSharpは非常にうまく機能するため、私は独自のプッシュ技術を構築しようとしたことは一度もありません。彼はモノドロイドとモノタッチの例を実際のコードと共に持っています。私たちは常にそれを仕事で使用してきましたが、いくつかの古いバグが修正されたことを除けば、ライブラリはしっかりしています。

私は自分のアプリが生成するマニフェストを見てきましたが、あなたのものにはないものがあります。独自のサービスを構築することを主張する場合は、少なくとも彼のコードを見て、彼がどのようにそれを行っているかを確認してください。

GitHub プロジェクトへのリンク

于 2013-10-16T18:08:59.043 に答える