Android 蓝牙

Posted HJ0101

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 蓝牙相关的知识,希望对你有一定的参考价值。

首先需要添加权限

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

Android中的蓝牙是通过BluetoothAdapter来操作的,

//先获取BlueToothAdapter的实例
BluetoothAdapter blueToothAdapter=BluetoothAdapter.getDefaultAdapter();

打开蓝牙,断开蓝牙

//判断蓝牙是否打开
        if (!bluetoothAdapter.isEnabled()) {
            //第一种 调用enable()直接打开
            bluetoothAdapter.enable();
            //断开蓝牙
            bluetoothAdapter.disable();
            Toast.makeText(this, "蓝牙功能已开启", Toast.LENGTH_SHORT).show();

        }

 

设置蓝牙可见性,能被周围设备扫描到

if (bluetoothAdapter.getScanMode() !=
                BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
            Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
            //设置最多可见时间为300秒
            discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
            startActivity(discoverableIntent);
        }

蓝牙的搜索功能

  blueToothAdapter.startDiscovery();

当搜索到设备后系统会以广播的形式接收,自定义一个广播

class BluetoothReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {

            if (intent.getAction().equals(BluetoothDevice.ACTION_FOUND)) {
                Log.e(getPackageName(), "找到新设备了");
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            }
        }
    }

注册广播

//注册广播
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
registerReceiver(new BluetoothReceiver(), intentFilter);

注意 ,如果你的代码将运行在(Build.VERSION.SDK_INT >= 23)的设备上,需要获取设备的定位权限才能进行蓝牙搜索功能,并在代码中动态的申请权限.

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

动态申请权限

private void requestPermission() {
        if (Build.VERSION.SDK_INT >= 23) {
            int checkAccessFinePermission = ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
            if (checkAccessFinePermission != PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                        REQUEST_PERMISSION_ACCESS_LOCATION);
                Log.e(getPackageName(), "没有权限,请求权限");
                return;
            }
            Log.e(getPackageName(), "已有定位权限");
            //这里可以开始搜索操作
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        switch (requestCode) {
            case REQUEST_PERMISSION_ACCESS_LOCATION: {
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                    Log.e(getPackageName(), "开启权限permission granted!");
                    //这里可以开始搜索操作
                } else {
                    Log.e(getPackageName(), "没有定位权限,请先开启!");
                }
            }
        }
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

蓝牙的配对,调用BluetoothDevice的createBondde()方法,如果我们想监听配对的这个过程,那么我们可以为广播接收器再注册一个action。

                        try {
                            Method method = null;
                            method = BluetoothDevice.class.getMethod("createBond");
                            Log.e(getPackageName(), "开始配对");
                            method.invoke(device);
                            flag = true;
                        } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
                            Log.e(getPackageName(), "配对失败");
                            e.printStackTrace();
                        }

如果想监听配对过程,可以通过广播的形式,在注册一个action

//绑定状态发生变化
intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);

广播接收器中

if (intent.getAction().equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED)) {
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                switch (device.getBondState()) {
                    case BluetoothDevice.BOND_NONE:
                        Log.e(getPackageName(), "取消配对");
                        break;
                    case BluetoothDevice.BOND_BONDING:
                        Log.e(getPackageName(), "配对中");
                        break;
                    case BluetoothDevice.BOND_BONDED:
                        Log.e(getPackageName(), "配对成功");
                        break;
                }
}

配对设配发送数据

发送数据分为客户端和服务端,通过Socket来进行消息交互

服务端

new Thread(new Runnable() {
            @Override
            public void run() {
                InputStream is = null;
                try {
                    BluetoothServerSocket serverSocket = blueToothAdapter.listenUsingRfcommWithServiceRecord("serverSocket", uuid);
                    mHandler.sendEmptyMessage(startService);
                    BluetoothSocket accept = serverSocket.accept();
                    is = accept.getInputStream();

                    byte[] bytes = new byte[1024];
                    int length = is.read(bytes);

                    Message msg = new Message();
                    msg.what = getMessageOk;
                    msg.obj = new String(bytes, 0, length);
                    mHandler.sendMessage(msg);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();

客户端

new Thread(new Runnable() {
            @Override
            public void run() {
                OutputStream os = null;
                try {
                    BluetoothSocket socket = strArr.get(i).createRfcommSocketToServiceRecord(uuid);
                    socket.connect();
                    os = socket.getOutputStream();
                    os.write("testMessage".getBytes());
                    os.flush();
                    mHandler.sendEmptyMessage(sendOver);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();

可以看到无论是服务端还是客户端,都需要新起一个子线程来操作。那么服务端和客户端是怎么识别对方的呢,那么就需要用到UUID了,只有当服务端和客户端的UUID相同的时候才能够建立连接。

private static final UUID uuid = UUID.fromString(Constants.CONNECTTION_UUID);
public static final String CONNECTTION_UUID = "fa87c0d0-afac-11de-8a39-0800200c9a66";

 

以上是关于Android 蓝牙的主要内容,如果未能解决你的问题,请参考以下文章

android怎么来判断蓝牙开、关的状态?求代码

Qt低功耗蓝牙系列三(低功耗蓝牙客户端的程序设计纯Android代码)

Qt低功耗蓝牙系列三(低功耗蓝牙客户端的程序设计纯Android代码)

Android蓝牙系统框架和代码架构

Android4.42-Settings源代码分析之蓝牙模块Bluetooth总体实现(总)

Android 蓝牙扫描代码