文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

android蓝牙简单开发的方法是什么

2023-06-21 23:47

关注

本篇内容介绍了“android蓝牙简单开发的方法是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

概述

前段时间学习了一些蓝牙开发的知识,记录一下Android中蓝牙的简单开发。下面是最重要的两个类。

BluetoothAdapter : 蓝牙适配器,通过getDefaultAdapter ()去获取一个实例,如果设备不支持蓝牙的话,返回的是一个null对象,通过它,可以打开、关闭蓝牙,扫描设备、向指定设备创建socket通道…

BluetoothDevice : 代表一个设备对象,可以通过它获取设备的名字、地址、类型等,也可以创建匹配,建立socket通道等等。

1、权限申请

<uses-permission android:name="android.permission.BLUETOOTH"/> 使用蓝牙所需要的权限<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/> 使用扫描和设置蓝牙的权限(申明这一个权限必须申明上面一个权限)

Android6以上版本,扫描其他蓝牙还需要位置权限

// Android 9 以下版本<user-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> // Android 9 以上<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

2、打开蓝牙

mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();// 如果设备不支持蓝牙if (mBluetoothAdapter == null){    return;}// 设备支持蓝牙功能,调用startActivityForResult去启动蓝牙if (!mBluetoothAdapter.isEnabled()){    startBlueTooth.launch(new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE));}

打开蓝牙功能是通过startActivity去启动的,但是startActivity这个函数已经过期了,所以我使用官方推荐的Activity Result替代它

ActivityResultLauncher<Intent> startBlueTooth = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(),            new ActivityResultCallback<ActivityResult>() {                @Override                public void onActivityResult(ActivityResult result) {                    if (result==null){                        Toast.makeText(BlueToothActivity.this, "open failed", Toast.LENGTH_SHORT).show();                    }else {                        if (result.getResultCode() == RESULT_CANCELED){                            Toast.makeText(BlueToothActivity.this,"用户取消",Toast.LENGTH_SHORT);                        }                    }                }            });

3、接收蓝牙状态的改变

通过广播去接收蓝牙状态的改变

class BluetoothStateChangeReceiver extends BroadcastReceiver{    public int DEFAULT_VALUE_BLUETOOTH = 1000;    @Override    public void onReceive(Context context, Intent intent) {        String action = intent.getAction();        if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)){            int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,DEFAULT_VALUE_BLUETOOTH);            switch(state){                case BluetoothAdapter.STATE_ON:                    Log.d(TAG, "onReceive: open");                    break;                case BluetoothAdapter.STATE_OFF:                    Log.d(TAG, "onReceive: off");                    break;                case BluetoothAdapter.STATE_TURNING_ON :                    Log.d(TAG, "onReceive: 正在打开");                    break;                case BluetoothAdapter.STATE_TURNING_OFF:                    Log.d(TAG, "onReceive: 正在关闭");                    break;            }        }    }}

别忘了广播的注册和解注册

IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);stateReceiver = new BluetoothStateChangeReceiver() ;registerReceiver(stateReceiver,filter);

4、扫描其他的设备

同样通过广播接收,action是BluetoothDevice.ACTION_FOUND

class MyReceiver extends BroadcastReceiver{        @Override        public void onReceive(Context context, Intent intent) {            String action = intent.getAction();            if (BluetoothDevice.ACTION_FOUND.equals(action)) {                // 从intent对象中获取蓝牙设备的信息                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);                // 当发现新设备不存在于配对列表中时添加                if (device.getBondState() != BluetoothDevice.BOND_BONDED) {                    blueNames.add(device.getName()+"\t"+device.getAddress());                }                blueAdpater.notifyDataSetChanged();                Log.d(TAG, "onReceive: " + device.getName());            }        }    }

动态注册广播

IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);registerReceiver(mReceiver,filter);

开启扫描

mBluetoothAdapter.startDiscovery();

5、蓝牙配对

public class BondReceiver extends BroadcastReceiver{        @Override        public void onReceive(Context context, Intent intent) {            if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(intent.getAction())){                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);                switch(device.getBondState()){                    case BluetoothDevice.BOND_BONDED:                        Log.d(TAG, "onReceive: 配对完成");                        break;                    case BluetoothDevice.BOND_BONDING:                        Log.d(TAG, "onReceive: 正在配对");                        break;                    case BluetoothDevice.BOND_NONE:                        Log.d(TAG, "onReceive: 取消配对");                        break;                }            }        }    }

6、获取已经配对的设备

已经配对的设备会被存储起来,通过BluetoothAdpater直接获取即可

Set<BluetoothDevice> paireDevices = mBluetoothAdapter.getBondedDevices();if (paireDevices.size()>0){                        for (BluetoothDevice pairedDevice : pairedDevices) {                        blueNames.add(pairedDevice.getName()+"  "+pairedDevice.getAddress());                        Log.d(TAG, "onClick: "+pairedDevice.getName());                    }}

7、连接设备

想要在两台设备之间创建连接,必须实现客户端和服务端机制,他们之间使用套接字机制进行连接,服务端开放服务器套接字,客户端通过MAC地址向服务端发起连接。客户端和服务端以不同的方式获得BluetoothSocket,当客户端和服务端在同一个RFCOMM通道上分别拥有已连接的BluetoothSocket时,将他们视为彼此已经连接,于是每台设备都获得输入和输出流式传输,并开始传输数据。

连接技术

一种实现技术是自动将每台设备准备为一个服务器,从而使每台设备开放一个服务套接字并侦听连接,在此情况下,任何一台设备都可以发起与另一台设备的连接并称为客户端。

服务器

设置服务器套接字并接受连接,步骤依次如下

调用listenUsingRfcommWithServiceRecord()获取一个BluetoothServerSocket, 该函数需要两个参数,第一个是服务器的名称,自己取一个即可,第二个是UUID,用来对信息做唯一性标识,我们可以从网上众多UUID生成器中随机的生成一个,然后使用UUID.fromString(String)初始化一个UUID。

通过accept()函数开始侦听连接请求

只有远程设备发送的连接请求中UUID与使用此套接字注册的UUID相匹配时服务器才会接受请求,accept函数会返回已连接的BluetoothSocket

连接成功后调用close()关闭BluetoothSocket

 private class AcceptThread extends Thread{        private final BluetoothServerSocket mmServerSocket;        private String mSocketType;        public AcceptThread(boolean secure){            BluetoothServerSocket tmp = null;            mSocketType = secure ? "secure" : "Insercure";            try{                if (secure){                    tmp = bluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME_SECURE,MY_UUID_SECURE);                }else{                    tmp = bluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME_INSECURE,MY_UUID_INSECURE);                }            } catch (IOException e) {                Log.e(TAG,"socket type"+ mSocketType + "listen() failed",e);            }            mmServerSocket = tmp;        }        @Override        public void run() {            Log.d(TAG, "Socket Type: " + mSocketType +                    "BEGIN mAcceptThread" + this);            setName("AcceptThread"+ mSocketType);            BluetoothSocket socket = null;            Log.d(TAG, "run: 开始监听");            while (true){                try{                    socket = mmServerSocket.accept();                    Log.d("acceptThread", "run: 连接成功");                    connected(socket,socket.getRemoteDevice(),mSocketType);                } catch (IOException e) {                    Log.e(TAG, "Socket Type: " + mSocketType + "accept() failed", e);                    break;                }            }            Log.i(TAG, "END mAcceptThread, socket Type: " + mSocketType);        }        public void cancel() {            Log.d(TAG, "Socket Type" + mSocketType + "cancel " + this);            try {                mmServerSocket.close();            } catch (IOException e) {                Log.e(TAG, "Socket Type" + mSocketType + "close() of server failed", e);            }        }    }

上面的secure和Insecure只是使用了不同的UUID而已。

客户端

远程设备开启监听后,我们就发起向此设备的连接,首先必须先获得远程设备的BluetoothDevice对象,然后获取BluetoothSocket发起连接。

基本步骤如下

使用BluetoothDevice通过调用createRfcommSocketToServiceRecord(UUID) 获取 BluetoothSocket

通过connect发起连接

private class ConnectThread extends Thread{        private final BluetoothSocket mmSocket;        private final BluetoothDevice mmDevice;        private String mSocketType;        public ConnectThread(BluetoothDevice device, boolean secure){            mmDevice = device;            BluetoothSocket tmp = null;            mSocketType = secure ? "Secure" : "Insecure";            try {                if (secure){                    tmp = device.createRfcommSocketToServiceRecord(MY_UUID_SECURE);                }else {                    tmp = device.createRfcommSocketToServiceRecord(MY_UUID_INSECURE);                }            } catch (IOException e) {                Log.e(TAG, "Socket Type: " + mSocketType + "create() failed", e);            }            mmSocket = tmp;        }        @Override        public void run() {            Log.i(TAG, "BEGIN mConnectThread SocketType:" + mSocketType);            setName("ConnectThred"+mSocketType);            // 总是取消发现,因为它会减慢连接            bluetoothAdapter.cancelDiscovery();            // connect            // Make a connection to the BluetoothSocket            try {                // This is a blocking call and will only return on a                // successful connection or an exception                mmSocket.connect();                Log.d(TAG, "run: socket连接成功");            } catch (IOException e) {                // Close the socket                Log.d(TAG, "run: 关闭socket");                try {                    mmSocket.close();                } catch (IOException e2) {                    Log.e(TAG, "unable to close() " + mSocketType +                            " socket during connection failure", e2);                }                return;            }            connected(mmSocket,mmDevice,mSocketType);        }        public void cancel(){            try{                mmSocket.close();            } catch (IOException e) {                Log.e(TAG, "close() of connect " + mSocketType + " socket failed", e);            }        }    }

发送数据

连接成功后,我们就可以通过socket发送数据了,客户端的Socket对象是BluetoothSocket, 服务端的socket是BluetoothServerSocket,特别注意不要混淆了。使用getInputStreamgetOutputStream分别获取通过套接字处理数据传输的InputStreamOutputStream。写数据比较简单,但是读数据就需要一个单独的线程一直监听才行。

private class ConnectedThread extends Thread{        private final BluetoothSocket mmSocket;        private InputStream mmInStream;        private OutputStream mmOutStream;        public ConnectedThread(BluetoothSocket socket, String socketType) throws IOException {            Log.d(TAG, "create ConnectedThread: " + socketType);            mmSocket = socket;            InputStream tmpIn = null;            OutputStream tmpOut = null;            try{                tmpIn = socket.getInputStream();                tmpOut = socket.getOutputStream();                if (socket != null){                    tmpOut.write(new String("hello").getBytes());                    Log.d(TAG, "ConnectedThread: socket不是null");                }            } catch (IOException e) {                Log.e(TAG,"temp socket not created", e);            }            mmInStream = tmpIn;            mmOutStream = tmpOut;            // mmOutStream.write(new String("hello").getBytes());        }        @RequiresApi(api = Build.VERSION_CODES.KITKAT)        @Override        public void run() {            Log.i(TAG, "BEGIN mConnectedThread");            byte[] buffer = new byte[1024];            int bytes;            while (true){                try{                    bytes = mmInStream.read(buffer);                    // send the bytes to the ui Activity                    String text = encodeByteToString(buffer,bytes);                    Log.d(TAG, "run: 收到消息:"+ text);                    chatItems.add(text);                    mHandler.sendMessage(mHandler.obtainMessage());                } catch (IOException e) {                    Log.d(TAG, "run: 没有收到消息");                    e.printStackTrace();                    break;                }            }        }        public String encodeByteToString(byte[] data,int length) {            byte[] temp = new byte[length];            for (int i = 0; i < length; i++) {                temp[i] = data[i];            }            try {                return new String(temp,"utf-8");            } catch (UnsupportedEncodingException e) {                return "";            }        }        public void write(byte[] buffer){            try{                mmOutStream.write(buffer);                // mHandler.obtainMessage(Constants.MESSAGE_WRITE,-1,-1,buffer).sendToTarget();            } catch (IOException e) {                e.printStackTrace();            }        }        public void cancel(){            try{                mmSocket.close();                Log.d(TAG, "cancel: connectedThread");            } catch (IOException e) {                Log.e(TAG, "close() of connect socket failed", e);            }        }    }

“android蓝牙简单开发的方法是什么”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯