Android服务实现蓝牙流媒体

时间:2018-06-19 07:53:05

标签: java android bluetooth-lowenergy

我正在构建一个实现Ble Streaming的应用程序来从BLE设备获取数据。

所以在我的代码中,我在一个特性上启用了notify,但是从不调用onCharacteristicRead方法。

这是我的服务类:

public class BleStreamingService extends Service {
    public DbLayer db;
    Setting settingApp;
    List<ScanFilter> filters;
    String[] stringSequence = new String[] {CHARACTERISTIC_FORZA_STRING};
    BluetoothAdapter mBluetoothAdapter;
    BluetoothGatt mGatt;
    BluetoothDevice currDevice;
    static final long SCAN_PERIOD = 600;
    static String SPLIT_CHAR =";";
    BluetoothLeScanner mLEScanner;
    Handler mHandler;
    ScanSettings settings;
    private static final String TAG = BleStreamingService.class.getSimpleName();
    GattClientCallback gattClientCallback;
    final int numeroTentativiConnessione = 25;


    /**
     * DOPO NUOVA VERSIONE FIRMWARE BLUETOOTH
     */
    private Integer minAcquisizione;


    public BleStreamingService() {
    }

    @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.eresult.diabesitycare.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 {
            //intent.getStringExtra(Constants.MINUTI_ACQUISIZIONE);
            //RECUPERO I MINUTI DI ACQUISIZIOEN
            if (intent !=null && intent.getExtras()!=null)
                minAcquisizione = intent.getExtras().getInt(Constants.MINUTI_ACQUISIZIONE);

            //RECUPERO LE IMPOSTAZIONI SETTATE DALL'UTENTE
            settingApp = db.fetchSetting();
            if (settingApp != null &&
                    (settingApp.getAddressBleSX()!=null || settingApp.getAddressBleDX()!=null)) {


                final BluetoothManager bluetoothManager =
                        (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
                    mBluetoothAdapter = bluetoothManager.getAdapter();
                if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
                    //TODO inserire un messaggio di errore da comunicare all'utente
                    EventBus.getDefault().post(new MessageEvent(Constants.MESSAGE_EVENT_BLUETOOTH_SPENTO));
                }
                mLEScanner = mBluetoothAdapter.getBluetoothLeScanner();
                settings = new ScanSettings.Builder()
                        .setScanMode(ScanSettings.SCAN_MODE_LOW_POWER)
                        .build();
                //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>();
                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);

                EventBus.getDefault().post(new MessageEvent(Constants.MESSAGE_EVENT_SEARCH_BLE));
                //NON è DETTO CHE IL DISPOSITIVO SI CONNETTA
                //AL PRIMO COLPO, è NECESSARIO CHE FACCIO PARTIRE UN THREAD CHE VA A VERIFICARE
                //SE IL TELEFONO SI è RIUSCITO A COLLEGARE AL DISPOSITIVO O MENO
                final Thread thread = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        int nTentativi = 1;
                        while(nTentativi < numeroTentativiConnessione){
                            scanLeDevice(true);
                            try {
                                Thread.sleep(10000);
                            } catch (InterruptedException e) {
                                Log.e(TAG, e.getMessage());
                            }
                            if(currDevice != null){
                                EventBus.getDefault().post(new MessageEvent(Constants.MESSAGE_EVENT_CONNECTED_OK));
                                break;
                            }
                            EventBus.getDefault().post(new MessageEvent(Constants.MESSAGE_EVENT_TENTATIVO, nTentativi));
                            nTentativi++;

                            if(nTentativi==numeroTentativiConnessione){
                                //NON SONO RIUSCITO A CONNETTERMI AL DISPOSITIVO
                                EventBus.getDefault().post(new MessageEvent(Constants.MESSAGE_EVENT_TENTATIVI_FALLITI, nTentativi));
                            }
                        }
                        Thread.interrupted();
                    }
                });
                thread.start();
            }
        } catch (Exception e) {
           // Log.e("POWER_SERVICE", e.getMessage());
        }
        return super.onStartCommand(intent, flags, startId);
    }

    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
            writeCharacteristic();
        }
    }

    public boolean writeCharacteristic(){

        //check mBluetoothGatt is available
        if (mGatt == null) {
            Log.e(TAG, "lost connection");
            return false;
        }
        BluetoothGattService Service = mGatt.getService(Constants.SERVICE_UUID);
        if (Service == null) {
            Log.e(TAG, "service not found!");
            return false;
        }
        BluetoothGattCharacteristic charac = Service
                .getCharacteristic(Constants.CHARACTERISTIC_SCRITTURA_UUID);
        if (charac == null) {
            Log.e(TAG, "char not found!");
            return false;
        }
        //CALCOLO IL COMANDO DA INOLTRARE ALLA CALZA PER L'ACQUISIZIONE
        Integer numAcquisizioni = (3000 * minAcquisizione) / 1000;
        String comando = Constants.START_ACQUISIZIONE+numAcquisizioni;
        charac.setValue(comando);

        boolean status = mGatt.writeCharacteristic(charac);
        return status;
    }

    private BluetoothAdapter.LeScanCallback mLeScanCallback =
            new BluetoothAdapter.LeScanCallback() {
                @Override
                public void onLeScan(final BluetoothDevice device, int rssi,
                                     byte[] scanRecord) {
                    Handler h = new Handler(getApplicationContext().getMainLooper());
                    h.post(new Runnable() {
                        @Override
                        public void run() {
                            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 {
                            mGatt.close();
                            mGatt = null;
                            currDevice = null;
                        } catch (Exception e) {
                            Log.d("", "close ignoring: " + e);
                        }
                        mGatt = null;
                    }
                }
            }catch(Exception e){
                Log.e("tag", e.getMessage());
            }
        }

        public void disconnectGattServer() {
            if (mGatt != null) {
                try{
                    mGatt.disconnect();
                    // mGatt.close();
                }catch(Exception e){
                    mGatt = 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,null);

            for (BluetoothGattCharacteristic characteristic : matchingCharacteristics) {
                if(characteristic.getUuid().equals(Constants.CHARACTERISTIC_FORZA_UUID)){
                    //IMPOSTO L ON NOTIFYCHANGE DATA SU QUESTA CARATTERISTICA
                    gatt.setCharacteristicNotification(characteristic, true);
                }
            }
        }

        @Override
        public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            super.onCharacteristicWrite(gatt, characteristic, status);
            if (status == BluetoothGatt.GATT_SUCCESS) {
               // Log.i("INFO", "Characteristic written successfully");
            } else {
               // Log.e("ERROR","Characteristic write unsuccessful, status: " + status);
                disconnectGattServer();
            }
        }


        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
            //RECUPERO IL CORPO DEL MESSAGGIO
            try{
                String message = ByteBuffer.wrap(characteristic.getValue()).order(ByteOrder.LITTLE_ENDIAN).toString();

                SensorData mSenData = new SensorData(1,message,"","",
                        "","","","","",
                        Constants.CHARACTERISTIC_FORZA_STRING,
                        db.getDateTime(true));
                mSenData.setValueTimestamp(db.getDateTime(true));

                db.insertSensorData(mSenData);
                EventBus.getDefault().post(new MessageEvent(Constants.MESSAGE_EVENT_NEW_RILEVATION_FIND,mSenData));
            }catch(Exception e){
                Log.e(TAG, e.getMessage());
            }

        }
    }

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


        } catch (Exception e) {
            e.printStackTrace();
        }
    } 
}

正如我们在onStartCommand方法中看到的,我调用scanLeDevice方法在BLE设备上连接。 在&#34; onServicesDiscovered&#34;方法,我启用特征通知。 该方法被称为永不错误,但未找到流。

错误在哪里?

0 个答案:

没有答案