引言
上篇我们介绍了整体蓝牙模块的基本写法Android Studio开发学习(七、蓝牙模块java)-CSDN博客,当然我们检测到蓝牙设备肯定会连接蓝牙,那么如何实现蓝牙连接呢,这篇博客将实现这个功能。
设备连接
connectDevice 方法用于在后台线程中尝试连接到指定的蓝牙设备,并在连接成功或失败时显示相应的提示信息。成功时显示“连接成功”的提示并跳转到新 Activity,失败时显示“连接失败”的提示,使用唯一的UUID标识蓝牙服务,并确保UI更新在主线程中完成。
连接成功:
连接失败:
弹窗提示
我们在上篇博客基础上增加部分代码,使用 AlertDialog 来显示连接状态。先来介绍一下AlertDialog :
AlertDialog 是 Android 中用于显示警告信息、提示用户操作或要求用户确认操作的对话框组件。它可以显示标题、消息、按钮,甚至是自定义视图。AlertDialog 是通过 AlertDialog.Builder 类来构建和显示的。下面是一个显示简单的消息对话框例子:
new AlertDialog.Builder(context)
.setTitle("标题")
.setMessage("消息对话框")
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// 用户点击确定按钮后的操作
}
})
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// 用户点击取消按钮后的操作
}
})
.show();
蓝牙模块中的 AlertDialog 应用:

可以根据使用自行增加该方法。下面我会给出相关蓝牙实现代码,我是采用了蓝牙收发硬件温湿度数值,最后数据显示大家根据自身项目对应写即可,这里就不给出了(下面BlueToothActivity函数中蓝牙连接成功跳转HYGRO_data.class大家根据自身项目或手头传感器编写java和xml即可)
完整代码
BlueToothActivity.java
package com.example.myapplication.Slide_BlueTooth;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
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 androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import com.example.myapplication.R;
import java.util.ArrayList;
public class BlueTooth extends AppCompatActivity {
// 实例化蓝牙控制器
public BlueToothController btController = new BlueToothController();
// 蓝牙权限列表
public ArrayList<String> requestList = new ArrayList<>();
// 弹窗
private Toast mToast;
public ArrayAdapter adapter1;
//定义一个列表,存蓝牙设备地址,用于显示。
public ArrayList<String> device = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bluetooth);
// 获取ListView组件
ListView listView = (ListView) findViewById(R.id.listView1);
// 实例化ArrayAdapter对象
adapter1 = new ArrayAdapter(this, android.R.layout.simple_expandable_list_item_1, device);
// 添加到ListView组件中
listView.setAdapter(adapter1);
//ListView的列表点击事件
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@SuppressLint("MissingPermission")
@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 device1 = btController.find_device(rightStr);
if (device1.getBondState() == 12){
String S = "设备名:" + device1.getName() + "\n" + "设备地址:" + device1.getAddress();
if (device.contains(S)){
Intent intent = new Intent(BlueTooth.this, HYGRO_data.class);
Bundle bundle = new Bundle();
bundle.putString("deviceAddr",device1.getAddress());
intent.putExtras(bundle);
startActivity(intent);
finish();
}
}
}
});
Button open_Bt = (Button) findViewById(R.id.openBT);
open_Bt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
turnOnBt();
}
});
Button close_Bt = (Button) findViewById(R.id.closeBT);
close_Bt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
getPermision();
// 关闭蓝牙
btController.turnOffBlueTooth();
}
});
Button state_Bt = (Button) findViewById(R.id.stateBT);
state_Bt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
getPermision();
// 判断当前蓝牙状态
boolean ret = btController.getBlueToothStatus();
// 弹窗显示结果
showToast("当前蓝牙状态:" + ret);
}
});
Button update_list = (Button) findViewById(R.id.updateList);
update_list.setOnClickListener(new View.OnClickListener() {
@SuppressLint("MissingPermission")
@Override
public void onClick(View view) {
getPermision();
//初始化列表
device.clear();
adapter1.notifyDataSetChanged();
//获取已绑定蓝牙列表
ArrayList<BluetoothDevice> bluetoothDevices = btController.getBondedDeviceList();
//更新列表、
for (int i=0;i<bluetoothDevices.size();i++){
BluetoothDevice device1 = bluetoothDevices.get(i);
if (device1.getBondState() == 12){
device.add("设备名:" + device1.getName() + "\n" + "设备地址:" + device1.getAddress());
}else {
device.add("设备名:" + device1.getName() + "\n" + "设备地址:" + device1.getAddress() + "\n" + "连接状态:未知" + "\n");
}
adapter1.notifyDataSetChanged();
}
}
});
}
public static class BlueToothController{
private BluetoothAdapter BtAdapter;
/**
* 构造函数
*/
public BlueToothController() {
// 获取本地的蓝牙适配器
BtAdapter = BluetoothAdapter.getDefaultAdapter();
}
@SuppressLint("MissingPermission")
//打开蓝牙
public void turnOnBuleTooth(Activity activity, int requestCode){
if (!BtAdapter.isEnabled()){
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
activity.startActivityForResult(intent,requestCode);
}
}
@SuppressLint("MissingPermission")
//关闭蓝牙
public void turnOffBlueTooth(){
if (BtAdapter.isEnabled()) {
BtAdapter.disable();
}
}
//获取蓝牙状态
public boolean getBlueToothStatus() {
// 断言,避免BtAdapter为bull导致return出错
assert (BtAdapter != null);
// 蓝牙状态
return BtAdapter.isEnabled();
}
@SuppressLint("MissingPermission")
//获取设备信息
public ArrayList<BluetoothDevice> getBondedDeviceList() {
return new ArrayList<BluetoothDevice>(BtAdapter.getBondedDevices());
}
/**
* 根据蓝牙地址找到相应的设备
*
* @param addr
* @return
*/
public BluetoothDevice find_device(String addr) {
return BtAdapter.getRemoteDevice(addr);
}
}
public void turnOnBt(){
getPermision();
//打开蓝牙
btController.turnOnBuleTooth(this,1);
}
/**
* 动态申请权限
*/
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]), 1);
}
}
/**
* 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();
}}
activity_bluetooth.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"
android:background="@drawable/background1"
tools:context=".BlueTooth.BlueToothActivity">
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="136dp"
android:orientation="vertical"
app:layout_constraintBottom_toTopOf="@+id/listView1"
app:layout_constraintGuide_end="206dp"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/openBT"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="打开蓝牙"
app:layout_constraintBottom_toTopOf="@+id/stateBT"
app:layout_constraintEnd_toStartOf="@id/guideline1"
app:layout_constraintHorizontal_bias="0.567"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/closeBT"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="关闭蓝牙"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.473"
app:layout_constraintStart_toEndOf="@id/guideline1"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/stateBT"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="蓝牙状态"
app:layout_constraintEnd_toStartOf="@id/guideline1"
app:layout_constraintHorizontal_bias="0.567"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/openBT" />
<Button
android:id="@+id/updateList"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="更新列表"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.473"
app:layout_constraintStart_toEndOf="@id/guideline1"
app:layout_constraintTop_toBottomOf="@id/closeBT" />
<TextView
android:id="@+id/textView1"
android:layout_width="307dp"
android:layout_height="46dp"
android:layout_marginTop="92dp"
android:background="#2196F3"
android:gravity="center"
android:text="蓝牙列表"
android:textSize="24dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.495"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/stateBT" />
<ListView
android:id="@+id/listView1"
android:layout_width="332dp"
android:layout_height="350dp"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.491"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/textView1"
app:layout_constraintVertical_bias="0.316" />
</androidx.constraintlayout.widget.ConstraintLayout>
BT_data_RW .java
package com.example.myapplication.Slide_BlueTooth;
import static android.content.ContentValues.TAG;
import android.Manifest;
import android.annotation.SuppressLint;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import com.example.myapplication.R;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.UUID;
public class BT_data_RW extends AppCompatActivity {
//获取权限
private ArrayList<String> requestList = new ArrayList<>();
// 弹窗
private Toast mToast;
// 文字输入框
public EditText editText;
// listview控件
public ListView listView;
// 蓝牙服务
private BluetoothSocket bluetoothSocket;
// 消息列表
public ArrayList<String> msglist = new ArrayList<>();
// ArrayAdapter
public ArrayAdapter adapter1;
// 读取数据线程
public readThread readthread = new readThread();
// 实例化BTclient
private BTclient bTclient = new BTclient();
// 实例化蓝牙适配器类
public BlueTooth.BlueToothController mController = new BlueTooth.BlueToothController();
// 活动间消息传递
public Handler mHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bt_data_rw);
// 根据ID获取listview和editText
listView = (ListView) findViewById(R.id.read_list);
editText = (EditText) findViewById(R.id.editTEXT);
// 实例化ArrayAdapter
adapter1 = new ArrayAdapter(this, android.R.layout.simple_expandable_list_item_1, msglist);
// 设置listview
listView.setAdapter(adapter1);
// 获取intent
Intent intent = getIntent();
// 获取intent传来的数据
Bundle bundle = intent.getExtras();
// 连接服务
bTclient.connectDevice(mController.find_device(bundle.getString("deviceAddr")));
// 服务线程开始
bTclient.start();
// 实例化Handler
mHandler = new Handler(){
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
switch (msg.what){
case 1:
String s = msg.obj.toString();
msglist.add("接收数据:" + s);
adapter1.notifyDataSetChanged();
Log.i(TAG,"接收数据:" + s);
}
}
};
}
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]), 1);
}
}
public void showToast(String text){
if( mToast == null){
mToast = Toast.makeText(this, text, Toast.LENGTH_SHORT);
}
else{
mToast.setText(text);
}
mToast.show();
}
private class BTclient extends Thread{
@SuppressLint("MissingPermission")
private void connectDevice(BluetoothDevice device){
try {
getPermision();
bluetoothSocket = device.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
bluetoothSocket.connect();
readthread.start();
showToast("蓝牙连接成功");
} catch (IOException e) {
e.printStackTrace();
showToast("蓝牙连接失败");
}
}
}
public void send_msg(View view) {
String s = editText.getText().toString();
if (s.length() != 0){
sendMessageHandle(s);
msglist.add("发送数据:" + s + "\n");
adapter1.notifyDataSetChanged();
}
}
//发送数据
public void sendMessageHandle(String msg) {
getPermision();
if (bluetoothSocket == null)
{
showToast("没有连接");
return;
}
try {
OutputStream os = bluetoothSocket.getOutputStream();
os.write(msg.getBytes()); //发送出去的值为:msg
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private class readThread extends Thread {
private static final String TAG = "";
public void run() {
super.run();
byte[] buffer = new byte[1024];
int bytes;
InputStream mmInStream = null;
try {
mmInStream = bluetoothSocket.getInputStream();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
while (true) {
try {
// Read from the InputStream
if( (bytes = mmInStream.read(buffer)) > 0 )
{
byte[] buf_data = new byte[bytes];
for(int i=0; i<bytes; i++)
{
buf_data[i] = buffer[i];
}
String s = new String(buf_data);//接收的值inputstream 为 s
Log.e(TAG, "run: " + s);
Message message = Message.obtain();
message.what = 1;
message.obj = s;
mHandler.sendMessage(message);
if(s.equalsIgnoreCase("o")){ //o表示opend!
showToast("open");
}
else if(s.equalsIgnoreCase("c")){ //c表示closed!
showToast("closed");
}
}
} catch (IOException e) {
try {
mmInStream.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
break;
}
}
}
}
}
bt_data_rw.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=".Slide_BlueTooth.BT_data_RW">
<TextView
android:id="@+id/read_Text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="消息列表"
android:background="#03A9F4"
android:gravity="center"
android:textSize="24dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
<ListView
android:id="@+id/read_list"
android:layout_width="296dp"
android:layout_height="420dp"
app:layout_constraintBottom_toTopOf="@id/write_Text"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.495"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/read_Text" />
<TextView
android:id="@+id/write_Text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="发送消息"
android:background="#00BCD4"
android:gravity="center"
android:textSize="24dp"
app:layout_constraintTop_toBottomOf="@id/read_list"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toTopOf="@id/editTEXT"/>
<EditText
android:id="@+id/editTEXT"
android:layout_width="0dp"
android:layout_height="49dp"
android:ems="10"
android:inputType="textPersonName"
app:layout_constraintTop_toBottomOf="@id/write_Text"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/write_button"/>
<Button
android:id="@+id/write_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="发送"
app:layout_constraintTop_toBottomOf="@id/write_Text"
app:layout_constraintStart_toEndOf="@id/editTEXT"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:onClick="send_msg"/>
</androidx.constraintlayout.widget.ConstraintLayout>