网络调试助手:安卓APP集成TCP、UDP、经典蓝牙、低功耗蓝牙的调试demo

2023-05-16

1.前言

我终于不需要调试一个硬件设备装一个APP了,在应用商店下载别人的网络调试助手,又有广告,还不如直接写一个比较完整的网络调试助手。目前支持的功能有tcp客户端和服务端,udp,低功耗蓝牙客户端和服务端,经典蓝牙客户端和服务端。低功耗蓝牙可以动态获取服务端的UUID。

2.实现的方法

我是怎么实现一个个调试助手的呢?其实就是先下载别人的APP来测试,例如我先做的是tcp客户端,那我就会用我的客户端去和下载的APP开的服务端进行测试,测试成功了就写下一个,以此类推。我记得大三的时候,有个师兄说过,我们班的网络知识太差了,确实是,真的很差。我也是临近大四毕业才开始比较深入学习物联网的网络知识,像蓝牙这些知识,以前是看着都很害怕,感觉会很难的样子,仿佛心中隔了一道墙,蓝牙永远进不来我的内心一样。但是现在就很想把它们都学透,都收入我的碗里来,因为我想掌握更多的知识,才能成为更好的自己,不再逃避了。好吧,我话太多了。先来看看demo图吧。

3.APP效果图

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.不足之处

界面简洁,没有过多复杂的ui,主要实现对应的功能而已
以后会慢慢维护的,嘻嘻…

5.每一个调试工具的实现思路

由于代码太多,就不一 一陈列了。

(1)tcp客户端

1.创建Socket
2.打开连接到对应ip地址和端口号的Socket的输入/输出流。
3.按照协议对Socket进行读/写操作。
4.关闭输入输出流、关闭Socket。
但是呢,在安卓里面,涉及到网络连接等耗时操作时,不能将其放在UI主线程中,需要添加子线程,在子线程进行网络连接,这就涉及到安卓线程间的通信了,用Handle来实现。

(2)tcp服务端

1.创建服务端socket服务。通过ServerSocket对象。
2.服务端必须对外提供一个端口,否则客户端无法连接。
3.获取连接过来的客户端对象。
4.通过客户端对象获取socket流读取客户端发来的数据并打印在控制台上。
5.关闭资源: 关客户端,关服务端。

不知道为什么,客户端断开连接时,服务端不知道客户端断开了,就是获取不到客户端的断开请求,所以我就写成是当客户端发送“close”时服务端断开客户端的连接,另外客户端也有在请求断开的操作时发送 “close”。

(3)udp

1.建立连接的IP地址和端口号,IP即是你想要发送的地址,端口号则要选用闲置端口就是向8000~9000这样的端口号。
2.建立DatagramSocket sendSocket/receiveSocket ,用于发送和接受数据报文包。
3.创建报文包DatagramPacket sendPackage/receivePackage,将发送或接收的内容打包。
4.通过sendSocket.send(sendPackage)或者receiveSocket.receive(receivePackage),则完成了基于Socket的UDP通信。

发送和接收要开2个线程。
这个实现主要参考了 Android UDP 通信总结 (终于从坑中爬起来了)

这篇文章。

(4)低功耗蓝牙客户端

1.权限问题:先判断手机是否满足android4.3以上版本,再判断手机是否开启蓝牙。
2.搜索蓝牙:搜索蓝牙,回调接口中查看ble设备相关信息,一定时间停止扫描。
3.连接蓝牙:首先获取到ble设备的mac地址,然后调用connect()方法进行连接。
4.获取特征:蓝牙连接成功后,需要获取蓝牙的服务特征等,然后开启接收设置。
5.发送消息:writeCharacteristic()方法,发送数据给ble设备。
6.接收消息:通过蓝牙的回调接口中onCharacteristicRead()方法,接收蓝牙收的消息。
7.释放资源:断开连接,关闭资源。

低功耗蓝牙里是搜不到经典蓝牙的,我用hc-06模块作为服务端的时候就搜不到,换成经典蓝牙的时候就搜得到。
这里贴一下动态获取服务端的服务UUID的方法,在重写方法onServicesDiscovered()里:

   @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            super.onServicesDiscovered(gatt, status);

            List<BluetoothGattService> gattServiceList = gatt.getServices();
            Log.e("ard", "蓝牙模块服务开放状态:" + status + ",GATT:" + gatt.hashCode() + ",服务数量:" + gattServiceList.size());

            // 遍历Service
            for (int i = 0; i < gattServiceList.size(); i++) {
                BluetoothGattService gattService = gattServiceList.get(i);
                String serviceUUID = gattService.getUuid().toString();
                List<BluetoothGattCharacteristic> characteristicList = gattService.getCharacteristics();
                Log.i("ard", "服务UUID:" + serviceUUID + ",其下特征码数量: " + (null == characteristicList ? 0 : characteristicList.size()));
                UUID_SERVER=UUID.fromString(serviceUUID);

                // 遍历Characteristic
                for (int j = 0; j < characteristicList.size(); j++) {
                    BluetoothGattCharacteristic characteristic = characteristicList.get(j);
                    boolean b= bluetoothGatt.setCharacteristicNotification(characteristic, true); // 设置可接收回调消息
                    Log.e(TAG, "开启通知"+b );
                    String characteristicUUID = characteristic.getUuid().toString();
                    int properties = characteristic.getProperties();
                    Log.i("ard", "\t特征码UUID:" + characteristicUUID + ",属性:" + properties);

                    // 这个特征码是手机向蓝牙发数据的。根据蓝牙模块型号不同特征码uuid也不同,可以都尝试一下
                    characteristic2 = characteristic; // 设为全局的目标蓝牙模块写数据的控制器
                    

                    // --- 以下if块没有实质操作 ---
                    if ((properties | BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) { // Characteristic可以接收回调消息
                        List<BluetoothGattDescriptor> descriptorList = characteristic.getDescriptors();
                        if (null != descriptorList && descriptorList.size() > 0) {

                            // 遍历Descriptor
                            for (int k = 0; k < descriptorList.size(); k++) {
                                BluetoothGattDescriptor descriptor = descriptorList.get(k);
                                UUID descriptorUUID = descriptor.getUuid();
                                byte[] descriptorValue = descriptor.getValue();
                                Log.i("ard", "\t\t描述符UUID:" + descriptorUUID + "," + String.valueOf(descriptorValue));
                            }
                        }
                    }
                }
            }
        }

(5)低功耗蓝牙服务端(外围模式)

1.设置广播以及初始化广播数据
2.开始广播
3.配置Services以及Characteristic
4.Server回调以及操作

(6)经典蓝牙客户端

1.首先开启蓝牙,设置蓝牙可见
2.搜索可用设备
3.配对与连接(通过UUID)
4.创建蓝牙socket,获取输入输出流
5.读取和写入数据,用outputstream和inputstream进行接收和发送

(7)经典蓝牙服务端

1.首先开启蓝牙,设置蓝牙可见
2.服务器端serversocket等待接收客户端的连接,若一直没有连接,则为阻塞状态,故等待连接的代码应该放在子线程中进行
3.服务器端接受连接之后返回一个socket来管理对话,用outputstream和inputstream进行接收和发送

注意:客户端和服务端的UUID要一致,不然连接不上的。

6.源码

码云:https://gitee.com/wangjinchan/IOT.git

7.参考资料:

Android通过蓝牙(BLE低功耗蓝牙)实现设备间通讯 | 客户端 | 服务端

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

网络调试助手:安卓APP集成TCP、UDP、经典蓝牙、低功耗蓝牙的调试demo 的相关文章

  • Docker桌面版安装与使用(windows)

    目录 一 Docker概念二 下载安装三 docker镜像安装与操作四 制作自己的python镜像容器五 目录挂载六 多容器通信七 Docker Compose管理多个容器运行八 发布和部署九 备份数据迁移 一 Docker概念 1 Doc
  • Gradio 机器学习和数据科学开源 Python 库

    Gradio是一个开源的 Python 库 xff0c MIT的开源项目 xff0c 用于构建机器学习和数据科学演示和 Web 应用 Gradio的定位类似于Streamlit xff0c 但是更轻量 xff0c 因为它推荐的应用场景都是对
  • k8s安装

    目录 一 K8s概念二 minikube安装三 部署应用到集群中四 Service五 k8s部署爬虫1 意义 一 K8s概念 参考文章 xff0c 参考视频它是一个为 容器化 应用提供集群部署和管理的开源工具 xff0c 由 Google
  • 编程工具-GPT来AI编程代码

    一 安装介绍 1 https www cursor so 下载安装 xff0c 重要的说三遍 xff08 目前免费 xff01 免费 xff01 免费 xff01 xff09 xff0c 支持多平台 Mac Windows Linux xf
  • 某wipo专利_六宫格/cookie/css

    这里写目录标题 一 案例分析二 六宫格验证码三 列表页搜索式302四 详情页css链接cookie刷新 一 案例分析 案例网址 xff1a 案例网址 反爬点 xff1a 六宫格验证码 cookie反爬 时间强制等待 session数据强绑定
  • Python之urlencode()使用

    urlencode 传入参数类型 xff1a 字典功能 xff1a 将存入的字典参数编码为URL查询字符串 xff0c 即转换成以key1 61 value1 amp key2 61 value2的形式导入 xff1a from urlli
  • Python之Md5使用等加密

    目录 一 Python之md5使用二 Python之sha1使用三 Python之base64使用四 Python之rsa使用五 Python之aes des 一 Python之md5使用 功能 xff1a MD5签名是一个哈希函数 xff
  • Python之quote()使用

    quote 传入参数类型 xff1a 字符串功能 xff1a 将单个字符串编码转化为 xx 的形式导入 xff1a from urllib parse import quotePs xff1a url多个字符串编码用urlenocde 函数
  • ( 数组和矩阵) 645. 错误的集合 ——【Leetcode每日一题】

    645 错误的集合 难度 xff1a 简单 集合 s 包含从 1 到 n 的整数 不幸的是 xff0c 因为数据错误 xff0c 导致集合里面某一个数字复制了成了集合里面的另外一个数字的值 xff0c 导致集合 丢失了一个数字 并且 有一个
  • Kalman滤波(Part-1:信号模型基础)

    Kalman Filters Dynamical Signal Models 一阶高斯 马尔可夫过程 first order Gauss Markov process 描述采样点之间 xff08 相邻 xff09 的相关性 xff1a s
  • 【STM32】关于keil5中下载按钮灰色及出现#error “Please select first the target STM32F4xx devic....错误的解决方法

    解决首次运行报错问题 近期在网上购买了一个WIFI模组 xff0c 例程是使用HAL库编写的 xff0c 首次编译的时候出现USER stm32f4xx h 193 error 35 error directive 34 Please se
  • 【STM32】F429单片机的时钟系统浅析

    先把429的时钟树附上 xff1a 乍一看是不是很懵逼 xff0c 我也很懵逼 一堆乱七八糟的玩意 xff0c ST公司是真的狗 本文是基于库函数SetSysClock 展开的 xff0c 配合该函数使用时钟树效果更佳O O 讲解之间说一个
  • x-easypdf 基于pdfbox/fop 封装的框架

    x easypdf 是一个基于 pdfbox fop 二次封装的框架 xff0c 目前拥有两大模块 xff1a pdfbox 模块 与 fop 模块 pdfbox 模块 主打 pdf 编辑功能 xff0c 以组件化的形式进行 pdf 的构建
  • 【STM32】利用定时器实现最基本的定时功能(HAL)

    定时器简介 STM32F429单片机有许多定时器Timer xff0c 主要分成三类 xff0c 基本定时器 xff1b 通用定时器和高级定时器 三种类型的定时器功能由少变多 xff0c 高级定时器包含了低级定时器的功能 基本定时器 xff
  • 【STM32】通俗易懂的讲解回调函数

    转载 xff1a https blog csdn net vincent040 article details 50832955 回调函数在程序开发中是一个非常重要的概念 xff0c 所谓的回调其实就是不同程序模块之间的接口和约定 xff0
  • 【树莓派】设置树莓派开机自动运行python脚本

    近期因科研需要 xff0c 需命令树莓派开机后无需进行任何操作自动运行一个python脚本 xff0c 经查阅部分资料后实现了该功能 xff0c 为方便以后查看特此记录一下 1 打开cmd xff0c 输入 sudo vim span cl
  • 部分机器人领域顶会顶刊官网及22年顶会召开时间

    顶刊 Science Robotics AAAS The International Journal of Robotics Research IJRR Journal of Forestry Research JFR IEEE Trans
  • 服务器非root下安装Python cyglfw3库

    服务器非root下安装Python cyglfw3库 在服务器中跑PVNet的代码时遇到的 xff0c 废了比较大的劲才解决 xff0c 特意记录一下解决过程 如果你有sudo权限直接使用sudo apt get install libgl
  • FFB6D搭建环境

    文章目录 FFB6D搭建环境搭建前的准备 根据需要选择性浏览 安装apex安装normal speed安装opencv3 安装pybind11安装normal speed 安装RandLA运行代码前的准备运行代码有疑问多多交流 xff0c
  • win32Day06:控件

    1 什么是控件 xff1f 控件是具备特殊功能的窗口 xff0c 并且有模板 控件的特性 xff1a 一定是子窗口 和创建主窗口一样 xff0c 都是使用CreateWindow函数来创建 xff08 控件这种 xff09 子窗口和主窗口的

随机推荐