Android Studio开发学习(八、蓝牙设备连接)

引言

        上篇我们介绍了整体蓝牙模块的基本写法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 应用:

扫描二维码关注公众号,回复: 17499788 查看本文章

        可以根据使用自行增加该方法。下面我会给出相关蓝牙实现代码,我是采用了蓝牙收发硬件温湿度数值,最后数据显示大家根据自身项目对应写即可,这里就不给出了(下面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>

猜你喜欢

转载自blog.csdn.net/m0_74325713/article/details/140928920