1

I'm building an Android Service. This Service should to connect of BLE device and download all informatio that it have storage in yuor memory.

Now I want that this Service can running in background. This is my BlePowerService that extends Service

public class BlePowerService extends Service {
    public DbLayer db;
    Setting settingApp;
    List<ScanFilter> filters;
    String[] stringSequence = new String[] {CHARACTERISTIC_FORZA_STRING, CHARACTERISTIC_TEMPERATURA_STRING};
    BluetoothAdapter mBluetoothAdapter;
    BluetoothGatt mGatt;
    BluetoothDevice currDevice;
    static final long SCAN_PERIOD = 500;
    static String SPLIT_CHAR =";";
    BluetoothLeScanner mLEScanner;
    Handler mHandler;
    int ReadQueueIndex;
    List<BluetoothGattCharacteristic> ReadQueue;
    BluetoothGattCharacteristic caratteristicaDaLeggere;
    ScanSettings settings;
    Integer ultimaForzaLetta,ultimaTemperaturaLetta;
    boolean continuaLetturaForza, continuaLetturaTemperatura;
    boolean isReading = true;
    String LOG_CODE = "NOTIFSRV";
    GattClientCallback gattClientCallback;
    private static final int PERMISSION_REQUEST_COARSE_LOCATION = 1;


    public BlePowerService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        //throw new UnsupportedOperationException("Not yet implemented");
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        mHandler = new Handler();

        Context sharedContext = null;
        try {
            sharedContext = this.createPackageContext(
                    "com.care.devicesensor",
                    Context.CONTEXT_INCLUDE_CODE);
            if (sharedContext == null) {
                return;
            }
            db=new DbLayer(sharedContext);
            db.open();
        } catch (Exception e) {
            String error = e.getMessage();
          //  Log.d(LOG_CODE,"DB error : " + error);
            return;
        }
    }


    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        try {
            //RECUPERO LE IMPOSTAZIONI SETTATE DALL'UTENTE
            settingApp = db.fetchSetting();
            if (settingApp != null && settingApp.getAddressBleSX()!=null) {
                //POSSO FILTRARE DIRETTAMENTE PER L'UUID DEL DISPOSITIVO MEMORIZZATO
                //DALL'UTENTE
                ScanFilter.Builder scanFilterMac =
                        null;
                    scanFilterMac = new ScanFilter.Builder().setDeviceAddress(settingApp.getAddressBleSX());
                if(filters==null)
                    filters = new ArrayList<ScanFilter>();
                //if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                filters.add(scanFilterMac.build());
                //}
                //FILTRO ANCHE PER LA CARATTERISTICA DI FORZA
                ScanFilter filter = null;
                    filter = new ScanFilter.Builder().setServiceUuid(ParcelUuid.fromString(CHARACTERISTIC_FORZA_STRING)).build();
                filters.add(filter);

                final BluetoothManager bluetoothManager =
                        (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
                    mBluetoothAdapter = bluetoothManager.getAdapter();
                //mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
                    mLEScanner = mBluetoothAdapter.getBluetoothLeScanner();
                    settings = new ScanSettings.Builder()
                            .setScanMode(ScanSettings.SCAN_MODE_LOW_POWER)
                            .build();
                scanLeDevice(true);
                mTimer = new Timer();
                //ogni 2 ore
                continuaLetturaForza = true;
                continuaLetturaTemperatura = true;

                int nSecondi = settingApp.getFrequenzaDownload()!= null ? settingApp.getFrequenzaDownload() : 1;
                mTimer.schedule(timerTask, 10000, 1000 * nSecondi);
            }
        } catch (Exception e) {
           // Log.e("POWER_SERVICE", e.getMessage());
        }
        return super.onStartCommand(intent, flags, startId);
    }

    private Timer mTimer;

    TimerTask timerTask = new TimerTask() {

        @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
        @Override
        public void run() {
            //LEGGO TUTTI I DATI DAL SENSORE FINCHE CI SONO VALORI

            int counter = 0;
            while(continuaLetturaForza || continuaLetturaTemperatura){
                counter++;
                Log.v("CICLO WHILE", counter+"");
                if (currDevice != null) {

                    if(ReadQueue!= null && ReadQueue.size()>0){
                        int index =0;
                        for(index=0; index < ReadQueue.size(); index++){
                            isReading = mGatt.readCharacteristic(ReadQueue.get(index));
                            while(isReading){
                                try {
                                   Thread.sleep(1);
                                } catch (InterruptedException e) {
                                    e.printStackTrace();
                                }
                            }

                        }
                    }

                }else{
                    //provo a ricollegarmi al dispositivo probabile, abbia perso la connessione con esso
                    scanLeDevice(true);
                    try {
                        Thread.sleep(2500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    if(currDevice == null && counter == 25){
                        //in questo caso non è riuscito a trovare il dispositivo BLE
                        //esco dal ciclo
                        continuaLetturaForza = false;
                        continuaLetturaTemperatura = false;
                        continue;
                    }
                }

            }

            if(gattClientCallback!=null && mGatt != null)
                gattClientCallback.disconnectGattServer();
        }
    };


    public void connectToDevice(BluetoothDevice device) {
        //VERIFICO SE IL DEVICE è QUELLO CHE VOGLIO IO
        if (mGatt == null && settingApp != null
                && device.getAddress().equals(settingApp.getAddressBleSX())) {
            currDevice = device;
            gattClientCallback = new GattClientCallback();
            mGatt = currDevice.connectGatt(getBaseContext(), false, gattClientCallback);
            scanLeDevice(false);// will stop after first device detection
        }
    }

    private BluetoothAdapter.LeScanCallback mLeScanCallback =
            new BluetoothAdapter.LeScanCallback() {
                @Override
                public void onLeScan(final BluetoothDevice device, int rssi,
                                     byte[] scanRecord) {
                    Handler h = new Handler(getApplicationContext().getMainLooper());
                    // Although you need to pass an appropriate context
                    h.post(new Runnable() {
                        @Override
                        public void run() {
                          //  Log.i("onLeScan", device.toString());
                                connectToDevice(device);

                        }
                    });
                }
            };

    private void scanLeDevice(final boolean enable) {
        if (enable) {
            mHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    if (Build.VERSION.SDK_INT < 21) {
                        mBluetoothAdapter.stopLeScan(mLeScanCallback);
                    } else {
                        mLEScanner.stopScan(mScanCallback);

                    }
                }
            }, SCAN_PERIOD);
            if (Build.VERSION.SDK_INT < 21) {
                mBluetoothAdapter.startLeScan(mLeScanCallback);
            } else {
                mLEScanner.startScan(filters, settings, mScanCallback);
            }
        } else {
            if (Build.VERSION.SDK_INT < 21) {
                mBluetoothAdapter.stopLeScan(mLeScanCallback);
            } else {
                mLEScanner.stopScan(mScanCallback);
            }
        }
    }


    private ScanCallback mScanCallback = new ScanCallback() {
        @Override
        public void onScanResult(int callbackType, ScanResult result) {
           // Log.i("callbackType", String.valueOf(callbackType));
           // Log.i("result", result.toString());
            BluetoothDevice btDevice = null;
               btDevice = result.getDevice();
            connectToDevice(btDevice);
        }

        @Override
        public void onBatchScanResults(List<ScanResult> results) {
            for (ScanResult sr : results) {
                Log.i("ScanResult - Results", sr.toString());
            }
        }

        @Override
        public void onScanFailed(int errorCode) {
           Log.e("Scan Failed", "Error Code: " + errorCode);
        }
    };

    private class GattClientCallback extends BluetoothGattCallback {

        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            try{
                super.onConnectionStateChange(gatt, status, newState);
                Log.i("tag", "onConnectionStateChange newState: " + newState);

                if (status == BluetoothGatt.GATT_FAILURE) {
                    Log.e("ERROR_SERVICE", "Connection Gatt failure status " + status);
                    if(mGatt == null){

                    }else{
                        try {
                            gatt.close();
                        } catch (Exception e) {
                            Log.d("", "close ignoring: " + e);
                        }
                        mGatt = null;
                    }
                    return;
                } else if (status != BluetoothGatt.GATT_SUCCESS) {
                    // handle anything not SUCCESS as failure
                    Log.e("ERROR_SERVICE", "Connection not GATT sucess status " + status);
                    if(mGatt == null){

                    }else{
                        try {
                            gatt.close();
                        } catch (Exception e) {
                            Log.d("", "close ignoring: " + e);
                        }
                        mGatt = null;
                    }
                    return;
                }

                if (newState == BluetoothProfile.STATE_CONNECTED) {
                    //Log.i("INFO", "Connected to device " + gatt.getDevice().getAddress());
                    gatt.discoverServices();
                } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                    Log.i("INFO", "Disconnected from device");
                    if(mGatt == null){

                    }else{
                        try {
                            gatt.close();
                        } catch (Exception e) {
                            Log.d("", "close ignoring: " + e);
                        }
                        mGatt = null;
                    }

                }
            }catch(Exception e){
                Log.e("tag", e.getMessage());
                continuaLetturaForza = true;
                continuaLetturaTemperatura = true;
            }
        }

        public void disconnectGattServer() {
            //Log.i("INFo", "Closing Gatt connection");
            //  clearLogs();
            //mConnected = false;
            //mEchoInitialized = false;
            continuaLetturaForza = false;
            continuaLetturaTemperatura = false;
            if (mGatt == null) {

            }
            else{
                try{
                    mGatt.disconnect();
                   // mGatt.close();
                }catch(Exception e){
                    mGatt = null;
                }

            }
            //mGatt = null;
            //currDevice = null;
        }

        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            super.onServicesDiscovered(gatt, status);

            if (status != BluetoothGatt.GATT_SUCCESS) {
             //   Log.i("INFO", "Device service discovery unsuccessful, status " + status);
                return;
            }

            List<BluetoothGattCharacteristic> matchingCharacteristics =
                    BluetoothUtils.findCharacteristics(gatt,stringSequence);
            if (matchingCharacteristics.isEmpty()) {
              //  Log.e("ERROR_SERVICE","Unable to find characteristics.");
                return;
            }else {

                //INIZIALIZZO LA LISTA DI CARATTERISTICHE CHE DEVO ANDARE A LEGGERE
                ReadQueue = new ArrayList<>();
                for (BluetoothGattCharacteristic characterist : matchingCharacteristics) {
                    ReadQueue.add(characterist);
                }
            }



        }

        @Override
        public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            super.onCharacteristicRead(gatt, characteristic, status);
            if (status == BluetoothGatt.GATT_SUCCESS) {
                Log.v("INSERT_DB", "*****************************************");
                Log.v("INSERT_DB", "*****************************************");
                Log.v("INSERT_DB", "*****************************************");
                Log.v("INSERT_DB", "INSERISCO LE CARATTERISTICHE LETTE SUL DB");
                //readCharacteristic(characteristic);
                String valoreRestituito = characteristic.getStringValue(0);
                if(valoreRestituito==null){
                    int i = 0;
                    i = i + 1;
                    return;
                }
                //SPLITTO PER IL CARATTERE ;
                String[] arrayValori = valoreRestituito.split(SPLIT_CHAR);
                //1 valore è l ID
                try{
                    int id = new Integer(arrayValori[0]);
                    //VERIFICO SE STO LEGGENDO TEMPERATURA O FORZA
                    if(characteristic.getUuid().equals(CHARACTERISTIC_FORZA_UUID)){
                        Log.v("CARATTERISTICA", "*****************************************");
                        Log.v("FORZA", "*****************************************");
                        if(ultimaForzaLetta!= null && ultimaForzaLetta == id){
                            continuaLetturaForza = false;
                            isReading = false;
                            return;
                        }
                        ultimaForzaLetta = id;
                    }else if(characteristic.getUuid().equals( CHARACTERISTIC_TEMPERATURA_UUID)){
                        Log.v("CARATTERISTICA", "*****************************************");
                        Log.v("TEMPERATURA", "*****************************************");
                        if(ultimaTemperaturaLetta!= null && ultimaTemperaturaLetta == id){
                            continuaLetturaTemperatura = false;
                            isReading = false;
                            return;
                        }
                        ultimaTemperaturaLetta = id;
                    }

                    SensorData mSenData = new SensorData();
                    mSenData.setIdType(id);
                    mSenData.setValue1(arrayValori[1]);
                    mSenData.setValue2(arrayValori[2]);
                    mSenData.setValue3(arrayValori[3]);
                    mSenData.setValue4(arrayValori[4]);
                    mSenData.setValue5(arrayValori[5]);
                    mSenData.setValue6(arrayValori[6]);
                    mSenData.setValue7(arrayValori[7]);
                    mSenData.setValue8(arrayValori[8]);
                    //TO-DO HO COMMENTATO QUESTA RIGA DI CODICE
                    // mSenData.setIdType(st.getId());
                    mSenData.setCharacteristic(characteristic.getUuid().toString());
                    mSenData.setValueTimestamp(db.getDateTime(true));
                    //inserisco i dati nel db
                    Log.v("INSERT_DB",valoreRestituito);
                    Log.v("INSERT_DB", "*****************************************");
                    Log.v("INSERT_DB", "*****************************************");
                    Log.v("INSERT_DB", "*****************************************");
                    Log.v("INSERT_DB", "*****************************************");
                    Log.v("INSERT_DB", "*****************************************");
                    Log.v("INSERT_DB", "*****************************************");
                    Log.v("INSERT_DB", "FINE LE CARATTERISTICHE LETTE SUL DB");
                    db.insertSensorData(mSenData);

                    EventBus.getDefault().post(new MessageEvent("update"));

                    //EventBus.getDefault().post(new UnfriendEvent(userId));
                }catch (Exception e){
                    Log.e("ERROR", e.getMessage());
                }
                isReading = false;

            } else {
                isReading = false;
                Log.e("ERROR_SERVICE", "Characteristic read unsuccessful, status: " + status);
                Log.e("ERROR_SERVICE", "Characteristic read unsuccessful, status: " + status);
                Log.e("ERROR_SERVICE", "Characteristic read unsuccessful, status: " + status);
                Log.e("ERROR_SERVICE", "Characteristic read unsuccessful, status: " + status);
                Log.e("ERROR_SERVICE", "Characteristic read unsuccessful, status: " + status);
                Log.e("ERROR_SERVICE", "Characteristic read unsuccessful, status: " + status);
                Log.e("ERROR_SERVICE", "Characteristic read unsuccessful, status: " + status);
                Log.e("ERROR_SERVICE", "Characteristic read unsuccessful, status: " + status);
                Log.e("ERROR_SERVICE", "Characteristic read unsuccessful, status: " + status);

                // Trying to read from the Time Characteristic? It doesnt have the property or permissions
                // set to allow this. Normally this would be an error and you would want to:
                disconnectGattServer();

                return;
            }
        }
    }

    public void onDestroy() {
        try {
            db.close();
            Log.d(LOG_CODE,"DB connection closed" );

            mTimer.cancel();
            timerTask.cancel();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


}

In the onStartCommand method I create a Timer that run the service every X time.

The "cycle while" can download all information of BLE device, throught onCharacteristicRead method.

Now the question is, if unit I can to read a characteristic, I turn off the BLE device, I can rileve this status change connection by onConnectionStateChange method, but the Timer it is never performed again.

Why the Timer is not execute again?

bircastri
  • 2,169
  • 13
  • 50
  • 119
  • 1
    Are you sure your first execution of TimerTask is completing? Maybe the execution of the task does not complete and the timer is not rescheduled. Try with mTimer.scheduleAtFixedRate(timerTask, 10000, 1000 * nSecondi); and see if something changes. Be aware that the schedule() method executes the timertask only if the previous execution has finished, reference here: https://stackoverflow.com/questions/22486997/what-is-the-difference-between-schedule-and-scheduleatfixedrate – Nicola Gallazzi May 11 '18 at 14:16
  • I have insert your code and I'm not sure now that my TimerTask is completing. Now there is a way to set TimerTask complete ? – bircastri May 11 '18 at 14:28
  • 1
    "In fixed-rate execution, each execution is scheduled relative to the scheduled execution time of the initial execution" With scheduleAtFixedRate your timerTask is always rescheduled no matter what happens to the previous execution – Nicola Gallazzi May 11 '18 at 14:34
  • Did you solve your problem? – Nicola Gallazzi May 14 '18 at 10:46
  • No, I don't solve my problem – bircastri May 14 '18 at 14:11

0 Answers0