android 传统蓝牙开发 (附示例源码)

版权声明:属QiaoJim原创,请尊重这小小的成果 https://blog.csdn.net/Qiao_Jim/article/details/73008695

前:本文为QiaoJim原创,转载请附原文链接,谢谢合作!

http://blog.csdn.net/qiao_jim/article/details/73008695


----------------------------------------------------------------------------------


最近学习了android传统蓝牙,自己整理了一下思路,然后写了一个BluetoothStudy小测试程序,来运用所理解的android传统蓝牙开发技术,写下

一些心得和思路,供其他android热爱者参考,也方便日后回顾。

博客如有错误之处,欢迎留言之处,十分感谢。博客最后会附上源码,可下载借鉴。


一、整体思路和对应相关方法

1、获得BluetoothAdapter:BluetoothAdapter.getDefaultAdapter();

2、打开蓝牙:询问用户打开(推荐)或直接bluetoothAdapter.enable();

3、查询已绑定设备,发现新设备:bluetoothAdapter.getBondedDevices();bluetoothAdapter.startDiscovery();

4.1、服务端,一直监听请求,当该端主动发出请求时,关闭该端的监听,角色转为客户端:

bluetoothDevice.createRfcommSocketToServiceRecord(UUID);

4.2、客户端,点击目标设备,配对连接:

bluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME, UUID);

5、通过BluetoothSocket通信:IO流读写



二、开发详解

1、声明权限,注意可能需要的运行时权限

        <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" />


android 6.0以上设备发现新蓝牙时,需加入运行时权限,否则无法监听ACTION_FOUND广播

        if (Build.VERSION.SDK_INT >= 6.0) {
            ActivityCompat.requestPermissions(getActivity(), 
                new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                             Params.MY_PERMISSION_REQUEST_CONSTANT);
        }

        public void onRequestPermissionsResult(int requestCode, String permissions[],
                                               int[] grantResults) {
           switch (requestCode) {
              case Params.MY_PERMISSION_REQUEST_CONSTANT: {
                  if (grantResults.length > 0 
                          && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                       // 运行时权限已授权
                   }
                  return;
               }
           }
        }


2、打开蓝牙,推荐用对话框形式让用户打开

       bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

       // 蓝牙未打开,询问打开
       if (!bluetoothAdapter.isEnabled()) {
            Intent turnOnBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(turnOnBtIntent, Params.REQUEST_ENABLE_BT);
        }

        @Override
        public void onActivityResult(int requestCode, int resultCode, Intent data) {
            switch (requestCode) {
                case Params.REQUEST_ENABLE_BT: {
                    //用户打开蓝牙
                    if (resultCode == RESULT_OK) {
                        //显示已绑定蓝牙设备
                        showBondDevice();
                    }
                    break;
                }
                case Params.REQUEST_ENABLE_VISIBILITY: {
                    //设置该蓝牙设备可被其他设备发现,600是设置的设备可发现时间(博客最后有简单说明)
                    if (resultCode == 600) {
                        toast("蓝牙已设置可见");
                    } else if (resultCode == RESULT_CANCELED) {
                        toast("蓝牙设置可见失败,请重试");
                    }
                    break;
                }
            }
        }



3、通过BluetoothAdapter获取已绑定的蓝牙设备

        private void showBondDevice() {
            deviceList.clear();
            // 所有已绑定设备,一个Set集合
            Set<BluetoothDevice> tmp = bluetoothAdapter.getBondedDevices();
            for (BluetoothDevice d : tmp) {
                deviceList.add(d);
            }
            //更新列表
            listAdapter.notifyDataSetChanged();
        }



4、发现蓝牙设备,发现一个设备,会发送一条ACTION_FOUND广播,注册广播接收器,可获得对应蓝牙设备信息

        bluetoothAdapter.startDiscovery();

        intentFilter = new IntentFilter();
        btReceiver = new MyBtReceiver();
        //监听 搜索开始,搜索结束,发现新设备 3条广播
        intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
        intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
        intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
        getActivity().registerReceiver(btReceiver, intentFilter);

        //广播接收器
        private class MyBtReceiver extends BroadcastReceiver {
            @Override
            public void onReceive(Context context, Intent intent) {
                String action = intent.getAction();
                if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) {
                    toast("开始搜索 ...");
                } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
                    toast("搜索结束");
                } else if (BluetoothDevice.ACTION_FOUND.equals(action)) {
                    //获得发现的设备
                    BluetoothDevice device = 
                        intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                    if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
                        deviceList.add(device);
                        listAdapter.notifyDataSetChanged();
                    }
                }
            }
        }


5、设备连接,服务器端开启线程一直等待连接,客户端点击某个目标设备,关闭服务器线程监听,并开启线程,发出连接请求。 

注意:客户端连接前,一定cancelDiscovery()

        // 蓝牙已开启
        if (bluetoothAdapter.isEnabled()) {
            showBondDevice();
            // 默认开启服务线程监听
            if (serverThread != null) {
                serverThread.cancel();
            }
            serverThread = new ServerThread(bluetoothAdapter, uiHandler);
            new Thread(serverThread).start();
        }

        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, 
                                    int position, long id) {
                // 关闭服务器监听
                if (serverThread != null) {
                    serverThread.cancel();
                    serverThread=null;
                }
                BluetoothDevice device = deviceList.get(position);
                // 开启客户端线程,连接点击的远程设备
                clientThread = new ClientThread(bluetoothAdapter, device, uiHandler);
                new Thread(clientThread).start();

                // 通知 ui 连接的服务器端设备
                Message message = new Message();
                message.what = Params.MSG_CONNECT_TO_SERVER;
                message.obj = device;
                uiHandler.sendMessage(message);
            }
        });



6、建立BluetoothSocket连接以后,使用IO流数据传输,服务器和客户端读写数据类似,贴一部分代码供参考

        public void writeData(String dataSend) {
            if (serverThread != null) {
                serverThread.write(dataSend);
            } else if (clientThread != null) {
                clientThread.write(dataSend);
            }
        }
        //写数据
        public void write(String data){
            try {
                out.write(data.getBytes("utf-8"));            
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        new Thread(new Runnable() {
                @Override
                public void run() {
                    byte[] buffer = new byte[1024];
                    int len;
                    String content;
                    try {
                        //读数据
                        while ((len=in.read(buffer)) != -1) {
                            content=new String(buffer, 0, len);
                            Message message = new Message();
                            message.what = Params.MSG_CLIENT_REV_NEW;
                            message.obj = content;
                            //更新 ui
                            uiHandler.sendMessage(message);
                        }

                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }).start();



7、其他说明

(1)新设备绑定,bluetoothDevice.createBond()

(2)设置设备可被发现的时间:

Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);  
enableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 600);  
startActivityForResult(enableIntent, Params.REQUEST_ENABLE_VISIBILITY); 


(3)服务器获得远端设备,bluetoothSocket.getRemoteDevice() 

(4)通过MAC获得蓝牙设备,bluetoothAdapter.getRemoteDevice(String address) 

(5)关闭蓝牙,bluetoothAdapter.disable()



三、源码示例下载

附上源码github地址,有帮助的话别忘了加 ★ 噢。 
https://github.com/QiaoJim/BluetoothStudy

感谢阅读,如有错误,请留言。如果觉得博文不错,请点赞支持。 


四、效果图

              


展开阅读全文

没有更多推荐了,返回首页