Запуск фонового сервиса для сканирования и сохранения данных с устройств Bluetooth - PullRequest
0 голосов
/ 10 апреля 2019

Я создаю сервис, который сканирует устройство Bluetooth в фоновом режиме и сохраняет его данные в sqlite. Я не могу получить доступ к контейнеру призмы после перезапуска приложения.

Я создал службу, где я сканирую устройства Bluetooth бесконечно. Теперь я получаю результат в обратном вызове и пытаюсь сохранить данные в sqlite. Я зарегистрировал одноэлементный класс обслуживания «SensorDataService», который сохраняет данные в sqlite. Все работает, когда я запускаю сервис, но через некоторое время или когда я закрываю приложение (в этот момент сервис перезапускается, я думаю), я получаю исключение нулевого указателя при получении экземпляра Sensordataservice из контейнера призмы. Я думаю, что когда приложение закрывается, контейнер призмы уничтожается. Теперь я понятия не имею, как получить доступ к контейнеру призмы из фоновых служб, когда результаты сканирования получены с устройства Bluetooth.

[Service]
public class PodScanningService : Service 
{

    private IAdapter BleAdapter;

    public override IBinder OnBind(Intent intent)
    {
        return null;
    }

    [return: GeneratedEnum]
    public override StartCommandResult OnStartCommand(Intent intent, [GeneratedEnum] StartCommandFlags flags, int startId)
    {

        Intent receiverIntent = new Intent(this, typeof(MyReceiver)); 
        receiverIntent.SetAction("com.company.ACTION_FOUND");
        PendingIntent pendingIntent = PendingIntent.GetBroadcast(this, 1, receiverIntent, PendingIntentFlags.UpdateCurrent);

        BluetoothAdapter adapter = BluetoothAdapter.DefaultAdapter;
        BluetoothLeScanner bluetoothLeScanner = adapter.BluetoothLeScanner;
        ScanFilter filter = GetScanFilter();
        List<ScanFilter> scanFilters = new List<ScanFilter>();
        scanFilters.Add(filter);

        if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
        {
            bluetoothLeScanner.StartScan(scanFilters, getScanSettings(), pendingIntent);
        }
        else
        {
            bluetoothLeScanner.StartScan(new MScanCallBack());
        }

        string CHANNEL_ID = "SAS101";
        if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
        {
            var channelName = "SAS";
            var channelDescription = "SAS Experiment Service";
            var channel = new NotificationChannel(CHANNEL_ID, channelName, NotificationImportance.Default)
            {
                Description = channelDescription
            };
            var notificationManager = (NotificationManager)GetSystemService(NotificationService);
            notificationManager.CreateNotificationChannel(channel);
        }

        NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
            .SetContentTitle("SAS_Experiment")
            .SetContentText("Scanning Service Running")
            .SetSmallIcon(Resource.Drawable.abc_btn_radio_material)
            .SetOngoing(true);

        Notification notification = builder.Build();

        var SERVICE_RUNNING_NOTIFICATION_ID = 1200;


        StartForeground(SERVICE_RUNNING_NOTIFICATION_ID, notification);

        return StartCommandResult.Sticky;
    }

    private ScanFilter GetScanFilter()
    {
        ScanFilter.Builder builder = new ScanFilter.Builder();
        return builder.Build();
    }

    private ScanSettings getScanSettings()
    {
        ScanSettings.Builder builder = new ScanSettings.Builder();
        builder.SetScanMode(Android.Bluetooth.LE.ScanMode.LowLatency);
        return builder.Build();
    }
}

public class MScanCallBack : ScanCallback
{
   public override void OnScanResult([GeneratedEnum] ScanCallbackType callbackType, Android.Bluetooth.LE.ScanResult result)
   {
       base.OnScanResult(callbackType, result);
        Console.WriteLine("Device Found300:" + "TEST:300");
        if (result != null)
       {
           var bytes = result.ScanRecord.GetBytes();
           if (bytes[2] == 0xB0 && bytes[3] == 0xA0)
           {

               ISensorDataService sensorDataService = App.ContainerResolve<ISensorDataService>(); 
               var idStr = result.Device.Address;
               var dataStr = BitConverter.ToString(bytes).Replace("-", "");
               var timeStamp = DateTime.UtcNow;
               sensorDataService.SaveData(new SensorData()
               {
                   Data = dataStr,
                   TimeStamp = timeStamp,
                   RSSI = result.Rssi,
                   DeviceId = idStr
               });
           }
       }

   }

    public override void OnScanFailed([GeneratedEnum] ScanFailure errorCode)
    {
        base.OnScanFailed(errorCode);
    }
}

[BroadcastReceiver]
public class MyReceiver : BroadcastReceiver
{
    public override void OnReceive(Context context, Intent intent)
    {
        var action = intent.Action;
        if (intent.HasExtra(BluetoothLeScanner.ExtraListScanResult))
        {
            var x = intent.GetParcelableArrayListExtra(BluetoothLeScanner.ExtraListScanResult);
            var res = x.Cast<Android.Bluetooth.LE.ScanResult>().ToList();
            Console.WriteLine("Device Found400:" + "TEST:");

            foreach (var result in res)
            {
                var bytes = result.ScanRecord.GetBytes();
                if (bytes[2] == 0xB0 && bytes[3] == 0xA0)
                {
                    ISensorDataService sensorDataService = App.ContainerResolve<ISensorDataService>(); // This is where the problem is
                    Console.WriteLine("Device Found:" + result.Device.Address + DateTime.Now);
                    var idStr = result.Device.Address;
                    var dataStr = BitConverter.ToString(bytes).Replace("-", "");
                    var timeStamp = DateTime.UtcNow;
                    sensorDataService.SaveData(new SensorData()
                    {
                        Data = dataStr,
                        TimeStamp = timeStamp,
                        RSSI = result.Rssi,
                        DeviceId = idStr
                    });
                }
            }
        }
    }
}

Я инициализировал синглтон в инициализаторе Android:

public class AndroidInitializer : IPlatformInitializer
    {
    public void RegisterTypes(IContainerRegistry containerRegistry)
    {
        containerRegistry.RegisterSingleton<ISQLiteProvider, SQLiteProvider>();
        containerRegistry.RegisterSingleton<ISensorDataService, SensorDataService>();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...