我正在构建一个实现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;方法,我启用特征通知。 该方法被称为永不错误,但未找到流。
错误在哪里?