Android BLE(2)---蓝牙学习

Android 普通蓝牙学习

需要的权限
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH" />


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

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

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对象,通过BluetoothAdapter的listenUsingInsecureRfcommWithServiceRecord(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对象,调用BluetoothDevice的createInsecureRfcommSocketToServiceRecord(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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值