Android基础——实现安卓蓝牙2.0模块的通信功能

实现安卓蓝牙2.0模块的通信功能


事先说明:

安卓蓝牙2.0的开发和BLE4.0的开发完全是不一样的,不过很多设备都采用双模蓝牙,所以掌握2.0也是很有必要的

安卓蓝牙需要手动申请定位权限,可参考我的博客点击打开链接


蓝牙连接过程:

1、查询用户是否开启蓝牙。

2、搜索附近的可用的蓝牙。

3、进行蓝牙配对。

4、进行蓝牙连接。

5、获取输入流和输出流。

6、发送消息。


蓝牙开发思路:

蓝牙从连接到通信整个过程都是通过接收和发送广播进行的,下面是蓝牙进行特定操作时发出来的广播图,晒上我自己画的美图



蓝牙广播内容:

ACTION_STATE_CHANGED   当你蓝牙开启或者关闭的时候发送
ACTION_FOUND  当你匹配到附近蓝牙设备时发送
ACTION_DISCOVERY_STARTED  当你开始搜索附近蓝牙设备时发送
ACTION_DISCOVERY_FINISHED  当你结束搜索附近蓝牙设备时发送
ACTION_BOND_STATE_CHANGED  当你蓝牙设备匹配状态发生变化时发送

实现需要的权限:

由于安卓4.x以上的版本使用蓝牙,需要开启定位权限才能搜索到附近的蓝牙设备

    <uses-permission android:name="android.permission.BLUETOOTH"/>
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />


这里使用俩手机,实现蓝牙之间的通信,下面是Demo的效果图



(一)服务端


实现思路:

1、拿到本地蓝牙设备。

2、蓝牙之间的通讯需要一个唯一识别UUID来匹配正确的设备,使用UUID获取蓝牙的通讯Socket。

3、开启获取数据的线程

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    BluetoothSocket BTSocket;
    BluetoothAdapter BTAdapter;
    Button bt_start;
    TextView tv_msg;
    StringBuilder sb;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        bt_start = (Button) findViewById(R.id.bt_start);
        tv_msg = (TextView) findViewById(R.id.tv_msg);
        bt_start.setOnClickListener(this);
        sb = new StringBuilder();

        show("服务端:检查BT");
        checkBT(this);
    }

    /**
     * 检查蓝牙
     */
    public void checkBT(Context context) {
        BTAdapter = BluetoothAdapter.getDefaultAdapter();
        if (BTAdapter != null) {
            if (!BTAdapter.isEnabled()) {
                Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                // 设置蓝牙可见性,最多300秒
                intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
                context.startActivity(intent);
            }
        } else {
            show("本地设备驱动异常!");
        }
    }

    /**
     * UI文本输出
     *
     * @param msg
     */
    public void show(String msg) {
        sb.append(msg + "\n");
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                tv_msg.setText(sb.toString());
            }
        });
    }

    @Override
    public void onClick(View v) {
        //开启服务器
        ServerThread startServerThread = new ServerThread();
        startServerThread.start();
    }

    /**
     * 开启服务器
     */
    private class ServerThread extends Thread {
        public void run() {
            try {
                BluetoothServerSocket mserverSocket = BTAdapter.listenUsingRfcommWithServiceRecord("btspp",
                        UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
                show("服务端:等待连接");

                BTSocket = mserverSocket.accept();
                show("服务端:连接成功");

                readThread mreadThread = new readThread();
                mreadThread.start();
                show("服务端:启动接受数据");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 读取数据
     */
    private class readThread extends Thread {
        public void run() {
            byte[] buffer = new byte[1024];
            int bytes;
            InputStream mmInStream = null;
            try {
                mmInStream = BTSocket.getInputStream();
                show("服务端:获得输入流");
            } catch (IOException e1) {
                e1.printStackTrace();
            }
            while (true) {
                try {
                    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);
                        show("服务端:读取数据了~~" + s);
                    }
                } catch (IOException e) {
                    try {
                        mmInStream.close();
                    } catch (IOException e1) {
                        e1.printStackTrace();
                    }
                    break;
                }
            }
        }
    }
}

(二)客户端


实现思路:

1、检查是否开启蓝牙。

2、注册一系列蓝牙的广播。

3、由于蓝牙每经过一个阶段都会发送一个广播,根据广播来实现对应的方法。

4、蓝牙配对->蓝牙连接->发送消息(UUID必须相同)

其实客户端的操作就是上面那张思路图,根据里面的步骤进行就可以完成


① 检查蓝牙

    /**
     * 检查蓝牙
     */
    public void checkBT(Context context) {
        BTAdapter = BluetoothAdapter.getDefaultAdapter();
        if (BTAdapter != null) {
            if (!BTAdapter.isEnabled()) {
                Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                // 设置蓝牙可见性,最多300秒
                intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
                context.startActivity(intent);
            }
        } else {
            show("本地设备驱动异常!");
        }
    }


② 注册广播

    /**
     * 注册广播
     */
    public void registerBTReceiver() {
        // 设置广播信息过滤
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
        intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
        intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
        intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
        intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
        // 注册广播接收器,接收并处理搜索结果
        registerReceiver(BTReceive, intentFilter);
    }


③ 搜索附近设备

BTAdapter.startDiscovery();


④ 获取搜索到设备的通知

    /**
     * 广播接收者
     */
    private BroadcastReceiver BTReceive = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            //打印Action,调试使用
            show(action);
            //找到设备通知  ACTION_FOUND,设备已配对通知  ACTION_BOND_STATE_CHANGED
            if (BluetoothDevice.ACTION_FOUND.equals(action)) {
                device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                show("客户端:找到的BT名:" + device.getName());
                // 如果查找到的设备符合,添加到UI上
                addBT();
            } else if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) {
                // 获取蓝牙设备的连接状态
                int connectState = device.getBondState();
                // 已配对
                if (connectState == BluetoothDevice.BOND_BONDED) {
                    try {
                        show("客户端:开始连接:");
                        clientThread clientConnectThread = new clientThread();
                        clientConnectThread.start();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    };

    /**
     * 添加找到的BT
     */
    private void addBT() {
        Button bt = new Button(MainActivity.this);
        bt.setTag(device.getName());
        bt.setText(device.getName());
        ly_device.addView(bt);
        //处理选中BT设备,进行绑定
        bt.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                bondBT((String) v.getTag());
            }
        });
    }

    /**
     * 绑定蓝牙
     *
     * @param deviceName
     */
    private void bondBT(String deviceName) {
        if (device.getName().equalsIgnoreCase(deviceName)) {
            show("客户端:配对蓝牙开始");
            // 搜索蓝牙设备的过程占用资源比较多,一旦找到需要连接的设备后需要及时关闭搜索
            BTAdapter.cancelDiscovery();
            // 获取蓝牙设备的连接状态
            int connectState = device.getBondState();

            switch (connectState) {
                // 未配对
                case BluetoothDevice.BOND_NONE:
                    show("客户端:开始配对");
                    try {
                        Method createBondMethod = BluetoothDevice.class.getMethod("createBond");
                        createBondMethod.invoke(device);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    break;
                // 已配对
                case BluetoothDevice.BOND_BONDED:
                    try {
                        show("客户端:开始连接:");
                        clientThread clientConnectThread = new clientThread();
                        clientConnectThread.start();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    break;
            }
        }
    }


⑤ 进行连接

    /**
     * 开启客户端
     */
    private class clientThread extends Thread {
        public void run() {
            try {
                //创建一个Socket连接:只需要服务器在注册时的UUID号
                BTSocket = device.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
                //连接
                show("客户端:开始连接...");
                BTSocket.connect();
                show("客户端:连接成功");
                //启动接受数据
                show("客户端:启动接受数据");
                readThread mreadThread = new readThread();
                mreadThread.start();
            } catch (IOException e) {
                show("客户端:连接服务端异常!断开连接重新试一试");
                e.printStackTrace();
            }
        }
    }


⑥ 读取数据

    /**
     * 读取数据
     */
    private class readThread extends Thread {
        public void run() {
            byte[] buffer = new byte[1024];
            int bytes;
            InputStream is = null;
            try {
                is = BTSocket.getInputStream();
                show("客户端:获得输入流");
            } catch (IOException e1) {
                e1.printStackTrace();
            }
            while (true) {
                try {
                    if ((bytes = is.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);
                        show("客户端:读取数据了" + s);
                    }
                } catch (IOException e) {
                    try {
                        is.close();
                    } catch (IOException e1) {
                        e1.printStackTrace();
                    }
                    break;
                }
            }
        }
    }


⑦ 发送数据

    /**
     * 发送数据
     */
    public void sendMessage() {
        if (BTSocket == null) {
            Toast.makeText(this, "没有连接", Toast.LENGTH_SHORT).show();
            return;
        }
        try {
            OutputStream os = BTSocket.getOutputStream();
            os.write("我爱你dahsid132456@#%¥*".getBytes());
            os.flush();
            show("客户端:发送信息成功");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


蓝牙2.0比较简单,大家可以通过源码进行理解
源码下载:工具是Android Studio2.1 (建议使用Import Project导入)


评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

许英俊潇洒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值