android BLE4.0 流程图

BLE蓝牙在android上连接,底层实现读取的详细执行过程:

1、扫描:

使用BluetoothAdapter.startLeScan来扫描低功耗蓝牙设备,获取设备对象device,通过device.address,device.name获取设备名称和mac地址,通过mac地址分配每个设备唯一名称,例:体温计1,体温计2...

在扫描到设备的回调函数中获得所有device对象,并使用BluetoothAdapter.stopLeScan停止扫描

2、连接和读写数据:

使用BluetoothDevice.connectGatt来获取到BluetoothGatt对象;

执行BluetoothGatt.discoverServices,这个方法是异步操作,在回调函数onServicesDiscovered中得到status,通过判断status是否等于BluetoothGatt.GATT_SUCCESS来判断查找Service是否成功;

如果成功了,则通过BluetoothGatt.getService来获取BluetoothGattService;

接着通过BluetoothGattService.getCharacteristic获取BluetoothGattCharacteristic;

然后通过BluetoothGattCharacteristic.getValue获取体温数据。


主要使用BluetoothLeService对上图流程进行控制。BluetoothLeService封装了androidframework 层bluetooth的相关对象和操作方法、回调方法包括:

android.bluetooth.BluetoothAdapter;

android.bluetooth.BluetoothDevice;

android.bluetooth.BluetoothGatt;

android.bluetooth.BluetoothGattCallback;

android.bluetooth.BluetoothGattCharacteristic;

android.bluetooth.BluetoothGattService;

android.bluetooth.BluetoothManager;

android.bluetooth.BluetoothProfile;

initialize();初始化

disconnect();断开与远程设备的GATT连接

close();关闭关闭GATT

readCharacteristic();读取指定的characteristic

readDeviceData();读取设备信息

connect();连接设备

getCharacteristic();获取BluetoothGattCharacteristic对象

SendReadOrder();发送读数据指令

getSupportedGattServices();获取所有服务

 

BluetoothLeService采用与显示层bindunbind的方式,在后台保持运行,并提供与前台交互的android组件BroadcastReceiver传递消息。


/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.mehow.mehowhealth.bluetooth;

import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;

import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;


public class BluetoothLeService extends Service implements BleManager{

	private final static String TAG = BluetoothLeService.class.getSimpleName();

	private BluetoothManager mBluetoothManager;
	private BluetoothAdapter mBluetoothAdapter;
	private String mBluetoothDeviceAddress;
	private BluetoothGatt mBluetoothGatt;
	private int order;// 表示发送的是什么读取命令
	private BluetoothGattCharacteristic characteristic;

	private final IBinder mBinder = new LocalBinder();

	private int mConnectionState = STATE_DISCONNECTED;
	private static final int STATE_DISCONNECTED = 0;
	private static final int STATE_CONNECTING = 1;
	private static final int STATE_CONNECTED = 2;

	// 广播标识
	public final static String ACTION_GATT_CONNECTED = "com.example.bluetooth.le.ACTION_GATT_CONNECTED";
	public final static String ACTION_GATT_DISCONNECTED = "com.example.bluetooth.le.ACTION_GATT_DISCONNECTED";
	public final static String ACTION_GATT_SERVICES_DISCOVERED = "com.example.bluetooth.le.ACTION_GATT_SERVICES_DISCOVERED";
	public final static String ACTION_DATA_AVAILABLE = "com.example.bluetooth.le.ACTION_DATA_AVAILABLE";
	public final static String EXTRA_DATA = "com.example.bluetooth.le.EXTRA_DATA";

	public final static UUID UUID_HEART_RATE_MEASUREMENT = UUID.fromString("00002a37-0000-1000-8000-00805f9b34fb");


	public final static String CHANGE_PRODUCT_PARAMETER = "CHANGE_PRODUCT_PARAMETER";

	/**
	 * 判断BluetoothAdapter对象
	 * 
	 */
	public boolean initialize() {
		if (mBluetoothManager == null) {
			mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
			if (mBluetoothManager == null) {
				return false;
			}
		}

		mBluetoothAdapter = mBluetoothManager.getAdapter();
		if (mBluetoothAdapter == null) {
			return false;
		}

		return true;
	}

	/**
	 * 断开与远程设备的GATT连接
	 */
	public void disconnect() {
		if (mBluetoothAdapter == null || mBluetoothGatt == null) {
			return;
		}
		mBluetoothGatt.disconnect();
		Log.i(TAG, "disconnect:--------2"+mBluetoothGatt);
	}

	/**
	 * 关闭关闭GATT
	 */
	public void close() {
		if (mBluetoothGatt == null) {
			return;
		}
		mBluetoothGatt.close();
		mBluetoothGatt = null;
		Log.i(TAG, "disconnect:--------2"+mBluetoothGatt);
	}

	/**
	 * 读取指定的characteristic
	 */
	public boolean readCharacteristic(BluetoothGattCharacteristic characteristic) {
		if (mBluetoothAdapter == null || mBluetoothGatt == null) {
			return false;
		}
		this.characteristic = characteristic;
		return mBluetoothGatt.readCharacteristic(characteristic);
	}

	public interface onReadListener {
		public void ReadData(byte[] bys, int order);
	}

	// 供上层调用
	public void getReadtData(onReadListener listener) {
		byte[] by = readDeviceData();
		listener.ReadData(by, order);
	}

	// 读取设备信息
	public byte[] readDeviceData() {
		byte[] data = null;
		if (characteristic == null) {
			return null;
		}
		if (UUID.fromString(Constant.SERVICEUUID).equals(
				characteristic.getUuid())) {

			int flag = characteristic.getProperties();
			int format = -1;
			if ((flag & 0x01) != 0) {
				format = BluetoothGattCharacteristic.FORMAT_UINT16;
			} else {
				format = BluetoothGattCharacteristic.FORMAT_UINT8;
			}
			final int heartRate = characteristic.getIntValue(format, 1);
		} else {
			data = characteristic.getValue();
		}
		return data;

	}

	/**
	 * 连接设备
	 */
	public boolean connect(final String address) {
		if (mBluetoothAdapter == null || address == null) {
			return false;
		}

		if (mBluetoothDeviceAddress != null&& address.equals(mBluetoothDeviceAddress)&& mBluetoothGatt != null) {
			if (mBluetoothGatt.connect()) {
				mConnectionState = STATE_CONNECTING;
				return true;
			} else {
				return false;
			}
		}
		final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
		if (device == null) {
			return false;
		}
		mBluetoothGatt = device.connectGatt(this, false, back);
		Log.i("FH", "mBluetoothGatt:"+mBluetoothGatt);

		mBluetoothDeviceAddress = address;
		mConnectionState = STATE_CONNECTING;
		return true;
	}

	// 获取制定UUID的BluetoothGattCharacteristic对象
	// 参数:service_uuid--BluetoothGattService的UUID;characteristic_uuid:BluetoothGattCharacteristic的UUID
	public BluetoothGattCharacteristic getCharacteristic(String service_uuid,String characteristic_uuid) {
		BluetoothGattService gService = mBluetoothGatt.getService(UUID
				.fromString(service_uuid));
		if (gService == null) {
			return null;
		}
		BluetoothGattCharacteristic characteristic = gService
				.getCharacteristic(UUID.fromString(characteristic_uuid));
		return characteristic;
	}

	// 发送读数据指令
	// 参数:by--要发送的指令;characteristic---要发给具体的对象
	public boolean SendReadOrder(byte[] by,BluetoothGattCharacteristic characteristic, int identifying) {
		if (by == null || characteristic == null) {
			return false;
		}
		order = identifying;
		boolean status = false;
		int storedLevel = characteristic.getWriteType();
		Log.d(TAG, "storedLevel() - storedLevel=" + storedLevel);
		characteristic.setValue(by);
		characteristic
		.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
		status = mBluetoothGatt.writeCharacteristic(characteristic);
		Log.d(TAG, "writeLlsAlertLevel() - status=" + status);
		return status;

	}

	/**
	 * 获取所有服务
	 */
	public List<BluetoothGattService> getSupportedGattServices() {
		if (mBluetoothGatt == null)
			return null;

		return mBluetoothGatt.getServices();
	}

	public class LocalBinder extends Binder {

		public BluetoothLeService getService() {
			return BluetoothLeService.this;
		}
	}

	@Override
	public IBinder onBind(Intent intent) {
		return mBinder;
	}



	/**
	 * BluetoothGatt回调函数
	 */
	private final BluetoothGattCallback back = new BluetoothGattCallback() {
		@Override
		public void onConnectionStateChange(BluetoothGatt gatt, int status,int newState) {
			String intentAction;
			if (newState == BluetoothProfile.STATE_CONNECTED) {
				intentAction = ACTION_GATT_CONNECTED;
				mConnectionState = STATE_CONNECTED;
				Log.i(TAG, "Connected to GATT server.");
				// Attempts to discover services after successful connection.
				Log.i(TAG, "Attempting to start service discovery:"+ mBluetoothGatt.discoverServices());
				Log.i("FH", "mBluetoothGatt-------7897987987:"+mBluetoothGatt.getServices().size());
					System.out.println("已经连接上设备");
					broadcastUpdate(intentAction);
					Log.i(TAG, "Connected to GATT server.");
					// Attempts to discover services after successful connection.
			} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
				intentAction = ACTION_GATT_DISCONNECTED;
				mConnectionState = STATE_DISCONNECTED;
				Log.i(TAG, "Disconnected from GATT server.");
				broadcastUpdate(intentAction);
				System.out.println("已经断开设备");
			}
		}

		@Override
		public void onServicesDiscovered(BluetoothGatt gatt, int status) {
			if (status == BluetoothGatt.GATT_SUCCESS) {
				System.out.println("onServicesDiscovered------4623462462------------");
				broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
				Log.i("FH", "mBluetoothGatt:"+mBluetoothGatt.getServices().size());
			} else {
				Log.w(TAG, "onServicesDiscovered received: " + status);
			}
		}

		@Override
		public void onCharacteristicRead(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic, int status) {
			if (status == BluetoothGatt.GATT_SUCCESS) {
				broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
			}
			Log.i(TAG, "characteristic----------1:"+characteristic);
			Log.i(TAG, "mBluetoothGatt----------1:"+mBluetoothGatt.getServices().size());
		}

		@Override
		public void onCharacteristicChanged(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic) {
			broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
			Log.i(TAG, "characteristic----------2:"+characteristic);
			Log.i(TAG, "mBluetoothGatt----------2:"+mBluetoothGatt.getServices().size());
		}

		@Override
		public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
			Log.d(TAG, "onCharacteristicWrite" + Arrays.toString(characteristic.getValue()));
		};

	};


	private void broadcastUpdate(final String action) {
		final Intent intent = new Intent(action);
		sendBroadcast(intent);
	}

	/**
	 * 发送广播
	 * 
	 * @param action
	 * @param characteristic
	 */
	private void broadcastUpdate(final String action,final BluetoothGattCharacteristic characteristic) {
		final Intent intent = new Intent(action);

		// This is special handling for the Heart Rate Measurement profile. Data
		// parsing is
		// carried out as per profile specifications:
		// http://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.heart_rate_measurement.xml
		if (UUID_HEART_RATE_MEASUREMENT.equals(characteristic.getUuid())) {
			int flag = characteristic.getProperties();
			Log.d(TAG, flag + "");
			int format = -1;
			if ((flag & 0x01) != 0) {
				format = BluetoothGattCharacteristic.FORMAT_UINT16;
				Log.d(TAG, "Heart rate format UINT16.");
			} else {
				format = BluetoothGattCharacteristic.FORMAT_UINT8;
				Log.d(TAG, "Heart rate format UINT8.");
			}
			final int heartRate = characteristic.getIntValue(format, 1);
			Log.d(TAG, String.format("Received heart rate: %d", heartRate));
			intent.putExtra(EXTRA_DATA, String.valueOf(heartRate));
		} else {
			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));
				}
				// stringBuilder.append(String.valueOf(byteChar));

				intent.putExtra(EXTRA_DATA, new String(data) + "\n"+ stringBuilder.toString());
				SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// 设置日期格式
				System.out.println(df.format(System.currentTimeMillis())+ "-----" + stringBuilder.toString());
				intent.putExtra("byte", data);
				intent.putExtra("order", order);
				// -------------------------------------------------

			}
			// For all other profiles, writes the data formatted in HEX.

		}
		sendBroadcast(intent);
	}




	/**
	 * 解绑Service
	 */
	@Override
	public boolean onUnbind(Intent intent) {
		close();
		return super.onUnbind(intent);
	}

	@Override
	public byte[] initReadOrder(int identifying, byte[] be) {
		byte[] by = null;
		switch (identifying) {
		case Constant.PRODUCT_PARAMETER:
			if (be != null) {

				by = new byte[7];
				by[0] = 0x11;
				by[1] = 0x08;
				by[2] = 0x01;
				by[3] = 0x03;
				by[4] = be[0];
				by[5] = be[1];
				by[6] = be[2];
			}
			break;
		case Constant.DATA:
			by = new byte[4];
			by[0] = 0x11;
			by[1] = 0x02;
			by[2] = 0x08;
			by[3] = 0x00;
			break;
		case Constant.HISTORY_RECORD:// 历史记录
			if (be != null) {

				by = new byte[6];
				by[0] = Constant.SERIES_NUMBER[0];
				by[1] = Constant.SERIES_NUMBER[1];
				by[2] = Constant.SERIES_NUMBER[2];
				by[3] = Constant.SERIES_NUMBER[3];
				by[4] = be[0];
				by[5] = be[1];
			}
			break;
		case Constant.USER_INFO:// 写入用户信息
			by = new byte[14];
			by[0] = 0x11;
			by[1] = 0x04;
			by[2] = 0x08;
			by[3] = 0x0A;
			by[4] = Constant.SERIES_NUMBER[0];
			by[5] = Constant.SERIES_NUMBER[1];
			by[6] = Constant.SERIES_NUMBER[2];
			by[7] = Constant.SERIES_NUMBER[3];
			break;
		case Constant.USER_HISTORY_RECORD:// 读取用户信息,查询是否有历史记录
			by = new byte[8];
			by[0] = 0x11;
			by[1] = 0x03;
			by[2] = 0x08;
			by[3] = 0x04;
			by[4] = Constant.SERIES_NUMBER[0];
			by[5] = Constant.SERIES_NUMBER[1];
			by[6] = Constant.SERIES_NUMBER[2];
			by[7] = Constant.SERIES_NUMBER[3];
			break;

		default:
			break;
		}
		return by;
	}

	@Override
	public byte[] int2byte(int res) {
		byte[] targets = new byte[2];
		targets[0] = (byte) ((res >> 8) & 0xff);
		targets[1] = (byte) (res & 0xff);
		return targets;
	}
}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值