├── serial_lib ├── .gitignore ├── src │ └── main │ │ ├── res │ │ └── values │ │ │ └── strings.xml │ │ ├── AndroidManifest.xml │ │ ├── cpp │ │ ├── CMakeLists.txt │ │ ├── SerialPort.h │ │ └── SerialPort.c │ │ └── java │ │ └── com │ │ └── cl │ │ └── serialportlibrary │ │ ├── enumerate │ │ ├── SerialStatus.java │ │ └── SerialPortEnum.java │ │ ├── listener │ │ ├── OnOpenSerialPortListener.java │ │ └── OnSerialPortDataListener.java │ │ ├── stick │ │ ├── AbsStickPackageHelper.java │ │ ├── BaseStickPackageHelper.java │ │ ├── StaticLenStickPackageHelper.java │ │ ├── TimeoutStickPackageHelper.java │ │ ├── CompositeStickPackageHelper.java │ │ ├── VariableLenStickPackageHelper.java │ │ ├── StickyPacketHelperFactory.java │ │ └── SpecifiedStickPackageHelper.java │ │ ├── Device.java │ │ ├── SerialPort.java │ │ ├── Driver.java │ │ ├── SerialPortFinder.java │ │ ├── thread │ │ └── SerialPortReadThread.java │ │ ├── SerialConfig.java │ │ ├── utils │ │ └── SerialPortLogUtil.java │ │ ├── SerialPortManager.java │ │ └── example │ │ └── MultiSerialPortExample.java ├── proguard-rules.pro ├── consumer-rules.pro └── build.gradle ├── img ├── qq2.jpg ├── pc_ck.jpg ├── QRCode_336.png ├── device-img.png ├── sample_picture.png ├── multiple_images.png ├── test_erformance1.png ├── test_erformance2.png └── test_erformance3.png ├── app ├── src │ └── main │ │ ├── res │ │ ├── values │ │ │ ├── dimens.xml │ │ │ ├── strings.xml │ │ │ ├── colors.xml │ │ │ ├── themes.xml │ │ │ └── string_arrays.xml │ │ ├── mipmap-xxhdpi │ │ │ ├── bg_bjt.jpeg │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ ├── color │ │ │ ├── selector_log_text.xml │ │ │ └── selector_spinner_text.xml │ │ ├── mipmap-anydpi-v26 │ │ │ ├── ic_launcher.xml │ │ │ └── ic_launcher_round.xml │ │ ├── layout │ │ │ ├── include_fragment_container.xml │ │ │ ├── spinner_item.xml │ │ │ ├── spinner_default_item.xml │ │ │ ├── item_device.xml │ │ │ ├── activity_select_serial_port.xml │ │ │ ├── item_log.xml │ │ │ ├── activity_main.xml │ │ │ ├── fragment_log.xml │ │ │ └── activity_main_java.xml │ │ ├── values-night │ │ │ └── themes.xml │ │ ├── drawable-v24 │ │ │ └── ic_launcher_foreground.xml │ │ └── drawable │ │ │ └── ic_launcher_background.xml │ │ ├── java │ │ └── com │ │ │ └── cl │ │ │ └── myapplication │ │ │ ├── constant │ │ │ └── PreferenceKeys.java │ │ │ ├── message │ │ │ ├── IMessage.java │ │ │ ├── ConversionNoticeEvent.java │ │ │ ├── SendMessage.java │ │ │ ├── RecvMessage.java │ │ │ └── LogManager.java │ │ │ ├── util │ │ │ ├── TimeUtil.java │ │ │ ├── ListViewHolder.java │ │ │ ├── PrefHelper.java │ │ │ └── ByteUtil.java │ │ │ ├── App.java │ │ │ ├── adapter │ │ │ ├── SpAdapter.java │ │ │ └── DeviceAdapter.java │ │ │ ├── SelectSerialPortActivity.kt │ │ │ ├── MainActivity.kt │ │ │ ├── fragment │ │ │ └── LogFragment.java │ │ │ └── SingleSerialPortActivity.java │ │ └── AndroidManifest.xml ├── proguard-rules.pro └── build.gradle ├── gradle ├── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties └── libs.versions.toml ├── .gitignore ├── .github └── ISSUE_TEMPLATE │ └── 提交bug.md ├── settings.gradle ├── gradle.properties ├── gradlew.bat ├── gradlew ├── README4.1.1.md └── README.md /serial_lib/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /img/qq2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cl-6666/serialPort/HEAD/img/qq2.jpg -------------------------------------------------------------------------------- /img/pc_ck.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cl-6666/serialPort/HEAD/img/pc_ck.jpg -------------------------------------------------------------------------------- /img/QRCode_336.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cl-6666/serialPort/HEAD/img/QRCode_336.png -------------------------------------------------------------------------------- /img/device-img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cl-6666/serialPort/HEAD/img/device-img.png -------------------------------------------------------------------------------- /img/sample_picture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cl-6666/serialPort/HEAD/img/sample_picture.png -------------------------------------------------------------------------------- /img/multiple_images.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cl-6666/serialPort/HEAD/img/multiple_images.png -------------------------------------------------------------------------------- /img/test_erformance1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cl-6666/serialPort/HEAD/img/test_erformance1.png -------------------------------------------------------------------------------- /img/test_erformance2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cl-6666/serialPort/HEAD/img/test_erformance2.png -------------------------------------------------------------------------------- /img/test_erformance3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cl-6666/serialPort/HEAD/img/test_erformance3.png -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cl-6666/serialPort/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/bg_bjt.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cl-6666/serialPort/HEAD/app/src/main/res/mipmap-xxhdpi/bg_bjt.jpeg -------------------------------------------------------------------------------- /serial_lib/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | SerialPortLibrary 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cl-6666/serialPort/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cl-6666/serialPort/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cl-6666/serialPort/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cl-6666/serialPort/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cl-6666/serialPort/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cl-6666/serialPort/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cl-6666/serialPort/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cl-6666/serialPort/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cl-6666/serialPort/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cl-6666/serialPort/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/color/selector_log_text.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /serial_lib/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sun Sep 28 20:08:42 CST 2025 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip 5 | zipStoreBase=GRADLE_USER_HOME 6 | zipStorePath=wrapper/dists 7 | -------------------------------------------------------------------------------- /serial_lib/src/main/cpp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.4.1) 2 | 3 | add_library(SerialPort SHARED 4 | SerialPort.c) 5 | 6 | # Include libraries needed for libserial_port lib 7 | target_link_libraries(SerialPort 8 | android 9 | log) -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | local.properties 16 | -------------------------------------------------------------------------------- /app/src/main/res/color/selector_spinner_text.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /serial_lib/src/main/java/com/cl/serialportlibrary/enumerate/SerialStatus.java: -------------------------------------------------------------------------------- 1 | package com.cl.serialportlibrary.enumerate; 2 | 3 | /** 4 | * name:cl 5 | * date:2023/2/20 6 | * desc: 7 | */ 8 | public enum SerialStatus { 9 | NO_READ_WRITE_PERMISSION, 10 | OPEN_FAIL, 11 | SUCCESS_OPENED 12 | } 13 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/layout/include_fragment_container.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/java/com/cl/myapplication/constant/PreferenceKeys.java: -------------------------------------------------------------------------------- 1 | package com.cl.myapplication.constant; 2 | 3 | 4 | public class PreferenceKeys { 5 | 6 | /** 7 | * 串口设备 8 | */ 9 | public static String SERIAL_PORT_DEVICES = "serial_port_devices"; 10 | /** 11 | * 波特率 12 | */ 13 | public static String BAUD_RATE = "baud_rate"; 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/com/cl/myapplication/message/IMessage.java: -------------------------------------------------------------------------------- 1 | package com.cl.myapplication.message; 2 | 3 | /** 4 | * 日志消息数据接口 5 | */ 6 | 7 | public interface IMessage { 8 | /** 9 | * 消息文本 10 | * 11 | * @return 12 | */ 13 | String getMessage(); 14 | 15 | /** 16 | * 是否发送的消息 17 | * 18 | * @return 19 | */ 20 | boolean isToSend(); 21 | } 22 | -------------------------------------------------------------------------------- /serial_lib/src/main/java/com/cl/serialportlibrary/enumerate/SerialPortEnum.java: -------------------------------------------------------------------------------- 1 | package com.cl.serialportlibrary.enumerate; 2 | 3 | /** 4 | * name:cl 5 | * date:2023/2/20 6 | * desc:串口枚举类型 7 | */ 8 | public enum SerialPortEnum { 9 | //串口1 10 | SERIAL_ONE, 11 | //串口2 12 | SERIAL_TWO, 13 | //串口3 14 | SERIAL_THREE, 15 | //串口4 16 | SERIAL_FOUR, 17 | //串口5 18 | SERIAL_FIVE, 19 | //串口6 20 | SERIAL_SIX 21 | 22 | } 23 | -------------------------------------------------------------------------------- /serial_lib/src/main/java/com/cl/serialportlibrary/listener/OnOpenSerialPortListener.java: -------------------------------------------------------------------------------- 1 | package com.cl.serialportlibrary.listener; 2 | 3 | import com.cl.serialportlibrary.enumerate.SerialPortEnum; 4 | import com.cl.serialportlibrary.enumerate.SerialStatus; 5 | 6 | import java.io.File; 7 | 8 | /** 9 | * 打开串口监听 10 | */ 11 | public interface OnOpenSerialPortListener { 12 | 13 | void openState(SerialPortEnum serialPortEnum, File device, SerialStatus status); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/cl/myapplication/util/TimeUtil.java: -------------------------------------------------------------------------------- 1 | package com.cl.myapplication.util; 2 | 3 | import java.text.SimpleDateFormat; 4 | import java.util.Date; 5 | 6 | 7 | public class TimeUtil { 8 | 9 | public static final SimpleDateFormat DEFAULT_FORMAT = 10 | new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); 11 | 12 | public static String currentTime() { 13 | Date date = new Date(); 14 | return DEFAULT_FORMAT.format(date); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/提交bug.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 提交BUG 3 | about: Create a report to help us improve 4 | title: 建议 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | ## 【警告:请务必按照 issue 模板填写】 11 | 12 | ## 问题描述 13 | 14 | * 框架版本【必填】:XXX 15 | 16 | * 问题描述【必填】:XXX 17 | 18 | * 复现步骤【必填】:XXX 19 | 20 | * 是否必现【必填】:填是/否 21 | 22 | * 出现问题机型信息【必填】:请填写出现问题的品牌和机型 23 | 24 | * 出现问题的安卓版本【必填】:请填写出现问题的 Android 版本 25 | 26 | ## 其他 27 | 28 | * 提供报错堆栈(如果有报错的话必填,注意不要拿被混淆过的代码堆栈上来) 29 | 30 | * 提供截图或视频(根据需要提供,此项不强制) 31 | 32 | * 提供解决方案(如果已经解决了的话,此项不强制) 33 | -------------------------------------------------------------------------------- /app/src/main/java/com/cl/myapplication/message/ConversionNoticeEvent.java: -------------------------------------------------------------------------------- 1 | package com.cl.myapplication.message; 2 | 3 | /** 4 | * 项目:serialPort 5 | * 作者:Arry 6 | * 创建日期:2021/10/20 7 | * 描述: 8 | * 修订历史: 9 | */ 10 | public class ConversionNoticeEvent { 11 | 12 | private String message; 13 | 14 | public ConversionNoticeEvent(String message) { 15 | this.message = message; 16 | } 17 | 18 | public String getMessage() { 19 | return message; 20 | } 21 | 22 | public void setMessage(String message) { 23 | this.message = message; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /serial_lib/src/main/java/com/cl/serialportlibrary/listener/OnSerialPortDataListener.java: -------------------------------------------------------------------------------- 1 | package com.cl.serialportlibrary.listener; 2 | 3 | import com.cl.serialportlibrary.enumerate.SerialPortEnum; 4 | 5 | /** 6 | * 串口消息监听 7 | */ 8 | public interface OnSerialPortDataListener { 9 | 10 | /** 11 | * 数据接收 12 | * 13 | * @param bytes 接收到的数据 14 | */ 15 | void onDataReceived(byte[] bytes, SerialPortEnum serialPortEnum); 16 | 17 | /** 18 | * 数据发送 19 | * 20 | * @param bytes 发送的数据 21 | */ 22 | void onDataSent(byte[] bytes,SerialPortEnum serialPortEnum); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 串口调试助手 4 | 串口设备: 5 | 波特率 6 | 打开串口 7 | 关闭串口 8 | 找不到串口设备 9 | 发送命令 10 | 输入命令 11 | 加载命令列表 12 | 数据位: 13 | 校验位: 14 | 停止位: 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/cl/myapplication/message/SendMessage.java: -------------------------------------------------------------------------------- 1 | package com.cl.myapplication.message; 2 | 3 | 4 | import com.cl.myapplication.util.TimeUtil; 5 | 6 | /** 7 | * 发送的日志 8 | */ 9 | 10 | public class SendMessage implements IMessage { 11 | 12 | private String command; 13 | private String message; 14 | 15 | public SendMessage(String command) { 16 | this.command = command; 17 | this.message = TimeUtil.currentTime() + " 发送命令:" + command; 18 | } 19 | 20 | @Override 21 | public String getMessage() { 22 | return message; 23 | } 24 | 25 | @Override 26 | public boolean isToSend() { 27 | return true; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /serial_lib/src/main/java/com/cl/serialportlibrary/stick/AbsStickPackageHelper.java: -------------------------------------------------------------------------------- 1 | package com.cl.serialportlibrary.stick; 2 | 3 | import java.io.InputStream; 4 | 5 | /** 6 | * Accept the message, the helper of the sticky packet processing, 7 | * return the final data through the inputstream, 8 | * manually process the sticky packet, and the returned byte[] is the complete data we expect 9 | * Note: This method will be called repeatedly until a complete piece of data is parsed. 10 | * This method is synchronous, try not to do time-consuming operations, otherwise it will block reading data 11 | */ 12 | public interface AbsStickPackageHelper { 13 | byte[] execute(InputStream is); 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/com/cl/myapplication/message/RecvMessage.java: -------------------------------------------------------------------------------- 1 | package com.cl.myapplication.message; 2 | 3 | 4 | import com.cl.myapplication.util.TimeUtil; 5 | 6 | /** 7 | * 收到的日志 8 | */ 9 | 10 | public class RecvMessage implements IMessage { 11 | 12 | private String command; 13 | private String message; 14 | 15 | public RecvMessage(String command) { 16 | this.command = command; 17 | this.message = TimeUtil.currentTime() + " 收到命令:" + command; 18 | } 19 | 20 | @Override 21 | public String getMessage() { 22 | return message; 23 | } 24 | 25 | @Override 26 | public boolean isToSend() { 27 | return false; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/res/layout/spinner_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/res/layout/spinner_default_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_device.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 12 | 13 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /serial_lib/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in D:\Android\sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | google { 4 | content { 5 | includeGroupByRegex("com\\.android.*") 6 | includeGroupByRegex("com\\.google.*") 7 | includeGroupByRegex("androidx.*") 8 | } 9 | } 10 | mavenCentral() 11 | gradlePluginPortal() 12 | maven { url 'https://jitpack.io' } 13 | } 14 | } 15 | dependencyResolutionManagement { 16 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) 17 | repositories { 18 | google() 19 | mavenCentral() 20 | maven { url 'https://jitpack.io' } 21 | } 22 | } 23 | 24 | rootProject.name = "serialPort" 25 | include ':serial_lib' 26 | include ':app' -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /serial_lib/consumer-rules.pro: -------------------------------------------------------------------------------- 1 | # Consumer proguard rules for serial_lib 2 | 3 | # Keep all public APIs 4 | -keep public class com.cl.serialportlibrary.** { *; } 5 | 6 | # Keep native methods 7 | -keepclasseswithmembernames class * { 8 | native ; 9 | } 10 | 11 | # Keep enums 12 | -keepclassmembers enum * { 13 | public static **[] values(); 14 | public static ** valueOf(java.lang.String); 15 | } 16 | 17 | # Keep Serializable classes 18 | -keepclassmembers class * implements java.io.Serializable { 19 | static final long serialVersionUID; 20 | private static final java.io.ObjectStreamField[] serialPersistentFields; 21 | private void writeObject(java.io.ObjectOutputStream); 22 | private void readObject(java.io.ObjectInputStream); 23 | java.lang.Object writeReplace(); 24 | java.lang.Object readResolve(); 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/res/values-night/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16 | -------------------------------------------------------------------------------- /serial_lib/src/main/cpp/SerialPort.h: -------------------------------------------------------------------------------- 1 | /* DO NOT EDIT THIS FILE - it is machine generated */ 2 | #include 3 | /* Header for class android_serialport_api_SerialPort */ 4 | 5 | #ifndef _Included_qingwei_kong_serialportlibrary_SerialPort 6 | #define _Included_qingwei_kong_serialportlibrary_SerialPort 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | /* 12 | * Class: android_serialport_api_SerialPort 13 | * Method: open 14 | * Signature: (Ljava/lang/String;II)Ljava/io/FileDescriptor; 15 | */ 16 | JNIEXPORT jobject JNICALL Java_com_cl_serialportlibrary_SerialPort_open 17 | (JNIEnv *, jclass, jstring, jint, jint,jint,jint,jint); 18 | 19 | /* 20 | * Class: android_serialport_api_SerialPort 21 | * Method: close 22 | * Signature: ()V 23 | */ 24 | JNIEXPORT void JNICALL Java_com_cl_serialportlibrary_SerialPort_close 25 | (JNIEnv *, jobject); 26 | 27 | #ifdef __cplusplus 28 | } 29 | #endif 30 | #endif 31 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_select_serial_port.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 12 | 13 | 17 | 18 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /gradle/libs.versions.toml: -------------------------------------------------------------------------------- 1 | [versions] 2 | agp = "8.12.2" 3 | kotlin = "2.0.21" 4 | coreKtx = "1.10.1" 5 | junit = "4.13.2" 6 | junitVersion = "1.1.5" 7 | espressoCore = "3.5.1" 8 | appcompat = "1.6.1" 9 | material = "1.10.0" 10 | 11 | [libraries] 12 | androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } 13 | junit = { group = "junit", name = "junit", version.ref = "junit" } 14 | androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" } 15 | androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" } 16 | androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" } 17 | material = { group = "com.google.android.material", name = "material", version.ref = "material" } 18 | 19 | [plugins] 20 | android-application = { id = "com.android.application", version.ref = "agp" } 21 | kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } 22 | 23 | -------------------------------------------------------------------------------- /serial_lib/src/main/java/com/cl/serialportlibrary/Device.java: -------------------------------------------------------------------------------- 1 | package com.cl.serialportlibrary; 2 | 3 | import java.io.File; 4 | import java.io.Serializable; 5 | 6 | 7 | public class Device implements Serializable{ 8 | 9 | private static final String TAG = Device.class.getSimpleName(); 10 | private String name; 11 | private String root; 12 | private File file; 13 | 14 | public Device(String name, String root, File file) { 15 | this.name = name; 16 | this.root = root; 17 | this.file = file; 18 | } 19 | 20 | public String getName() { 21 | return name; 22 | } 23 | 24 | public void setName(String name) { 25 | this.name = name; 26 | } 27 | 28 | public String getRoot() { 29 | return root; 30 | } 31 | 32 | public void setRoot(String root) { 33 | this.root = root; 34 | } 35 | 36 | public File getFile() { 37 | return file; 38 | } 39 | 40 | public void setFile(File path) { 41 | this.file = file; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFBB86FC 4 | #FF6200EE 5 | #FF3700B3 6 | #FF03DAC5 7 | #FF018786 8 | #FF000000 9 | #FFFFFFFF 10 | 11 | 12 | #3F51B5 13 | #303F9F 14 | #FF4081 15 | #e4e4e4 16 | #55a0a7cc 17 | #ffa0a7cc 18 | 19 | #e5e5e5 20 | 21 | #00000000 22 | #30bfbfbf 23 | #727272 24 | #B6B6B6 25 | 26 | #888888 27 | #20ffffff 28 | -------------------------------------------------------------------------------- /app/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16 | 17 | 18 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/values/string_arrays.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 110 6 | 300 7 | 600 8 | 1200 9 | 2400 10 | 4800 11 | 9600 12 | 14400 13 | 19200 14 | 38400 15 | 56000 16 | 57600 17 | 115200 18 | 128000 19 | 256000 20 | 21 | 22 | 23 | 24 | 1 25 | 2 26 | 3 27 | 4 28 | 5 29 | 6 30 | 7 31 | 8 32 | 9 33 | 10 34 | 35 | 36 | 37 | 0:设备默认 38 | 1:快 20ms 39 | 2:中 40ms 40 | 3:慢 60ms 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | # AndroidX package structure to make it clearer which packages are bundled with the 15 | # Android operating system, and which are packaged with your app"s APK 16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 17 | android.useAndroidX=true 18 | # Automatically convert third-party libraries to use AndroidX 19 | android.enableJetifier=true 20 | # Kotlin code style for this project: "official" or "obsolete": 21 | kotlin.code.style=official -------------------------------------------------------------------------------- /app/src/main/java/com/cl/myapplication/message/LogManager.java: -------------------------------------------------------------------------------- 1 | package com.cl.myapplication.message; 2 | 3 | import org.greenrobot.eventbus.EventBus; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | /** 9 | * log管理类 10 | */ 11 | 12 | public class LogManager { 13 | 14 | public final List messages; 15 | private boolean mAutoEnd = true; 16 | 17 | public LogManager() { 18 | messages = new ArrayList<>(); 19 | } 20 | 21 | private static class InstanceHolder { 22 | 23 | public static LogManager sManager = new LogManager(); 24 | } 25 | 26 | public static LogManager instance() { 27 | return InstanceHolder.sManager; 28 | } 29 | 30 | public void add(IMessage message) { 31 | messages.add(message); 32 | } 33 | 34 | public void post(IMessage message) { 35 | EventBus.getDefault().post(message); 36 | } 37 | 38 | public void clear() { 39 | messages.clear(); 40 | } 41 | 42 | public boolean isAutoEnd() { 43 | return mAutoEnd; 44 | } 45 | 46 | public void setAutoEnd(boolean autoEnd) { 47 | mAutoEnd = autoEnd; 48 | } 49 | 50 | public void changAutoEnd() { 51 | mAutoEnd = !mAutoEnd; 52 | } 53 | } 54 | 55 | -------------------------------------------------------------------------------- /app/src/main/java/com/cl/myapplication/App.java: -------------------------------------------------------------------------------- 1 | package com.cl.myapplication; 2 | 3 | import android.app.Application; 4 | 5 | import com.hjq.toast.ToastUtils; 6 | import com.cl.serialportlibrary.SimpleSerialPortManager; 7 | 8 | /** 9 | * 项目:serialPort 10 | * 作者:Arry 11 | * 创建日期:2021/10/20 12 | * 描述: 13 | * 修订历史: 14 | */ 15 | public class App extends Application { 16 | 17 | @Override 18 | public void onCreate() { 19 | super.onCreate(); 20 | // 初始化 Toast 框架 21 | ToastUtils.init(this); 22 | 23 | // 使用新的SimpleSerialPortManager进行全局初始化 24 | new SimpleSerialPortManager.QuickConfig() 25 | .setIntervalSleep(50) // 读取间隔50ms 26 | .setEnableLog(true) // 启用日志 27 | .setLogTag("SerialPortApp") // 设置日志标签 28 | .setDatabits(8) // 数据位8 29 | .setParity(0) // 无校验 30 | .setStopbits(1) // 停止位1 31 | .setStickyPacketStrategy(SimpleSerialPortManager.StickyPacketStrategy.NO_PROCESSING) // 不处理黏包 32 | .setMaxPacketSize(1024) // 最大包大小1KB 33 | .apply(this); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /serial_lib/src/main/java/com/cl/serialportlibrary/stick/BaseStickPackageHelper.java: -------------------------------------------------------------------------------- 1 | package com.cl.serialportlibrary.stick; 2 | 3 | import android.os.SystemClock; 4 | 5 | import com.cl.serialportlibrary.utils.SerialPortLogUtil; 6 | 7 | import java.io.IOException; 8 | import java.io.InputStream; 9 | 10 | /** 11 | * The simplest thing to do is not to deal with sticky packets, 12 | * read directly and return as much as InputStream.available() reads 13 | */ 14 | public class BaseStickPackageHelper implements AbsStickPackageHelper { 15 | public BaseStickPackageHelper() { 16 | } 17 | 18 | @Override 19 | public byte[] execute(InputStream is) { 20 | try { 21 | int available = is.available(); 22 | if (available > 0) { 23 | byte[] buffer = new byte[available]; 24 | int size = is.read(buffer); 25 | if (size > 0) { 26 | return buffer; 27 | } 28 | SerialPortLogUtil.d("BaseStickPackageHelper", "原始数据长度: " + buffer.length); 29 | } else { 30 | SystemClock.sleep(50); // 默认50ms间隔 31 | } 32 | 33 | } catch (IOException e) { 34 | e.printStackTrace(); 35 | } 36 | return null; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_log.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 13 | 14 | 23 | 24 | 25 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /serial_lib/src/main/java/com/cl/serialportlibrary/stick/StaticLenStickPackageHelper.java: -------------------------------------------------------------------------------- 1 | package com.cl.serialportlibrary.stick; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | 6 | /** 7 | * Fixed-length adhesive package treatment 8 | * Example: The protocol stipulates that the length of each packet is 16 9 | */ 10 | public class StaticLenStickPackageHelper implements AbsStickPackageHelper { 11 | private int stackLen = 16; 12 | 13 | public StaticLenStickPackageHelper(int stackLen) { 14 | this.stackLen = stackLen; 15 | } 16 | 17 | /** 18 | * 默认构造函数,使用16字节固定长度 19 | */ 20 | public StaticLenStickPackageHelper() { 21 | this.stackLen = 16; 22 | } 23 | 24 | @Override 25 | public byte[] execute(InputStream is) { 26 | int count = 0; 27 | int len = -1; 28 | byte temp; 29 | byte[] result = new byte[stackLen]; 30 | try { 31 | while (count < stackLen && (len = is.read()) != -1) { 32 | temp = (byte) len; 33 | result[count] = temp; 34 | count++; 35 | } 36 | if (len == -1) { 37 | return null; 38 | } 39 | } catch (IOException e) { 40 | e.printStackTrace(); 41 | return null; 42 | } 43 | return result; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /serial_lib/src/main/java/com/cl/serialportlibrary/SerialPort.java: -------------------------------------------------------------------------------- 1 | package com.cl.serialportlibrary; 2 | 3 | import java.io.File; 4 | import java.io.FileDescriptor; 5 | import java.io.IOException; 6 | 7 | public class SerialPort { 8 | 9 | static { 10 | System.loadLibrary("SerialPort"); 11 | } 12 | 13 | private static final String TAG = SerialPort.class.getSimpleName(); 14 | 15 | /** 16 | * 文件设置最高权限 777 可读 可写 可执行 17 | * 18 | * @param file 文件 19 | * @return 权限修改是否成功 20 | */ 21 | boolean chmod777(File file) { 22 | if (null == file || !file.exists()) { 23 | // 文件不存在 24 | return false; 25 | } 26 | try { 27 | // 获取ROOT权限 28 | Process su = Runtime.getRuntime().exec("/system/bin/su"); 29 | // 修改文件属性为 [可读 可写 可执行] 30 | String cmd = "chmod 777 " + file.getAbsolutePath() + "\n" + "exit\n"; 31 | su.getOutputStream().write(cmd.getBytes()); 32 | if (0 == su.waitFor() && file.canRead() && file.canWrite() && file.canExecute()) { 33 | return true; 34 | } 35 | } catch (IOException | InterruptedException e) { 36 | // 没有ROOT权限 37 | e.printStackTrace(); 38 | } 39 | return false; 40 | } 41 | 42 | // 打开串口 43 | protected native FileDescriptor open(String path, int baudrate, int flags, int databits, int stopbits, int parity); 44 | 45 | // 关闭串口 46 | protected native void close(); 47 | } 48 | -------------------------------------------------------------------------------- /serial_lib/src/main/java/com/cl/serialportlibrary/Driver.java: -------------------------------------------------------------------------------- 1 | package com.cl.serialportlibrary; 2 | 3 | import java.io.File; 4 | import java.util.ArrayList; 5 | 6 | /** 7 | * 串口驱动信息类 8 | * 简化版本,仅用于SerialPortFinder 9 | */ 10 | public class Driver { 11 | 12 | private String mDriverName; 13 | private String mDeviceRoot; 14 | 15 | public Driver(String name, String root) { 16 | mDriverName = name; 17 | mDeviceRoot = root; 18 | } 19 | 20 | /** 21 | * 获取驱动名称 22 | */ 23 | public String getName() { 24 | return mDriverName; 25 | } 26 | 27 | /** 28 | * 获取设备根路径 29 | */ 30 | public String getRoot() { 31 | return mDeviceRoot; 32 | } 33 | 34 | /** 35 | * 获取该驱动下的所有设备 36 | */ 37 | public ArrayList getDevices() { 38 | ArrayList devices = new ArrayList<>(); 39 | File dev = new File("/dev"); 40 | File[] files = dev.listFiles(); 41 | 42 | if (files != null) { 43 | for (File file : files) { 44 | if (file.getAbsolutePath().startsWith(mDeviceRoot)) { 45 | devices.add(file); 46 | } 47 | } 48 | } 49 | 50 | return devices; 51 | } 52 | 53 | @Override 54 | public String toString() { 55 | return "Driver{" + 56 | "name='" + mDriverName + '\'' + 57 | ", root='" + mDeviceRoot + '\'' + 58 | '}'; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 13 | 14 | 19 | 20 | 28 | 29 |