我正在构建Android服务。该服务应连接BLE设备并下载存储在内存中的所有信息。
现在我想要这个服务可以在后台运行。 这是我的BlePowerService,它扩展了服务
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();
}
}
}
在onStartCommand方法中,我创建了一个每X次运行一次服务的Timer。
&#34;&#34;周期&#34;可以通过onCharacteristicRead方法下载BLE设备的所有信息。
现在的问题是,如果单元I能够读取特性,我关闭BLE设备,我可以通过onConnectionStateChange方法来改变这种状态改变连接,但是它永远不会再执行。
为什么Timer不再执行?