android 如何在应用程序处于后台时扫描和连接 ble 设备?
How to scan and connect ble devices when app is in background in android?
我开发了一个 android 应用程序来扫描 ble 设备,并在应用程序处于用户交互时读取和写入 gatt 特性。我想保持与特定 ble 设备的连接,并希望在应用程序处于前台且 background.Here 是我的 BluetoothLeService class.
时读写 gatt 特性
public class BluetoothLeService extends Service
{
public static final String ACTION_DATA_AVAILABLE = "com.example.tracker.service.ACTION_DATA_AVAILABLE";
public static final String ACTION_GATT_CONNECTED = "com.example.tracker.service.ACTION_GATT_CONNECTED";
public static final String ACTION_GATT_DISCONNECTED = "com.example.tracker.service.ACTION_GATT_DISCONNECTED";
public static final String ACTION_GATT_RSSI_UPDATE = "com.example.tracker.service.ACTION_GATT_RSSI_UPDATE";
public static final String ACTION_GATT_SERVICES_DISCOVERED = "com.example.tracker.service.ACTION_GATT_SERVICES_DISCOVERED";
public static final String ACTION_GATT_WRITE_FAILED = "com.example.tracker.service.ACTION_GATT_WRITE_FAILED";
protected static final UUID CHARACTERISTIC_UPDATE_NOTIFICATION_DESCRIPTOR_UUID = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
public static final String CHARACTERISTIC_UUID = "com.example.tracker.service.CHARACTERISTIC_UUID";
public static final String EXTRA_DATA = "com.example.tracker.service.EXTRA_DATA";
public static final String SIGNAL = "SIGNAL";
private static final String TAG = BluetoothLeService.class.getSimpleName();
private final IBinder mBinder = new LocalBinder();
private BluetoothAdapter mBluetoothAdapter;
private String mBluetoothDeviceAddress;
private BluetoothGatt mBluetoothGatt;
private BluetoothManager mBluetoothManager;
private BluetoothGattCharacteristic mFocusedCharacteristic;
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
if (newState == 2) {
BluetoothLeService.this.broadcastUpdate(BluetoothLeService.ACTION_GATT_CONNECTED);
Log.i(BluetoothLeService.TAG, "Connected to GATT server.");
Log.i("MyActivity", "Connected to GATT server.");
Log.i("MyActivity", "Attempting to start service discovery:" + BluetoothLeService.this.mBluetoothGatt.discoverServices());
} else if (newState == 0) {
String intentAction = BluetoothLeService.ACTION_GATT_DISCONNECTED;
Log.i("MyActivity", "Disconnected from GATT server.");
BluetoothLeService.this.broadcastUpdate(intentAction);
}
}
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == 0) {
BluetoothLeService.this.broadcastUpdate(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED);
} else {
Log.w("MyActivity", "onServicesDiscovered received: " + status);
}
}
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
if (status == 0) {
BluetoothLeService.this.broadcastUpdate(BluetoothLeService.ACTION_DATA_AVAILABLE, characteristic);
Log.i("MyActivity", "Characteristic flags " + characteristic.getProperties());
BluetoothLeService.this.mFocusedCharacteristic = characteristic;
}
}
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
if (status == 0) {
BluetoothLeService.this.broadcastUpdate(BluetoothLeService.ACTION_DATA_AVAILABLE, characteristic);
if ((characteristic.getProperties() & 2) > 0) {
BluetoothLeService.this.readCharacteristic();
Log.i("MyActivity", "Characteristic permits read");
}
Log.i("MyActivity", "Characteristic was written");
return;
}
Log.i("MyActivity", "Failed to write characteristic");
BluetoothLeService.this.broadcastUpdate(BluetoothLeService.ACTION_GATT_WRITE_FAILED);
}
public void onReadRemoteRssi(BluetoothGatt gatt, int Rssi, int status) {
if (status == 0) {
BluetoothLeService.this.broadcastUpdate(BluetoothLeService.ACTION_GATT_RSSI_UPDATE, Rssi);
}
}
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
Log.i("MyActivity", "Characteristic has changed");
BluetoothLeService.this.broadcastUpdate(BluetoothLeService.ACTION_DATA_AVAILABLE, characteristic);
}
};
public class LocalBinder extends Binder {
public BluetoothLeService getService() {
return BluetoothLeService.this;
}
}
private void broadcastUpdate(String action) {
sendBroadcast(new Intent(action));
}
private void broadcastUpdate(String action, int Rssi) {
Intent intent = new Intent(action);
intent.putExtra(EXTRA_DATA, Rssi);
sendBroadcast(intent);
}
private void broadcastUpdate(String action, BluetoothGattCharacteristic characteristic) {
Intent intent = new Intent(action);
byte[] data = characteristic.getValue();
if (data != null && data.length > 0) {
StringBuilder stringBuilder = new StringBuilder(data.length);
int length = data.length;
for (int i = 0; i < length; i++) {
stringBuilder.append(String.format("%02X ", new Object[]{Byte.valueOf(data[i])}));
}
intent.putExtra(EXTRA_DATA, new StringBuilder(String.valueOf(new String(data))).append(" [ ").append(stringBuilder.toString()).toString());
intent.putExtra(CHARACTERISTIC_UUID, characteristic.getUuid().toString());
}
sendBroadcast(intent);
}
public IBinder onBind(Intent intent) {
return this.mBinder;
}
public boolean onUnbind(Intent intent) {
close();
return super.onUnbind(intent);
}
public boolean initialize() {
if (this.mBluetoothManager == null) {
this.mBluetoothManager = (BluetoothManager) getSystemService("bluetooth");
if (this.mBluetoothManager == null) {
Log.e(TAG, "Unable to initialize BluetoothManager.");
return false;
}
}
this.mBluetoothAdapter = this.mBluetoothManager.getAdapter();
if (this.mBluetoothAdapter != null) {
return true;
}
Log.e(TAG, "Unable to obtain a BluetoothAdapter.");
return false;
}
public boolean connect(String address) {
if (this.mBluetoothAdapter == null || address == null) {
Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
return false;
} else if (this.mBluetoothDeviceAddress == null || !address.equals(this.mBluetoothDeviceAddress) || this.mBluetoothGatt == null) {
BluetoothDevice device = this.mBluetoothAdapter.getRemoteDevice(address);
if (device == null) {
Log.w(TAG, "LocalDevice not found. Unable to connect.");
return false;
}
this.mBluetoothGatt = device.connectGatt(this, false, this.mGattCallback);
Log.d(TAG, "Trying to create a new connection.");
this.mBluetoothDeviceAddress = address;
return true;
} else {
Log.d(TAG, "Trying to use an existing mBluetoothGatt for connection.");
if (this.mBluetoothGatt.connect()) {
return true;
}
return false;
}
}
public void disconnect() {
if (this.mBluetoothAdapter == null || this.mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
} else {
this.mBluetoothGatt.disconnect();
}
}
public void readRemoteRssi() {
if (this.mBluetoothAdapter == null || this.mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
} else {
this.mBluetoothGatt.readRemoteRssi();
}
}
public BluetoothGattCharacteristic CurrentCharacteristic() {
return this.mFocusedCharacteristic;
}
public String getCurrentCharacteristicUuid() {
return this.mFocusedCharacteristic.getUuid().toString();
}
public void writeCharacteristic(byte[] c) {
mFocusedCharacteristic.setValue(c);
if (mBluetoothGatt!=null && mFocusedCharacteristic!=null){
mBluetoothGatt.writeCharacteristic(mFocusedCharacteristic);
}
}
public void readCharacteristic() {
Log.i("MyActivity", "Read Characteristic");
this.mBluetoothGatt.readCharacteristic(this.mFocusedCharacteristic);
}
public void notifyCharacteristic() {
Log.i("MyActivity", "Notify Characteristic");
setCharacteristicNotification(this.mFocusedCharacteristic, true);
}
public void setCurrentCharacteristic(BluetoothGattCharacteristic characteristic) {
this.mFocusedCharacteristic = characteristic;
}
public void close() {
if (this.mBluetoothGatt != null) {
this.mBluetoothGatt.close();
this.mBluetoothGatt = null;
}
}
public void readCharacteristic(BluetoothGattCharacteristic characteristic) {
if (this.mBluetoothAdapter == null || this.mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
} else {
this.mBluetoothGatt.readCharacteristic(characteristic);
}
}
public boolean setCharacteristicNotification(BluetoothGattCharacteristic characteristic, boolean enable) {
Log.i("MyActivity", "setCharacteristicNotification");
this.mBluetoothGatt.setCharacteristicNotification(characteristic, enable);
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(CHARACTERISTIC_UPDATE_NOTIFICATION_DESCRIPTOR_UUID);
descriptor.setValue(enable ? BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE : new byte[2]);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
SystemClock.sleep(200);
return this.mBluetoothGatt.writeDescriptor(descriptor);
}
public List<BluetoothGattService> getSupportedGattServices() {
if (this.mBluetoothGatt == null) {
return null;
}
return this.mBluetoothGatt.getServices();
}
}
无论您的应用是在前台还是后台,API 都是一样的。您唯一需要做的就是确保系统不会在应用程序处于后台时将其终止。为此,只需在您的应用进程中的某处设置一个前台服务 运行。
在 android 中当应用程序处于后台时使用服务扫描和连接 ble 设备。
package com.example.tracker.service;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanSettings;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Handler;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.support.v4.widget.SwipeRefreshLayout;
import android.util.Log;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.SeekBar;
import android.widget.Toast;
import com.google.firebase.auth.FirebaseAuth;
import com.example.tracker.R;
import com.example.tracker.utils.SampleGattAttributes;
import com.example.tracker.utils.SharedPreferencesUtils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
import static com.example.tracker.constant.SharedFreferencesConstant.KEY_SP_MOBILE_NUMBER;
/**
* Created by Jprashant on 12/9/17.
*/
public class BackgroundService extends Service{
private int scanPeriod;
Context context;
String TAG="BackgroundService";
private BluetoothAdapter mBluetoothAdapter;
private boolean mScanning;
private Handler mHandler;
public String[] advDataTypes = new String[256];
ArrayList<BluetoothDevice> bluetoothDeviceArrayList=new ArrayList<>();
ArrayList<BluetoothDevice> bluetoothDeviceArrayListTwo=new ArrayList<>();
private static final int REQUEST_ENABLE_BT = 1;
// Stops scanning after 10 seconds.
private static final long SCAN_PERIOD = 10000;
/*Connect Ble Device*/
String deviceId;
public static String arrayDidOpnSec2;
BluetoothGattService gattService4;
public static ArrayList<BluetoothGattCharacteristic> lastCharacteristic;
// AlertDialog.Builder alertDialog;
private float avgRssi = 0.0f;
// private Dialog dialog;
private BluetoothLeService mBluetoothLeService;
private boolean mConnected = false;
private ArrayList<ArrayList<BluetoothGattCharacteristic>> mGattCharacteristics = new ArrayList();
//service and char uuid
private static final int TRACKER_ON_OFF = 2;
private static final UUID TRACER_TRIPPLE_PRESS_SERVICE=UUID.fromString("edfec62e-9910-0bac-5241-d8bda6932a2f");
private static final UUID TRACKER_TRIPPLE_PRESS_CHAR=UUID.fromString("772ae377-b3d2-4f8e-4042-5481d1e0098c");
private static final UUID IMMEDIATE_ALERT_UUID = UUID.fromString("00001802-0000-1000-8000-00805f9b34fb");
private static final UUID ALERT_LEVEL_UUID = UUID.fromString("00002a06-0000-1000-8000-00805f9b34fb");
private Button btnSMS;
public static String mDeviceName,mDeviceAddress,connectionStatus;
/*-------------------------------------------------------------------------------*/
public static final String PREFS_NAME = "PreferencesFile";
public int deviceCount = 0;
public String[] mData = new String[400];
private Handler mHandler1;
private ListView listItems;
/*--------for > 21--------------*/
private BluetoothLeScanner mLEScanner;
private ScanSettings settings;
private List<ScanFilter> filters;
private BluetoothGatt mGatt;
public BackgroundService() {
}
public BackgroundService(Context context) {
this.context = context;
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// getting systems default ringtone
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(),"CALL YOUR METHOD",Toast.LENGTH_LONG).show();
mHandler = new Handler();
// Use this check to determine whether BLE is supported on the device. Then you can
// selectively disable BLE-related features.
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
Toast.makeText(context, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
}
// Initializes a Bluetooth adapter. For API level 18 and above, get a reference to
// BluetoothAdapter through BluetoothManager.
final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
// Checks if Bluetooth is supported on the device.
if (mBluetoothAdapter == null) {
Toast.makeText(context, R.string.error_bluetooth_not_supported, Toast.LENGTH_SHORT).show();
return;
}
for (int i = 0; i < 256; i += REQUEST_ENABLE_BT) {
advDataTypes[i] = "Unknown Data Type";
}
advDataTypes[REQUEST_ENABLE_BT] = "Flags";
advDataTypes[2] = "Incomplete List of 16-bit Service Class UUIDs";
advDataTypes[3] = "Complete List of 16-bit Service Class UUIDs";
advDataTypes[4] = "Incomplete List of 32-bit Service Class UUIDs";
advDataTypes[5] = "Complete List of 32-bit Service Class UUIDs";
advDataTypes[6] = "Incomplete List of 128-bit Service Class UUIDs";
advDataTypes[7] = "Complete List of 128-bit Service Class UUIDs";
advDataTypes[8] = "Shortened Local Name";
advDataTypes[9] = "Complete Local Name";
advDataTypes[10] = "Tx Power Level";
advDataTypes[13] = "Class of LocalDevice";
advDataTypes[14] = "Simple Pairing Hash";
advDataTypes[15] = "Simple Pairing Randomizer R";
advDataTypes[16] = "LocalDevice ID";
advDataTypes[17] = "Security Manager Out of Band Flags";
advDataTypes[18] = "Slave Connection Interval Range";
advDataTypes[20] = "List of 16-bit Solicitaion UUIDs";
advDataTypes[21] = "List of 128-bit Solicitaion UUIDs";
advDataTypes[22] = "Service Data";
advDataTypes[23] = "Public Target Address";
advDataTypes[24] = "Random Target Address";
advDataTypes[25] = "Appearance";
advDataTypes[26] = "Advertising Interval";
advDataTypes[61] = "3D Information Data";
advDataTypes[255] = "Manufacturer Specific Data";
scanPeriod = getApplicationContext().getSharedPreferences(PREFS_NAME, 0).getInt("scan_interval", 6000);
scanTrackerDevices();
}
}, 10000);
return START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
}
public void scanTrackerDevices(){
Log.e(TAG,"scanTrackerDevices");
if (!mBluetoothAdapter.isEnabled()) {
if (!mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
}
}
scanLeDevice(true);
}
private void scanLeDevice(final boolean enable) {
bluetoothDeviceArrayList.clear();
if (enable) {
// Stops scanning after a pre-defined scan period.
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
mScanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
int arraySize=bluetoothDeviceArrayListTwo.size();
Log.e(TAG,"bluetoothDeviceArrayListTwo Size in scan :"+arraySize);
for (int i=0;i<bluetoothDeviceArrayListTwo.size();i++){
BluetoothDevice bluetoothDevice=bluetoothDeviceArrayListTwo.get(i);
Log.e(TAG,"Device Name in scan :"+bluetoothDevice.getName());
Log.e(TAG,"Device Address in scan :"+bluetoothDevice.getAddress());
if (i==0){
mBluetoothLeService.connect(bluetoothDevice.getAddress());
}
}
}
}, scanPeriod);
mScanning = true;
mBluetoothAdapter.startLeScan(mLeScanCallback);
} else {
mScanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
}
}
private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
public void onLeScan(final BluetoothDevice device, final int rssi, final byte[] scanRecord) {
String d = "";
String rd = "";
String h = "0123456789ABCDEF";
int ln = 0;
int i = 0;
while (i < scanRecord.length) {
int x = scanRecord[i] & 255;
rd = new StringBuilder(String.valueOf(rd)).append(h.substring(x / 16, (x / 16) + REQUEST_ENABLE_BT)).append(h.substring(x % 16, (x % 16) +REQUEST_ENABLE_BT)).toString();
if (i == ln) {
ln = (i + x) + REQUEST_ENABLE_BT;
if (x == 0) {
break;
}
d = new StringBuilder(String.valueOf(d)).append("\r\n Length: ").append(h.substring(x / 16, (x / 16) + REQUEST_ENABLE_BT)).append(h.substring(x % 16, (x % 16) +REQUEST_ENABLE_BT)).toString();
i += REQUEST_ENABLE_BT;
x = scanRecord[i] & 255;
d = new StringBuilder(String.valueOf(d)).append(", Type :").append(h.substring(x / 16, (x / 16) + REQUEST_ENABLE_BT)).append(h.substring(x % 16, (x % 16) + REQUEST_ENABLE_BT)).append(" = ").append(advDataTypes[x]).append(", Value: ").toString();
rd = new StringBuilder(String.valueOf(rd)).append(h.substring(x / 16, (x / 16) + REQUEST_ENABLE_BT)).append(h.substring(x % 16, (x % 16) + REQUEST_ENABLE_BT)).toString();
} else {
d = new StringBuilder(String.valueOf(d)).append(" ").append(h.substring(x / 16, (x / 16) + REQUEST_ENABLE_BT)).append(h.substring(x % 16, (x % 16) +REQUEST_ENABLE_BT)).toString();
}
i += REQUEST_ENABLE_BT;
}
Log.e(TAG,"UUID : "+device.getUuids());
String[] arrayDeviceName=String.valueOf(device.getName()).split(" ");
String deviceName0=arrayDeviceName[0];
bluetoothDeviceArrayListTwo.add(device);
}
};
/*-------------------Connect BLE---------------------------------------------*/
private Handler mHandler2;
public final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent)
{
String action = intent.getAction();
if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action))
{
numberOfRssi = 0;
avgRssi = 0.0f;
mConnected = true;
updateConnectionState(R.string.connected);
mHandler2.postDelayed(startRssi, 300);
Log.e(TAG,"ACTION_GATT_CONNECTED");
}
else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) {
mConnected = false;
updateConnectionState(R.string.disconnected);
Log.e(TAG,"ACTION_GATT_DISCONNECTED");
} else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) {
displayGattServicesForDimmer(mBluetoothLeService.getSupportedGattServices());// For dimmer
Log.e(TAG,"ACTION_GATT_SERVICES_DISCOVERED");
} else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) {
Log.e(TAG,"ACTION_DATA_AVAILABLE");
String unknownServiceString = context.getResources().getString(R.string.unknown_service);
displayDimmerData("<<" + SampleGattAttributes.lookup(intent.getStringExtra(BluetoothLeService.CHARACTERISTIC_UUID), unknownServiceString) + ">> Value: " + intent.getStringExtra(BluetoothLeService.EXTRA_DATA) + "]");
displayDimmer2(intent.getStringExtra(BluetoothLeService.EXTRA_DATA));
} else if (BluetoothLeService.ACTION_GATT_RSSI_UPDATE.equals(action)) {
updateRssi(intent.getIntExtra(BluetoothLeService.EXTRA_DATA, -400));
} else if (BluetoothLeService.ACTION_GATT_WRITE_FAILED.equals(action)) {
Log.e(TAG,"ACTION_GATT_WRITE_FAILED");
}
}
};
/*------------------------------------------------------------------------*/
@Override
public void onCreate() {
super.onCreate();
// -------------------Connect Ble--------------------------------------
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothLeService.ACTION_GATT_CONNECTED);
intentFilter.addAction(BluetoothLeService.ACTION_GATT_DISCONNECTED);
intentFilter.addAction(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED);
intentFilter.addAction(BluetoothLeService.ACTION_DATA_AVAILABLE);
intentFilter.addAction(BluetoothLeService.ACTION_GATT_RSSI_UPDATE);
intentFilter.addAction(BluetoothLeService.ACTION_GATT_WRITE_FAILED);
Log.e(TAG,"OnResume()");
getApplicationContext().registerReceiver(mGattUpdateReceiver, intentFilter);
getApplicationContext().bindService(new Intent(getApplicationContext(), BluetoothLeService.class), mServiceConnection, 1);
mHandler2=new Handler();
}
private BluetoothGattCharacteristic mNotifyCharacteristic;
private final ServiceConnection mServiceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName componentName, IBinder service) {
mBluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService();
if (!mBluetoothLeService.initialize()) {
Log.e(TAG, "Unable to initialize Bluetooth");
}
}
public void onServiceDisconnected(ComponentName componentName) {
mBluetoothLeService = null;
}
};
private boolean notificationActive = true;
private int numberOfRssi = 0;
private Runnable startRssi = new Runnable() {
public void run() {
if (mConnected) {
mBluetoothLeService.readRemoteRssi();
mHandler2.postDelayed(startRssi, 200);
}
}
};
public BluetoothGatt getmGatt() {
return mGatt;
}
//code from DeviceControlActivity
private void updateConnectionState(final int resourceId) {
connectionStatus= String.valueOf(resourceId);
Log.e(TAG,"Resource ID"+resourceId);
}
private void displayDimmerData(String data){
Log.e(TAG,"Display Data :"+data);
}
private void displayDimmer2(String data){
Log.e(TAG,"display Dimmer2"+data);
String sosString = data.substring(0, Math.min(data.length(), 3));
Log.e(TAG,"SOS String :"+sosString);
if (sosString.equals("SOS")){
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.setData(Uri.parse("tel:"+ SharedPreferencesUtils.getStringFromSharedPreferences(KEY_SP_MOBILE_NUMBER,getApplicationContext())));
callIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplicationContext().startActivity(callIntent);
}
}
private void updateRssi(int data) {
if (data > -400) {
if (this.numberOfRssi > 10) {
this.avgRssi = ((9.0f * this.avgRssi) + ((float) data)) / 10.0f;
} else {
this.avgRssi = (this.avgRssi + ((float) data)) / 2.0f;
this.numberOfRssi++;
}
connectionStatus="Connected, RSSI:" + data + ", Avg:" + Math.round(this.avgRssi);
}
}
/*-------------------------disaplay gatt service for dimmer----------------------*/
private void displayGattServicesForDimmer(List<BluetoothGattService> gattServices) {
if (gattServices != null) {
String unknownServiceString = getResources().getString(R.string.unknown_service);
String unknownCharaString = getResources().getString(R.string.unknown_characteristic);
ArrayList<HashMap<String, String>> gattServiceData = new ArrayList();
ArrayList<ArrayList<HashMap<String, String>>> gattCharacteristicData = new ArrayList();
this.mGattCharacteristics = new ArrayList();
for (BluetoothGattService gattService : gattServices) {
HashMap<String, String> currentServiceData = new HashMap();
String uuid = gattService.getUuid().toString();
currentServiceData.put("NAME", SampleGattAttributes.lookup(uuid, unknownServiceString));
currentServiceData.put("UUID", uuid);
gattServiceData.add(currentServiceData);
ArrayList<HashMap<String, String>> gattCharacteristicGroupData = new ArrayList();
List<BluetoothGattCharacteristic> gattCharacteristics = gattService.getCharacteristics();
ArrayList<BluetoothGattCharacteristic> charas = new ArrayList();
for (BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) {
charas.add(gattCharacteristic);
HashMap<String, String> currentCharaData = new HashMap();
uuid = gattCharacteristic.getUuid().toString();
currentCharaData.put("NAME", "\t\t\t<<" + SampleGattAttributes.lookup(uuid, unknownCharaString) + ">>");
currentCharaData.put("UUID", "\t\t\tUUID: 0x" + uuid.substring(4, 8) + ", Properties: " + translateProperties(gattCharacteristic.getProperties()));
gattCharacteristicGroupData.add(currentCharaData);
Log.i(TAG,"CUrrent CHARACTERISTIC DATA"+currentCharaData);
Log.i(TAG,"UUID : "+uuid.substring(4, 8));
Log.i(TAG,"Proprties : "+gattCharacteristic.getProperties());
Log.i(TAG,"Translate Proprties : "+translateProperties(gattCharacteristic.getProperties()));
Log.i(TAG,"char list"+gattCharacteristicData.toString());
}
gattService4=gattService;
this.mGattCharacteristics.add(charas);
}
if (mGattCharacteristics.get(3)!=null) {
lastCharacteristic = new ArrayList<>(mGattCharacteristics.get(3));
enableNotifyOfCharcteristicForDimmer(lastCharacteristic);
}
}
}
private String translateProperties(int properties) {
String s = "";
if ((properties & 1) > 0) {
s = new StringBuilder(String.valueOf(s)).append("/Broadcast").toString();
}
if ((properties & 2) > 0) {
s = new StringBuilder(String.valueOf(s)).append("/Read").toString();
}
if ((properties & 4) > 0) {
s = new StringBuilder(String.valueOf(s)).append("/WriteWithoutResponse").toString();
}
if ((properties & 8) > 0) {
s = new StringBuilder(String.valueOf(s)).append("/Write").toString();
}
if ((properties & 16) > 0) {
s = new StringBuilder(String.valueOf(s)).append("/Notify").toString();
}
if ((properties & 32) > 0) {
s = new StringBuilder(String.valueOf(s)).append("/Indicate").toString();
}
if ((properties & 64) > 0) {
s = new StringBuilder(String.valueOf(s)).append("/SignedWrite").toString();
}
if ((properties & 128) > 0) {
s = new StringBuilder(String.valueOf(s)).append("/ExtendedProperties").toString();
}
if (s.length() > 1) {
return s.substring(1);
}
return s;
}
// Enable Characteristic for dimmer
public void enableNotifyOfCharcteristicForDimmer(ArrayList<BluetoothGattCharacteristic> lastCharacteristic){
if(mGattCharacteristics!=null) {
checkCharacteristicPresent(lastCharacteristic.get(0));
mBluetoothLeService.setCharacteristicNotification(lastCharacteristic.get(0), true);
notificationActive = true;
Log.e(TAG,"Characteristic index : "+0+":\nM GATT CHARACTERISTIC AT "+"Service 4 : CHAR"+ 0 +" :" +lastCharacteristic.get(0).toString());
checkCharacteristicPresent(lastCharacteristic.get(1));
mBluetoothLeService.setCharacteristicNotification(lastCharacteristic.get(1), true);
notificationActive = true;
Log.e(TAG,"Characteristic index : "+1+":\nM GATT CHARACTERISTIC AT "+"Service 4 : CHAR"+ 1 +" :" +lastCharacteristic.get(1).toString());
checkCharacteristicPresent(lastCharacteristic.get(2));
mBluetoothLeService.setCharacteristicNotification(lastCharacteristic.get(2), true);
notificationActive = true;
Log.e(TAG,"Characteristic index : "+2+":\nM GATT CHARACTERISTIC AT "+"Service 4 : CHAR"+ 2 +" :" +lastCharacteristic.get(2).toString());
checkCharacteristicPresent(lastCharacteristic.get(3));
mBluetoothLeService.setCharacteristicNotification(lastCharacteristic.get(3), true);
notificationActive = true;
Log.e(TAG,"Characteristic index : "+3+":\nM GATT CHARACTERISTIC AT "+"Service 4 : CHAR"+ 3 +" :" +lastCharacteristic.get(3).toString());
checkCharacteristicPresent(lastCharacteristic.get(4));
mBluetoothLeService.setCharacteristicNotification(lastCharacteristic.get(4), true);
notificationActive = true;
Log.e(TAG,"Characteristic index : "+4+":\nM GATT CHARACTERISTIC AT "+"Service 4 : CHAR"+ 4 +" :" +lastCharacteristic.get(4).toString());
checkCharacteristicPresent(lastCharacteristic.get(5));
mBluetoothLeService.setCharacteristicNotification(lastCharacteristic.get(5), true);
notificationActive = true;
Log.e(TAG,"Characteristic index : "+5+":\nM GATT CHARACTERISTIC AT "+"Service 4 : CHAR"+ 5 +" :" +lastCharacteristic.get(5).toString());
checkCharacteristicPresent(lastCharacteristic.get(2));
mBluetoothLeService.setCharacteristicNotification(lastCharacteristic.get(2), true);
notificationActive = true;
Log.e(TAG,"Characteristic index : "+2+":\nM GATT CHARACTERISTIC AT "+"Service 4 : CHAR"+ 2 +" :" +lastCharacteristic.get(2).toString());
}
}
// Check the type of characteristic i.e READ/WRITE/NOTIFY
public void checkCharacteristicPresent(BluetoothGattCharacteristic characteristic) {
int charaProp = characteristic.getProperties();
Log.e(TAG, "checkCharacteristicPresent Prop : " + charaProp);
mBluetoothLeService.setCurrentCharacteristic(characteristic);
if ((charaProp & 2) > 0) {
Log.e(TAG, "CharProp & 2 : " + charaProp);
mBluetoothLeService.readCharacteristic(characteristic);
}
if ((charaProp & 16) > 0) {
Log.e(TAG, "CharProp & 16 : " + charaProp);
mNotifyCharacteristic = characteristic;
} else {
if (mNotifyCharacteristic != null) {
mBluetoothLeService.setCharacteristicNotification(mNotifyCharacteristic, false);
mNotifyCharacteristic = null;
}
}
if ((charaProp & 8) > 0 || (charaProp & 4) > 0) {
Log.e(TAG, "CharProp & 4 : " + charaProp);
} else {
Log.e(TAG, "Else : " + charaProp);
}
}
}
我开发了一个 android 应用程序来扫描 ble 设备,并在应用程序处于用户交互时读取和写入 gatt 特性。我想保持与特定 ble 设备的连接,并希望在应用程序处于前台且 background.Here 是我的 BluetoothLeService class.
时读写 gatt 特性public class BluetoothLeService extends Service
{
public static final String ACTION_DATA_AVAILABLE = "com.example.tracker.service.ACTION_DATA_AVAILABLE";
public static final String ACTION_GATT_CONNECTED = "com.example.tracker.service.ACTION_GATT_CONNECTED";
public static final String ACTION_GATT_DISCONNECTED = "com.example.tracker.service.ACTION_GATT_DISCONNECTED";
public static final String ACTION_GATT_RSSI_UPDATE = "com.example.tracker.service.ACTION_GATT_RSSI_UPDATE";
public static final String ACTION_GATT_SERVICES_DISCOVERED = "com.example.tracker.service.ACTION_GATT_SERVICES_DISCOVERED";
public static final String ACTION_GATT_WRITE_FAILED = "com.example.tracker.service.ACTION_GATT_WRITE_FAILED";
protected static final UUID CHARACTERISTIC_UPDATE_NOTIFICATION_DESCRIPTOR_UUID = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
public static final String CHARACTERISTIC_UUID = "com.example.tracker.service.CHARACTERISTIC_UUID";
public static final String EXTRA_DATA = "com.example.tracker.service.EXTRA_DATA";
public static final String SIGNAL = "SIGNAL";
private static final String TAG = BluetoothLeService.class.getSimpleName();
private final IBinder mBinder = new LocalBinder();
private BluetoothAdapter mBluetoothAdapter;
private String mBluetoothDeviceAddress;
private BluetoothGatt mBluetoothGatt;
private BluetoothManager mBluetoothManager;
private BluetoothGattCharacteristic mFocusedCharacteristic;
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
if (newState == 2) {
BluetoothLeService.this.broadcastUpdate(BluetoothLeService.ACTION_GATT_CONNECTED);
Log.i(BluetoothLeService.TAG, "Connected to GATT server.");
Log.i("MyActivity", "Connected to GATT server.");
Log.i("MyActivity", "Attempting to start service discovery:" + BluetoothLeService.this.mBluetoothGatt.discoverServices());
} else if (newState == 0) {
String intentAction = BluetoothLeService.ACTION_GATT_DISCONNECTED;
Log.i("MyActivity", "Disconnected from GATT server.");
BluetoothLeService.this.broadcastUpdate(intentAction);
}
}
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == 0) {
BluetoothLeService.this.broadcastUpdate(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED);
} else {
Log.w("MyActivity", "onServicesDiscovered received: " + status);
}
}
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
if (status == 0) {
BluetoothLeService.this.broadcastUpdate(BluetoothLeService.ACTION_DATA_AVAILABLE, characteristic);
Log.i("MyActivity", "Characteristic flags " + characteristic.getProperties());
BluetoothLeService.this.mFocusedCharacteristic = characteristic;
}
}
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
if (status == 0) {
BluetoothLeService.this.broadcastUpdate(BluetoothLeService.ACTION_DATA_AVAILABLE, characteristic);
if ((characteristic.getProperties() & 2) > 0) {
BluetoothLeService.this.readCharacteristic();
Log.i("MyActivity", "Characteristic permits read");
}
Log.i("MyActivity", "Characteristic was written");
return;
}
Log.i("MyActivity", "Failed to write characteristic");
BluetoothLeService.this.broadcastUpdate(BluetoothLeService.ACTION_GATT_WRITE_FAILED);
}
public void onReadRemoteRssi(BluetoothGatt gatt, int Rssi, int status) {
if (status == 0) {
BluetoothLeService.this.broadcastUpdate(BluetoothLeService.ACTION_GATT_RSSI_UPDATE, Rssi);
}
}
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
Log.i("MyActivity", "Characteristic has changed");
BluetoothLeService.this.broadcastUpdate(BluetoothLeService.ACTION_DATA_AVAILABLE, characteristic);
}
};
public class LocalBinder extends Binder {
public BluetoothLeService getService() {
return BluetoothLeService.this;
}
}
private void broadcastUpdate(String action) {
sendBroadcast(new Intent(action));
}
private void broadcastUpdate(String action, int Rssi) {
Intent intent = new Intent(action);
intent.putExtra(EXTRA_DATA, Rssi);
sendBroadcast(intent);
}
private void broadcastUpdate(String action, BluetoothGattCharacteristic characteristic) {
Intent intent = new Intent(action);
byte[] data = characteristic.getValue();
if (data != null && data.length > 0) {
StringBuilder stringBuilder = new StringBuilder(data.length);
int length = data.length;
for (int i = 0; i < length; i++) {
stringBuilder.append(String.format("%02X ", new Object[]{Byte.valueOf(data[i])}));
}
intent.putExtra(EXTRA_DATA, new StringBuilder(String.valueOf(new String(data))).append(" [ ").append(stringBuilder.toString()).toString());
intent.putExtra(CHARACTERISTIC_UUID, characteristic.getUuid().toString());
}
sendBroadcast(intent);
}
public IBinder onBind(Intent intent) {
return this.mBinder;
}
public boolean onUnbind(Intent intent) {
close();
return super.onUnbind(intent);
}
public boolean initialize() {
if (this.mBluetoothManager == null) {
this.mBluetoothManager = (BluetoothManager) getSystemService("bluetooth");
if (this.mBluetoothManager == null) {
Log.e(TAG, "Unable to initialize BluetoothManager.");
return false;
}
}
this.mBluetoothAdapter = this.mBluetoothManager.getAdapter();
if (this.mBluetoothAdapter != null) {
return true;
}
Log.e(TAG, "Unable to obtain a BluetoothAdapter.");
return false;
}
public boolean connect(String address) {
if (this.mBluetoothAdapter == null || address == null) {
Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
return false;
} else if (this.mBluetoothDeviceAddress == null || !address.equals(this.mBluetoothDeviceAddress) || this.mBluetoothGatt == null) {
BluetoothDevice device = this.mBluetoothAdapter.getRemoteDevice(address);
if (device == null) {
Log.w(TAG, "LocalDevice not found. Unable to connect.");
return false;
}
this.mBluetoothGatt = device.connectGatt(this, false, this.mGattCallback);
Log.d(TAG, "Trying to create a new connection.");
this.mBluetoothDeviceAddress = address;
return true;
} else {
Log.d(TAG, "Trying to use an existing mBluetoothGatt for connection.");
if (this.mBluetoothGatt.connect()) {
return true;
}
return false;
}
}
public void disconnect() {
if (this.mBluetoothAdapter == null || this.mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
} else {
this.mBluetoothGatt.disconnect();
}
}
public void readRemoteRssi() {
if (this.mBluetoothAdapter == null || this.mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
} else {
this.mBluetoothGatt.readRemoteRssi();
}
}
public BluetoothGattCharacteristic CurrentCharacteristic() {
return this.mFocusedCharacteristic;
}
public String getCurrentCharacteristicUuid() {
return this.mFocusedCharacteristic.getUuid().toString();
}
public void writeCharacteristic(byte[] c) {
mFocusedCharacteristic.setValue(c);
if (mBluetoothGatt!=null && mFocusedCharacteristic!=null){
mBluetoothGatt.writeCharacteristic(mFocusedCharacteristic);
}
}
public void readCharacteristic() {
Log.i("MyActivity", "Read Characteristic");
this.mBluetoothGatt.readCharacteristic(this.mFocusedCharacteristic);
}
public void notifyCharacteristic() {
Log.i("MyActivity", "Notify Characteristic");
setCharacteristicNotification(this.mFocusedCharacteristic, true);
}
public void setCurrentCharacteristic(BluetoothGattCharacteristic characteristic) {
this.mFocusedCharacteristic = characteristic;
}
public void close() {
if (this.mBluetoothGatt != null) {
this.mBluetoothGatt.close();
this.mBluetoothGatt = null;
}
}
public void readCharacteristic(BluetoothGattCharacteristic characteristic) {
if (this.mBluetoothAdapter == null || this.mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
} else {
this.mBluetoothGatt.readCharacteristic(characteristic);
}
}
public boolean setCharacteristicNotification(BluetoothGattCharacteristic characteristic, boolean enable) {
Log.i("MyActivity", "setCharacteristicNotification");
this.mBluetoothGatt.setCharacteristicNotification(characteristic, enable);
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(CHARACTERISTIC_UPDATE_NOTIFICATION_DESCRIPTOR_UUID);
descriptor.setValue(enable ? BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE : new byte[2]);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
SystemClock.sleep(200);
return this.mBluetoothGatt.writeDescriptor(descriptor);
}
public List<BluetoothGattService> getSupportedGattServices() {
if (this.mBluetoothGatt == null) {
return null;
}
return this.mBluetoothGatt.getServices();
}
}
无论您的应用是在前台还是后台,API 都是一样的。您唯一需要做的就是确保系统不会在应用程序处于后台时将其终止。为此,只需在您的应用进程中的某处设置一个前台服务 运行。
在 android 中当应用程序处于后台时使用服务扫描和连接 ble 设备。
package com.example.tracker.service;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanSettings;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Handler;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.support.v4.widget.SwipeRefreshLayout;
import android.util.Log;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.SeekBar;
import android.widget.Toast;
import com.google.firebase.auth.FirebaseAuth;
import com.example.tracker.R;
import com.example.tracker.utils.SampleGattAttributes;
import com.example.tracker.utils.SharedPreferencesUtils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
import static com.example.tracker.constant.SharedFreferencesConstant.KEY_SP_MOBILE_NUMBER;
/**
* Created by Jprashant on 12/9/17.
*/
public class BackgroundService extends Service{
private int scanPeriod;
Context context;
String TAG="BackgroundService";
private BluetoothAdapter mBluetoothAdapter;
private boolean mScanning;
private Handler mHandler;
public String[] advDataTypes = new String[256];
ArrayList<BluetoothDevice> bluetoothDeviceArrayList=new ArrayList<>();
ArrayList<BluetoothDevice> bluetoothDeviceArrayListTwo=new ArrayList<>();
private static final int REQUEST_ENABLE_BT = 1;
// Stops scanning after 10 seconds.
private static final long SCAN_PERIOD = 10000;
/*Connect Ble Device*/
String deviceId;
public static String arrayDidOpnSec2;
BluetoothGattService gattService4;
public static ArrayList<BluetoothGattCharacteristic> lastCharacteristic;
// AlertDialog.Builder alertDialog;
private float avgRssi = 0.0f;
// private Dialog dialog;
private BluetoothLeService mBluetoothLeService;
private boolean mConnected = false;
private ArrayList<ArrayList<BluetoothGattCharacteristic>> mGattCharacteristics = new ArrayList();
//service and char uuid
private static final int TRACKER_ON_OFF = 2;
private static final UUID TRACER_TRIPPLE_PRESS_SERVICE=UUID.fromString("edfec62e-9910-0bac-5241-d8bda6932a2f");
private static final UUID TRACKER_TRIPPLE_PRESS_CHAR=UUID.fromString("772ae377-b3d2-4f8e-4042-5481d1e0098c");
private static final UUID IMMEDIATE_ALERT_UUID = UUID.fromString("00001802-0000-1000-8000-00805f9b34fb");
private static final UUID ALERT_LEVEL_UUID = UUID.fromString("00002a06-0000-1000-8000-00805f9b34fb");
private Button btnSMS;
public static String mDeviceName,mDeviceAddress,connectionStatus;
/*-------------------------------------------------------------------------------*/
public static final String PREFS_NAME = "PreferencesFile";
public int deviceCount = 0;
public String[] mData = new String[400];
private Handler mHandler1;
private ListView listItems;
/*--------for > 21--------------*/
private BluetoothLeScanner mLEScanner;
private ScanSettings settings;
private List<ScanFilter> filters;
private BluetoothGatt mGatt;
public BackgroundService() {
}
public BackgroundService(Context context) {
this.context = context;
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// getting systems default ringtone
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(),"CALL YOUR METHOD",Toast.LENGTH_LONG).show();
mHandler = new Handler();
// Use this check to determine whether BLE is supported on the device. Then you can
// selectively disable BLE-related features.
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
Toast.makeText(context, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
}
// Initializes a Bluetooth adapter. For API level 18 and above, get a reference to
// BluetoothAdapter through BluetoothManager.
final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
// Checks if Bluetooth is supported on the device.
if (mBluetoothAdapter == null) {
Toast.makeText(context, R.string.error_bluetooth_not_supported, Toast.LENGTH_SHORT).show();
return;
}
for (int i = 0; i < 256; i += REQUEST_ENABLE_BT) {
advDataTypes[i] = "Unknown Data Type";
}
advDataTypes[REQUEST_ENABLE_BT] = "Flags";
advDataTypes[2] = "Incomplete List of 16-bit Service Class UUIDs";
advDataTypes[3] = "Complete List of 16-bit Service Class UUIDs";
advDataTypes[4] = "Incomplete List of 32-bit Service Class UUIDs";
advDataTypes[5] = "Complete List of 32-bit Service Class UUIDs";
advDataTypes[6] = "Incomplete List of 128-bit Service Class UUIDs";
advDataTypes[7] = "Complete List of 128-bit Service Class UUIDs";
advDataTypes[8] = "Shortened Local Name";
advDataTypes[9] = "Complete Local Name";
advDataTypes[10] = "Tx Power Level";
advDataTypes[13] = "Class of LocalDevice";
advDataTypes[14] = "Simple Pairing Hash";
advDataTypes[15] = "Simple Pairing Randomizer R";
advDataTypes[16] = "LocalDevice ID";
advDataTypes[17] = "Security Manager Out of Band Flags";
advDataTypes[18] = "Slave Connection Interval Range";
advDataTypes[20] = "List of 16-bit Solicitaion UUIDs";
advDataTypes[21] = "List of 128-bit Solicitaion UUIDs";
advDataTypes[22] = "Service Data";
advDataTypes[23] = "Public Target Address";
advDataTypes[24] = "Random Target Address";
advDataTypes[25] = "Appearance";
advDataTypes[26] = "Advertising Interval";
advDataTypes[61] = "3D Information Data";
advDataTypes[255] = "Manufacturer Specific Data";
scanPeriod = getApplicationContext().getSharedPreferences(PREFS_NAME, 0).getInt("scan_interval", 6000);
scanTrackerDevices();
}
}, 10000);
return START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
}
public void scanTrackerDevices(){
Log.e(TAG,"scanTrackerDevices");
if (!mBluetoothAdapter.isEnabled()) {
if (!mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
}
}
scanLeDevice(true);
}
private void scanLeDevice(final boolean enable) {
bluetoothDeviceArrayList.clear();
if (enable) {
// Stops scanning after a pre-defined scan period.
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
mScanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
int arraySize=bluetoothDeviceArrayListTwo.size();
Log.e(TAG,"bluetoothDeviceArrayListTwo Size in scan :"+arraySize);
for (int i=0;i<bluetoothDeviceArrayListTwo.size();i++){
BluetoothDevice bluetoothDevice=bluetoothDeviceArrayListTwo.get(i);
Log.e(TAG,"Device Name in scan :"+bluetoothDevice.getName());
Log.e(TAG,"Device Address in scan :"+bluetoothDevice.getAddress());
if (i==0){
mBluetoothLeService.connect(bluetoothDevice.getAddress());
}
}
}
}, scanPeriod);
mScanning = true;
mBluetoothAdapter.startLeScan(mLeScanCallback);
} else {
mScanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
}
}
private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
public void onLeScan(final BluetoothDevice device, final int rssi, final byte[] scanRecord) {
String d = "";
String rd = "";
String h = "0123456789ABCDEF";
int ln = 0;
int i = 0;
while (i < scanRecord.length) {
int x = scanRecord[i] & 255;
rd = new StringBuilder(String.valueOf(rd)).append(h.substring(x / 16, (x / 16) + REQUEST_ENABLE_BT)).append(h.substring(x % 16, (x % 16) +REQUEST_ENABLE_BT)).toString();
if (i == ln) {
ln = (i + x) + REQUEST_ENABLE_BT;
if (x == 0) {
break;
}
d = new StringBuilder(String.valueOf(d)).append("\r\n Length: ").append(h.substring(x / 16, (x / 16) + REQUEST_ENABLE_BT)).append(h.substring(x % 16, (x % 16) +REQUEST_ENABLE_BT)).toString();
i += REQUEST_ENABLE_BT;
x = scanRecord[i] & 255;
d = new StringBuilder(String.valueOf(d)).append(", Type :").append(h.substring(x / 16, (x / 16) + REQUEST_ENABLE_BT)).append(h.substring(x % 16, (x % 16) + REQUEST_ENABLE_BT)).append(" = ").append(advDataTypes[x]).append(", Value: ").toString();
rd = new StringBuilder(String.valueOf(rd)).append(h.substring(x / 16, (x / 16) + REQUEST_ENABLE_BT)).append(h.substring(x % 16, (x % 16) + REQUEST_ENABLE_BT)).toString();
} else {
d = new StringBuilder(String.valueOf(d)).append(" ").append(h.substring(x / 16, (x / 16) + REQUEST_ENABLE_BT)).append(h.substring(x % 16, (x % 16) +REQUEST_ENABLE_BT)).toString();
}
i += REQUEST_ENABLE_BT;
}
Log.e(TAG,"UUID : "+device.getUuids());
String[] arrayDeviceName=String.valueOf(device.getName()).split(" ");
String deviceName0=arrayDeviceName[0];
bluetoothDeviceArrayListTwo.add(device);
}
};
/*-------------------Connect BLE---------------------------------------------*/
private Handler mHandler2;
public final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent)
{
String action = intent.getAction();
if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action))
{
numberOfRssi = 0;
avgRssi = 0.0f;
mConnected = true;
updateConnectionState(R.string.connected);
mHandler2.postDelayed(startRssi, 300);
Log.e(TAG,"ACTION_GATT_CONNECTED");
}
else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) {
mConnected = false;
updateConnectionState(R.string.disconnected);
Log.e(TAG,"ACTION_GATT_DISCONNECTED");
} else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) {
displayGattServicesForDimmer(mBluetoothLeService.getSupportedGattServices());// For dimmer
Log.e(TAG,"ACTION_GATT_SERVICES_DISCOVERED");
} else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) {
Log.e(TAG,"ACTION_DATA_AVAILABLE");
String unknownServiceString = context.getResources().getString(R.string.unknown_service);
displayDimmerData("<<" + SampleGattAttributes.lookup(intent.getStringExtra(BluetoothLeService.CHARACTERISTIC_UUID), unknownServiceString) + ">> Value: " + intent.getStringExtra(BluetoothLeService.EXTRA_DATA) + "]");
displayDimmer2(intent.getStringExtra(BluetoothLeService.EXTRA_DATA));
} else if (BluetoothLeService.ACTION_GATT_RSSI_UPDATE.equals(action)) {
updateRssi(intent.getIntExtra(BluetoothLeService.EXTRA_DATA, -400));
} else if (BluetoothLeService.ACTION_GATT_WRITE_FAILED.equals(action)) {
Log.e(TAG,"ACTION_GATT_WRITE_FAILED");
}
}
};
/*------------------------------------------------------------------------*/
@Override
public void onCreate() {
super.onCreate();
// -------------------Connect Ble--------------------------------------
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothLeService.ACTION_GATT_CONNECTED);
intentFilter.addAction(BluetoothLeService.ACTION_GATT_DISCONNECTED);
intentFilter.addAction(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED);
intentFilter.addAction(BluetoothLeService.ACTION_DATA_AVAILABLE);
intentFilter.addAction(BluetoothLeService.ACTION_GATT_RSSI_UPDATE);
intentFilter.addAction(BluetoothLeService.ACTION_GATT_WRITE_FAILED);
Log.e(TAG,"OnResume()");
getApplicationContext().registerReceiver(mGattUpdateReceiver, intentFilter);
getApplicationContext().bindService(new Intent(getApplicationContext(), BluetoothLeService.class), mServiceConnection, 1);
mHandler2=new Handler();
}
private BluetoothGattCharacteristic mNotifyCharacteristic;
private final ServiceConnection mServiceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName componentName, IBinder service) {
mBluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService();
if (!mBluetoothLeService.initialize()) {
Log.e(TAG, "Unable to initialize Bluetooth");
}
}
public void onServiceDisconnected(ComponentName componentName) {
mBluetoothLeService = null;
}
};
private boolean notificationActive = true;
private int numberOfRssi = 0;
private Runnable startRssi = new Runnable() {
public void run() {
if (mConnected) {
mBluetoothLeService.readRemoteRssi();
mHandler2.postDelayed(startRssi, 200);
}
}
};
public BluetoothGatt getmGatt() {
return mGatt;
}
//code from DeviceControlActivity
private void updateConnectionState(final int resourceId) {
connectionStatus= String.valueOf(resourceId);
Log.e(TAG,"Resource ID"+resourceId);
}
private void displayDimmerData(String data){
Log.e(TAG,"Display Data :"+data);
}
private void displayDimmer2(String data){
Log.e(TAG,"display Dimmer2"+data);
String sosString = data.substring(0, Math.min(data.length(), 3));
Log.e(TAG,"SOS String :"+sosString);
if (sosString.equals("SOS")){
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.setData(Uri.parse("tel:"+ SharedPreferencesUtils.getStringFromSharedPreferences(KEY_SP_MOBILE_NUMBER,getApplicationContext())));
callIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplicationContext().startActivity(callIntent);
}
}
private void updateRssi(int data) {
if (data > -400) {
if (this.numberOfRssi > 10) {
this.avgRssi = ((9.0f * this.avgRssi) + ((float) data)) / 10.0f;
} else {
this.avgRssi = (this.avgRssi + ((float) data)) / 2.0f;
this.numberOfRssi++;
}
connectionStatus="Connected, RSSI:" + data + ", Avg:" + Math.round(this.avgRssi);
}
}
/*-------------------------disaplay gatt service for dimmer----------------------*/
private void displayGattServicesForDimmer(List<BluetoothGattService> gattServices) {
if (gattServices != null) {
String unknownServiceString = getResources().getString(R.string.unknown_service);
String unknownCharaString = getResources().getString(R.string.unknown_characteristic);
ArrayList<HashMap<String, String>> gattServiceData = new ArrayList();
ArrayList<ArrayList<HashMap<String, String>>> gattCharacteristicData = new ArrayList();
this.mGattCharacteristics = new ArrayList();
for (BluetoothGattService gattService : gattServices) {
HashMap<String, String> currentServiceData = new HashMap();
String uuid = gattService.getUuid().toString();
currentServiceData.put("NAME", SampleGattAttributes.lookup(uuid, unknownServiceString));
currentServiceData.put("UUID", uuid);
gattServiceData.add(currentServiceData);
ArrayList<HashMap<String, String>> gattCharacteristicGroupData = new ArrayList();
List<BluetoothGattCharacteristic> gattCharacteristics = gattService.getCharacteristics();
ArrayList<BluetoothGattCharacteristic> charas = new ArrayList();
for (BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) {
charas.add(gattCharacteristic);
HashMap<String, String> currentCharaData = new HashMap();
uuid = gattCharacteristic.getUuid().toString();
currentCharaData.put("NAME", "\t\t\t<<" + SampleGattAttributes.lookup(uuid, unknownCharaString) + ">>");
currentCharaData.put("UUID", "\t\t\tUUID: 0x" + uuid.substring(4, 8) + ", Properties: " + translateProperties(gattCharacteristic.getProperties()));
gattCharacteristicGroupData.add(currentCharaData);
Log.i(TAG,"CUrrent CHARACTERISTIC DATA"+currentCharaData);
Log.i(TAG,"UUID : "+uuid.substring(4, 8));
Log.i(TAG,"Proprties : "+gattCharacteristic.getProperties());
Log.i(TAG,"Translate Proprties : "+translateProperties(gattCharacteristic.getProperties()));
Log.i(TAG,"char list"+gattCharacteristicData.toString());
}
gattService4=gattService;
this.mGattCharacteristics.add(charas);
}
if (mGattCharacteristics.get(3)!=null) {
lastCharacteristic = new ArrayList<>(mGattCharacteristics.get(3));
enableNotifyOfCharcteristicForDimmer(lastCharacteristic);
}
}
}
private String translateProperties(int properties) {
String s = "";
if ((properties & 1) > 0) {
s = new StringBuilder(String.valueOf(s)).append("/Broadcast").toString();
}
if ((properties & 2) > 0) {
s = new StringBuilder(String.valueOf(s)).append("/Read").toString();
}
if ((properties & 4) > 0) {
s = new StringBuilder(String.valueOf(s)).append("/WriteWithoutResponse").toString();
}
if ((properties & 8) > 0) {
s = new StringBuilder(String.valueOf(s)).append("/Write").toString();
}
if ((properties & 16) > 0) {
s = new StringBuilder(String.valueOf(s)).append("/Notify").toString();
}
if ((properties & 32) > 0) {
s = new StringBuilder(String.valueOf(s)).append("/Indicate").toString();
}
if ((properties & 64) > 0) {
s = new StringBuilder(String.valueOf(s)).append("/SignedWrite").toString();
}
if ((properties & 128) > 0) {
s = new StringBuilder(String.valueOf(s)).append("/ExtendedProperties").toString();
}
if (s.length() > 1) {
return s.substring(1);
}
return s;
}
// Enable Characteristic for dimmer
public void enableNotifyOfCharcteristicForDimmer(ArrayList<BluetoothGattCharacteristic> lastCharacteristic){
if(mGattCharacteristics!=null) {
checkCharacteristicPresent(lastCharacteristic.get(0));
mBluetoothLeService.setCharacteristicNotification(lastCharacteristic.get(0), true);
notificationActive = true;
Log.e(TAG,"Characteristic index : "+0+":\nM GATT CHARACTERISTIC AT "+"Service 4 : CHAR"+ 0 +" :" +lastCharacteristic.get(0).toString());
checkCharacteristicPresent(lastCharacteristic.get(1));
mBluetoothLeService.setCharacteristicNotification(lastCharacteristic.get(1), true);
notificationActive = true;
Log.e(TAG,"Characteristic index : "+1+":\nM GATT CHARACTERISTIC AT "+"Service 4 : CHAR"+ 1 +" :" +lastCharacteristic.get(1).toString());
checkCharacteristicPresent(lastCharacteristic.get(2));
mBluetoothLeService.setCharacteristicNotification(lastCharacteristic.get(2), true);
notificationActive = true;
Log.e(TAG,"Characteristic index : "+2+":\nM GATT CHARACTERISTIC AT "+"Service 4 : CHAR"+ 2 +" :" +lastCharacteristic.get(2).toString());
checkCharacteristicPresent(lastCharacteristic.get(3));
mBluetoothLeService.setCharacteristicNotification(lastCharacteristic.get(3), true);
notificationActive = true;
Log.e(TAG,"Characteristic index : "+3+":\nM GATT CHARACTERISTIC AT "+"Service 4 : CHAR"+ 3 +" :" +lastCharacteristic.get(3).toString());
checkCharacteristicPresent(lastCharacteristic.get(4));
mBluetoothLeService.setCharacteristicNotification(lastCharacteristic.get(4), true);
notificationActive = true;
Log.e(TAG,"Characteristic index : "+4+":\nM GATT CHARACTERISTIC AT "+"Service 4 : CHAR"+ 4 +" :" +lastCharacteristic.get(4).toString());
checkCharacteristicPresent(lastCharacteristic.get(5));
mBluetoothLeService.setCharacteristicNotification(lastCharacteristic.get(5), true);
notificationActive = true;
Log.e(TAG,"Characteristic index : "+5+":\nM GATT CHARACTERISTIC AT "+"Service 4 : CHAR"+ 5 +" :" +lastCharacteristic.get(5).toString());
checkCharacteristicPresent(lastCharacteristic.get(2));
mBluetoothLeService.setCharacteristicNotification(lastCharacteristic.get(2), true);
notificationActive = true;
Log.e(TAG,"Characteristic index : "+2+":\nM GATT CHARACTERISTIC AT "+"Service 4 : CHAR"+ 2 +" :" +lastCharacteristic.get(2).toString());
}
}
// Check the type of characteristic i.e READ/WRITE/NOTIFY
public void checkCharacteristicPresent(BluetoothGattCharacteristic characteristic) {
int charaProp = characteristic.getProperties();
Log.e(TAG, "checkCharacteristicPresent Prop : " + charaProp);
mBluetoothLeService.setCurrentCharacteristic(characteristic);
if ((charaProp & 2) > 0) {
Log.e(TAG, "CharProp & 2 : " + charaProp);
mBluetoothLeService.readCharacteristic(characteristic);
}
if ((charaProp & 16) > 0) {
Log.e(TAG, "CharProp & 16 : " + charaProp);
mNotifyCharacteristic = characteristic;
} else {
if (mNotifyCharacteristic != null) {
mBluetoothLeService.setCharacteristicNotification(mNotifyCharacteristic, false);
mNotifyCharacteristic = null;
}
}
if ((charaProp & 8) > 0 || (charaProp & 4) > 0) {
Log.e(TAG, "CharProp & 4 : " + charaProp);
} else {
Log.e(TAG, "Else : " + charaProp);
}
}
}