如何在 Android (Xamarin) 上为 AWS SNS 启用推送通知

Posted

技术标签:

【中文标题】如何在 Android (Xamarin) 上为 AWS SNS 启用推送通知【英文标题】:how to enable push notifications on Android (Xamarin) for AWS SNS 【发布时间】:2016-03-11 20:53:05 【问题描述】:

我已经尝试了几个小时来为 android 启用推送通知,以便可以将它与 Amazon SNS 一起使用。已尝试按照文档中描述的代码进行操作:http://docs.aws.amazon.com/mobile/sdkforxamarin/developerguide/getting-started-sns-android.html

似乎我做错了什么,因为我创建的“意图”将“动作”设置为 null,这会导致 OnHandleIntent 中出现异常。有没有人有这方面的经验?我对 Android 还很陌生,所以我对“意图”的理解……相当有限。

这里是 MainActivity

[Activity (Label = "awst", MainLauncher = true, Icon = "@mipmap/icon")]
public class MainActivity : Activity

int count = 1;

    protected override void OnCreate (Bundle savedInstanceState)
    
        base.OnCreate (savedInstanceState);

        // Set our view from the "main" layout resource
        SetContentView (Resource.Layout.Main);

        // Get our button from the layout resource,
        // and attach an event to it
        Button button = FindViewById<Button> (Resource.Id.myButton);

        button.Click += delegate 

            button.Text = string.Format ("0 clicks!", count++);

            var intent = new Intent (this, typeof (GCMIntentService));      


        ;

    


[BroadcastReceiver(Permission = "com.google.android.c2dm.permission.SEND")]
[IntentFilter(new string[] 
    "com.google.android.c2dm.intent.RECEIVE"
, Categories = new string[] 
    "com.companyname.awst" /* change to match your package */
)]
[IntentFilter(new string[] 
    "com.google.android.c2dm.intent.REGISTRATION"
, Categories = new string[] 
    "com.companyname.awst" /* change to match your package */
)]
[IntentFilter(new string[] 
    "com.google.android.gcm.intent.RETRY"
, Categories = new string[] 
    "com.companyname.awst" /* change to match your package */
)]

public class GCMBroadcastReceiver: BroadcastReceiver 
    const string TAG = "PushHandlerBroadcastReceiver";
    public override void OnReceive(Context context, Intent intent) 

        GCMIntentService.RunIntentInService(context, intent);
        SetResult(Result.Ok, null, null);
    


[BroadcastReceiver]
[IntentFilter(new[] 
    Android.Content.Intent.ActionBootCompleted
)]

public class GCMBootReceiver: BroadcastReceiver 
    public override void OnReceive(Context context, Intent intent) 
        GCMIntentService.RunIntentInService(context, intent);
        SetResult(Result.Ok, null, null);
    


和 Intent 服务

namespace awst.Droid

[Service]
public class GCMIntentService: 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(GCMIntentService));

        // 
        context.StartService(intent); 
    

    protected override void OnHandleIntent(Intent intent) 
        try 
            Context context = this.ApplicationContext;
            string action = intent.Action;

            // !!!!!!
            // this is where the code fails with action beeing null
            // !!!!!!

            if (action.Equals("com.google.android.c2dm.intent.REGISTRATION")) 
                HandleRegistration(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(Intent intent) 

        Globals config = Globals.Instance;

        string registrationId = intent.GetStringExtra("registration_id");
        string error = intent.GetStringExtra("error");
        string unregistration = intent.GetStringExtra("unregistered");

        if (string.IsNullOrEmpty(error)) 

            config.snsClient.CreatePlatformEndpointAsync(new CreatePlatformEndpointRequest 
                Token = registrationId,
                PlatformApplicationArn = config.AWS_PlaformARN /* insert your platform application ARN here */
            );
        
    

    private void HandleMessage(Intent intent) 
        string message = string.Empty;
        Bundle extras = intent.Extras;
        if (!string.IsNullOrEmpty(extras.GetString("message"))) 
            message = extras.GetString("message");
         else 
            message = extras.GetString("default");
        

        Log.Info("Messages", "message received = " + message);

        ShowNotification("SNS Push", message);
        //show the message

    

    public void ShowNotification(string contentTitle,
        string contentText) 
        // Intent
        Notification.Builder builder = new Notification.Builder(this)
            .SetContentTitle(contentTitle)
            .SetContentText(contentText)
            .SetDefaults(NotificationDefaults.Sound | NotificationDefaults.Vibrate)
            //todo
            .SetSmallIcon(Resource.Mipmap.Icon)
            .SetSound(RingtoneManager.GetDefaultUri(RingtoneType.Notification));

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

        notificationManager.Notify(1001, builder.Build());
    


所以问题:

如何注册设备,然后我可以从 SNS 发送推送?我应该考虑其他方式吗??? 我必须采取任何其他步骤才能使其正常工作吗?我确实将证书上传到 AWS,但我需要在应用代码中配置任何权限吗??

非常感谢!!!

克里斯

【问题讨论】:

【参考方案1】:

您可能希望查看 GitHub 中的 SNS 示例或通过 Xamarin component store 来增加入门指南,您可能会发现一些您遗漏的内容并且未在入门指南中完整介绍。示例中存在但您的代码中没有的东西是主要活动中的RegisterForGCM()

private void RegisterForGCM()

    string senders = Constants.GoogleConsoleProjectId;
    Intent intent = new Intent("com.google.android.c2dm.intent.REGISTER");
    intent.SetPackage("com.google.android.gsf");
    intent.PutExtra("app", PendingIntent.GetBroadcast(this, 0, new Intent(), 0));
    intent.PutExtra("sender", senders);
    StartService(intent);

【讨论】:

非常感谢 - 这绝对是缺失的。我已经下载了示例并正在尝试它:我认为在 Constants.GoogleConsoleProjectId 中,我实际上需要但项目编号而不是 id。是对的吗?现在我已经能够运行示例,并且确实在 SNS 上注册了一个新端点,但是当我使用 SNS 控制台发送推送时,什么也没有发生。还有什么我需要做的吗?我需要订阅应用程序中的某些主题吗?我可以检查什么是错的吗? ....谢谢 已解决 - 刚刚在 GCM 上重新生成项目并更新了 SNS,它就可以工作了! 你救了我无数个小时! aws 文档很烂,所以过时了.. 我一直在他们的文档中寻找几个小时,但没有运气! 嗨@chrisb - 我也在努力遵循这些示例,我似乎已经达到了与您相同的点,即创建端点但设备没有收到通知。我正在通过模拟器运行它(它有 Google API 和 Google 帐户),我只是想知道除了重新生成项目并使用项目编号而不是应用程序 ID 之外,您是否做了任何其他事情,因为它们都不适合我?谢谢 好吧,我真的想不出我做过的任何其他事情,这也是不久前的事了。我的建议是重新生成所有密钥、项目……看看是否可行

以上是关于如何在 Android (Xamarin) 上为 AWS SNS 启用推送通知的主要内容,如果未能解决你的问题,请参考以下文章

Xamarin 中的单元测试查询

Android - 如何在 Google 地图上为 Google 徽标设置底部填充

如何在 Android 中的另一个视图上为文本设置动画?

如何在画布上为路径设置动画 - android

如何在android studio上为下划线着色?

如何在 Android TV 主屏幕上为当前正在运行的任务设置图标和标题