用于GCM \远程通知的Xamarin广播接收器

时间:2015-04-21 16:09:47

标签: android xamarin broadcastreceiver xamarin.android

我是xamarin和Android的新手,所以这个问题可能很简单。但是,我正在尝试在this article

之后创建广播接收器和意图服务

我似乎从未在接收器或目标服务中遇到任何调试点。我不确定我错过了什么。这是我的表现:

<application android:label="gcc">
    <receiver android:name=".TrialBR" android:permission="com.google.android.c2dm.permission.SEND">
        <intent-filter>
            <action android:name="com.google.android.c2dm.intent.RECEIVE" />
            <category android:name="gcc.gcc" />
        </intent-filter>
    </receiver>
    <service android:name=".MyIntentService" />
</application>
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<permission android:name="gcc.gcc.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<uses-permission android:name="gcc.gcc.permission.C2D_MESSAGE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

我不完全确定包名。我只是关注项目的android设置中的包名称。这是我的接收者:

[BroadcastReceiver]
[IntentFilter(new[] { Android.Content.Intent.ActionBootCompleted })]
public class TrialBR : BroadcastReceiver
{
    public override void OnReceive (Context context, Intent intent)
    {
        MyIntentService.RunIntentInService(context, intent);
        SetResult(Result.Ok, null, null);
        Toast.MakeText (context, "Received intent!", ToastLength.Short).Show ();
    }
} 

这是我的意向服务:

[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(context, intent);
            }
        }
        finally
        {
            lock (LOCK)
            {
                //Sanity check for null as this is a public method
                if (sWakeLock != null)
                    sWakeLock.Release();
            }
        }
    }

    void HandleRegistration (Context context, Intent intent)
    {
        string senders = "123456789";
        Intent intent1 = new Intent("com.google.android.c2dm.intent.REGISTER");
        intent1.SetPackage("com.google.android.gsf");
        intent1.PutExtra("app", PendingIntent.GetBroadcast(context, 0, new Intent(), 0));
        intent1.PutExtra("sender", senders);
        context.StartService(intent1);
    }

    void HandleMessage (Context context, Intent intent)
    {
        string registrationId = intent.GetStringExtra("registration_id");
        string error = intent.GetStringExtra("error");
        string unregistration = intent.GetStringExtra("unregistered");
        Console.WriteLine ("Registration ID: " + registrationId);
    }
}

如果有人能指出我做错的正确方向,我真的很感激。我真的很感激。

1 个答案:

答案 0 :(得分:0)

我在这里发表了关于这个问题的答案:https://stackoverflow.com/a/29141884/2452682

但是从您的解决方案中快速查看,首先您可以从清单文件中删除这些手动定义,并将它们放在代码中。这可能是您没有收到推送通知的原因,因为我可以看到我生成的清单文件和您的清单文件之间存在一些差异(接收器看起来完全不同)

无论如何,我已经从我在链接中提供的解决方案中复制了实现的android部分:

1)在共享项目中,创建一个名为IPushNotificationRegister

的接口
 public interface IPushNotificationRegister
{
    void ExtractTokenAndRegister();
}

此接口用于获取推送令牌,然后将其发送到服务器。这个令牌每个设备都是唯一的。

2)在您的共享项目中,您应该调用ExtractTokenAndRegister(使用您最喜欢的IOC,我在登录后立即调用它。)

Android实施:

添加接收器以收听Google GCM服务收到的活动:

a)[BroadcastReceiver] [IntentFilter(new[] { Intent.ActionBootCompleted })] public class GCMBootReceiver : BroadcastReceiver { public override void OnReceive(Context context, Intent intent) { MyIntentService.RunIntentInService(context, intent); SetResult(Result.Ok, null, null); } }

b)

[assembly: Permission(Name = "@PACKAGE_NAME@.permission.C2D_MESSAGE")]
    [assembly: UsesPermission(Name = "android.permission.WAKE_LOCK")]
    [assembly: UsesPermission(Name = "@PACKAGE_NAME@.permission.C2D_MESSAGE")]
    [assembly: UsesPermission(Name = "com.google.android.c2dm.permission.RECEIVE")]
    [assembly: UsesPermission(Name = "android.permission.GET_ACCOUNTS")]
    [assembly: UsesPermission(Name = "android.permission.INTERNET")]

namespace Consumer.Mobile.Droid.PushNotification
{
    [BroadcastReceiver(Permission = "com.google.android.c2dm.permission.SEND")]
    [IntentFilter(new string[] { "com.google.android.c2dm.intent.RECEIVE" }, Categories = new string[] { "@PACKAGE_NAME@" })]
    [IntentFilter(new string[] { "com.google.android.c2dm.intent.REGISTRATION" }, Categories = new string[] { "@PACKAGE_NAME@" })]
    [IntentFilter(new string[] { "com.google.android.gcm.intent.RETRY" }, Categories = new string[] { "@PACKAGE_NAME@" })]
    [IntentFilter (new[]{ Intent.ActionBootCompleted }, Categories = new[]{ Intent.CategoryDefault })]
    public class GCMBroadcastReceiver : BroadcastReceiver
    {
        public override void OnReceive(Context context, Intent intent)
        {
            MyIntentService.RunIntentInService(context, intent);
            SetResult(Result.Ok, null, null);
        }
    }
}

c)添加Intent服务以处理通知

using Android.App;
using Android.Content;
using Android.Graphics;
using Android.Media;
using Android.OS;
using Android.Support.V4.App;
using Consumer.Mobile.Infra;
using Consumer.Mobile.Services.PushNotification;
using Java.Lang;
using XLabs.Ioc;
using TaskStackBuilder = Android.Support.V4.App.TaskStackBuilder;

namespace Consumer.Mobile.Droid.PushNotification
{
    [Service]
    public class MyIntentService : IntentService
    {
        private readonly ILogger _logger;
        private readonly IPushNotificationService _notificationService;
        private readonly IPushNotificationRegister _pushNotificationRegister;

        public MyIntentService()
        {
            _logger = Resolver.Resolve<ILogger>();
            _notificationService = Resolver.Resolve<IPushNotificationService>();
            _pushNotificationRegister = Resolver.Resolve<IPushNotificationRegister>();
        }

        static PowerManager.WakeLock _sWakeLock;
        static readonly 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(context, intent);
                }
            }
            finally
            {
                lock (Lock)
                {
                    //Sanity check for null as this is a public method
                    if (_sWakeLock != null)
                        _sWakeLock.Release();
                }
            }
        }

        private void HandleMessage(Context context, Intent intent)
        {

            Intent resultIntent = new Intent(this, typeof(MainActivity));


            TaskStackBuilder stackBuilder = TaskStackBuilder.Create(this);

            var c = Class.FromType(typeof(MainActivity));
            stackBuilder.AddParentStack(c);
            stackBuilder.AddNextIntent(resultIntent);

            string alert = intent.GetStringExtra("Alert");
            int number = intent.GetIntExtra("Badge", 0);

            var imageUrl = intent.GetStringExtra("ImageUrl");
            var title = intent.GetStringExtra("Title");

            Bitmap bitmap = GetBitmap(imageUrl);

            PendingIntent resultPendingIntent = stackBuilder.GetPendingIntent(0, (int)PendingIntentFlags.UpdateCurrent);

            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(title) // Set the title
                .SetNumber(number) // Display the count in the Content Info
                .SetSmallIcon(Resource.Drawable.Icon) // This is the icon to display
                .SetLargeIcon(bitmap)
                .SetSound(RingtoneManager.GetDefaultUri(RingtoneType.Notification))
                .SetContentText(alert); // the message to display.

            // Build the notification:
            Notification notification = builder.Build();

            // Get the notification manager:
            NotificationManager notificationManager =
                GetSystemService(Context.NotificationService) as NotificationManager;

            // Publish the notification:
            const int notificationId = 0;
            notificationManager.Notify(notificationId, notification);
        }

        private void HandleRegistration(Context context, Intent intent)
        {
            var token = intent.GetStringExtra("registration_id");
            _logger.Info(this.Class.SimpleName, "Received Token : " + token);

            if (_pushNotificationRegister.ShouldSendToken(token))
            {
                var uid = Android.Provider.Settings.Secure.GetString(MainActivity.Context.ContentResolver, Android.Provider.Settings.Secure.AndroidId);
                _notificationService.AddPushToken(token, DeviceUtils.GetDeviceType(), uid);
            }
        }


        private Bitmap GetBitmap(string url)
        {

            try
            {
                System.Net.WebRequest request =
                    System.Net.WebRequest.Create(url);
                System.Net.WebResponse response = request.GetResponse();
                System.IO.Stream responseStream =
                    response.GetResponseStream();
                return BitmapFactory.DecodeStream(responseStream);


            }
            catch (System.Net.WebException)
            {
                return null;
            }

        }

    }
}

d)实施接口IPushNotificationRegister:     使用Android.App;     使用Android.Content;     使用Consumer.Mobile.Services;     使用Consumer.Mobile.Services.PushNotification;

[assembly: Permission(Name = "@PACKAGE_NAME@.permission.C2D_MESSAGE")]
[assembly: UsesPermission(Name = "@PACKAGE_NAME@.permission.C2D_MESSAGE")]

// Gives the app permission to register and receive messages.
[assembly: UsesPermission(Name = "com.google.android.c2dm.permission.RECEIVE")]

// Needed to keep the processor from sleeping when a message arrives
[assembly: UsesPermission(Name = "android.permission.WAKE_LOCK")]
[assembly: UsesPermission(Name = "android.permission.RECEIVE_BOOT_COMPLETED")]
namespace Consumer.Mobile.Droid.PushNotification
{
    public class PushNotificationRegister : IPushNotificationRegister
    {          
        public override void ExtractTokenAndRegister()
        {
            string senders = AndroidConfig.GCMSenderId;
            Intent intent = new Intent("com.google.android.c2dm.intent.REGISTER");
            intent.SetPackage("com.google.android.gsf");
            intent.PutExtra("app", PendingIntent.GetBroadcast(MainActivity.Context, 0, new Intent(), 0));
            intent.PutExtra("sender", senders);
            MainActivity.Context.StartService(intent);
        }


    }
}