Android连接蓝牙流程(完整代码在末尾)
- 声明权限
1) 在 AndroidManifest 清单文件中声明权限(注意:搜索蓝牙需要获取位置权限!!)
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
2) 申请运行时权限
if (ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED ) {
ActivityCompat.requestPermissions(this, new String[]{
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.BLUETOOTH_SCAN,
Manifest.permission.BLUETOOTH_CONNECT}, 0);
}
// 在onRequestPermissionsResult方法中处理权限请求的结果
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == 0) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// 用户授予了蓝牙连接权限,执行蓝牙连接相关操作
// 获取配对列表
for (BluetoothDevice bondedDevice : bluetoothAdapter.getBondedDevices()) {
deviceListAdapter.add(bondedDevice.getName() + "\n" + bondedDevice.getAddress());
}
} else {
// 用户拒绝了蓝牙连接权限,可能需要显示一个提示消息或提供解释
Toast.makeText(this, "请授权蓝牙权限", Toast.LENGTH_LONG).show();
}
}
}
- 获取蓝牙适配器
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (bluetoothAdapter == null) {
Toast.makeText(MainActivity.this, "此设备不支持蓝牙!", Toast.LENGTH_SHORT).show();
}
- 启动蓝牙
// 启动蓝牙
if (!bluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, 1);
}
- 创建蓝牙展示列表
deviceListView = findViewById(R.id.deviceListView);
deviceListAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1);
deviceListView.setAdapter(deviceListAdapter);
- 注册蓝牙广播接收器(用于接收蓝牙搜索的结果)
// 注册蓝牙广播接收器
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
registerReceiver(new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
deviceListAdapter.add(device.getName() + "\n" + device.getAddress());
}
}
}, filter);
- 搜索蓝牙
if (bluetoothAdapter.isDiscovering()) {
bluetoothAdapter.cancelDiscovery();
}
deviceListAdapter.clear();
bluetoothAdapter.startDiscovery();
- 连接蓝牙(异步代码中执行)
// 连接蓝牙
deviceListView.setOnItemClickListener((parent, view, position, id) -> {
String deviceInfo = (String) parent.getItemAtPosition(position);
String deviceAddress = deviceInfo.substring(deviceInfo.length() - 17);
BluetoothDevice myDevice = bluetoothAdapter.getRemoteDevice(deviceAddress);
new Thread(new Runnable() {
@Override
public void run() {
try {
Looper.prepare();
if (mySocket != null) {
Toast.makeText(MainActivity.this, "断开已连接的蓝牙", Toast.LENGTH_SHORT).show();
mySocket.close();
}
mySocket = myDevice.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB")); // uuid通用
mySocket.connect();
myOutStream = mySocket.getOutputStream();
myInStream = mySocket.getInputStream();
Toast.makeText(MainActivity.this, "蓝牙连接上了:" + myDevice.getName(), Toast.LENGTH_SHORT).show();
} catch (Exception e2) {
Toast.makeText(MainActivity.this, "蓝牙连接失败" + e2.getMessage(), Toast.LENGTH_SHORT).show();
myInStream = null;
myOutStream = null;
mySocket = null;
}
Looper.loop();
}
}).start();
});
关键API
// 获取蓝牙适配器
BluetoothAdapter.getDefaultAdapter();
// 蓝牙是否启动
bluetoothAdapter.isEnabled();
// 开启蓝牙
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, 1);
// 蓝牙是否在搜索
bluetoothAdapter.isDiscovering();
// 搜索蓝牙
bluetoothAdapter.startDiscovery();
// 停止搜索蓝牙
bluetoothAdapter.cancelDiscovery();
// 获取蓝牙设备
bluetoothAdapter.getRemoteDevice();
// 获取蓝牙socket
BluetoothSocket mySocket = myDevice.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
// 连接蓝牙
mySocket.connect();
// 获取输入流输出流
myOutStream = mySocket.getOutputStream();
myInStream = mySocket.getInputStream();
完整代码
MainActivity
package com.example.bluetoothdemo;
import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Looper;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;
public class MainActivity extends AppCompatActivity {
private BluetoothAdapter bluetoothAdapter; // 蓝牙
private ArrayAdapter<String> deviceListAdapter;
private ListView deviceListView;
private static BluetoothSocket mySocket = null;
private static OutputStream myOutStream = null;
private static InputStream myInStream = null;
// 运行时权限
public static final String[] PERMISSIONS = new String[]{
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.BLUETOOTH_SCAN,
Manifest.permission.BLUETOOTH_CONNECT,
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 检查蓝牙扫描权限
if (ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED
|| ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED
|| ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
|| ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.BLUETOOTH_SCAN,
Manifest.permission.BLUETOOTH_CONNECT}, 0);
}
// 获取蓝牙
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (bluetoothAdapter == null) {
Toast.makeText(MainActivity.this, "此设备不支持蓝牙!", Toast.LENGTH_SHORT).show();
return;
}
// 设置蓝牙列表
deviceListView = findViewById(R.id.deviceListView);
deviceListAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1);
deviceListView.setAdapter(deviceListAdapter);
// 启动蓝牙
if (!bluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, 1);
}
// 注册蓝牙广播接收器
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
registerReceiver(new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
deviceListAdapter.add(device.getName() + "\n" + device.getAddress());
}
}
}, filter);
Button startScanBluetooth = findViewById(R.id.start_scan_bluetooth); // 搜索蓝牙
Button stopScanBluetooth = findViewById(R.id.stop_scan_bluetooth); // 停止搜索蓝牙
startScanBluetooth.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (bluetoothAdapter.isDiscovering()) {
bluetoothAdapter.cancelDiscovery();
}
deviceListAdapter.clear();
bluetoothAdapter.startDiscovery();
}
});
stopScanBluetooth.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
bluetoothAdapter.cancelDiscovery();
}
});
// 连接蓝牙
deviceListView.setOnItemClickListener((parent, view, position, id) -> {
String deviceInfo = (String) parent.getItemAtPosition(position);
String deviceAddress = deviceInfo.substring(deviceInfo.length() - 17);
BluetoothDevice myDevice = bluetoothAdapter.getRemoteDevice(deviceAddress);
new Thread(new Runnable() {
@Override
public void run() {
try {
Looper.prepare();
if (mySocket != null) {
Toast.makeText(MainActivity.this, "断开已连接的蓝牙", Toast.LENGTH_SHORT).show();
mySocket.close();
}
mySocket = myDevice.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB")); // uuid通用
mySocket.connect();
myOutStream = mySocket.getOutputStream();
myInStream = mySocket.getInputStream();
Toast.makeText(MainActivity.this, "蓝牙连接上了:" + myDevice.getName(), Toast.LENGTH_SHORT).show();
} catch (Exception e2) {
Toast.makeText(MainActivity.this, "蓝牙连接失败" + e2.getMessage(), Toast.LENGTH_SHORT).show();
myInStream = null;
myOutStream = null;
mySocket = null;
}
Looper.loop();
}
}).start();
});
}
// 在onRequestPermissionsResult方法中处理权限请求的结果
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == 0) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// 用户授予了蓝牙连接权限,执行蓝牙连接相关操作
// 已配对列表
for (BluetoothDevice bondedDevice : bluetoothAdapter.getBondedDevices()) {
deviceListAdapter.add(bondedDevice.getName() + "\n" + bondedDevice.getAddress());
}
} else {
// 用户拒绝了蓝牙连接权限,可能需要显示一个提示消息或提供解释
Toast.makeText(this, "请授权蓝牙权限", Toast.LENGTH_LONG).show();
}
}
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/start_scan_bluetooth"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="搜索蓝牙" />
<Button
android:id="@+id/stop_scan_bluetooth"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="停止搜索蓝牙" />
<ListView
android:id="@+id/deviceListView"
android:layout_marginTop="30dp"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>