diff --git a/README.md b/README.md index 5fb6410..f54c0ec 100644 --- a/README.md +++ b/README.md @@ -1,38 +1,82 @@ # Android-SerialPort-API +[Fork](https://code.google.com/archive/p/android-serialport-api/)自Google开源的Android串口通信Demo,修改成Android Studio项目 -**Gradle 引用** +This lib is a [fork](https://code.google.com/archive/p/android-serialport-api/) of the Android serial port communication Demo open sourced by Google. -添加依赖 +## Installation & Usage +**Gradle** + +添加依赖: + +Add the dependency: ``` +allprojects { + repositories { + ... + jcenter() + mavenCentral() // since 2.1.3 + } +} + dependencies { - implementation 'com.licheedev:android-serialport:2.1.2' + // 传统4KB内存页面版本 + implementation 'com.licheedev:android-serialport:2.1.4' + // 适配16KB页面版本,https://developer.android.google.cn/guide/practices/page-sizes?hl=zh-cn + implementation 'com.licheedev:android-serialport:2.1.5' } ``` -**修改`su`路径** +**Import** + +```java +import android.serialport.SerialPort; +``` + +**`su` path** + +In order to read/write to a serial port in Android you'll need `su` binary installed on device (this can be done by rooting the device). Usually Android devices that has the ability to communicate with serial ports have `su` installed on the default path `"/system/bin/su"`. To change this use: ```java // su默认路径为 "/system/bin/su" +// The default path of su is "/system/bin/su" // 可通过此方法修改 +// If the path is different then change it using this SerialPort.setSuPath("/system/xbin/su"); ``` -**可选配置数据位、校验位、停止位** - -实现方式参考 -> https://juejin.im/post/5c010a19e51d456ac27b40fc +**Usage** ```java - // 默认8N1(8数据位、无校验位、1停止位) +// Default 8N1 (8 data bits, no parity bit, 1 stop bit) SerialPort serialPort = new SerialPort(path, baudrate); -// 7E2(7数据位、偶校验、2停止位) -SerialPort serialPort = SerialPort // - .newBuilder(path, baudrate) // 串口地址地址,波特率 - .parity(2) // 校验位;0:无校验位(NONE,默认);1:奇校验位(ODD);2:偶校验位(EVEN) - .dataBits(7) // 数据位,默认8;可选值为5~8 - .stopBits(2) // 停止位,默认1;1:1位停止位;2:2位停止位 +// 可选配置数据位、校验位、停止位 - 7E2(7数据位、偶校验、2停止位) +// or with builder (with optional configurations) - 7E2 (7 data bits, even parity, 2 stop bits) +SerialPort serialPort = SerialPort + .newBuilder(path, baudrate) +// 校验位;0:无校验位(NONE,默认);1:奇校验位(ODD);2:偶校验位(EVEN) +// Check bit; 0: no check bit (NONE, default); 1: odd check bit (ODD); 2: even check bit (EVEN) +// .parity(2) +// 数据位,默认8;可选值为5~8 +// Data bit, default 8; optional value is 5~8 +// .dataBits(7) +// 停止位,默认1;1:1位停止位;2:2位停止位 +// Stop bit, default 1; 1:1 stop bit; 2: 2 stop bit +// .stopBits(2) .build(); + +// read/write to serial port - needs to be in different thread! +InputStream in = serialPort.getInputStream(); +OutputStream out = serialPort.getOutputStream(); + +// close +serialPort.tryClose(); ``` + +实现方式参考 + +Implementation reference +1. Check [sample project](https://github.com/licheedev/Android-SerialPort-API/tree/master/sample) +2. https://juejin.im/post/5c010a19e51d456ac27b40fc diff --git a/build.gradle b/build.gradle index fd36fc3..a47094e 100644 --- a/build.gradle +++ b/build.gradle @@ -4,13 +4,13 @@ buildscript { repositories { google() jcenter() + mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:4.0.1' + classpath 'com.android.tools.build:gradle:4.2.2' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files - classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.4' - classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1' + classpath 'org.jetbrains.dokka:dokka-gradle-plugin:1.4.32' } } @@ -18,6 +18,7 @@ allprojects { repositories { google() jcenter() + mavenCentral() } } @@ -31,6 +32,6 @@ ext { minSdkVersion = 8 targetSdkVersion = 29 - versionCode = 2 - versionName = "2.1.2" + versionCode = 3 + versionName = "2.1.5" } \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e95cacb..3ed5e54 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Wed Aug 26 17:00:59 CST 2020 +#Fri Sep 06 10:04:58 CST 2024 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip diff --git a/maven_publish.gradle b/maven_publish.gradle new file mode 100644 index 0000000..e8a2281 --- /dev/null +++ b/maven_publish.gradle @@ -0,0 +1,130 @@ +// 依赖信息 +def groupIdDefined = "com.licheedev" +def artifactIdDefined = "android-serialport" +// 如果是测试版,版本号后面加上 -SNAPSHOT +def versionDefined = rootProject.ext.versionName +// 其他信息 +def gitUrl = "https://github.com/licheedev/Android-SerialPort-API" + +// 配置是否上传 +def toUpload = true + +//在根build.gradle中加入,最新版本号参考 https://github.com/Kotlin/dokka#using-dokka +//classpath 'org.jetbrains.dokka:dokka-gradle-plugin:1.4.32' + +//在module的build.gradle末位加入 +//apply from: '../maven_publish.gradle' + +if (toUpload) { + apply plugin: 'signing' + apply plugin: 'maven-publish' + apply plugin: 'org.jetbrains.dokka' + + // + // 打包源码 + task sourcesJar(type: Jar) { + from android.sourceSets.main.java.srcDirs + classifier = 'sources' + } + + task javadoc(type: Javadoc) { + failOnError false + source = android.sourceSets.main.java.sourceFiles + options { + encoding = "utf-8" + charSet 'UTF-8' + } + classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) + classpath += configurations.compile + } + + // 打包javadoc + task javadocJar(type: Jar, dependsOn: javadoc) { + classifier = 'javadoc' + from javadoc.destinationDir + } + + // 打包包含kotlin源码的javadoc + task kotlinDocJar(type: Jar, dependsOn: dokkaHtml) { + classifier = 'javadoc' + from dokkaHtml.outputDirectory + } + // + + afterEvaluate { + + publishing { + publications { + mavenAndroid(MavenPublication) { + from components.release + + groupId "$groupIdDefined" + artifactId "$artifactIdDefined" + version "$versionDefined" + // 上传source + artifact sourcesJar + // 上传javadoc + if (project.plugins.hasPlugin('kotlin-android')) { + artifact kotlinDocJar + } else { + artifact javadocJar + } + + pom { + name = 'Android-SerialPort-API' + description = 'Android-SerialPort-API' + url = "$gitUrl" + + //licenses { + // license { + // name = 'The MIT License' + // url = 'https://opensource.org/licenses/MIT' + // } + //} + + licenses { + license { + name = 'The Apache License, Version 2.0' + url = 'http://www.apache.org/licenses/LICENSE-2.0.txt' + } + } + + developers { + developer { + id = 'licheedev' + name = 'John Lee' + email = 'licheedev@foxmail.com' + } + } + scm { + connection = "$gitUrl" + developerConnection = "${gitUrl}.git" + url = "$gitUrl" + } + } + } + } + + repositories { + + maven { + // 依赖发布地址 + def releasesRepoUrl = "https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/" + def snapshotsRepoUrl = "https://s01.oss.sonatype.org/content/repositories/snapshots/" + url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl + + // 配置账号密码 + println "user=${ossrhUsername},key=${ossrhPassword}" + credentials { + username "${ossrhUsername}" + password "${ossrhPassword}" + } + } + } + } + + signing { + sign publishing.publications.mavenAndroid + } + } +} \ No newline at end of file diff --git a/sample/build.gradle b/sample/build.gradle index 167098d..00bc09a 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -27,6 +27,6 @@ dependencies { }) implementation 'androidx.appcompat:appcompat:1.2.0' testImplementation 'junit:junit:4.13' -// implementation project(':serialport') - implementation 'com.licheedev:android-serialport:2.1.1' + //implementation project(':serialport') + implementation 'com.licheedev:android-serialport:2.1.5' } diff --git a/serialport/CMakeLists.txt b/serialport/CMakeLists.txt index f16cb32..80def00 100644 --- a/serialport/CMakeLists.txt +++ b/serialport/CMakeLists.txt @@ -2,7 +2,7 @@ # This ensures that a certain set of CMake features is available to # your build. -cmake_minimum_required(VERSION 3.4.1) +cmake_minimum_required(VERSION 3.18.1) # Specifies a library name, specifies whether the library is STATIC or # SHARED, and provides relative paths to the source code. You can @@ -35,4 +35,10 @@ target_link_libraries( # Specifies the target library. # Links the target library to the log library # included in the NDK. - ${log-lib} ) \ No newline at end of file + ${log-lib} ) + +target_link_options( + serial_port + PRIVATE + "-Wl,-z,max-page-size=16384" +) \ No newline at end of file diff --git a/serialport/bintray.gradle b/serialport/bintray.gradle deleted file mode 100644 index fbb21ef..0000000 --- a/serialport/bintray.gradle +++ /dev/null @@ -1,86 +0,0 @@ -//在根build.gradle中加入 -//classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.4' -//classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1' - -//在module的build.gradle末位加入 -//apply from: './bintray.gradle' - -// 执行 ./gradlew clean bintrayUpload - -def toUpload = true // 配置是否上传 -if (toUpload) { - apply plugin: 'com.github.dcendents.android-maven' - apply plugin: 'com.jfrog.bintray' - - // 定义参数 - // 依赖信息 - def groupIdDefined = "com.licheedev" - def artifactIdDefined = "android-serialport" - def versionDefined = rootProject.ext.versionName - // 其他信息 - def siteUrl = "https://github.com/licheedev" - def gitUrl = "https://github.com/licheedev/Android-SerialPort-API.git" - def libName = "$artifactIdDefined" - - // 待发布项目的groupId和version。android-maven-gradle-plugin插件需要这么配置。 - group = "$groupIdDefined" - version = "$versionDefined" - - // bintray平台信息配置 - bintray { - user = BINTRAY_USER - key = BINTRAY_KEY - - println "user=${user},key=${key}" - - configurations = ['archives'] - publish = true - pkg { - repo = "maven" - name = libName - licenses = [" Apache-2.0"] - websiteUrl = siteUrl - vcsUrl = gitUrl - version { - name = "$versionDefined" - } - } - } - - // pom文件信息配置 - install { - repositories.mavenInstaller { - pom.project { - groupId "$groupIdDefined" - artifactId "$artifactIdDefined" - version "$versionDefined" - packaging 'aar' - } - } - } - - // 生成sourceJar和javaDocJar - task sourcesJar(type: Jar) { - from android.sourceSets.main.java.srcDirs - classifier = 'sources' - } - - task javadoc(type: Javadoc) { - failOnError false - source = android.sourceSets.main.java.sourceFiles - options { - encoding = "utf-8" - } - classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) - classpath += configurations.compile - } - task javadocJar(type: Jar, dependsOn: javadoc) { - classifier = 'javadoc' - from javadoc.destinationDir - } - - artifacts { - archives sourcesJar - archives javadocJar - } -} diff --git a/serialport/build.gradle b/serialport/build.gradle index 874cafa..b5a36b4 100644 --- a/serialport/build.gradle +++ b/serialport/build.gradle @@ -21,6 +21,12 @@ android { externalNativeBuild { cmake { path 'CMakeLists.txt' + version "3.18.1" + } + } + packagingOptions { + jniLibs { + useLegacyPackaging true } } } @@ -37,5 +43,5 @@ dependencies { api "androidx.annotation:annotation:1.1.0" } -apply from: './bintray.gradle' +apply from: '../maven_publish.gradle' diff --git a/serialport/src/main/java/android/serialport/SerialPort.java b/serialport/src/main/java/android/serialport/SerialPort.java index 8d4b53d..a07b705 100644 --- a/serialport/src/main/java/android/serialport/SerialPort.java +++ b/serialport/src/main/java/android/serialport/SerialPort.java @@ -82,8 +82,10 @@ public static String getSuPath() { * @throws SecurityException * @throws IOException */ - public SerialPort(@NonNull File device, int baudrate, int dataBits, int parity, int stopBits, - int flags) throws SecurityException, IOException { + public SerialPort( + @NonNull File device, int baudrate, int dataBits, int parity, int stopBits, + int flags + ) throws SecurityException, IOException { this.device = device; this.baudrate = baudrate; @@ -92,6 +94,10 @@ public SerialPort(@NonNull File device, int baudrate, int dataBits, int parity, this.stopBits = stopBits; this.flags = flags; + if (!device.exists()) { + throw new IOException("SerialPort(" + device.getAbsolutePath() + ") not exists"); + } + /* Check access permission */ if (!device.canRead() || !device.canWrite()) { try { @@ -112,7 +118,9 @@ public SerialPort(@NonNull File device, int baudrate, int dataBits, int parity, mFd = open(device.getAbsolutePath(), baudrate, dataBits, parity, stopBits, flags); if (mFd == null) { Log.e(TAG, "native open returns null"); - throw new IOException(); + throw new IOException("native open" + + "SerialPort(" + device.getAbsolutePath() + + ") returns null"); } mFileInputStream = new FileInputStream(mFd); mFileOutputStream = new FileOutputStream(mFd); @@ -188,8 +196,10 @@ public int getFlags() { } // JNI - private native FileDescriptor open(String absolutePath, int baudrate, int dataBits, int parity, - int stopBits, int flags); + private native FileDescriptor open( + String absolutePath, int baudrate, int dataBits, int parity, + int stopBits, int flags + ); public native void close();