连接到BLE设备

如何解决连接到BLE设备

因此,我制作了这个应用程序,在其中找到了所有带名称的BLE设备。但是我如何才能使其中一个特定字段(可单击并自动连接到该设备)成为可能,以便我可以开始从该设备进行写入/读取操作?

适配器

public class ListAdapter_BTLE_Devices extends ArrayAdapter<BTLE_Device> {

    Activity activity;
    int layoutResourceID;
    ArrayList<BTLE_Device> devices;

    public ListAdapter_BTLE_Devices(Activity activity,int resource,ArrayList<BTLE_Device> objects) {
        super(activity.getApplicationContext(),resource,objects);
        this.activity = activity;
        layoutResourceID = resource;
        devices = objects;
    }

    @Override
    public View getView(int position,View convertView,ViewGroup parent) {

        if (convertView == null) {
            LayoutInflater inflater =
                    (LayoutInflater) activity.getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = inflater.inflate(layoutResourceID,parent,false);
        }

        BTLE_Device device = devices.get(position);
        String name = device.getName();
        String address = device.getAddress();
        int rssi = device.getRSSI();

        TextView BLE_name = (TextView) convertView.findViewById(R.id.BLE_name);
        if (name != null && name.length() > 0) {
            BLE_name.setText(device.getName());
        }
        else {
            BLE_name.setText("No Name");
        }

        TextView BLE_rssi = (TextView) convertView.findViewById(R.id.BLE_rssi);
        BLE_rssi.setText("RSSI: " + Integer.toString(rssi));

        TextView BLE_macaddr = (TextView) convertView.findViewById(R.id.BLE_macaddr);
        if (address != null && address.length() > 0) {
            BLE_macaddr.setText("MAC-addr: "+device.getAddress());
        }
        else {
            BLE_macaddr.setText("No Address");
        }

        return convertView;
    }
}

编辑

我认为我现在可能已加入关贸总协定,所以我要做的是.. 首先,我从 Mainactivity 获取MAC地址,然后将其保存在一个intent中,并在onclick上启动了另一个活动。 我在这里做了 DeviceAddress = intent.getStringExtra(MainActivity.EXTRAS_BLE_ADDRESS);

BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(DeviceAddress);

device.connectGatt(this,false,mGattCallback);

当我调用connectGatt时,它会显示消息Log.d(TAG,"Connection State: 1");,这是正确的方法吗?


private BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
        @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt,int status,int newState) {
            Log.d(TAG,"Connection State Change: "+status+" -> "+connectionState(newState));
            if (status == BluetoothGatt.GATT_SUCCESS && newState == BluetoothProfile.STATE_CONNECTED) {
                /*
                 * Once successfully connected,we must next discover all the services on the
                 * device before we can read and write their characteristics.
                 */
                Log.d(TAG,"Connection State: 1");
                gatt.discoverServices();
            } else if (status == BluetoothGatt.GATT_SUCCESS && newState == BluetoothProfile.STATE_DISCONNECTED) {
                /*
                 * If at any point we disconnect,send a message to clear the weather values
                 * out of the UI
                 */
                Log.d(TAG,"Connection State: 2");
            } else if (status != BluetoothGatt.GATT_SUCCESS) {
                /*
                 * If there is a failure at any stage,simply disconnect
                 */
                Log.d(TAG,"Connection State: 3");
                gatt.disconnect();
            }
        }

解决方法

要首先连接到设备,您必须执行BLE扫描(如果您使用入门代码,则运行BLE扫描)并运行回调并将其添加到找到的设备列表中。

在其中添加过滤器,仅允许您要查找的设置设备。当BLE通告最多31个字节的数据包时,您应该在此处包含一些可以识别设备的数据,例如制造商ID或数据等。或者,如果您正在从事一个简单的项目,则可以通过编程的方式在设备地址中硬编码。

然后,从扫描中发现该设备时,您可以停止BLE扫描并自动将连接请求排队。这将要求发出GATT请求,因此,将授予您访问GATT服务以及设备上的特征的权限。

,

如果您在使用蓝牙LE时遇到问题,建议您使用我的蓝牙le库(不要重新发明轮子,我花了大约3/4个月的时间来制作该库,所以进行蓝牙le通信确实很棘手),它是开源的,因此您也可以看到具有实现示例的代码,我将您链接到github页面:https://github.com/niedev/BluetoothCommunicator

要在项目中使用库,必须将jitpack.io添加到根build.gradle(项目)中:

allprojects {
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}

然后将最新版本的BluetoothCommunicator添加到您的应用程序build.gradle

dependencies {
        implementation 'com.github.niedev:BluetoothCommunicator:1.0.6'
}

要使用此库,请将以下权限添加到清单中:

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

然后将android:largeHeap =“ true”添加到清单中的应用程序标签中:
例子

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

<application
    android:name="com.bluetooth.communicatorexample.Global"
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:largeHeap="true"
    android:theme="@style/Theme.Speech">
    <activity android:name="com.bluetooth.communicatorexample.MainActivity"
        android:configChanges="orientation|screenSize">

        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

一旦下载了libray并设置了清单,就需要创建一个蓝牙通信器对象,该对象可以处理蓝牙低能耗库的所有操作,如果要管理多个活动中的蓝牙连接,我建议您可以将该对象保存为扩展Application并创建getter的自定义类的属性,以便可以通过以下任何活动或服务访问bluetoothCommunicator:

((custom class name) getApplication()).getBluetoothCommunicator();

下一步是初始化bluetoothCommunicator,参数为:上下文,其他设备看到我们的名称(限制为18个字符,并且只能是BluetoothTools.getSupportedUTFCharacters(context)中列出的字符,因为字节数广告信标的限制)和策略(目前唯一受支持的策略是BluetoothCommunicator.STRATEGY_P2P_WITH_RECONNECTION)

bluetoothCommunicator = new BluetoothCommunicator(this,"device name",BluetoothCommunicator.STRATEGY_P2P_WITH_RECONNECTION);

然后添加蓝牙通讯器回调,该回调将侦听蓝牙通讯器的所有事件:

bluetoothCommunicator.addCallback(new BluetoothCommunicator.Callback() {
    @Override
    public void onBluetoothLeNotSupported() {
        super.onBluetoothLeNotSupported();
        
        Notify that bluetooth low energy is not compatible with this device
    }
   
    @Override
    public void onAdvertiseStarted() {
        super.onAdvertiseStarted();

        Notify that advertise has started,if you want to do something after the start of advertising do it here,because
        after startAdvertise there is no guarantee that advertise is really started (it is delayed)
    }

    @Override
    public void onDiscoveryStarted() {
        super.onDiscoveryStarted();

        Notify that discovery has started,if you want to do something after the start of discovery do it here,because
        after startDiscovery there is no guarantee that discovery is really started (it is delayed)
    }

    @Override
    public void onAdvertiseStopped() {
        super.onAdvertiseStopped();

        Notify that advertise has stopped,if you want to do something after the stop of advertising do it here,because
        after stopAdvertising there is no guarantee that advertise is really stopped (it is delayed)
    }

    @Override
    public void onDiscoveryStopped() {
        super.onDiscoveryStopped();

        Notify that discovery has stopped,if you want to do something after the stop of discovery do it here,because
        after stopDiscovery there is no guarantee that discovery is really stopped (it is delayed)
    }

    @Override
    public void onPeerFound(Peer peer) {
        super.onPeerFound(peer);
        
        Here for example you can save peer in a list or anywhere you want and when the user
        choose a peer you can call bluetoothCommunicator.connect(peer founded) but if you want to
        use a peer for connect you have to have peer updated (see onPeerUpdated or onPeerLost),if you use a
        non updated peer the connection might fail
        instead if you want to immediate connect where peer is found you can call bluetoothCommunicator.connect(peer) here
    }

    @Override
    public void onPeerLost(Peer peer){
        super.onPeerLost(peer);
        
        It means that a peer is out of range or has interrupted the advertise,here you can delete the peer lost from a eventual collection of founded peers
    }

    @Override
    public void onPeerUpdated(Peer peer,Peer newPeer){
        super.onPeerUpdated(peer,newPeer);

        It means that a founded peer (or connected peer) has changed (name or address or other things),if you have a collection of founded peers,you need to replace peer with newPeer if you want to connect successfully to that peer.

        In case the peer updated is connected and you have saved connected peers you have to update the peer if you want to successfully
        send a message or a disconnection request to that peer.
    }

    @Override
    public void onConnectionRequest(Peer peer){
        super.onConnectionRequest(peer);

        It means you have received a connection request from another device (peer) (that have called connect)
        for accept the connection request and start connection call bluetoothCommunicator.acceptConnection(peer);
        for refusing call bluetoothCommunicator.rejectConnection(peer); (the peer must be the peer argument of onConnectionRequest)
    }

    @Override
    public void onConnectionSuccess(Peer peer,int source){
        super.onConnectionSuccess(peer,source);

        This means that you have accepted the connection request using acceptConnection or the other
        device has accepted your connection request and the connection is complete,from now on you
        can send messages or data (or disconnection request) to this peer until onDisconnected

        To send messages to all connected peers you need to create a message with a context,a header,represented by a single character string
        (you can use a header to distinguish between different types of messages,or you can ignore it and use a random
        character),the text of the message,or a series of bytes if you want to send any kind of data and the peer you want to send the message to
        (must be connected to avoid errors),example: new Message(context,"a","hello world",peer);
        If you want to send message to a specific peer you have to set the sender of the message with the corresponding peer.

        To send disconnection request to connected peer you need to call bluetoothCommunicator.disconnect(peer);
    }

    @Override
    public void onConnectionFailed(Peer peer,int errorCode){
        super.onConnectionFailed(peer,errorCode);

        This means that your connection request is rejected or has other problems,to know the cause of the failure see errorCode (BluetoothCommunicator.CONNECTION_REJECTED
        means rejected connection and BluetoothCommunicator.ERROR means generic error)
    }

    @Override
    public void onConnectionLost(Peer peer){
        super.onConnectionLost(peer);

        This means that a connected peer has lost the connection with you and the library is trying
        to restore it,in this case you can update the gui to notify this problem.

        You can still send messages in this situation,all sent messages are put in a queue
        and sent as soon as the connection is restored
    }

    @Override
    public void onConnectionResumed(Peer peer){
        super.onConnectionResumed(peer);
        
        Means that connection lost is resumed successfully
    }

    @Override
    public void onMessageReceived(Message message,int source){
        super.onMessageReceived(message,source);

        Means that you have received a message containing TEXT,for know the sender you can call message.getSender() that return
        the peer that have sent the message,you can ignore source,it indicate only if you have received the message
        as client or as server
    }

    @Override
    public void onDataReceived(Message data,int source){
        super.onDataReceived(data,source);

        Means that you have received a message containing DATA,it indicate only if you have received the message
        as client or as server
    }

    @Override
    public void onDisconnected(Peer peer,int peersLeft){
        super.onDisconnected(peer,peersLeft);

        Means that the peer is disconnected,peersLeft indicate the number of connected peers remained
    }

    @Override
    public void onDisconnectionFailed(){
        super.onDisconnectionFailed();

        Means that a disconnection is failed,super.onDisconnectionFailed will reactivate bluetooth for forcing disconnection
        (however the disconnection will be notified in onDisconnection)
    }
});

最后,您可以开始发现和/或宣传:

bluetoothCommunicator.startAdvertising();
bluetoothCommunicator.startDiscovery();

其他所有可以执行的操作都在我之前编写的回调代码中用注释进行了解释。

,

您可以将视图添加到您的所有者,并为其设置一个点击侦听器。视图可以是显示卡周围(或使用的任何物体)周围的透明矩形。

我建议深入阅读this有关BLE使用的信息。在点击监听器上,您可以将连接请求排队。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-