Android 开发SPP经典蓝牙。
1、传统蓝牙采用的是SPP(Serial Port Profile)协议进行数据传输。
2、SPP的UUID:00001101-0000-1000-8000-00805F9B34FB
3、手机一般以客户端的角色主动连接SPP协议设备
概念:
BluetoothAdapter:
本地蓝牙适配器,是所有蓝牙交互的入口,表示蓝牙设备自身的一个蓝牙适配器,整个系统只有一个蓝牙适配器,通过他可以发现其他蓝牙设备,查询绑定(配对)设备列表,使用MAC地址实例化BluetoothDevice以及创建BluetoothServerSocket用来侦听来自其他设备的通信。
myBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();//获取默认的蓝牙Adapter
BluetoothDevice:
远程的蓝牙设备。
private static BluetoothDevice myDevice;
myDevice = myBluetoothAdapter.getRemoteDevice(BDAddr);//获取远程设备,通过蓝牙的MAC地址来获取一个远程对象
两种连接方式
BluetoothSocket
客户端:调用BluetoothDevice的createRfcommSocketToServiceRecord()可以获取该对象;调用connect()方法可以建立连接。
private static BluetoothSocket mySocket = null;
private static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
Method m = myDevice.getClass().getMethod("createRfcommSocket", new Class[] {int.class});//由BluetoothDevice衍生出BluetoothSocket, createRfcommSocket来选择连接的服务和协议
mySocket = (BluetoothSocket) m.invoke(myDevice, 1);
BluetoothServerSocket:
服务端:通过BluetoothServerSocket对象可以创建BluetoothSocket对象,调用BluetoothServerSocket的accept()的方法可以得到改对象。
开发流程:
1:声明权限:
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
2:启动和关闭蓝牙
获取蓝牙适配器,使用close()接口可以关闭蓝牙适配器
myBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();//获取默认的蓝牙Adapter
启动蓝牙
if (!blueadapter.isEnabled())
//判断本机蓝牙是否打开
{//如果没打开,则打开蓝牙
blueadapter.enable();
}
3.使用BlueAdatper搜索
使用bluetoothAdapter搜索设备,bluetoothAdapter.startDiscovery()在搜索过程中,系统会发出三个广播信息:
ACTION_DISCOVERY_START:开始搜索
ACTION_DISCOVERY_FINISHED:搜索结束
ACTION_FOUND:找到设备
if (bluetoothAdapter.isDiscovering()) {
bluetoothAdapter.cancelDiscovery();//如果蓝牙设备未连接则取消搜索
}
bluetoothAdapter.startDiscovery();
}
4:(1)通过注册广播获取搜索到的设备。
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothDevice.ACTION_FOUND);//找到设备广播
intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);//搜索完成广播
registerReceiver(receiver, intentFilter);//注册广播接收器
// receiver
private final BroadcastReceiver receiver = new BroadcastReceiver(){
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
// find a device
BluetoothDevice device = intent .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
//未配对设备
newDeviceArrayAdapter.add(device.getName() + "\n" + device.getAddress());
}else {
//已经配对过的设备
TextView tvPaired = (TextView)findViewById(R.id.tv_paired);
tvPaired.setVisibility(View.VISIBLE);
lvPairedDevices.setVisibility(View.VISIBLE);
pairedDeviceArrayAdapter.add(device.getName() + "\n" + device.getAddress());
}
Log.i(TAG,"name:" + device.getName() + " address"+ device.getAddress());
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action){
// search finish
Log.i(TAG, "search finish!");
}
}
};
(2),直接得到当前的蓝牙设备后,就可用通过遍历pairedDevices ,得到当前手机已经配对过的蓝牙设备。
Set<BluetoothDevice> pairedDevices = myBluetoothAdapter.getBondedDevices();//获取当前蓝牙设备
if (pairedDevices.size() <= 0) return false;
for (BluetoothDevice device : pairedDevices) {
Map<String, String> map = new HashMap<String, String>();
map.put("DeviceName", device.getName());
map.put("BDAddress", device.getAddress());
list.add(map);
5.建立连接
private static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
Method m = myDevice.getClass().getMethod("createRfcommSocket", new Class[] {int.class});//由BluetoothDevice衍生出BluetoothSocket, createRfcommSocket来选择连接的服务和协议
mySocket = (BluetoothSocket) m.invoke(myDevice, 1);
mySocket.connect();//使用BluetoothSocket来连接设备
6.把得到的蓝牙设备给通过点击ListView选择设备。
listView.setOnItemClickListener(new ListView.OnItemClickListener() {
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
SelectedBDAddress = list.get(arg2).get("BDAddress");
if (((ListView) arg0).getTag() != null) {
((View) ((ListView) arg0).getTag()).setBackgroundDrawable(null);
}
((ListView) arg0).setTag(arg1);
arg1.setBackgroundColor(Color.BLUE);
myDevice = myBluetoothAdapter.getRemoteDevice(SelectedBDAddress);
}
});
7.客户端发送数据
当两个设备成功连接之后,双方都会有一个BluetoothSocket对象,这时,就可以在设备之间传送数据了。
1.使用getOutputStream()方法来获取输出流来处理传输。
2.调用write()。
os = socket.getOutputStream();//获取输出流
if (os != null) {//判断输出流是否为空
os.write(message.getBytes("UTF-8"));
}
os.flush();//将输出流的数据强制提交
os.close();//关闭输出流
}
将输出流中的数据提交后,要记得关闭输出流,否则,可能会造成只能发送一次数据。
8.服务端接收数据
1.使用getInputStream()方法来获取输入流来处理传输。
2.调用read()。
InputStream im=null;
im=bluetoothSocket.getInputStream();
byte buf[] = new byte[1024];
if (is != null) {
is.read(buf, 0, buf.length);//读取发来的数据
String message = new String(buf);//把发来的数据转化为String类型
BuletoothMainActivity.UpdateRevMsg(message);//更新信息在显示文本框
is.close();//关闭输入流
使用服务端接收数据时,要先从客户端向服务端发起连接,只有接收到连接请求之后,才会返回一个BluetoothSocket对象。有BluetoothSocket对象才能获取到输入流。