首先要说的是如果程序想操作蓝牙,必须拥有两个权限,最好先写到清单文件中

<!-- 声明蓝牙权限 -->
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <!-- 允许程序发现和配对蓝牙设备 -->
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />

接下来咱们说说蓝牙的最具跨时代的版本吧,蓝牙4.0,蓝牙4.0是2012年最新蓝牙版本,是3.0的升级版本;较3.0版本更省电、成本低、3毫秒低延迟、超长有效连接距离、AES-128加密等;通常用在蓝牙耳机、蓝牙音箱等设备上。对程序影响最大的就数蓝牙4.0版本和咱们android4.3了,因为在android4.3之前的版本,android系统是不支持蓝牙4.0的所以有了这个分水岭,在开发的时候要特别的注意了。

1、蓝牙的打开和关闭

通过BluetoothAdapter类来控制本地蓝牙设备。该类代表运行应用程序的Android设备。为了访问默认的bluetooth adapter ,需要调用getDefaultAdapter ,一些Android设备有多个BluetoothAdapter ,但目前只可以访问默认设备。

BluetoothAdapter bluetooth = BluetoothAdapter.getDefaultAdapter();

BluetoothAdapter提供了用于读取并设置本地蓝牙硬件的属性的方法,使用isEnabled方法确认设备已经启动,然后使用getName和getAddress方法分别访问BluetoothAdapter的“友好”的名称(由用户设置的、用于标识特定设备的任意字符串)以及硬件地址。

// 蓝牙打开
	bluetooth.enable();
	// 蓝牙关闭
	bluetooth.disable();

如何友好的向用户展示这一个过程呢?建议用以下方式提示用户,让用户自己做选择

if (!bluetooth.isEnabled()) {
		//蓝牙未启用,提示用户打开它
		Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
		startActivityForResult(intent, 1);
	}else{
		//蓝牙已经开启,关闭蓝牙或者做其他的操作
	}

这样在onActivityResult中就能得到用户的选择了

@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		if (requestCode == 1) {
			if (resultCode ==  RESULT_CANCELED) {
				Log.d(TAG, "requestCode = 1 RESULT_CANCELED ");
			}else if (resultCode == RESULT_OK) {
				Log.d(TAG, "requestCode = 1 RESULT_OK ");
			}
		}
	}



2、设置蓝牙的可发现性

Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 200); //第二个参数是本机蓝牙被发现的时间,系统默认范围[1-300]秒,系统默认120秒
startActivityForResult(intent, 2);

同样的,在onActivityResult中加入此判断,如果用户取消了,在这里做处理。

3、扫描周边设备

private ArrayList<BluetoothDevice> devicesList = new ArrayList<BluetoothDevice>();
	public void discoveryDevice() {
		IntentFilter intent = new IntentFilter();
		intent.addAction(BluetoothDevice.ACTION_FOUND);
		intent.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
		registerReceiver(searchDevices, intent);
		if (bluetooth.isEnabled() && !bluetooth.isDiscovering()) {
			devicesList.clear();
			bluetooth.startDiscovery();
		}
	}
	private BroadcastReceiver searchDevices = new BroadcastReceiver() {
		@SuppressLint("UseSparseArrays")
		public void onReceive(Context context, Intent intent) {
			String action = intent.getAction();
			if (BluetoothDevice.ACTION_FOUND.equals(action)) {
				BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
				devicesList.add(device);
			} else if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) {
				BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
				switch (device.getBondState()) {
				case BluetoothDevice.BOND_BONDING:
					Log.d("BlueToothTestActivity", "正在配对......");
					break;
				case BluetoothDevice.BOND_BONDED:
					Log.d("BlueToothTestActivity", "完成配对");
					connect(device);// 连接设备
					break;
				case BluetoothDevice.BOND_NONE:
					Log.d("BlueToothTestActivity", "取消配对");
				default:
					break;
				}
			}
		}
	};

将扫描到的设备都存在一个列表中,这里也写了点绑定设备的代码,接下来要用。


4、绑定/连接设备

public void connectDevice(int index) {
		if (bluetooth.isDiscovering())
			bluetooth.cancelDiscovery();
		BluetoothDevice remoteDevice = devicesList.get(index);
		try {
			if (remoteDevice.getBondState() == BluetoothDevice.BOND_NONE) {
				// 利用反射方法调用BluetoothDevice.createBond(BluetoothDevice remoteDevice);
				Method createBondMethod = BluetoothDevice.class.getMethod("createBond");
				Log.d("BlueToothTestActivity", "开始配对");
				createBondMethod.invoke(remoteDevice);
			} else if (remoteDevice.getBondState() == BluetoothDevice.BOND_BONDED) {
				connect(remoteDevice);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

在3的代码中,如果绑定成功将直接连接设备,方法如下:

private void connect(BluetoothDevice btDev) {
		UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");//SPP协议  蓝牙串行端口基于SPP协议(Serial Port Profile),能在蓝牙设备之间创建串口进行数据传输。
		try {
			btSocket = btDev.createRfcommSocketToServiceRecord(uuid);
			btSocket.connect();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}



关于UUID的相关资料,可以问问度娘。