Android 之 蓝牙通信(2.0 经典)
一、环境配置
1. 添加依赖
在 build.gradle
中添加库依赖:
dependencies {implementation 'com.github.akexorcist:bluetoothspp:1.0.0'
}
2. 权限声明(AndroidManifest.xml)
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<!-- Android 12+ 额外权限 -->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <!-- Android 6.0+ 需要 --> [4,8](@ref)
二、页面布局(activity_main.xml)
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"android:padding="16dp"><!-- 状态显示 --><TextViewandroid:id="@+id/tv_status"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="蓝牙未连接"android:textSize="18sp"/><!-- 设备列表 --><ListViewandroid:id="@+id/lv_devices"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"/><!-- 操作按钮 --><Buttonandroid:id="@+id/btn_scan"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="扫描设备"/><Buttonandroid:id="@+id/btn_send"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="发送数据"android:enabled="false"/> <!-- 默认禁用 --></LinearLayout>
三、核心代码(MainActivity.java)
1. 初始化蓝牙服务
public class MainActivity extends AppCompatActivity {private BluetoothSPP bt;private TextView tvStatus;private Button btnScan, btnSend;private ListView lvDevices;private List<BluetoothDevice> deviceList = new ArrayList<>();private ArrayAdapter<String> adapter;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);tvStatus = findViewById(R.id.tv_status);btnScan = findViewById(R.id.btn_scan);btnSend = findViewById(R.id.btn_send);lvDevices = findViewById(R.id.lv_devices);// 初始化设备列表适配器adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1);lvDevices.setAdapter(adapter);// 初始化蓝牙bt = new BluetoothSPP(this);if (!bt.isBluetoothAvailable()) {Toast.makeText(this, "蓝牙不可用", Toast.LENGTH_SHORT).show();finish();}// 设置数据接收监听器bt.setOnDataReceivedListener((data, message) -> {tvStatus.setText("收到数据: " + message); // [1,6](@ref)});// 设置连接状态监听器bt.setBluetoothConnectionListener(new BluetoothSPP.BluetoothConnectionListener() {@Overridepublic void onDeviceConnected(String name, String address) {tvStatus.setText("已连接至 " + name);btnSend.setEnabled(true); // 启用发送按钮}@Overridepublic void onDeviceDisconnected() {tvStatus.setText("连接断开");btnSend.setEnabled(false);}@Overridepublic void onDeviceConnectionFailed() {tvStatus.setText("连接失败");}});// 启动蓝牙服务bt.setupService();bt.startService(BluetoothState.DEVICE_OTHER); // [1,6](@ref)// 扫描按钮事件btnScan.setOnClickListener(v -> scanDevices());// 发送按钮事件btnSend.setOnClickListener(v -> sendData());// 设备列表点击事件lvDevices.setOnItemClickListener((parent, view, position, id) -> {BluetoothDevice device = deviceList.get(position);connectDevice(device.getAddress()); // 连接选中的设备 [3](@ref)});}// 扫描设备private void scanDevices() {if (!checkPermissions()) {requestPermissions(); // 动态申请权限return;}deviceList.clear();adapter.clear();bt.setDeviceTarget(BluetoothState.DEVICE_OTHER);bt.startDiscovery(); // 开始扫描 [6](@ref)// 注册广播接收器IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);registerReceiver(discoveryReceiver, filter);}// 广播接收器(处理设备发现)private final BroadcastReceiver discoveryReceiver = new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {String action = intent.getAction();if (BluetoothDevice.ACTION_FOUND.equals(action)) {BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);deviceList.add(device);adapter.add(device.getName() + "\n" + device.getAddress()); // 显示设备名和地址 [8](@ref)}}};// 连接设备(带延迟避免冲突)private void connectDevice(String address) {new Handler().postDelayed(() -> {bt.connect(address); // 延迟500ms连接 [3](@ref)}, 500);}// 发送数据private void sendData() {bt.send("Hello Device!", true); // 发送字符串(自动添加CR/LF)[1](@ref)}// 权限检查(兼容Android 12+)private boolean checkPermissions() {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {return checkSelfPermission(BLUETOOTH_SCAN) == PERMISSION_GRANTED && checkSelfPermission(BLUETOOTH_CONNECT) == PERMISSION_GRANTED;} else {return checkSelfPermission(ACCESS_FINE_LOCATION) == PERMISSION_GRANTED;}}// 动态请求权限private void requestPermissions() {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {requestPermissions(new String[]{Manifest.permission.BLUETOOTH_SCAN,Manifest.permission.BLUETOOTH_CONNECT,Manifest.permission.ACCESS_FINE_LOCATION}, 1);} else {requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1);}}@Overrideprotected void onDestroy() {super.onDestroy();unregisterReceiver(discoveryReceiver); // 注销广播bt.stopService(); // 释放资源 [6](@ref)}
}