前:本文为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、声明权限,注意可能需要的运行时权限

                                


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

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


四、效果图

android 传统蓝牙开发 (附示例源码)_第1张图片       android 传统蓝牙开发 (附示例源码)_第2张图片       


更多相关文章

  1. Android ----蓝牙架构
  2. Android 设置默认桌面,默认应用,辅助功能,电池优化,设备管理器,
  3. Ubuntu下使用adb和USB连接的方式进行android设备调试
  4. 【阿里聚安全·安全周刊】500万台Android设备受感染|YouTube封杀
  5. android如何打开系统wifi、蓝牙等设置界面
  6. Android USB Gadget复合设备驱动(打印机)测试方法
  7. Android蓝牙开发
  8. 使用User Agent分辨出Android设备类型的安全做法

随机推荐

  1. Android(安卓)gdb调试
  2. 选项卡使用方法二(Android学习随笔十三)
  3. ndk下使用sqlite
  4. android MTP 过滤指定的文件格式
  5. Android中TextView中内容不换行的解决方
  6. Android(安卓)Handler 消息机制原理解析
  7. 简单实现Android顶部工具栏和底部工具栏(
  8. 【Android热修复与插件化 三】ClassLoade
  9. 介绍一个Android开源项目:GifView——Andr
  10. android 5.0多用户支持