Сервис AltBeacon в отдельном процессе Android

Мне нужна помощь. Есть приложение для Xamarin Android. Внутри запускается служба, которая работает с библиотекой AltBeacon. В этом сервисе создается поток, в котором маяки постоянно сканируются. Служба запущена как StartForeground(...). Служба должна работать постоянно, поэтому было решено запустить ее в отдельном процессе, потому что через некоторое время система Android перестает выделять память и служба завершается. Если вы запускаете приложение и службу в одном процессе, все работает нормально. Сервис работает, маяки сканируются. Но как только я запускаю его в отдельном процессе (используя атрибут Process =: myProcess), сканирование не работает. Метод DidRangeBeaconsInRegion не работает для объекта реализации IRangeNotifier. Это просто не работает, исключений нет. Краткая кодовая база:

public class BeaconsWorker : Java.Lang.Object, IBeaconConsumer
    {
 private string[] guids;



        private readonly Context context;
        private readonly BeaconManager beaconManager;
        private readonly RangeNotifier rangeNotifier;
        private readonly List<BeaconEntry> beacons;



        public Context ApplicationContext
        {
            get { return context.ApplicationContext; }
        }


        public BeaconsWorker(Context context, string[] guids, int scanTime)
        {
            ...
            this.context = context;         
            rangeNotifier = new RangeNotifier();
            beaconManager = BeaconManager.GetInstanceForApplication(context);
            beaconManager.SetForegroundBetweenScanPeriod(1000);
            beaconManager.SetForegroundScanPeriod(1000);
            beaconManager.SetBackgroundMode(false);
            var beaconParser = new BeaconParser();
            beaconParser.SetBeaconLayout("...");
            beaconManager.BeaconParsers.Add(beaconParser);
            rangeNotifier.DidRangeBeaconsInRegionComplete += OnBeaconsRanging;
            beaconManager.SetRangeNotifier(rangeNotifier);


        }


        public bool BindService(Intent intent, IServiceConnection serviceConnection, [GeneratedEnum] Bind flags)
        {
            return context.BindService(intent, serviceConnection, flags);
        }

        public void OnBeaconServiceConnect()
        {

            foreach (var region in beaconManager.RangedRegions.ToList())
                beaconManager.StopRangingBeaconsInRegion(region);

                    for (int i = 0; i < guids.Length; i++)
                    {
                        var uuid = Identifier.Parse(guids[i]);
                        var region = new Region("R" + i, uuid, null, null);
                        beaconManager.StartRangingBeaconsInRegion(region);
                }   

        }

        public void UnbindService(IServiceConnection serviceConnection)
        {
            context.UnbindService(serviceConnection);
        }


        public async Task<BeaconEntry> GetLocationResult()
        {

            beaconManager.Bind(this);
            await Task.Delay(scanTime * 1000);         
            beaconManager.Unbind(this);
            ...

            return result;
        }


        private void OnBeaconsRanging(object sender, RangeEventArgs e)
        {

            lock (beacons)
                foreach (var item in e.Beacons)
                {
                    var beacon = new BeaconEntry()
                    {
                        BeaconGUID = item.Id1.ToString(),
                        BeaconMajor = Int32.Parse(item.Id2.ToString()),
                        BeaconMinor = Int32.Parse(item.Id3.ToString())
                    };

                    beacons.Add(beacon);
                }  
        }


        private class RangeEventArgs : EventArgs
        {
            public Region Region { get; set; }

            public ICollection<Beacon> Beacons { get; set; }
        }

        private class RangeNotifier : Java.Lang.Object, IRangeNotifier
        {
            public event EventHandler<RangeEventArgs> DidRangeBeaconsInRegionComplete;

            public void DidRangeBeaconsInRegion(ICollection<Beacon> beacons, Region region)
            {

                OnDidRangeBeaconsInRegion(beacons, region);
            }

            private void OnDidRangeBeaconsInRegion(ICollection<Beacon> beacons, Region region)
            {                
                DidRangeBeaconsInRegionComplete?.Invoke(this, new RangeEventArgs { Beacons = beacons, Region = region });
            }
        }

1 ответ

Можно настроить библиотеку Android Beacon для запуска в отдельном процессе. Вы можете прочитать основные инструкции по настройке здесь:

https://github.com/AltBeacon/android-beacon-library/pull/479

Эта многопроцессорная установка была успешно протестирована с библиотекой версии 2.11. Версия 2.12, однако, включала значительные доработки для поддержки Android 8, и я не тестировал многопроцессорную поддержку с версиями 2.12+, поэтому используйте эти версии с осторожностью. Лучше всего использовать версию 2.11.

Приведенные выше инструкции написаны для приложений Android, созданных с использованием стандартного набора инструментов разработки Java или Kotlin с Android Studio или Gradle. Очевидно, что необходимы модификации, чтобы сделать эту работу с Xamarin. Поскольку я не эксперт по Xamarin, мне трудно помочь больше.

Другие вопросы по тегам