Android 普通蓝牙学习笔记

来源:互联网 发布:阿里云香港服务器 翻墙 编辑:程序博客网 时间:2024/06/05 07:25

Android 普通蓝牙学习

虽然做开发有一段时间了,但是有关蓝牙方面一直接触的不多,正好目前有一个关于蓝牙开发的需求,虽然是用到的BLE和普通蓝牙有些区别,但是既然学习了就顺便把普通蓝牙也学习一下,也为了以后自己少走些弯路,先将这些学习笔记学习下来。官方文档

本例的源码已经上传,查看源码

需要的权限

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

蓝牙有关的所有的类如下:

android蓝牙的类

普通蓝牙用到的几个关键的类:

  • BluetoothAdapter 蓝牙适配器

    Represents the local device Bluetooth adapter. The BluetoothAdapter lets you perform fundamental Bluetooth tasks, such as initiate device discovery,

    query a list of bonded (paired) devices, instantiate a BluetoothDevice using a known MAC address, and create a BluetoothServerSocket to listen for

    connection requests from other devices, and start a scan for Bluetooth LE devices.

    根据官方文档的说明,BluetoothAdapter可以执行基本的蓝牙任务,比如启动设备发现,查询已配对的蓝牙列表,使用已知的地址实例化一个BluetoothDevice,创建一个BluetoothServerSocket

    监听链接请求等。

  • BluetoothDevice 蓝牙设备

    Represents a remote Bluetooth device. A BluetoothDevice lets you create a connection with the respective device or query information about it,

    such as the name, address, class, and bonding state.

    代表一个远程蓝牙设备。BluetoothDevice允许创建一个连接的设备或查询相关信息,如名称、地址、阶级和配对的状态。

  • BluetoothSocket

    The interface for Bluetooth Sockets is similar to that of TCP sockets: Socket and ServerSocket.

    顾名思义蓝牙连接

  • BluetoothServerSocket

    The interface for Bluetooth Sockets is similar to that of TCP sockets: Socket and ServerSocket.

    蓝牙服务链接,后两者都是和TCP端口类似的一个socket

BluetoothAdapter

首先打开蓝牙开始搜索等;

主要用到的几个方法:

  • getDefaultAdapter() 获取一个适配器对象

  • getName() 获取本地蓝牙名称

  • getAddress() 获取本地蓝牙的地址

  • enable() 打开本地蓝牙(低版本中不会提示用户)

  • isEnabled() 判断蓝牙是否已经打开

  • disable() 关闭本地蓝牙

  • startDiscovery() 开始搜索(发现)

  • cancelDiscovery() 取消设备搜索(发现)

  • isDiscovering() 返回当前是否是在搜索设备

  • listenUsingRfcommWithServiceRecord(String name, UUID uuid) 创建一个安全的BluetoothServerSocket

打开蓝牙

        bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();        //打开蓝牙 方法一        if (!bluetoothAdapter.isEnabled()) {            bluetoothAdapter.enable();        }        //方法二 推荐        Intent enabler = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);        startActivityForResult(enabler, REQUEST_ENABLE);

开始搜索设备

调用startDiscovery()开始搜索设备,但是仅仅调用此方法是没有任何作用的,startDiscovery()是异步调用,立即返回,需要注册一个广播接收者

来接受搜索的结果。整个搜索过程持续12秒。

//注册IntentFilter intentFilter = new IntentFilter();intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);intentFilter.addAction(BluetoothDevice.ACTION_FOUND);registerReceiver(mReceiver, intentFilter);//广播接收者BroadcastReceiver mReceiver = new BroadcastReceiver() {        public void onReceive(Context context, Intent intent) {            String action = intent.getAction();            //找到设备            if (BluetoothDevice.ACTION_FOUND.equals(action)) {                BluetoothDevice device = intent                        .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);                Log.d("MainActivity", "搜索到设备");                //在列表中显示搜索出的设备                adapter.add("name : " + device.getName() + "\n address : " + device.getAddress());                bluetoothDevices.add(device);            }            //搜索完成            else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED                    .equals(action)) {                Log.d("MainActivity", "搜索结束");            } else if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) {                Log.d("MainActivity", "开始搜索");            }        }    };

连接设备

建立连接,Android sdk支持的蓝牙连接是通过BluetoothSocket建立连接,服务器端(BluetoothServerSocket)和客户端(BluetoothSocket)需指定同样的UUID,才能建立连接,因为建立连接的方法会阻塞线程,所以服务器端和客户端都应启动新线程连接。

UUID的格式如下:

String uuid = "a60f35f0-b93a-11de-8a39-08002009c666";

建立服务器端代码如下:

首先建立服务器,获取BluetoothServerSocket对象,通过BluetoothAdapterlistenUsingInsecureRfcommWithServiceRecord(String name, UUID uuid)方法和listenUsingRfcommWithServiceRecord(String name, UUID uuid)方法,其中前者是不安全的链接,后者是安全的链接。

然后使用BluetoothServerSocket.accept()方法接受客户端连接,当连接成功返回一个BluetoothSocket对象。

    private class ServiceThread extends Thread {        @Override        public void run() {            BluetoothServerSocket serverSocket = null;            try {                serverSocket = bluetoothAdapter.listenUsingRfcommWithServiceRecord("my_test_lianjie", UUID.fromString(uuid));                Log.d("ServiceThread", "建立服务器成功");            } catch (IOException e) {                e.printStackTrace();                Log.d("ServiceThread", "建立服务器失败");            }            try {                socket = serverSocket.accept();                Log.d("ServiceThread", "客户端连接成功");                new ReadThread().start();            } catch (IOException e) {                e.printStackTrace();                Log.d("ServiceThread", "客户端连接失败");            }        }    }

建立客户端链接代码如下:

这里需要注意的是要对首先检测设备是否进行了配对,只有首先进行配对才能进行连接。蓝牙配对是通过反射的方法调用BluetoothDevice.creMethod()方法。

建立连接首先获取BluetoothSocket对象,调用BluetoothDevicecreateInsecureRfcommSocketToServiceRecord(UUID uuid)或者createRfcommSocketToServiceRecord(UUID uuid)方法,其中前者是不安全的链接,后者是安全的链接。

然后调用BluetoothSocket.connect()方法进行连接。

    private class ConnectThread extends Thread {        BluetoothDevice device;        public ConnectThread(BluetoothDevice device) {            this.device = device;        }        @Override        public void run() {            try {                socket = device.createRfcommSocketToServiceRecord(UUID.fromString(uuid));            } catch (IOException e) {                e.printStackTrace();            }            if (device.getBondState() == BluetoothDevice.BOND_BONDED) { //已配对设备 直接进行链接                connectSocket();            } else if (device.getBondState() == BluetoothDevice.BOND_NONE) { //未配对设备 先配对再链接                Method creMethod = null;                try {                    creMethod = BluetoothDevice.class.getMethod("createBond");                } catch (NoSuchMethodException e) {                    e.printStackTrace();                }                Log.e("TAG", "开始配对");                try {                    creMethod.invoke(device);                } catch (IllegalAccessException e) {                    e.printStackTrace();                    Log.e("TAG", "配对失败");                } catch (InvocationTargetException e) {                    e.printStackTrace();                }            }        }        private void connectSocket() {            try {                socket.connect();                Log.e("TAG", "连接成功");                new ReadThread().start();            } catch (IOException e) {                e.printStackTrace();                Log.e("TAG", "连接失败");            }        }        public void cancel() {            try {                socket.close();                socket = null;            } catch (Exception e) {                e.printStackTrace();            } finally {            }        }    }

注意

客户端建立连接的方式有很多种,这里使用的是先获得一个socket然后再检查是否需要进行配对,再建立连接。

还可以通过反射的方法,通过端口进行连接。

进行通讯

蓝牙通讯是通过流的方式进行的:

OutputStream outS = socket.getOutputStream();InputStream inS = socket.getInputStream();

发送的方法如:

                OutputStream os = null;                try {                    os = socket.getOutputStream();                } catch (IOException e) {                    e.printStackTrace();                }                try {                    os.write("你好".getBytes());                    Log.d("MainActivity", "发送成功");                } catch (IOException e) {                    e.printStackTrace();                    Log.d("MainActivity", "发送失败");                }

接受的方法如:

    private class ReadThread extends Thread {        @Override        public void run() {            byte[] buffer = new byte[1024];            int bytes;            InputStream mmInStream = null;            try {                mmInStream = socket.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);                        Log.d("ReadThread", s);                    }                } catch (IOException e) {                    try {                        mmInStream.close();                    } catch (IOException e1) {                        // TODO Auto-generated catch block                        e1.printStackTrace();                    }                    break;                }            }        }    }

至此,普通蓝牙的基本发现、连接、通讯功能就完成了,当然还有许多需要完善的地方。

写的可能有些混乱,不足之处,还请指正,不喜忽喷。

0 0
原创粉丝点击