Android BLE开发

1,987 阅读11分钟

​这是我参与11月更文挑战的第12天,活动详情查看:2021最后一次更文挑战

这次实际项目中要求了手机终端和低功耗蓝牙即蓝牙4.0通讯的功能,所以这次我也就把我自己的Android代码同大家分享,稍后考虑将框架整理后上传Github供大家交流学习。

1.蓝牙初始化

   //初始化蓝牙设备
    private void init_ble() {
        // 手机硬件支持蓝牙
        if (!getPackageManager().hasSystemFeature(
                PackageManager.FEATURE_BLUETOOTH_LE)) {

            Toast.makeText(this, "不支持BLE", Toast.LENGTH_SHORT).show();
        }
        // Initializes Bluetooth adapter.
        // 获取手机本地的蓝牙适配器
        final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        mBluetoothAdapter = bluetoothManager.getAdapter();
        // 打开蓝牙权限
        if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
            Intent enableBtIntent = new Intent(
                    BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
        }

    }

首先判断手机硬件是否支持低功耗蓝牙,如果支持那么获取手机的蓝牙适配器,接着判断蓝牙权限是否已经开启,如果未开启则去申请。

在这里大家也可以重写onActivityResult方法来对蓝牙开启成功后进行一个提示,这里我就没有写了。

2.简单蓝牙Fragment的实现

Fragment界面

在这里我们单独使用一个Fragment来进行蓝牙功能的演示,界面如下:

蓝牙Fragment 具体布局很简单,主要就是几个扫描和断开连接,下面三个按钮与此功能无关,是发送命令的,中间的listview显示可以连接的设备。

好了,下面我们将重点讲解具体的程序流程。

功能控件的定义

包括以下几个:

//扫描蓝牙按钮
    private Button btnScan;
    //取消蓝牙连接按钮
    private Button btnDiscoonect;
    //蓝牙适配器
    BluetoothAdapter mBluetoothAdapter;
    // 蓝牙信号强度
    private ArrayList<Integer> rssis;
    // 自定义Adapter
    LeDeviceListAdapter mleDeviceListAdapter;

    //蓝牙连接状态
    private boolean mConnected = false;
    private String status = "disconnected";
    //蓝牙特征值
    private ArrayList<ArrayList<BluetoothGattCharacteristic>> mGattCharacteristics = new ArrayList<ArrayList<BluetoothGattCharacteristic>>();
    private static BluetoothGattCharacteristic target_chara = null;
     //蓝牙设备的list
    private ListView lvDevice;
    // 描述扫描蓝牙的状态
    private boolean mScanning;
    private boolean scan_flag;
     //设备信息
    public String deviceName;
    public String deviceAddress;
    public String deviceRssi;
    // 蓝牙扫描时间
    private static final long SCAN_PERIOD = 10000;

扫描蓝牙设备

 case R.id.btn_scan_dev:
                if (scan_flag) {
                    boolean gps_able = false;
                    mleDeviceListAdapter = new LeDeviceListAdapter();
                    lvDevice.setAdapter(mleDeviceListAdapter);
                    gps_able = isGpsEnable(getActivity());
                    if (gps_able == true) {
                        scanLeDevice(true);
                    } else {
                        Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                        int requestCode = 1;
                        this.startActivityForResult(intent, requestCode);
                    }

                } else {
                    scanLeDevice(false);
                    btnScan.setText("Scan Device");
                }
                break;

注意:大家可能会对其中对于GPS的操作感到疑惑,但是在Android6.0之后的系统中,想要扫描到蓝牙必须动态添加位置权限。

首先判断当前是否已经扫描,初始flag为true,然后初始化listview的适配器并检查当前位置权限有没有开启,如果开启了则开始扫描。

 private void scanLeDevice(final boolean enable) {
        if (enable) {
			/* 开始扫描蓝牙设备,带mLeScanCallback 回调函数 */
            Log.i("SCAN", "begin.....................");
            mScanning = true;
            scan_flag = false;
            btnScan.setText("Stop Scanning");
            mBluetoothAdapter.startLeScan(mLeScanCallback);
            //TODO:版本
			/*if(android.os.Build.VERSION.SDK_INT<21)
				bluetoothAdapter.startLeScan(this);
			else{
				bluetoothLeScanner.startScan(callBack);
			}*/
        } else {
            Log.i("Stop", "stoping................");
            mScanning = false;
            mBluetoothAdapter.stopLeScan(mLeScanCallback);
            scan_flag = true;
        }

    }

核心还是调用了蓝牙适配器的startLeScan方法或者StartScan方法,这个看你的API版本了,下面我们需要重写我们的LeScanCallback函数,用来扫描到的蓝牙信息并添加到我们的listview中去。

 /**
     * 蓝牙扫描回调函数 实现扫描蓝牙设备,回调蓝牙BluetoothDevice,可以获取name MAC等信息
     **/
    private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {

        @Override
        public void onLeScan(final BluetoothDevice device, final int rssi,
                             byte[] scanRecord) {
            // TODO Auto-generated method stub

            getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
					/* 讲扫描到设备的信息输出到listview的适配器 */
                    mleDeviceListAdapter.addDevice(device, rssi);
                    mleDeviceListAdapter.notifyDataSetChanged();
                }
            });

            System.out.println("Address:" + device.getAddress());
            System.out.println("Name:" + device.getName());
            System.out.println("rssi:" + rssi);

        }
    };

注意我们是在Fragment中运行的,想要修改UI需要利用上述runOnUiThread方法。

以上就完成了扫描蓝牙设备并添加更新listview的功能了。

蓝牙设备的连接

当点击的listview中展示的对应设备Item的时候我们将对此设备进行连接:

 /* listview点击函数 */
        lvDevice.setOnItemClickListener(new AdapterView.OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> arg0, View v, int position,
                                    long id) {
                // TODO Auto-generated method stub
                final BluetoothDevice device = mleDeviceListAdapter
                        .getDevice(position);
                //这里是更新工具类的信息,可以不看
                fBleUtils.setDeviceName(device.getName());
                fBleUtils.setDeviceAddress(device.getAddress());
                fBleUtils.setRssi(rssis.get(position).toString());
                fBleUtils.setBluetoothDevice(device);
                fBleUtils.setBluetoothAdapter(mBluetoothAdapter);

				//获取Item的信息
                deviceName = device.getName();
                deviceAddress = device.getAddress();
                deviceRssi = rssis.get(position).toString();
			
                if (device == null)
                    return;
                //扫描到蓝牙设备即为true
                if (mScanning) {
                    /* 停止扫描设备 */
                    mBluetoothAdapter.stopLeScan(mLeScanCallback);
                    mScanning = false;
                }
                try {
                    //启动蓝牙服务
                    Intent gattServiceIntent = new Intent(getActivity(), BluetoothLeService.class);
                    getActivity().bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);
                    //注册广播接收器
                    getActivity().registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter());
                    if (mBluetoothLeService != null) {
                        //根据蓝牙地址,建立连接
                        final boolean result = mBluetoothLeService.connect(deviceAddress);
                        Log.d(TAG, "Connect request result=" + result);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    // TODO: handle exception
                }
            }
        });

首先获取我们点击的设备Item的相关信息,然后关闭扫描。

之后我们需要启动我们的蓝牙服务类(这个类会在下面一节介绍),相当于启动了蓝牙服务。

最后我们根据定义的过滤器来为当前活动注册一个广播接收器(接收蓝牙服务类传来的信息),并根据地址来建立连接。

 /* BluetoothLeService绑定的回调函数 */
    private final ServiceConnection mServiceConnection = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName componentName,
                                       IBinder service) {
            mBluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService();
            if (!mBluetoothLeService.initialize()) {
                Log.e(TAG, "Unable to initialize Bluetooth");
            }
            // Automatically connects to the device upon successful start-up
            // initialization.
            // 根据蓝牙地址,连接设备
            mBluetoothLeService.connect(deviceAddress);
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {

        }

    };

注册广播接收器-蓝牙信息接收

具体注册2.4已经说明了,这里把接收器内容提一下:

/**
     * 广播接收器,负责接收BluetoothLeService类发送的数据
     */
    private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
            if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action))//Gatt连接成功
            {
                mConnected = true;
                status = "connected";
                //更新连接状态
                updateConnectionState(status);
                System.out.println("BroadcastReceiver :" + "device connected");
                Toast.makeText(getActivity(),"AM_Tool连接成功!",Toast.LENGTH_SHORT).show();

            } else if (BluetoothLeService.ACTION_GATT_DISCONNECTED//Gatt连接失败
                    .equals(action)) {
                mConnected = false;
                status = "disconnected";
                //更新连接状态
                updateConnectionState(status);
                System.out.println("BroadcastReceiver :"
                        + "device disconnected");
                Toast.makeText(getActivity(),"AM_Tool连接失败!",Toast.LENGTH_SHORT).show();

            } else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED//发现GATT服务器
                    .equals(action)) {
                // Show all the supported services and characteristics on the
                // user interface.
                //获取设备的所有蓝牙服务
                displayGattServices(mBluetoothLeService
                        .getSupportedGattServices());
                System.out.println("BroadcastReceiver :"
                        + "device SERVICES_DISCOVERED");
            } else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action))//有效数据
            {
                //处理发送过来的数据
               displayData(intent.getExtras().getString(
                        BluetoothLeService.EXTRA_DATA));
                System.out.println("BroadcastReceiver onData:"
                        + intent.getStringExtra(BluetoothLeService.EXTRA_DATA));
            }
        }
    };

/* 更新连接状态 */ private void updateConnectionState(String status) { tvStatus.setText(status); if (status.equals("connected")){ btnDiscoonect.setEnabled(true); }else { btnDiscoonect.setEnabled(false); } }

过滤器:

/* 意图过滤器 */
    private static IntentFilter makeGattUpdateIntentFilter() {
        final 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);
        return intentFilter;
    }

其实逻辑很简单,根据蓝牙服务类intent传来的action的类别进行不同的处理,对应的action已经通过Filter添加了。

主要就是根据蓝牙连接情况进行用户提示以及UI变更:Gatt连接成功时候提示连接成功并更新TextView,失败时候同理。

displayGattServices这个方法我也将在下面介绍一下,但是这个功能应该是固定的,如果就是使用的话不需要变动。

下面的displayData就是对于我们开发者来说比较重要的功能了,它主要获得蓝牙服务接收到的数据包,简而言之就是协议处理过后的下位机或者终端发送的数据了:

/**
     * @param @param rev_string(接受的数据)
     * @return void
     * @throws
     * @Title: displayData
     * @Description: TODO(接收到的数据另外两个Fragment中显示!!!)
     */
    private void displayData(final String rev_string) {
        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                String[] direction = rev_string.split("=");
                if (direction[0].equals("left_distance")){
                    fBleUtils.setLeftXLocation(60.0f - Float.parseFloat(direction[1]));
                    fBleUtils.setLeftDistance(Float.parseFloat(direction[1]));

                }else if (direction[0].equals("center_distance")){
                    fBleUtils.setCenterYLocation(60.0f - Float.parseFloat(direction[1]));
                    fBleUtils.setCenterDistance(Float.parseFloat(direction[1]));
                }else if (direction[0].equals("right_distance")){
                    fBleUtils.setRightFloatDistance(Float.parseFloat(direction[1]));
                    fBleUtils.setRightDistance(Float.parseFloat(direction[1]));
                }
                tvStatus.setText(rev_string);
                mDrawerActivity.setBleUtils(fBleUtils);
                btnDiscoonect.setEnabled(true);
            }
        });
    }

这里我们用这个数据更新了我们的对应数据TextView与工具类

蓝牙信息的发送

//TODO:选择关闭和开启的红外测距模块
            case R.id.btn_left_operation:
                if (btnLeftOp.getText().equals("L_Open")) {
                    Toast.makeText(getActivity(),"打开左边红外测距器",Toast.LENGTH_SHORT).show();
                    target_chara.setValue("3");
                    //调用蓝牙服务的写特征值方法实现发送数据
                    mBluetoothLeService.writeCharacteristic(target_chara);
                    btnLeftOp.setText(R.string.left_close_status);
                } else {
                    Toast.makeText(getActivity(),"关闭左边红外测距器",Toast.LENGTH_SHORT).show();
                    target_chara.setValue("2");
                    //调用蓝牙服务的写特征值方法实现发送数据
                    mBluetoothLeService.writeCharacteristic(target_chara);
                    btnLeftOp.setText(R.string.left_open_status);
                }
                break;

这里我们以一个命令发送按钮为例,首先我们需要给特征值target_chara赋值,然后调用蓝牙服务的发送特征值的命令即可,前提是我们已经连接上了对应设备。

以上我们基本完成了蓝牙初始化-扫描发现蓝牙设备-蓝牙设备的连接-蓝牙接收信息的读取-蓝牙信息的发送这样一套基本的开发流程,如果只是使用蓝牙,那么以上的信息和步骤应该可以满足需求。下面我将具体分析蓝牙服务这个类的功能,帮助大家更好的理解蓝牙通信。

3.蓝牙服务类BluetoothLeService

这个蓝牙服务类运行于后台,帮助我们同蓝牙设备进行连接,并和蓝牙Fragment的广播接收器进行交流,完成蓝牙数据接收和发送的功能。

功能控件的定义

private final static String TAG = "BluetoothLeService";// luetoothLeService.class.getSimpleName();
	private List<Sensor> mEnabledSensors = new ArrayList<Sensor>();
	//蓝牙相关类
	private BluetoothManager mBluetoothManager;
	private BluetoothAdapter mBluetoothAdapter;
	private String mBluetoothDeviceAddress;
	private BluetoothGatt mBluetoothGatt;
	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 =zzzzzzzzzzzzz
	// UUID.fromString(SampleGattAttributes.HEART_RATE_MEASUREMENT);
	private OnDataAvailableListener mOnDataAvailableListener;

这里比较重要的就是BluetoothGatt这个类,这个类通过同给定address的终端设备连接后获得,通过这个类去进行蓝牙通信的操作。

蓝牙服务初始化

这个方法是BleFragment里面BluetoothLeService绑定的回调函数里面调用的:

private final ServiceConnection mServiceConnection = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName componentName,
                                       IBinder service) {
            mBluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService();
            if (!mBluetoothLeService.initialize()) {
                Log.e(TAG, "Unable to initialize Bluetooth");
            }
            // Automatically connects to the device upon successful start-up
            // initialization.
            // 根据蓝牙地址,连接设备
            mBluetoothLeService.connect(deviceAddress);
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {

        }

    };

首先获取服务,然后进行服务的初始化,接着根据地址进行蓝牙设备的连接,初始化代码如下:

/* service 中蓝牙初始化 */
	public boolean initialize()
	{
		// For API level 18 and above, get a reference to BluetoothAdapter
		// through
		// BluetoothManager.
		if (mBluetoothManager == null)
		{   //获取系统的蓝牙管理器
			mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
			if (mBluetoothManager == null)
			{
				Log.e(TAG, "Unable to initialize BluetoothManager.");
				return false;
			}
		}
          
		mBluetoothAdapter = mBluetoothManager.getAdapter();
		if (mBluetoothAdapter == null)
		{
			Log.e(TAG, "Unable to obtain a BluetoothAdapter.");
			return false;
		}

		return true;
	}

这里的初始化就是获取当前系统的蓝牙适配器

蓝牙连接

上一节当中我们直接在Fragment里面使用了服务类的connect方法进行连接,这里我们分析里面的功能:

// 连接远程蓝牙
	public boolean connect(final String address)
	{
		if (mBluetoothAdapter == null || address == null)
		{
			Log.w(TAG,
					"BluetoothAdapter not initialized or unspecified address.");
			return false;
		}

		// Previously connected device. Try to reconnect.
		if (mBluetoothDeviceAddress != null
				&& address.equals(mBluetoothDeviceAddress)
				&& mBluetoothGatt != null)
		{
			Log.d(TAG,
					"Trying to use an existing mBluetoothGatt for connection.");
			if (mBluetoothGatt.connect())//连接蓝牙,其实就是调用BluetoothGatt的连接方法
			{
				mConnectionState = STATE_CONNECTING;
				return true;
			} else
			{
				return false;
			}
		}
		/* 获取远端的蓝牙设备 */
		final BluetoothDevice device = mBluetoothAdapter
				.getRemoteDevice(address);
		if (device == null)
		{
			Log.w(TAG, "Device not found.  Unable to connect.");
			return false;
		}
		// We want to directly connect to the device, so we are setting the
		// autoConnect
		// parameter to false.
		/* 调用device中的connectGatt连接到远程设备 */
		mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
		Log.d(TAG, "Trying to create a new connection.");
		mBluetoothDeviceAddress = address;
		mConnectionState = STATE_CONNECTING;
		System.out.println("device.getBondState==" + device.getBondState());
		return true;
	}

首先判断有没有拿到蓝牙适配器,然后判断地址是否拿到且正确,Gatt有没有获得(第一次连接肯定是没有的)。

接着通过地址获取远端的蓝牙设备,然后拿到对应设备的Gatt,所以说第一次连接获得了Gatt()并且绑定了回调函数mGattCallback,第二次连接会进入第二个if中,执行Gatt的conncet方法进行连接并判断连接结果。

Gatt的回调函数BluetoothGattCallback

/* 连接远程设备的回调函数 */
	private final BluetoothGattCallback mGattCallback = 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;
				/* 通过广播更新连接状态 */
				broadcastUpdate(intentAction);
				Log.i(TAG, "Connected to GATT server.");
				// Attempts to discover services after successful connection.
				Log.i(TAG, "Attempting to start service discovery:"
						+ mBluetoothGatt.discoverServices());

			} else if (newState == BluetoothProfile.STATE_DISCONNECTED)//连接失败
			{
				intentAction = ACTION_GATT_DISCONNECTED;
				mConnectionState = STATE_DISCONNECTED;
				Log.i(TAG, "Disconnected from GATT server.");
				broadcastUpdate(intentAction);
			}
		}
        /*
         * 重写onServicesDiscovered,发现蓝牙服务
         * 
         * */
		@Override
		public void onServicesDiscovered(BluetoothGatt gatt, int status)
		{
			if (status == BluetoothGatt.GATT_SUCCESS)//发现到服务
			{
				broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
				Log.i(TAG, "--onServicesDiscovered called--");
			} else
			{
				Log.w(TAG, "onServicesDiscovered received: " + status);
				System.out.println("onServicesDiscovered received: " + status);
			}
		}
         /*
          * 特征值的读写
          * */
		@Override
		public void onCharacteristicRead(BluetoothGatt gatt,
                                         BluetoothGattCharacteristic characteristic, int status)
		{
			if (status == BluetoothGatt.GATT_SUCCESS)
			{
				Log.i(TAG, "--onCharacteristicRead called--");
				//从特征值读取数据
				byte[] sucString = characteristic.getValue();
				String string = new String(sucString);
				//将数据通过广播到Ble_Fragment
				broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
			}
			
		}
         /*
          * 特征值的改变
          * */
		@Override
		public void onCharacteristicChanged(BluetoothGatt gatt,
				BluetoothGattCharacteristic characteristic)
		{
			System.out.println("++++++++++++++++");
			broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
	
		}
        /*
         * 特征值的写
         * */
		@Override
		public void onCharacteristicWrite(BluetoothGatt gatt,
                                          BluetoothGattCharacteristic characteristic, int status)
		{
			
			Log.w(TAG, "--onCharacteristicWrite--: " + status);
			// 以下语句实现 发送完数据或也显示到界面上
			broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
		}
        /*
         * 读描述值
         * */
		@Override
		public void onDescriptorRead(BluetoothGatt gatt,
                                     BluetoothGattDescriptor descriptor, int status)
		{
			// TODO Auto-generated method stub
			// super.onDescriptorRead(gatt, descriptor, status);
			Log.w(TAG, "----onDescriptorRead status: " + status);
			byte[] desc = descriptor.getValue();
			if (desc != null)
			{
				Log.w(TAG, "----onDescriptorRead value: " + new String(desc));
			}

		}
         /*
          * 写描述值
          * */
		@Override
		public void onDescriptorWrite(BluetoothGatt gatt,
                                      BluetoothGattDescriptor descriptor, int status)
		{
			// TODO Auto-generated method stub
			// super.onDescriptorWrite(gatt, descriptor, status);
			Log.w(TAG, "--onDescriptorWrite--: " + status);
		}
         /*
          * 读写蓝牙信号值
          * */
		@Override
		public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status)
		{
			// TODO Auto-generated method stub
			// super.onReadRemoteRssi(gatt, rssi, status);
			Log.w(TAG, "--onReadRemoteRssi--: " + status);
			broadcastUpdate(ACTION_DATA_AVAILABLE, rssi);
		}

		@Override
		public void onReliableWriteCompleted(BluetoothGatt gatt, int status)
		{
			// TODO Auto-generated method stub
			// super.onReliableWriteCompleted(gatt, status);
			Log.w(TAG, "--onReliableWriteCompleted--: " + status);
		}

	};

广播更新状态:

 //广播意图
	private void broadcastUpdate(final String action, int rssi)
	{
		final Intent intent = new Intent(action);
		intent.putExtra(EXTRA_DATA, String.valueOf(rssi));
		sendBroadcast(intent);
	}
     //广播意图
	private void broadcastUpdate(final String action)
	{
		final Intent intent = new Intent(action);
		sendBroadcast(intent);
	}

	/* 广播远程发送过来的数据 */
	public void broadcastUpdate(final String action,
			final BluetoothGattCharacteristic characteristic)
	{
		final Intent intent = new Intent(action);
		//从特征值获取数据
		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));

				Log.i(TAG, "***broadcastUpdate: byteChar = " + byteChar);

			}
			intent.putExtra(EXTRA_DATA, new String(data));
			System.out.println("broadcastUpdate for  read data:"
					+ new String(data));
		}
		sendBroadcast(intent);
	}

这里代码看上去非常多,但是主要就是对蓝牙终端的各种状态的响应,并且和Fragment中注册的广播接收器相配合,完成前后台的交接工作。

这里通过broadcastUpdate方法将不同状态的信息存入intent的EXTRA_DATA中,然后发送广播,与前面广播接收器的过滤器都是一一对应的,确保能够接收到。

其他方法

该服务类还有几个其他方法,具体代码还是比较简单的,这里就直接贴在下面:

/** 
	* @Title: disconnect 
	* @Description: TODO(取消蓝牙连接) 
	* @return void
	* @throws 
	*/ 
	public void disconnect()
	{
		if (mBluetoothAdapter == null || mBluetoothGatt == null)
		{
			Log.w(TAG, "BluetoothAdapter not initialized");
			return;
		}
		mBluetoothGatt.disconnect();

	}
/**
	 * After using a given BLE device, the app must call this method to ensure
	 * resources are released properly.
	 */
	/** 
	* @Title: close 
	* @Description: TODO(关闭所有蓝牙连接) 
	* @return void
	* @throws 
	*/ 
	public void close()
	{
		if (mBluetoothGatt == null)
		{
			return;
		}
		mBluetoothGatt.close();
		mBluetoothGatt = null;
	}

close就是直接关闭了,想要连接还需要重新获取Gatt

/** 
	* @Title: readCharacteristic 
	* @Description: TODO(读取特征值) 
	* @param @param characteristic(要读的特征值)
	* @return void    返回类型 
	* @throws 
	*/ 
	public void readCharacteristic(BluetoothGattCharacteristic characteristic)
	{
		if (mBluetoothAdapter == null || mBluetoothGatt == null)
		{
			Log.w(TAG, "BluetoothAdapter not initialized");
			return;
		}
		mBluetoothGatt.readCharacteristic(characteristic);

	}
// 写入特征值
	public void writeCharacteristic(BluetoothGattCharacteristic characteristic)
	{
		if (mBluetoothAdapter == null || mBluetoothGatt == null)
		{
			Log.w(TAG, "BluetoothAdapter not initialized");
			return;
		}
		mBluetoothGatt.writeCharacteristic(characteristic);

	}

	// 读取RSSi
	public void readRssi()
	{
		if (mBluetoothAdapter == null || mBluetoothGatt == null)
		{
			Log.w(TAG, "BluetoothAdapter not initialized");
			return;
		}
		mBluetoothGatt.readRemoteRssi();
	}