Open-source project
xmaihh/Android-Serialport avatar
xmaihh/Android-Serialport

Android-Serialport and the missing half of Google's serial API

移植谷歌官方串口库,仅支持串口名称及波特率,该项目添加支持校验位、数据位、停止位、流控配置项

700 stars162 forksJavaMIT

At a glance

What is it?
Android-Serialport is a Java port of Google's old android-serialport-api that adds the configuration Google's library never exposed: parity, data bits, stop bits and flow control. It is MIT licensed, small enough to read in an evening, and its one hard requirement is a device node your app can open without root.
Who is it for?
Android-Serialport is a good fit for an Android app talking to a serial device that needs anything beyond a port name and a baud rate, because parity, data bits, stop bits and flow control are exactly the settings industrial and sensor hardware tends to require, and the API is small enough to read in full.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Activity is slowing. The repository last received commits 6 months ago.
What is it written in?
Mainly Java, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What the port of Google's library left out

The project description states the difference from the original in one sentence. Android-Serialport is a port of Google's official android-serialport-api, and the original supports only the serial port name and the baud rate, while this project adds support for parity, data bits, stop bits and flow control.

That gap is the whole reason this library exists. Google's library was written for a narrow case, and anyone whose hardware needs anything other than 8N1 was left with no option but to fork it or write their own JNI wrapper. The upstream project it is based on now lives only as a code.google.com archive link.

The library is Java, published to Maven Central as io.github.xmaihh:serialport, and the repository carries a source tree under serialport/ with a Gradle build, plus a demo app under app/ and an art directory with the logo and a screenshot.

The audience is an Android developer who has already proven the hardware works over a serial port and now needs the line settings to be configurable, or who needs sticky package handling on a device that does not frame its messages cleanly.

The line settings and their defaults

The property table in the README is the spec, and the defaults are worth reading carefully because they are not all the usual ones.

Baud rate is the original API's single configurable value, and it links to the BAUDRATE field in the SerialPort class. Data bits support 5, 6, 7 and 8, with 8 as the default.

Parity is where this fork diverges most usefully. It supports no parity, odd parity, even parity, 0 parity (SPACE) and 1 parity (MARK), with no parity as the default. The SPACE and MARK options are the two that a stock 8N1 assumption cannot express, and the 2.1.2 changelog records both of them as the additions in that release, along with support for setting a custom baud rate.

Stop bits support 1 or 2, defaulting to 1. Flow control supports none, hardware flow control with RTS and CTS, and software flow control with XON and XOFF, defaulting to none.

So the default configuration is 8 data bits, no parity, 1 stop bit, no flow control, which is the common case, and every deviation from it is reachable without leaving the library.

Adding the dependency and the ordering rule that bites people

The dependency is two Gradle edits, and the README is explicit that the repository block belongs in the root build.gradle of the project, in the allprojects repositories section, with mavenCentral() among the entries:

code
allprojects {
    repositories {
        ...
        mavenCentral()
    }
}

Then the module's own build.gradle gets the implementation line:

code
dependencies {
    implementation 'io.github.xmaihh:serialport:2.1.1'
}

The version in that example is 2.1.1, and the repository's most recent tag is 2.1.3 from 2023-09-19, so the sample is one release behind what exists.

There is one behavioural rule that the README flags with a warning badge, and it is the kind of detail that produces a confusing bug report: the serial port properties only take effect if they are set before the open() call. The order is set the port, set the baud rate and the rest, then open, and configuring a port after it is open does nothing.

The call sequence itself is short. You set the properties, then:

code
serialHelper.open();

and to release it:

code
serialHelper.close();

A dedicated serial port finder lists the available devices:

code
serialPortFinder.getAllDevicesPath();

Sticky package handling, which is the real contribution

Serial reads give you bytes, not messages, and a device that writes several frames in one burst, or splits one frame across two reads, leaves you to work out the boundaries yourself. The project calls this sticky package handling, and it ships four strategies plus a hook for your own.

The first is to not handle it at all, which is the default. The second handles a leading and trailing special character as a frame delimiter. The third handles fixed length frames. The fourth handles dynamic length frames, which is the hard case and the one most devices need.

The extension point is an interface with a single method:

code
    byte[] execute(InputStream is);
}

The interface comment explains the contract, that the helper accepts a message, does the sticky package handling, returns the final data through the input stream, and that the returned byte array is the complete data you expected. It also notes that the method is called repeatedly until a complete message is parsed, and that it is synchronous, so you should avoid time-consuming work inside it or you will block the read.

You install your implementation with:

code
serialHelper.setStickPackageHelper(AbsStickPackageHelper mStickPackageHelper);

The README credits the socket sticky package handling approach to XAndroidSocket, and links issue one in this repository as the reason the feature exists. That is a good sign about the feature, since it was built in response to a real report rather than speculatively.

Sending in three encodings and receiving through a callback

Sending comes in three flavours, and the naming is a little confusing until you see it. There is a method that sends a byte array, one that sends a hexadecimal string, and one that sends ASCII text. The last is the one to be careful with, because a serial port has no notion of encoding, so anything beyond plain ASCII is going to be corrupted.

Receiving is callback based. You subclass the helper and override a method, and the data arrives in a bean with the received bytes in it. The README's example is an Android toast that decodes the bytes as UTF-8 and shows them, which is enough to prove the wiring but is obviously not what a real app would do.

Note the shape of the callback. It fires with whatever has arrived, and the sticky package helper is what decides whether that is a complete message. If you use the default helper with no processing, your callback will receive whatever happened to be in the buffer, which may be half a frame or three frames at once. That is the interaction to understand before you build on the library, and it is why the four strategies are not optional extras.

Permissions: the library does not get you root

The FAQ answers the question every Android serial developer asks first, and the answer is that this library does not provide root permissions and that you have to open the serial port permissions yourself. The command given is:

shell
adb shell  chmod 666 /dev/ttyS1

That is a development-machine command, and it is worth being explicit about what it implies. It grants world read and write on the device node, which is fine on a bench and not something you ship in an application, and it does not survive a reboot on most devices.

This is the real constraint on the library, and it is not a shortcoming of the code. On modern Android, access to a serial device node is governed by the SELinux policy and by the device's own permissions, and an app that needs a specific UART typically needs either a device-specific permission grant from the vendor, a system-signed application, or a rooted device with a modified policy. No amount of Java API surface changes that.

The upstream Google library had the same requirement, so this is inherited rather than introduced. But it does mean the audience for this library is narrower than it first looks. It suits devices with a vendor-granted serial node, engineering devices where the app is deployed as a system app, and development hardware where the port is already open.

Maintenance and the version gap in the sample code

The repository is not archived, and the last push was on 2026-04-23. The tagged releases are v2.1.3 from 2023-09-19, v2.1.2 from 2023-08-11 and v2.1.1 from 2023-08-11.

That release history is a small, tidy progression and the changelog explains each step. Version 1.0 was the base functionality, setting the port name and baud rate and sending and receiving data. Version 2.0 added the parity, data bits, stop bits and flow control configuration. Version 2.1 added sticky package handling on receive, with support for custom handling. Version 2.1.1 fixed a dependency reference issue and migrated the artifact to Maven Central, and version 2.1.2 added the SPACE and MARK parity options plus custom baud rate support.

The releases are on 2023 while the repository was pushed to in April 2026, so the tree is ahead of the last tag and the published artifact is two years and change behind the source. The README's dependency example pins 2.1.1, which is behind even the last tag. If you are starting a new integration, check whether a newer version is available on Maven Central rather than copying the sample, and read the diff between the tag and master before relying on either.

The licence is MIT, which is the permissive end and means the code can be vendored into a closed application with only the notice retained. The repository also ships a README_EN.md for English readers and a Windows serial debugging utility as a prebuilt executable in the tree, which is a small sign of the audience.

Editorial conclusion

Android-Serialport is a good fit for an Android app talking to a serial device that needs anything beyond a port name and a baud rate, because parity, data bits, stop bits and flow control are exactly the settings industrial and sensor hardware tends to require, and the API is small enough to read in full. It is a poor fit for hardware behind a USB-to-serial adapter that enumerates as a different device, and a poor fit if you need USB host support or a threaded reader, since the project does not describe those. Before integrating, confirm the device node path the app will open and make sure it is readable and writable by your app without root, since the FAQ states the library does not provide root and that you must open the port permissions yourself, and read the sticky package handling options if your device sends variable length frames.

Frequently asked questions

How do I add Android-Serialport to my Android project?

Add mavenCentral() to the repositories block in the root build.gradle, then add implementation 'io.github.xmaihh:serialport:2.1.1' to the dependencies block in your module's build.gradle. The published artifact is on Maven Central.

What serial port settings does Android-Serialport support?

Baud rate, data bits of 5, 6, 7 or 8 with 8 as the default, parity of none, odd, even, SPACE or MARK with none as the default, stop bits of 1 or 2 with 1 as the default, and flow control of none, hardware RTS/CTS or software XON/XOFF with none as the default.

Why are my serial port settings ignored?

The properties only take effect if they are set before the open() call is executed, so the port name, baud rate, stop bits, data bits, parity and flow control must all be set before you open the port.

Does Android-Serialport need root to open a serial port?

No. The FAQ states that the library does not provide root permissions and that you have to open the serial port permissions yourself, for example with adb shell chmod 666 /dev/ttyS1 on a development machine.

Official sources

  1. Issues
  2. License: MIT
  3. README
  4. Releases
  5. xmaihh/Android-Serialport on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/xmaihh-android-serialport.svg)](https://hysenlabs.com/projects/xmaihh-android-serialport)

Was this useful?