Сервис 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, мне трудно помочь больше.