Android Studio开发蓝牙应用(一)
环境
- window 11
- 安卓12
- HC-06蓝牙模块
创建空project
-
选择Empty Activity,后点击Next
-
可修改项目名,自定义,后点击Finish即可。
-
首先设计布局,布局文件位于app/src/main/res/layout下
-
直接使用约束布局方式,这种方式布局代码大部分可自动生成,方便
- 项目实现的功能
- 查看手机是否支持蓝牙
- 查看当前蓝牙状态
- 蓝牙开关
- 使蓝牙可见
- 搜索可见蓝牙
- 查看已绑定的设备
- 项目实现的功能
- Acitivity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/button3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="是否支持蓝牙"
app:layout_constraintEnd_toStartOf="@+id/guideline2"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button4"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="当前蓝牙状态"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/guideline2"
app:layout_constraintTop_toTopOf="parent" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_begin="205dp" />
<Button
android:id="@+id/button7"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="打开蓝牙"
app:layout_constraintEnd_toStartOf="@+id/guideline2"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button3" />
<Button
android:id="@+id/button8"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="关闭蓝牙"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/guideline2"
app:layout_constraintTop_toBottomOf="@+id/button4" />
<Button
android:id="@+id/button9"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="使蓝牙可见"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button7" />
<Button
android:id="@+id/button10"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="搜索可见蓝牙"
app:layout_constraintEnd_toStartOf="@+id/guideline2"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button9" />
<Button
android:id="@+id/button11"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="查看已绑定蓝牙"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/guideline2"
app:layout_constraintTop_toBottomOf="@+id/button9" />
<ListView
android:id="@+id/listview1"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView" />
<TextView
android:id="@+id/textView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="#00BCD4"
android:gravity="center"
android:text="蓝牙列表"
android:textSize="24sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button10" />
</androidx.constraintlayout.widget.ConstraintLayout>
蓝牙权限问题
安卓12对蓝牙权限做了改动,且需要动态获取权限
- 首先在app/src/main/AndroidManifest.xml中添加权限
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.btapp">
<!-- 先前的蓝牙权限需求-->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<!-- 安卓12新增的蓝牙权限-->
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
<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" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.BTapp">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
- 在MainActivity.java中实现动态申请权限,在执行蓝牙相关函数时执行getPermission函数
public class MainActivity extends AppCompatActivity {
private static final int REQ_PERMISSION_CODE = 1;
// 蓝牙权限列表
public ArrayList<String> requestList = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
/**
* 动态申请权限
*/
public void getPermision(){
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.S){
requestList.add(Manifest.permission.BLUETOOTH_SCAN);
requestList.add(Manifest.permission.BLUETOOTH_ADVERTISE);
requestList.add(Manifest.permission.BLUETOOTH_CONNECT);
requestList.add(Manifest.permission.ACCESS_FINE_LOCATION);
requestList.add(Manifest.permission.ACCESS_COARSE_LOCATION);
requestList.add(Manifest.permission.BLUETOOTH);
}
if(requestList.size() != 0){
ActivityCompat.requestPermissions(this, requestList.toArray(new String[0]), REQ_PERMISSION_CODE);
}
}
}
实机测试
实机测试时若提示安装包异常,则在项目的gradle.properties后添加
android.injected.testOnly=false
功能实现
- 在app/src/main/java/com.example.btapp内新建蓝牙控制器类BlueToothController.java
- 获取蓝牙适配器类BlueToothAdpter
public class BlueToothController {
// 成员变量
private BluetoothAdapter mAdapter;
/**
* 构造函数
*/
public BlueToothController(){
// 获取本地的蓝牙适配器
mAdapter = BluetoothAdapter.getDefaultAdapter();
}
- 查看是否支持蓝牙
public boolean isSupportBlueTooth(){
// 若支持蓝牙,则本地适配器不为null
if(mAdapter != null){
return true;
}
// 否则不支持
else{
return false;
}
}
在 MainActivity.java中绑定对应功能
package com.example.btapp;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private static final int REQ_PERMISSION_CODE = 1;
// 实例化蓝牙控制器
public BlueToothController btController = new BlueToothController();
// 实例化蓝牙控制器
public BlueToothController btController = new BlueToothController();
// 弹窗
private Toast mToast;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 通过id获取“是否支持蓝牙”按钮
Button button_1 = (Button) findViewById(R.id.button3);
// 绑定按钮点击事件处理函数
button_1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// 获取蓝牙权限
getPermision();
// 判断是否支持蓝牙
boolean ret = btController.isSupportBlueTooth();
// 弹窗显示结果
showToast("是否支持蓝牙" + ret);
}
});
}
/**
* 动态申请权限
*/
public void getPermision(){
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.S){
requestList.add(Manifest.permission.BLUETOOTH_SCAN);
requestList.add(Manifest.permission.BLUETOOTH_ADVERTISE);
requestList.add(Manifest.permission.BLUETOOTH_CONNECT);
requestList.add(Manifest.permission.ACCESS_FINE_LOCATION);
requestList.add(Manifest.permission.ACCESS_COARSE_LOCATION);
requestList.add(Manifest.permission.BLUETOOTH);
}
if(requestList.size() != 0){
ActivityCompat.requestPermissions(this, requestList.toArray(new String[0]), REQ_PERMISSION_CODE);
}
}
/**
* Toast弹窗显示
* @param text 显示文本
*/
public void showToast(String text){
// 若Toast控件未初始化
if( mToast == null){
// 则初始化
mToast = Toast.makeText(this, text, Toast.LENGTH_SHORT);
}
// 否则
else{
// 修改显示文本
mToast.setText(text);
}
// 显示
mToast.show();
}
}
- 判断当前蓝牙状态
/**
* 判断当前蓝牙状态
* @return true为打开,false为关闭
*/
public boolean getBlueToothStatus(){
// 断言,为了避免mAdapter为null导致return出错
assert (mAdapter != null);
// 蓝牙状态
return mAdapter.isEnabled();
}
绑定功能
// 通过id获取“当前蓝牙状态”按钮
Button button_2 = (Button) findViewById(R.id.button4);
// 绑定按钮点击事件处理函数
button_2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// 获取蓝牙权限
getPermision();
// 判断当前蓝牙状态
boolean ret = btController.getBlueToothStatus();
// 弹窗显示结果
showToast("当前蓝牙状态:" + ret);
}
});
- 打开蓝牙
/**
* 打开蓝牙
*/
public boolean turnOnBlueTooth(Activity activity, int requestCode){
if(!mAdapter.isEnabled()) {
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
activity.startActivityForResult(intent, requestCode);
}
}
在MainActivity.java中绑定函数
// 蓝牙状态改变广播
private BroadcastReceiver receiver = new BroadcastReceiver(){
@Override
public void onReceive(Context context, Intent intent) {
int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1);
switch (state){
case BluetoothAdapter.STATE_OFF:
showToast("STATE_OFF");
break;
case BluetoothAdapter.STATE_ON:
showToast("STATE_ON");
break;
case BluetoothAdapter.STATE_TURNING_OFF:
showToast("STATE_TURNING_OFF");
break;
case BluetoothAdapter.STATE_TURNING_ON:
showToast("STATE_TURNING_ON");
break;
default:
showToast("UnKnow STATE");
unregisterReceiver(this);
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
// 注册广播
registerReceiver(receiver, filter);
// 通过id获取"打开蓝牙"按钮
Button button_3 = (Button) findViewById(R.id.button7);
// 绑定按钮点击事件处理函数
button_3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
turnOnbt();
}
});
}
/**
* 打开蓝牙
*/
public void turnONbt(){
// 获取蓝牙权限
getPermision();
// 打开蓝牙
btController.turnOnBlueTooth(this, 1);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data){
super.onActivityResult(requestCode, resultCode, data);
if(resultCode == RESULT_OK){
showToast("open successfully");
}
else{
showToast("open unsuccessfully");
}
}
- 关闭蓝牙
/**
* 关闭蓝牙
* @return
*/
public void turnOffBlueTooth() {
if(mAdapter.isEnabled()) {
mAdapter.disable();
}
}
在MainActivity,java绑定功能
// 通过id获取”关闭蓝牙“按钮
Button button_4 = (Button) findViewById(R.id.button8);
// 绑定按钮点击事件处理函数
button_4.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// 获取蓝牙权限
getPermision();
// 关闭蓝牙
btController.turnOffBlueTooth();
}
});
- 使蓝牙可见
/**
* 打开蓝牙可见性
* @param context
*/
public void enableVisibly(Context context){
Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
context.startActivity(discoverableIntent);
}
在MainActivity.java中绑定函数
@Override
protected void onCreate(Bundle savedInstanceState) {
// 通过id获取”使蓝牙可见“按钮
Button button_5 = (Button) findViewById(R.id.button9);
// 绑定按钮点击事件处理函数
button_5.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// 蓝牙可见
BTVisible();
}
});
}
/**
* 设置蓝牙可见
*/
public void BTVisible(){
// 获取蓝牙权限
getPermision();
// 打开蓝牙可见
btController.enableVisibly(this);
}
- 搜索可见蓝牙
/**
* 查找设备
*/
public boolean findDevice(){
assert(mAdapter!=null);
if(mAdapter.isDiscovering()){
mAdapter.cancelDiscovery();
return false;
}else {
return mAdapter.startDiscovery();
}
}
在MainActivity.java绑定函数
// 搜索蓝牙广播
private IntentFilter foundFilter;
//
public ArrayAdapter adapter1;
//定义一个列表,存蓝牙设备的地址。
public ArrayList<String> arrayList=new ArrayList<>();
//定义一个列表,存蓝牙设备地址,用于显示。
public ArrayList<String> deviceName=new ArrayList<>();
// 搜索蓝牙广播
private final BroadcastReceiver bluetoothReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
String s;
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (device.getBondState() == 12) {
s = "设备名:" + device.getName() + "\n" + "设备地址:" + device.getAddress() + "\n" + "连接状态:已配对" + "\n";
}
else if (device.getBondState() == 10){
s = "设备名:" + device.getName() + "\n" + "设备地址:" + device.getAddress() + "\n" + "连接状态:未配对" +"\n";
}else{
s = "设备名:" + device.getName() + "\n" + "设备地址:" + device.getAddress() + "\n" + "连接状态:未知" + "\n";
}
if (!deviceName.contains(s)) {
deviceName.add(s);//将搜索到的蓝牙名称和地址添加到列表。
arrayList.add(device.getAddress());//将搜索到的蓝牙地址添加到列表。
adapter1.notifyDataSetChanged();//更新
}
}else if(BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)){
showToast("搜索结束");
unregisterReceiver(this);
}else if(BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)){
showToast("开始搜索");
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
// 通过id获取”搜索可见蓝牙“按钮
Button button_6 = (Button) findViewById(R.id.button10);
// 绑定按钮点击事件处理函数
button_6.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// 获取蓝牙权限
getPermision();
// 注册广播
registerReceiver(bluetoothReceiver, foundFilter);
// 初始化各列表
arrayList.clear();
deviceName.clear();
adapter1.notifyDataSetChanged();
// 开始搜索
btController.findDevice();
}
});
//搜索蓝牙的广播
foundFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
foundFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
foundFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
// 获取ListView组件
ListView listView = (ListView) findViewById(R.id.listview1);
// 实例化ArrayAdapter对象
adapter1 = new ArrayAdapter(this, android.R.layout.simple_expandable_list_item_1, deviceName);
// 添加到ListView组件中
listView.setAdapter(adapter1);
}
- 查看已绑定的设备
/**
* 获取绑定设备
* @return
*/
public ArrayList<BluetoothDevice> getBondedDeviceList(){
return new ArrayList<BluetoothDevice>(mAdapter.getBondedDevices());
}
绑定功能
// 通过id获取”查看已绑定蓝牙“按钮
Button button_7 = (Button) findViewById(R.id.button11);
// 绑定按钮点击事件处理函数
button_7.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// 获取蓝牙权限
getPermision();
// 初始化各列表
deviceName.clear();
arrayList.clear();
adapter1.notifyDataSetChanged();
// 获取已绑定蓝牙
ArrayList<BluetoothDevice> bluetoothDevices = btController.getBondedDeviceList();
// 更新列表
for (int i = 0; i < bluetoothDevices.size(); i++){
BluetoothDevice device = bluetoothDevices.get(i);
arrayList.add(device.getAddress());
if (device.getBondState() == 12) {
deviceName.add("设备名:" + device.getName() + "\n" + "设备地址:" + device.getAddress() + "\n" + "连接状态:已配对" + "\n");
}
else if (device.getBondState() == 10){
deviceName.add("设备名:" + device.getName() + "\n" + "设备地址:" + device.getAddress() + "\n" + "连接状态:未配对" +"\n");
}else{
deviceName.add("设备名:" + device.getName() + "\n" + "设备地址:" + device.getAddress() + "\n" + "连接状态:未知" + "\n");
}
adapter1.notifyDataSetChanged();
}
}
});
ListView的列表点击事件
- 添加点击监听
@Override
protected void onCreate(Bundle savedInstanceState) {
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
CharSequence content = ((TextView) view).getText();
String con = content.toString();
String[] conArray = con.split("\n");
String rightStr = conArray[1].substring(5, conArray[1].length());
BluetoothDevice device = btController.find_device(rightStr);
if (device.getBondState() == 10) {
btController.cancelSearch();
String s = "设备名:" + device.getName() + "\n" + "设备地址:" + device.getAddress() + "\n" + "连接状态:未配对" + "\n";
deviceName.remove(s);
device.createBond();
s = "设备名:" + device.getName() + "\n" + "设备地址:" + device.getAddress() + "\n" + "连接状态:已配对" + "\n";
deviceName.add(s);
adapter1.notifyDataSetChanged();
showToast("配对:" + device.getName());
}
else{
btController.cancelSearch();
String s2 = "设备名:" + device.getName() + "\n" + "设备地址:" + device.getAddress() + "\n" + "连接状态:已配对" + "\n";
if(deviceName.contains(s2)) {
unpairDevice(device);
deviceName.remove(s2);
s2 = "设备名:" + device.getName() + "\n" + "设备地址:" + device.getAddress() + "\n" + "连接状态:未配对" +"\n";
deviceName.add(s2);
adapter1.notifyDataSetChanged();
showToast("取消配对:" + device.getName());
}
}
}
});
}
/**
* 尝试取消配对
* @param device
*/
private void unpairDevice(BluetoothDevice device) {
try {
Method m = device.getClass()
.getMethod("removeBond", (Class[]) null);
m.invoke(device, (Object[]) null);
} catch (Exception e) {
e.printStackTrace();
}
}
MainActivity.java
package com.example.btapp;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import java.lang.reflect.Method;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
// 常量
private static final int REQ_PERMISSION_CODE = 1;
// 实例化蓝牙控制器
public BlueToothController btController = new BlueToothController();
// 弹窗
private Toast mToast;
// 蓝牙权限列表
public ArrayList<String> requestList = new ArrayList<>();
// 搜索蓝牙广播
private IntentFilter foundFilter;
//
public ArrayAdapter adapter1;
//定义一个列表,存蓝牙设备的地址。
public ArrayList<String> arrayList=new ArrayList<>();
//定义一个列表,存蓝牙设备地址,用于显示。
public ArrayList<String> deviceName=new ArrayList<>();
// 蓝牙状态改变广播
private BroadcastReceiver receiver = new BroadcastReceiver(){
@Override
public void onReceive(Context context, Intent intent) {
int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1);
switch (state){
case BluetoothAdapter.STATE_OFF:
showToast("STATE_OFF");
break;
case BluetoothAdapter.STATE_ON:
showToast("STATE_ON");
break;
case BluetoothAdapter.STATE_TURNING_OFF:
showToast("STATE_TURNING_OFF");
break;
case BluetoothAdapter.STATE_TURNING_ON:
showToast("STATE_TURNING_ON");
break;
default:
showToast("UnKnow STATE");
unregisterReceiver(this);
break;
}
}
};
// 搜索蓝牙广播
private final BroadcastReceiver bluetoothReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
String s;
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (device.getBondState() == 12) {
s = "设备名:" + device.getName() + "\n" + "设备地址:" + device.getAddress() + "\n" + "连接状态:已配对" + "\n";
}
else if (device.getBondState() == 10){
s = "设备名:" + device.getName() + "\n" + "设备地址:" + device.getAddress() + "\n" + "连接状态:未配对" +"\n";
}else{
s = "设备名:" + device.getName() + "\n" + "设备地址:" + device.getAddress() + "\n" + "连接状态:未知" + "\n";
}
if (!deviceName.contains(s)) {
deviceName.add(s);//将搜索到的蓝牙名称和地址添加到列表。
arrayList.add(device.getAddress());//将搜索到的蓝牙地址添加到列表。
adapter1.notifyDataSetChanged();//更新
}
}else if(BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)){
showToast("搜索结束");
unregisterReceiver(this);
}else if(BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)){
showToast("开始搜索");
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 蓝牙状态改变信息
IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
// 注册广播
registerReceiver(receiver, filter);
//搜索蓝牙的广播
foundFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
foundFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
foundFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
// 获取ListView组件
ListView listView = (ListView) findViewById(R.id.listview1);
// 实例化ArrayAdapter对象
adapter1 = new ArrayAdapter(this, android.R.layout.simple_expandable_list_item_1, deviceName);
// 添加到ListView组件中
listView.setAdapter(adapter1);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
CharSequence content = ((TextView) view).getText();
String con = content.toString();
String[] conArray = con.split("\n");
String rightStr = conArray[1].substring(5, conArray[1].length());
BluetoothDevice device = btController.find_device(rightStr);
if (device.getBondState() == 10) {
btController.cancelSearch();
String s = "设备名:" + device.getName() + "\n" + "设备地址:" + device.getAddress() + "\n" + "连接状态:未配对" + "\n";
deviceName.remove(s);
device.createBond();
s = "设备名:" + device.getName() + "\n" + "设备地址:" + device.getAddress() + "\n" + "连接状态:已配对" + "\n";
deviceName.add(s);
adapter1.notifyDataSetChanged();
showToast("配对:" + device.getName());
}
else{
btController.cancelSearch();
String s2 = "设备名:" + device.getName() + "\n" + "设备地址:" + device.getAddress() + "\n" + "连接状态:已配对" + "\n";
if(deviceName.contains(s2)) {
unpairDevice(device);
deviceName.remove(s2);
s2 = "设备名:" + device.getName() + "\n" + "设备地址:" + device.getAddress() + "\n" + "连接状态:未配对" +"\n";
deviceName.add(s2);
adapter1.notifyDataSetChanged();
showToast("取消配对:" + device.getName());
}
}
}
});
// 通过id获取“是否支持蓝牙”按钮
Button button_1 = (Button) findViewById(R.id.button3);
// 绑定按钮点击事件处理函数
button_1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// 获取蓝牙权限
getPermision();
// 判断是否支持蓝牙
boolean ret = btController.isSupportBlueTooth();
// 弹窗显示结果
showToast("是否支持蓝牙" + ret);
}
});
// 通过id获取“当前蓝牙状态”按钮
Button button_2 = (Button) findViewById(R.id.button4);
// 绑定按钮点击事件处理函数
button_2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// 获取蓝牙权限
getPermision();
// 判断当前蓝牙状态
boolean ret = btController.getBlueToothStatus();
// 弹窗显示结果
showToast("当前蓝牙状态:" + ret);
}
});
// 通过id获取"打开蓝牙"按钮
Button button_3 = (Button) findViewById(R.id.button7);
// 绑定按钮点击事件处理函数
button_3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
turnONbt();
}
});
// 通过id获取”关闭蓝牙“按钮
Button button_4 = (Button) findViewById(R.id.button8);
// 绑定按钮点击事件处理函数
button_4.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// 获取蓝牙权限
getPermision();
// 关闭蓝牙
btController.turnOffBlueTooth();
}
});
// 通过id获取”使蓝牙可见“按钮
Button button_5 = (Button) findViewById(R.id.button9);
// 绑定按钮点击事件处理函数
button_5.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// 蓝牙可见
BTVisible();
}
});
// 通过id获取”搜索可见蓝牙“按钮
Button button_6 = (Button) findViewById(R.id.button10);
// 绑定按钮点击事件处理函数
button_6.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// 获取蓝牙权限
getPermision();
// 注册广播
registerReceiver(bluetoothReceiver, foundFilter);
// 初始化各列表
arrayList.clear();
deviceName.clear();
adapter1.notifyDataSetChanged();
// 开始搜索
btController.findDevice();
}
});
// 通过id获取”查看已绑定蓝牙“按钮
Button button_7 = (Button) findViewById(R.id.button11);
// 绑定按钮点击事件处理函数
button_7.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// 获取蓝牙权限
getPermision();
// 初始化各列表
deviceName.clear();
arrayList.clear();
adapter1.notifyDataSetChanged();
// 获取已绑定蓝牙
ArrayList<BluetoothDevice> bluetoothDevices = btController.getBondedDeviceList();
// 更新列表
for (int i = 0; i < bluetoothDevices.size(); i++){
BluetoothDevice device = bluetoothDevices.get(i);
arrayList.add(device.getAddress());
if (device.getBondState() == 12) {
deviceName.add("设备名:" + device.getName() + "\n" + "设备地址:" + device.getAddress() + "\n" + "连接状态:已配对" + "\n");
}
else if (device.getBondState() == 10){
deviceName.add("设备名:" + device.getName() + "\n" + "设备地址:" + device.getAddress() + "\n" + "连接状态:未配对" +"\n");
}else{
deviceName.add("设备名:" + device.getName() + "\n" + "设备地址:" + device.getAddress() + "\n" + "连接状态:未知" + "\n");
}
adapter1.notifyDataSetChanged();
}
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data){
super.onActivityResult(requestCode, resultCode, data);
if(resultCode == RESULT_OK){
showToast("open successfully");
}
else{
showToast("open unsuccessfully");
}
}
/**
* 尝试取消配对
* @param device
*/
private void unpairDevice(BluetoothDevice device) {
try {
Method m = device.getClass()
.getMethod("removeBond", (Class[]) null);
m.invoke(device, (Object[]) null);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 打开蓝牙
*/
public void turnONbt(){
// 获取蓝牙权限
getPermision();
// 打开蓝牙
btController.turnOnBlueTooth(this,1);
}
/**
* 设置蓝牙可见
*/
public void BTVisible(){
// 获取蓝牙权限
getPermision();
// 打开蓝牙可见
btController.enableVisibly(this);
}
/**
* 动态申请权限
*/
public void getPermision(){
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.S){
requestList.add(Manifest.permission.BLUETOOTH_SCAN);
requestList.add(Manifest.permission.BLUETOOTH_ADVERTISE);
requestList.add(Manifest.permission.BLUETOOTH_CONNECT);
requestList.add(Manifest.permission.ACCESS_FINE_LOCATION);
requestList.add(Manifest.permission.ACCESS_COARSE_LOCATION);
requestList.add(Manifest.permission.BLUETOOTH);
}
if(requestList.size() != 0){
ActivityCompat.requestPermissions(this, requestList.toArray(new String[0]), REQ_PERMISSION_CODE);
}
}
/**
* Toast弹窗显示
* @param text 显示文本
*/
public void showToast(String text){
// 若Toast控件未初始化
if( mToast == null){
// 则初始化
mToast = Toast.makeText(this, text, Toast.LENGTH_SHORT);
}
// 否则
else{
// 修改显示文本
mToast.setText(text);
}
// 显示
mToast.show();
}
}
list_item.xml
<?xml version="1.0" encoding="UTF-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="18sp"
>
</TextView>
BlueToothController.java
package com.example.btapp;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;
import java.lang.reflect.Method;
import java.util.ArrayList;
/**
* 蓝牙适配器
*/
public class BlueToothController {
// 成员变量
private BluetoothSocket btSocket;
private BluetoothAdapter mAdapter;
private String TAG = "";
public static final int RECV_VIEW = 0;
public static final int NOTICE_VIEW = 1;
/**
* 构造函数
*/
public BlueToothController(){
// 获取本地的蓝牙适配器
mAdapter = BluetoothAdapter.getDefaultAdapter();
}
/**
* 是否支持蓝牙
* @return true支持,false不支持
*/
public boolean isSupportBlueTooth(){
// 若支持蓝牙,则本地适配器不为null
if(mAdapter != null){
return true;
}
// 否则不支持
else{
return false;
}
}
/**
* 判断当前蓝牙状态
* @return true为打开,false为关闭
*/
public boolean getBlueToothStatus(){
// 断言?为了避免mAdapter为null导致return出错
assert (mAdapter != null);
// 蓝牙状态
return mAdapter.isEnabled();
}
/**
* 打开蓝牙
*/
public void turnOnBlueTooth(Activity activity, int requestCode){
if(!mAdapter.isEnabled()) {
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
activity.startActivityForResult(intent, requestCode);
}
}
/**
* 关闭蓝牙
* @return
*/
public void turnOffBlueTooth() {
if(mAdapter.isEnabled()) {
mAdapter.disable();
}
}
/**
* 打开蓝牙可见性
* @param context
*/
public void enableVisibly(Context context){
Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
context.startActivity(discoverableIntent);
}
/**
* 查找设备
*/
public boolean findDevice(){
assert(mAdapter!=null);
if(mAdapter.isDiscovering()){
mAdapter.cancelDiscovery();
return false;
}else {
return mAdapter.startDiscovery();
}
}
/**
* 获取绑定设备
* @return
*/
public ArrayList<BluetoothDevice> getBondedDeviceList(){
return new ArrayList<BluetoothDevice>(mAdapter.getBondedDevices());
}
/**
* 根据蓝牙地址找到相应的设备
* @param addr
* @return
*/
public BluetoothDevice find_device(String addr){
return mAdapter.getRemoteDevice(addr);
}
/**
* 连接设备
*/
public void connect_init(BluetoothDevice device){
mAdapter.cancelDiscovery();
try{
Method clientMethod = device.getClass().getMethod("createRfcommSocketToServiceRecord", new Class[]{int.class});
btSocket = (BluetoothSocket)clientMethod.invoke(device, 1);
connect(btSocket);
}catch (Exception e){
e.printStackTrace();
}
}
public void connect(final BluetoothSocket btSocket){
try {
if (btSocket.isConnected()){
Log.e(TAG, "connect: 已经连接");
return;
}
btSocket.connect();
if (btSocket.isConnected()){
Log.e(TAG, "connect: 连接成功");
}else{
Log.e(TAG, "connect: 连接失败");
btSocket.close();
}
}catch (Exception e){e.printStackTrace();}
}
public void cancelSearch() {
mAdapter.cancelDiscovery();
}
}