Android的蓝牙部分暂且分为2.0,4.0,虽然苹果已经出了5.0版本了,咱先不说这个。
简单讲解一下,4.0是兼容2.0的功能的,今天讲的bluetoothSocket通信是在2.0上面就已经有了。
Android手机蓝牙跟硬件蓝牙交互一般都是用的bluetoothGatt.
Android手机跟手机蓝牙通信一般用的是bluetoothSocket.
这里我暂且把要连接的设备叫客户端,扫描以及请求配对都由客户端操作,被连接的设备叫做服务端。
流程:(双方蓝牙都在打开并且服务端在可检测的情况下)
客户端–>扫描到服务端–>通过扫描到bluetoothDevice获取bluetoothSocket(UUID);再用
bluetoothSocket.connect();连接服务端,这里的UUID是服务端指定的UUID
服务端–>通过蓝牙适配器获取BluetoothServerSocket(Name,UUID);–Name跟UUID都有自己指定;客户端通过这个UUID连接服务端,建立双方通信。
服务端:
OutputStream outputStream;
BluetoothServerSocket serverSocket;
private void startServer(){
//新建线程,并且使服务端做好接收准备
new Thread(new Runnable() {
@Override
public void run() {
try {
//name以及UUID由服务端指定
serverSocket= bluetoothAdapter.listenUsingRfcommWithServiceRecord("Server" ,UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
Log.i("bluetooth" , "蓝牙服务器开始等待...");
BluetoothSocket socket = serverSocket.accept();
Log.i("bluetooth" , "蓝牙客户端连接上来了!");
outputStream = socket.getOutputStream();
InputStream inputStream = socket.getInputStream();
byte[] bytes = new byte[1024];
int n ;
while((n = inputStream.read(bytes)) != -1) {
String b = new String(bytes , 0 , n , "UTF-8");
Log.i("bluetooth" , "蓝牙服务器接收到数据" + b);
}
outputStream.close();
inputStream.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
/**
* 发送数据给客户端
*/
private void sendSocketData(){
if (outputStream !=null) {
Log.i("bluetooth" , "蓝牙服务器发送数据!");
try {
//指定发送的数据已经数据编码,编码统一,不然会乱码
outputStream.write("数据".getBytes("UTF-8"));
outputStream.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
客户端:
BluetoothAdapter adapter;
BluetoothDevice device;
private BluetoothSocket socket;
private OutputStream outputStream;
private InputStream inputStream;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_operator_login);
sendBroadcast();
adapter = BluetoothAdapter.getDefaultAdapter();
}
/**
* 发送数据给服务端
*/
private void sendData(){
if (outputStream != null) {
try {
outputStream.write("数据".getBytes("UTF-8"));
outputStream.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//发出蓝牙扫描的接受广播
private void sendBroadcast(){
BluetoothReceiver receiver = new BluetoothReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);//状态改变
filter.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);//行动扫描模式改变了
filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);//动作状态发生了变化
registerReceiver(receiver , filter);
}
class BluetoothReceiver extends BroadcastReceiver{
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(BluetoothDevice.ACTION_FOUND)){
//获取蓝牙设备
device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (device.getName().equals("OPPO A31")){
adapter.cancelDiscovery();
LogUtils.i("bluetoothInfo" , "扫描到的蓝牙设备名称" + device.getName());
try {
//这里的UUID必须跟服务端的UUID一样
socket = device.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
socket.connect();
LogUtils.i("bluetoothInfo" , "连接服务器成功");
outputStream = socket.getOutputStream();
inputStream = socket.getInputStream();
new Thread(new Runnable() {
@Override
public void run() {
try {
byte[] b = new byte[1024];
int n;
while ((n = inputStream.read(b)) != -1) {
String s = new String(b,0 , n ,"UTF-8");
LogUtils.i("bluetoothInfo" , "客户端收到服务器的数据了" + s);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
} catch (IOException e) {
e.printStackTrace();
}
}
} //状态改变时
else if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(intent.getAction())) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
switch (device.getBondState()) {
case BluetoothDevice.BOND_BONDING://正在配对
LogUtils.i("bluetoothInfo", "正在配对......");
break;
case BluetoothDevice.BOND_BONDED://配对结束
LogUtils.i("bluetoothInfo", "完成配对");
break;
case BluetoothDevice.BOND_NONE://取消配对/未配对
LogUtils.i("bluetoothInfo", "取消配对");
default:
break;
}
}
}
}
最后:
别忘了加权限
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
最后大家回想,你这个都没有配对啊,只是扫描了一下啊;其实在客户端扫描到服务端的时候;
bluetoothSocket.connect();的时候这步操作就已经包含了配对操作,会提前提示双方手机配对,当然已经配对过的就不会有。
操作基本上跟平时的tcp的Socket的用法都差不多。