c# - Xamarin 安卓后台服务

标签 c# android xamarin background xamarin.android

我遵循了一些关于自定义服务应用程序处于后台或被杀死(包括 Xamarin 的)时运行的教程,但我自己没能成功。

我假装的:

1- Firebase 服务向设备发送通知。 此服务确实在后台/被杀死时工作

2- 我的自定义服务必须执行一个小功能只要fcm 服务执行。特别是如果应用程序在后台/被杀死如果应用程序在前台运行,我的服务会运行。

有人能指出我哪里失败了吗? (或者帮助我了解更好的后台服务?)

到目前为止我的代码:

定制服务

using Android.App;
using Android.Content;
using Android.OS;
using Android.Util;
using ME.Leolin.Shortcutbadger;

namespace App1
{
    [Service]
    public class Badge_Service : Service
    {
        int n = 0;
        public IBinder Binder { get; private set; }

        public override IBinder OnBind(Intent intent)
        {
            Log.Debug("SS", "OnBind");
            this.Binder = new Badge_Binder(this);
            add_up(n); //custom function
            return this.Binder;
        }

        public override bool StopService(Intent name)
        {
            return base.StopService(name);
        }

        public void add_up(int count)
        {
            count++;
            ShortcutBadger.ApplyCount(ApplicationContext, count);
        }
    }

    public class Badge_Binder : Binder
    {
        public Badge_Service Service { get; private set; }

        public Badge_Binder(Badge_Service Service)
        {
            this.Service = Service;
        }
    }

    public class Badge_Conection : Java.Lang.Object, IServiceConnection
    {
        MyFirebaseMessagingService activity;

        public bool IsConnected { get; private set; }
        public Badge_Binder Binder { get; private set; }

        public Badge_Conection(MyFirebaseMessagingService activity)
        {
            IsConnected = false;
            Binder = null;
            this.activity = activity;
        }

        public void OnServiceDisconnected(ComponentName name)
        {
            Log.Debug("SS", "Disconnected");
            IsConnected = false;
            Binder = null;
        }

        public void OnServiceConnected(ComponentName name, IBinder Service)
        {
            Binder = Service as Badge_Binder;
            IsConnected = this.Binder != null;
            Log.Info("SS", "Connected");
        }
    }
}

Firebase 实现

using Android.App;
using Android.Content;
using Firebase.Iid;
using Android.Support.V7.App;
using Android.Media;
using Firebase.Messaging;

namespace App1
{
    [Service]
    [IntentFilter(new[] { "com.google.firebase.INSTANCE_ID_EVENT" })]
    public class MyFirebaseServices : FirebaseInstanceIdService
    {
        public override void OnTokenRefresh()
        {
            base.OnTokenRefresh();
            MClass.IDfcm = FirebaseInstanceId.Instance.Token;   //MClass just stores variables for later use.
            Android.Util.Log.Debug("Refreshed Token:", MClass.IDfcm);
        }
    }

    [Service]
    [IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })]
    public class MyFirebaseMessagingService : FirebaseMessagingService
    {
        public override void OnMessageReceived(RemoteMessage msg)
        {
            base.OnMessageReceived(msg);
            sendNotification(msg.GetNotification().Body);

            Intent serviceToStart = new Intent(this, typeof(Badge_Service));
            BindService(serviceToStart, new Badge_Conection(this), Bind.AutoCreate);
        }

        private void sendNotification(string msg)
        {
            var activity = new Intent(this, typeof(LogIn)); //LogIn is my MainActivity
            activity.AddFlags(ActivityFlags.ClearTop);
            var  screen = PendingIntent.GetActivity(this, 0, activity, PendingIntentFlags.OneShot);
            var sound = RingtoneManager.GetDefaultUri(RingtoneType.Notification);
            var notif = new NotificationCompat.Builder(this)
                .SetSmallIcon(Resource.Drawable.Icon)
                .SetContentTitle("New Notification")
                .SetContentText(msg)
                .SetAutoCancel(true)
                .SetSound(sound)
                .SetContentIntent(screen);

            var controller = NotificationManager.FromContext(this);
            controller.Notify(0, notif.Build());
        }
    }
}

最佳答案

我前段时间解决了我的问题,因为我看到没有其他人回答过它,我会发布我的解决方案以防其他人遇到这个问题:

失败很简单,因为从未在后台调用 OnMessageReceived。我通过使用 HandleIntent 绕过了这个问题,这使得我的后台服务变得不必要,如下所示:(类是相同的):

    public override void HandleIntent(Intent intent)
    {
        string msg = intent.GetStringExtra("body");
        if (msg == null) msg = "New Notification";


        ShortcutBadger.ApplyCount(this, Global.countNotifications());
        sendNotification(msg);
    }

额外说明

HandleIntent 不能使用 RemoteMessage 类型,因此(如果我没记错的话)它无法检索通知的正文。

需要一个自定义通知发送者,以便能够手动检索正文作为 json。

这就是我构建自己的方式:

(警告:代码可能不是那么整洁。我到了用脑袋敲击键盘的阶段 D:):

    public static string signalFCM(string msg, string user_firebase_id) //This must be gathered by storing a firebase_id created by an android device.
    {
        try
        {
            WebRequest tRequest = WebRequest.Create("https://fcm.googleapis.com/fcm/send");
            tRequest.Method = "post";
            tRequest.ContentType = "application/json";
            var data = new
            {
                to = user_firebase_id,
                notification = new  // *** THIS IS HOW FIREBASE SENDS THEM BY DEFAULT
                {
                    body = msg,
                    title = "MyAPP",
                    sound = "Enabled"
                },
                // **** THIS IS THE CUSTOM EXTRA TO RETRIEVE ITS CONTENT ****
                data = new
                {
                    body = msg,
                    title = "MyAPP",
                    payload = "1"
                }
                // ******************
            };

            var serializer = new JavaScriptSerializer();
            var json = serializer.Serialize(data);
            Byte[] byteArray = Encoding.UTF8.GetBytes(json);
            tRequest.Headers.Add(string.Format("Authorization: key={0}", APP_KEY)); //This must be gathered from the Firebase Console APP page
            tRequest.Headers.Add(string.Format("Sender: id={0}", APP_ID)); //This must be gathered from the Firebase Console APP page
            tRequest.ContentLength = byteArray.Length;

            using (Stream dataStream = tRequest.GetRequestStream())
            {
                dataStream.Write(byteArray, 0, byteArray.Length);
                using (WebResponse tResponse = tRequest.GetResponse())
                {
                    using (Stream dataStreamResponse = tResponse.GetResponseStream())
                    {
                        using (StreamReader tReader = new StreamReader(dataStreamResponse))
                        {
                            String sResponseFromServer = tReader.ReadToEnd();
                            return sResponseFromServer;
                        }
                    }
                }
            }
        }
        catch (Exception ex)    {   return ex.Message;    }
    }
}

关于c# - Xamarin 安卓后台服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47291492/

相关文章:

C# 你打算调用方法吗

c# - 谷歌地图处理服务器端

android - 将 Kotlin 源附加到 AAR 在 Android Studio 中不起作用

azure - 我可以在 xamarin 表单应用程序中使用除 id 之外的任何其他列名称吗?

.net - 在 Xamarin iOS 中使用 .NET 标准

c# - Application Insights 上未显示异常详细信息

c# - 如何在单元测试中设置自动增量 ID

java - 无法实例化以下类 : com. google.android.gms.ads.AdView。帮我?

c# - 文件 "obj\Debug\android\bin\packaged_resources"不存在。在 Windows 8.1 上的 Visual Studio 2015 Xamarin 跨平台中

ios - 启动 Xamarin iOS 应用程序失败并显示日志消息 "An error occurred searching types for the given assembly"