一、Android 中进行蓝牙开发需要用到的类和执行过程
1,使用BluetoothAdapter.startLeScance来扫描设备
2,在扫描到设备的回调函数中的得到BluetoothDevice 对象,并使用Bluetooth.stopLeScan停止扫描
3,使用BluetoothDevice.connectGatt来获取到BluetoothGatt对象
4,执行BluetoothGatt.discoverServices,这个方法是异步操作,在回调函数onServicesDiscovered中得到status,通过判断status是否等于BluetoothGatt.GATT_SUCCESS来 判断查找Service是否成功
5,如果成功了,则通过BluetoothGatt.getService来获取BluetoothGattService
6,接着通过BluetoothGattService.getCharacteristic获取BluetoothGattCharacteristic
7,然后通过BluetoothGattCharacteristic.getDescriptor获取BluetoothGattDescriptor
二、收发数据
收发数据是通过GATT,GATT是通过蓝牙收发数据的一种协议,包含Characteristic,Descriptor,Service 三个属性值,BLE 分为三个部分Service , Characteristic ,Descriptor 这三个部分都是由UUID做为唯一的标识符,一个蓝牙终端可以包含多个Service ,一个Service 可以包含多个Characteristic ,一个Characteristic 包含一个Value 和多个Descriptor,一个Descriptor包含一个Value
三、上代码(有些工具类是在其他文件里面,我这里没有在改了,直接复制上来了)
MainActivice.java:
BluetoothManager bluetoothManager;
BluetoothAdapter mBluetoothAdapter;
Intent intentBluetoothLeService = new Intent();
//低功耗蓝牙的文件名
public static String BLUETOOTHSERVICE = "com.boe.navapp.remote.BluetoothLeService";
bluetoothManager = (BluetoothManager) MainActivity.this
.getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
if (mBluetoothAdapter != null && mBluetoothAdapter.isEnabled()) {
if (!(CommonUtil.isServiceRunning(MainActivity.this,
Constants.BLUETOOTHSERVICE))) {
intentBluetoothLeService = new Intent(MainActivity.this,
BluetoothLeService.class);
startService(intentBluetoothLeService);
}
}
// 判断当前服务是否启动
public static boolean isServiceRunning(Context mContext, String className) {
boolean isRunning = false;
ActivityManager activityManager = (ActivityManager) mContext
.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningServiceInfo> serviceList = activityManager
.getRunningServices(70);
if (!(serviceList.size() > 0)) {
return false;
}
for (int i = 0; i < serviceList.size(); i++) {
if (serviceList.get(i).service.getClassName().equals(className) == true) {
isRunning = true;
break;
}
}
return isRunning;
}
BluetoothLeService.java:(這里我讲下主要代码,文件我会传上去)
public final static String REMOTE_CONNECT_STATUS = "REMOTE_CONNECT_STATUS";// 当前选择的遥控器连接状态
public final static String REMOTE_CONNECTED_DEVICES = "REMOTECONNECTEDDEVICES";// 存储已经连接的设备列表
public final static String REMOTE_DEVICE_INFO = "REMOTEDEVICEINFO";
public final static String REMOTE_CURR_ADDR = "REMOTECURRADDR";// 当前连接设备的地址
public final static String ACTION_GATT_REMOTESEVEN_DISCONNECTED = "com.infisight.hudprojector.bluetooth.le.ACTION_GATT_REMOTESEVEN_DISCONNECTED";
private static final String SP_NAME = "address";
@Override
public void onCreate() {
super.onCreate();
LogTools.i(TAG, "BluetoothLeService onCreate");
prefs = PreferenceManager.getDefaultSharedPreferences(this);
telMgr = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
prefs.edit().putBoolean(Constants.REMOTE_CONNECT_STATUS, false)
.commit();
LogTools.i(TAG, "BluetoothLeService before SaveUtils.loadArray");
addressList = SaveUtils.loadArray(this, SP_NAME); //存放连接的地址
GetDeviceInfo();
LogTools.i(TAG, "BluetoothLeService GetDeviceInfo");
}
/**
* 获取设备信息 lstNeedConnectDevices
*/
private void GetDeviceInfo() {
String connectedinfo = prefs.getString(
Constants.REMOTE_CONNECTED_DEVICES, "");
if (!connectedinfo.equals("")) {
Gson gson = new Gson();
try {
lstNeedConnectDevices = gson.fromJson(connectedinfo,
new TypeToken<List<BleConnectDevice>>() {
}.getType());
for (BleConnectDevice bleconnectdevice : lstNeedConnectDevices) {
if (!lstNeedConnectAddress.contains(bleconnectdevice
.getAddress()))
lstNeedConnectAddress
.add(bleconnectdevice.getAddress());
}
} catch (Exception e) {
}
}
}
public boolean initialize() {
// 获取蓝牙管理
if (mBluetoothManager == null) {
mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
if (mBluetoothManager == null) {
return false;
}
}
// 获取适配器
mBluetoothAdapter = mBluetoothManager.getAdapter();
return mBluetoothAdapter != null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
LogTools.d(TAG, "onStartCommand:flags=" + flags + ",startId=" + startId);
if (mBluetoothManager == null) {
if (!initialize()) {
LogTools.i(TAG, "Unable to initialize Bluetooth");
}
}
if (isFirstRun) {
try {
handler.postDelayed(runnable, 2000);
} catch (Exception e) {
}
} else {
LogTools.i(TAG, "Constants.REMOTE_DEVICE_INFO:");
String address = getSharedPreferences(Constants.REMOTE_DEVICE_INFO,
0).getString(Constants.REMOTE_CURR_ADDR, "0");
connect(address);
}
isFirstRun = false;
return START_STICKY;
}
/**
* 启动连接线程
*/
Runnable runnable = new Runnable() {
@Override
public void run() {
// 在这里启动连接,如果连接失败,就再重新试图连接
LogTools.i(TAG, "try connect runnable");
try {
mBluetoothAdapter.stopLeScan(mLeScanCallback);
mBluetoothAdapter.startLeScan(mLeScanCallback); //扫描低功耗蓝牙设备
} catch (Exception e) {
// TODO Auto-generated catch block
LogTools.i(TAG, "try connect runnable failed:" + e.getMessage());
e.printStackTrace();
}
handler.postDelayed(this, 10000);
}
};
// 设备查找回调得到BluetoothDevice对象
LeScanCallback mLeScanCallback = new LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice device, int rssi,
byte[] scanRecord) {
LogTools.d(TAG, "device.getName:" + device.getName() + ",device.address:" + device.getAddress());
if ("KeyCtrl".equals(device.getName())) {
close(mGattMap.get(device.getAddress()));
//获取BluetoothGatt 对象
BluetoothGatt mBluetoothGatt = device.connectGatt(
BluetoothLeService.this, false, mGattCallback);
mGattMap.put(device.getAddress(), mBluetoothGatt);
} else if ("infisight_r".equals(device.getName()))//对蓝牙OBD功能进行连接
{
try {
close(mGattMap.get(device.getAddress()));
BluetoothGatt mBluetoothGatt = device.connectGatt(
BluetoothLeService.this, false, mGattCallback);
mGattMap.put(device.getAddress(), mBluetoothGatt);
} catch (Exception e) {
LogTools.e(TAG, "mBluetoothGatt failed:" + e.getMessage());
}
}
}
};
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status,
int newState) {
// 连接状态发生变更
String intentAction = Constants.ACTION_GATT_REMOTESEVEN_DISCONNECTED;
LogTools.e(TAG, "onConnectionStateChange:name:" + gatt.getDevice().getName() + "Addr:" + gatt.getDevice().getAddress() + ",newState:" + newState);
if (newState == BluetoothProfile.STATE_CONNECTED) {
hmIsConnected.put(gatt.getDevice().getAddress(), true);
SaveUtils.saveArray(BluetoothLeService.this, SP_NAME,
addressList);
if ("KeyCtrl".equals(gatt.getDevice().getName())) {
intentAction = Constants.ACTION_GATT_REMOTE_CONNECTED;
} else if ("infisight_r".equals(gatt.getDevice().getName())) {
LogTools.e(TAG, "ble ACTION_GATT_REMOTE_CONNECTED");
intentAction = Constants.ACTION_GATT_REMOTESEVEN_CONNECTED;
}
prefs.edit().putBoolean(Constants.REMOTE_CONNECT_STATUS, true)
.commit();
broadcastUpdate(intentAction);
LogTools.e(TAG, "ble gatt.discoverServices");
gatt.discoverServices();
SaveDeviceInfo(gatt.getDevice());
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
LogTools.d(TAG, "BluetoothProfile.STATE_DISCONNECTED");
// 开启线程,不断时的试图连接设备
hmIsConnected.put(gatt.getDevice().getAddress(), false);
if ("KeyCtrl".equals(gatt.getDevice().getName())) {
intentAction = Constants.ACTION_GATT_REMOTE_DISCONNECTED;
} else if ("infisight_r".equals(gatt.getDevice().getName())) {
LogTools.d(TAG, "BLE BluetoothProfile.STATE_DISCONNECTED");
intentAction = Constants.ACTION_GATT_REMOTESEVEN_DISCONNECTED;
}
prefs.edit().putBoolean(Constants.REMOTE_CONNECT_STATUS, false)
.commit();
// close(gatt);
disconnect(gatt);
broadcastUpdate(intentAction);
}
}
//通过status 是否等于BluetoothGatt.GATT_SUCCESS来判断查找Service是否成功
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
// 发现服务的广播
LogTools.e(TAG, "onServicesDiscovered:" + gatt.getDevice().getAddress());
if (status == BluetoothGatt.GATT_SUCCESS) {
displayGattServices(getSupportedGattServices(gatt), gatt);
broadcastUpdate(Constants.ACTION_GATT_SERVICES_DISCOVERED);
}
}
@Override
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic, int status) {
LogTools.d(TAG, "onCharacteristicRead");
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(Constants.ACTION_DATA_AVAILABLE, gatt, characteristic);
}
}
@Override
public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
LogTools.d(TAG, "onCharacteristicChanged");
broadcastUpdate(Constants.ACTION_DATA_AVAILABLE, gatt, characteristic);
}
@Override
public void onCharacteristicWrite(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic, int status) {
}
};
public static boolean saveArray(Context context, String spname, ArrayList<String> list) {
mySharedPreferences = context.getSharedPreferences(spname, Context.MODE_PRIVATE);
Editor edit = mySharedPreferences.edit();
edit.putInt("Status_size", list.size()); /*sKey is an array*/
for (int i = 0; i < list.size(); i++) {
edit.putString("Status_" + i, list.get(i) + "");
}
// LogTools.i("saveArray", list+"");
return edit.commit();
}
private void broadcastUpdate(final String action) {
final Intent intent = new Intent(action);
sendBroadcast(intent);
}
/**
* 保存设备信息
*/
private void SaveDeviceInfo(BluetoothDevice bluetoothdevice) {
List<BleConnectDevice> lstConnectDevices = new ArrayList<BleConnectDevice>();
String connectedinfo = prefs.getString(
Constants.REMOTE_CONNECTED_DEVICES, "");
Gson gson = new Gson();
if (!connectedinfo.equals("")) {
try {
lstConnectDevices = gson.fromJson(connectedinfo,
new TypeToken<List<BleConnectDevice>>() {
}.getType());
} catch (Exception e) {
}
}
if (!lstNeedConnectAddress.contains(bluetoothdevice.getAddress())) {
lstNeedConnectAddress.add(bluetoothdevice.getAddress());
BleConnectDevice bledevice = new BleConnectDevice(); //保存设备的信息
bledevice.setAddress(bluetoothdevice.getAddress());
bledevice.setName(bluetoothdevice.getName());
lstConnectDevices.add(bledevice);
try {
String newaddr = gson.toJson(lstConnectDevices);
prefs.edit()
.putString(Constants.REMOTE_CONNECTED_DEVICES, newaddr)
.commit();
} catch (Exception e) {
}
} else if ("KeyCtrl".equals(bluetoothdevice.getName())) {
mTypeMap.put(bluetoothdevice.getAddress(), "remote");
// }else if (bluetoothdevice.getName().contains("BLE"))//对蓝牙OBD功能进行连接
} else if ("infisight_r".equals(bluetoothdevice.getName()))//对蓝牙OBD功能进行连接
{
mTypeMap.put(bluetoothdevice.getAddress(), "remote");
}
}
public boolean connect(final String address) {
// 确认已经获取到适配器并且地址不为空
if (mBluetoothAdapter == null || address == null || address.equals("0")) {
return false;
}
final BluetoothDevice device = mBluetoothAdapter
.getRemoteDevice(address);
// 通过设备地址获取设备
if (device == null) {
LogTools.e(TAG, "Device not found. Unable to connect.");
return false;
}
// LogTools.i(TAG, "device.connectGatt(this, false, mGattCallback)");
if (mGattMap.keySet().contains(address)) {
BluetoothGatt mBluetoothGatt = mGattMap.get(address);
if (mBluetoothGatt != null) {
// close(mBluetoothGatt);
disconnect(mBluetoothGatt);
}
}
BluetoothGatt mBluetoothGatt = device.connectGatt(this, false,
mGattCallback);
mGattMap.put(address, mBluetoothGatt);
addressList.add(address);
// mConnectionState = STATE_CONNECTING;
return true;
}
public void disconnect(BluetoothGatt mBluetoothGatt) {
// LogTools.i("LIFECYCLE", "disconnect");
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
LogTools.e(TAG, "BluetoothAdapter not initialized disconnect");
return;
}
mBluetoothGatt.disconnect();
// 断开连接
}
// 从特征中分析返回的数据并表示为action后进行广播
private void broadcastUpdate(final String action, BluetoothGatt gatt,
final BluetoothGattCharacteristic characteristic) {
if ("KeyCtrl".equals(gatt.getDevice().getName())) {
final byte[] data = characteristic.getValue();
if (data != null && data.length > 0) {
final StringBuilder stringBuilder = new StringBuilder(data.length);
for (byte byteChar : data)
stringBuilder.append(String.format("%02X ", byteChar));
if (stringBuilder.toString().trim().equals("01")) {
// 上
int operFlag = 1;
Message msg = sendKeyHandler.obtainMessage(operFlag);
msg.what = operFlag;
msg.sendToTarget();
LogTools.i(TAG, "keys01");
} else if (stringBuilder.toString().trim().equals("02")) {
LogTools.i(TAG, "isPhoneIng:"+ProcessMsgService.isPhoneIng);
if(ProcessMsgService.isPhoneIng == true)
{
try {
PhoneUtils.getITelephony(telMgr)
.answerRingingCall();
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
LogTools.i(TAG, "error:"+e.getMessage());
CommonUtil.answerRingingCall(this);
}
return;
}
// 确定
int operFlag = 5;
Message msg = sendKeyHandler.obtainMessage(operFlag);
msg.what = operFlag;
msg.sendToTarget();
// ProcessBroadcast(Constants.GESTURE_INFO,
// Constants.GESTURE_SINGLETAP);
LogTools.i(TAG, "keys02");
} else if (stringBuilder.toString().trim().equals("04")) {
// 唤醒
MainActivity.svr.controlToWake(true);
LogTools.i(TAG, "keys04");
} else if (stringBuilder.toString().trim().equals("08")) {
LogTools.i(TAG, "isPhoneIng:"+ProcessMsgService.isPhoneIng);
LogTools.i(TAG, "keys08");
if(ProcessMsgService.isPhoneIng == true)
{
try {
PhoneUtils.getITelephony(telMgr).endCall();
} catch (Exception e) {
e.printStackTrace();
}
return;
}
// 返回
int operFlag = 0;
Message msg = sendKeyHandler.obtainMessage(operFlag);
msg.what = operFlag;
msg.sendToTarget();
// ProcessBroadcast(Constants.GESTURE_INFO,
// Constants.GETSTURE_BACK);
LogTools.i(TAG, "keys08");
} else if (stringBuilder.toString().trim().equals("10")) {
// 下
int operFlag = 2;
Message msg = sendKeyHandler.obtainMessage(operFlag);
msg.what = operFlag;
msg.sendToTarget();
// ProcessBroadcast(Constants.GESTURE_INFO,
// Constants.GESTURE_TODOWN);
LogTools.i(TAG, "keys10");
}
// intent.putExtra(EXTRA_DATA, new String(data) + "\n" +
// stringBuilder.toString());
}
// }else if (gatt.getDevice().getName().contains("BLE"))
} else if ("infisight_r".equals(gatt.getDevice().getName())) {
final byte[] data = characteristic.getValue();
if (data != null && data.length > 0) {
final StringBuilder stringBuilder = new StringBuilder(data.length);
for (byte byteChar : data)
stringBuilder.append(String.format("%02X ", byteChar));
if (stringBuilder.toString().trim().equals("15")) {
// 上
int operFlag = 1;
Message msg = sendKeyHandler.obtainMessage(operFlag);
msg.what = operFlag;
msg.sendToTarget();
} else if (stringBuilder.toString().trim().equals("12")) {
//如果在通话中,接听电话
if(ProcessMsgService.isPhoneIng == true)
{
try {
PhoneUtils.getITelephony(telMgr)
.answerRingingCall();
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
CommonUtil.answerRingingCall(this);
}
return;
}
// 确定
int operFlag = 5;
Message msg = sendKeyHandler.obtainMessage(operFlag);
msg.what = operFlag;
msg.sendToTarget();
// ProcessBroadcast(Constants.GESTURE_INFO,
// Constants.GESTURE_SINGLETAP);
} else if (stringBuilder.toString().trim().equals("14")) {
// 唤醒
MainActivity.svr.controlToWake(true);
} else if (stringBuilder.toString().trim().equals("16")) {
//如果已经在通话中,直接挂断电话
LogTools.i(TAG, "key:16");
LogTools.i(TAG, "isPhoneIng:"+ProcessMsgService.isPhoneIng);
if(ProcessMsgService.isPhoneIng == true)
{
try {
PhoneUtils.getITelephony(telMgr).endCall();
} catch (Exception e) {
e.printStackTrace();
}
return;
}
// 返回
int operFlag = 0;
Message msg = sendKeyHandler.obtainMessage(operFlag);
msg.what = operFlag;
msg.sendToTarget();
// ProcessBroadcast(Constants.GESTURE_INFO,
// Constants.GETSTURE_BACK);
} else if (stringBuilder.toString().trim().equals("11")) {
// 下
int operFlag = 2;
Message msg = sendKeyHandler.obtainMessage(operFlag);
msg.what = operFlag;
msg.sendToTarget();
// ProcessBroadcast(Constants.GESTURE_INFO,
// Constants.GESTURE_TODOWN);
} else if (stringBuilder.toString().trim().equals("13")) {
// 左
int operFlag = 3;
Message msg = sendKeyHandler.obtainMessage(operFlag);
msg.what = operFlag;
msg.sendToTarget();
// ProcessBroadcast(Constants.GESTURE_INFO,
// Constants.GESTURE_TOLEFT);
} else if (stringBuilder.toString().trim().equals("17")) {
// 右
int operFlag = 4;
Message msg = sendKeyHandler.obtainMessage(operFlag);
msg.what = operFlag;
msg.sendToTarget();
// ProcessBroadcast(Constants.GESTURE_INFO,
// Constants.GESTURE_TORIGHT);
}
}
}
}
BluetoothService 下载地址http://download.csdn.net/detail/pigseesunset/9690371