Xamarin Droid后台服务

时间:2016-09-21 09:20:43

标签: service xamarin.android mvvmcross background-service

我正在尝试在Xamarin.Droid中使用后台服务(使用mvvmcross),该服务在登录后启动。 假设它应该每3个小时运行一次,即使应用程序被taskmanager杀死了。

由于服务执行的任务(获取gps位置,然后向服务器发送post请求)需要用户进行身份验证(通过令牌),因此只有在承载令牌有效时才应运行该任务。 基本上我希望它一直运行,除非我还没有登录,或者当我退出时。

下面,我的代码在https://technology.jana.com/2014/10/28/periodic-background-tasks-in-android/

的Java示例后面找到

的Manifest.xml

<receiver android:name="com.livelakecomo.PeriodicTaskReceiver">
       <intent-filter>
           <action android:name="android.intent.action.BATTERY_LOW" />
           <action android:name="android.intent.action.BATTERY_OKAY" />
           <action android:name="live.xam.lakecomo.droid.PERIODIC_TASK_HEART_BEAT" />
       </intent-filter>
   </receiver>
   <receiver android:name="com.livelakecomo.BootAndUpdateReceiver">
       <intent-filter>
           <action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
           <action android:name="android.intent.action.BOOT_COMPLETED" />
       </intent-filter>
   </receiver>
   <service android:name="com.livelakecomo.BackgroundService" />

BootAndUpdateReceiver.cs

using Android.Content;
using Android.Util;

namespace Live.Xam.LakeComo.Droid
{
    [BroadcastReceiver(Name = "com.livelakecomo.BootAndUpdateReceiver")]
    public class BootAndUpdateReceiver : BroadcastReceiver
    {

    private static string TAG = "BootAndUpdateReceiver";

    public override void OnReceive(Context context, Intent intent)
    {
            Log.Info(TAG, "Booted");
            System.Diagnostics.Debug.WriteLine("boot onreceive");
            if (intent.Action.Equals("android.intent.action.BOOT_COMPLETED") ||
                intent.Action.Equals("android.intent.action.MY_PACKAGE_REPLACED")) {
            Intent startServiceIntent = new Intent(context, typeof(BackgroundService));
            context.StartService(startServiceIntent);
        }
    }
    }
}

BackgroundService

using Android.App;
using Android.Content;
using Android.OS;
using Android.Util;
using Live.Base.Xam.Core;
using Plugin.CurrentActivity;

namespace Live.Xam.LakeComo.Droid
{

    public class BackgroundBinder : Binder
    {
        BackgroundService service;

        public BackgroundBinder(BackgroundService service)
        {
            this.service = service;
        }

    }
    public class BackgroundService : Service
    {
        BackgroundBinder binder;
        private static string TAG = "BackgroundService";

        PeriodicTaskReceiver mPeriodicTaskReceiver = new PeriodicTaskReceiver();

        public override IBinder OnBind(Intent intent)
        {
            binder = new BackgroundBinder(this);
            return binder;
        }

        public int OnStartCommand(Intent intent, int flags, int startId)
        {
            Log.Info(TAG, "OnstartCommand");
            MainApplication myApplication = (MainApplication)CrossCurrentActivity.Current.Activity.Application;
            ISharedPreferences sharedPreferences = myApplication.GetSharedPreferences("sharedprefs", FileCreationMode.WorldWriteable);
            IntentFilter batteryStatusIntentFilter = new IntentFilter(Intent.ActionBatteryChanged);
            Intent batteryStatusIntent = RegisterReceiver(null, batteryStatusIntentFilter);

            if (batteryStatusIntent != null)
            {
                int level = batteryStatusIntent.GetIntExtra(BatteryManager.ExtraLevel, -1);
                int scale = batteryStatusIntent.GetIntExtra(BatteryManager.ExtraScale, -1);
                float batteryPercentage = level / (float)scale;
                float lowBatteryPercentageLevel = 0.14f;

                try
                {
                    int lowBatteryLevel = Resources.GetInteger(Resources.GetIdentifier("config_lowBatteryWarningLevel", "integer", "android"));
                    lowBatteryPercentageLevel = lowBatteryLevel / (float)scale;
                }
                catch (Android.Content.Res.Resources.NotFoundException e)
                {
                    Android.Util.Log.Error(TAG, "Missing low battery threshold resource");
                }

                sharedPreferences.Edit().PutBoolean(LiveConstants.BACKGROUND_SERVICE_BATTERY_CONTROL, batteryPercentage >= lowBatteryPercentageLevel).Apply();
            }
            else
            {
                sharedPreferences.Edit().PutBoolean(LiveConstants.BACKGROUND_SERVICE_BATTERY_CONTROL, true).Apply();
            }

            mPeriodicTaskReceiver.RestartPeriodicTaskHeartBeat(ApplicationContext, myApplication);
            return (int)StartCommandResult.RedeliverIntent;
        }
    }
}

PeriodicTaskReceiver

using Android.Content;
using Android.Preferences;
using Android.App;
using Plugin.CurrentActivity;
using Android.OS;
using Live.Base.Xam.Core;
using System;
using Android.Locations;
using Android.Runtime;
using Android.Util;
using System.Threading.Tasks;
using Live.Base.Xam.Core.Services;

namespace Live.Xam.LakeComo.Droid
{
    [BroadcastReceiver(Name = "com.livelakecomo.PeriodicTaskReceiver")]
    public class PeriodicTaskReceiver : BroadcastReceiver, ILocationListener
    {

        private static string TAG = "PeriodicTaskReceiver";
        private static string INTENT_ACTION = "com.livelakecomo.PERIODIC_TASK_HEART_BEAT";
        private LocationManager _locationManager;
        private string _locationProvider;
        private Location _currentLocation;

        public override void OnReceive(Context context, Intent intent)
        {
            Log.Info("robbyPeriodic", "OnReceive");

            System.Diagnostics.Debug.WriteLine("robbysbobby OnReceive");
            var myApplication = (MainApplication)CrossCurrentActivity.Current.Activity.Application;
            if (!string.IsNullOrEmpty(intent.Action))
            {

                ISharedPreferences sharedPreferences = PreferenceManager.GetDefaultSharedPreferences(CrossCurrentActivity.Current.Activity.ApplicationContext);


                if (intent.Action.Equals("android.intent.action.BATTERY_LOW"))
                {
                    sharedPreferences.Edit().PutBoolean(LiveConstants.BACKGROUND_SERVICE_BATTERY_CONTROL, false).Apply();
                    StopPeriodicTaskHeartBeat(context);
                }
                else if (intent.Action.Equals("android.intent.action.BATTERY_OKAY"))
                {
                    sharedPreferences.Edit().PutBoolean(LiveConstants.BACKGROUND_SERVICE_BATTERY_CONTROL, true).Apply();
                    RestartPeriodicTaskHeartBeat(context, myApplication);
                }
                else if (intent.Action.Equals(INTENT_ACTION))
                {
                    DoPeriodicTask(context, myApplication);
                }
            }
        }

        private void DoPeriodicTask(Context context, MainApplication myApplication)
        {
            System.Diagnostics.Debug.WriteLine("robbysbobby DoPeriodicTask");
            Log.Info("robbyPeriodic", "DoPeriodic");
            InitializeLocationManager();
            System.Threading.Tasks.Task.Run(async () => { await SendInformationToServer(); }).Wait();
        }

        private async Task<bool> SendInformationToServer()
        {
            Log.Info("robbyPeriodic", "Dentro Sendnotify");

            System.Diagnostics.Debug.WriteLine("robbysbobby sendnotify");
            //if (_currentLocation == null)
            //    return false;

            var geo = Plugin.Geolocator.CrossGeolocator.Current;
            if (geo.IsGeolocationAvailable && geo.IsGeolocationEnabled)
            {
                try
                {
                    var position = await geo.GetPositionAsync(timeoutMilliseconds: LiveConstants.GpsTimeout);
                    await CommunicationService.Instance.UpdateUserLocation(position.Latitude, position.Longitude);
                    return true;
                }
                catch (Exception e)
                {
                    System.Diagnostics.Debug.WriteLine(e.StackTrace);
                    //no position

                }

            }
            return false;

           }

        public void RestartPeriodicTaskHeartBeat(Context context, MainApplication myApplication)
        {
            ISharedPreferences sharedPreferences = myApplication.GetSharedPreferences("sharedprefs", FileCreationMode.WorldWriteable);
            bool isBatteryOk = sharedPreferences.GetBoolean(LiveConstants.BACKGROUND_SERVICE_BATTERY_CONTROL, true);
            Intent alarmIntent = new Intent(context, typeof(PeriodicTaskReceiver));
            bool isAlarmUp = PendingIntent.GetBroadcast(context, 0, alarmIntent, PendingIntentFlags.NoCreate) != null;

            if (isBatteryOk && !isAlarmUp)
            {
                AlarmManager alarmManager = (AlarmManager)context.GetSystemService(Context.AlarmService);
                alarmIntent.SetAction(INTENT_ACTION);
                PendingIntent pendingIntent = PendingIntent.GetBroadcast(context, 0, alarmIntent, 0);
                alarmManager.SetInexactRepeating(AlarmType.ElapsedRealtimeWakeup, SystemClock.ElapsedRealtime(), 15 * 1000 , pendingIntent);
            }
        }

        public void StopPeriodicTaskHeartBeat(Context context)
        {
            AlarmManager alarmManager = (AlarmManager)context.GetSystemService(Context.AlarmService);
            Intent alarmIntent = new Intent(context, typeof(PeriodicTaskReceiver));
            alarmIntent.SetAction(INTENT_ACTION);
            PendingIntent pendingIntent = PendingIntent.GetBroadcast(context, 0, alarmIntent, 0);
            alarmManager.Cancel(pendingIntent);
        }
    }
}

在LoginViewmodel中

Mvx.Resolve<IBackgroundService>().StartBackgroundService();

调用droid实现

 public void StartBackgroundService()
    {
        Intent startServiceIntent = new Intent(CrossCurrentActivity.Current.Activity.ApplicationContext, typeof(BackgroundService));
        CrossCurrentActivity.Current.Activity.StartService(startServiceIntent);
        Log.Info("BGService", "Started Background Service");
        System.Diagnostics.Debug.WriteLine("Started Background Service");
    }
PS:我读了很多文章,但我不确定在actoin / receiver名称中我是否必须在类名之前放入包名或命名空间(小写)。

截至目前,我得到的是启动服务被调用,但我没有看到任何logcat写任何东西,所以它就像没有接收器或服务实际上开始做某事。 我做错了什么?

感谢您的帮助!!!

0 个答案:

没有答案