Library / SDK
jenly1314/WeChatQRCode avatar
jenly1314/WeChatQRCode

WeChatQRCode puts the WeChat QR engine into an Android library

⛄ 基于OpenCV开源的微信二维码引擎移植的二维码扫码识别库

898 stars166 forksJavaApache-2.0

At a glance

What is it?
WeChatQRCode is a Java library that ports the WeChat QR code engine from OpenCV and packages it as a set of Gradle modules, from the OpenCV runtime through to detection and a scanning interface. The author publishes it alongside two sibling scanning libraries built on ZXing and on MLKit, and the README is explicit that a compileSdk floor and an ABI choice are your responsibility.
Who is it for?
Adopt WeChatQRCode if you are building an Android application that must read WeChat style QR codes, including codes that other decoders struggle with, and if you already ship OpenCV native libraries or are willing to add them.
Can I use it commercially?
Yes. Apache-2.0 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?
Yes. The repository last received commits 42 days 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 25, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A port of the WeChat engine, in a family of three scanning libraries

WeChatQRCode is described as a QR code scanning and recognition library built by porting the open source WeChat QR code engine from OpenCV, and wrapping it.

The reason that matters is recognisability. The WeChat engine is a detector and decoder that was written to find WeChat's own QR codes, which are dense and are frequently reported as hard for general purpose decoders. A library that exposes that engine to an Android application gives you a decoder with a different failure profile from the one you already have, and for a product where the QR code is the whole point of the flow, that difference decides whether the feature works.

What the repository is not is a general scanning library. It is a port plus a wrapper, and the README is clear about the division of labour between the engine and the parts this project adds.

The most useful thing in the README is the comparison the author puts at the top. There are three open source scanning libraries by the same author, and he says plainly that the trade-offs between them are a matter for the reader to choose. The first is ZXingLite, built on ZXing. The second is MLKit, built on ML Kit. The third is this one, WeChatQRCode, built on OpenCV and the ported WeChat engine. He refers to them as wheels in the sense of reimplementations, and says there are already three of them, each with its own strengths and weaknesses.

That framing is a gift for an engineer, because the choice is a genuine trade rather than a default. ZXing is the general purpose Java decoder and is the lightest dependency. ML Kit brings Google's detector and works on device with a different pipeline. OpenCV plus the WeChat engine is the heaviest, since it drags in the OpenCV native runtime, and it is the one that handles the WeChat specific codes best.

Seven modules, and you pick which ones you need

The repository is a multi-module Gradle project, and the module list is the clearest statement of what the library does.

The opencv module holds the compiled OpenCV runtime and is marked as required in the dependency instructions. Four more modules carry the native libraries for a single ABI each: opencv-armv7a for armeabi-v7a, opencv-armv64 for arm64-v8a, opencv-x86 for x86 and opencv-x86_64 for x86_64. Each of those is a single libopencv_java4.so for its architecture.

Then there are two detection modules. The opencv-qrcode module wraps the QR code functionality that ships with OpenCV itself, exposed through a class called OpenCVQRCodeDetector, and the README describes it as a packaged API that gives you the open source QR code recognition from OpenCV with little effort.

The wechat-qrcode module is the same idea for the ported WeChat engine, exposed through WeChatQRCodeDetector. So the two detectors sit side by side in the API, and you can pick the general purpose one or the WeChat specific one without changing the shape of your code.

Finally there are two scanning modules, opencv-qrcode-scanning and wechat-qrcode-scanning, which supply the scanning interface that the detection layer lacks. The README frames these as needed because once you have the recognition capability you still need an interface for scanning, and describes the scanning modules as derived libraries built on the author's CameraScan project.

So the shape of the library is detection plus presentation, separated. If your app already has its own camera preview and analysis pipeline, you take a detection module. If you want a ready made scanning screen, you take the scanning module as well.

The ABI choice is yours, and it sets your APK size

The native library story is the part of this library that most affects a real integration, and the README handles it directly.

The base OpenCV dependency is marked as mandatory, since the detectors call into it. The four ABI modules are marked as optional, and the instruction is to choose the shared object library architectures you want to support, at least one.

bash
    implementation 'com.github.jenly1314.WeChatQRCode:opencv:2.6.0'
    implementation 'com.github.jenly1314.WeChatQRCode:opencv-armv7a:2.6.0'
    implementation 'com.github.jenly1314.WeChatQRCode:opencv-armv64:2.6.0'
    implementation 'com.github.jenly1314.WeChatQRCode:opencv-x86:2.6.0'
    implementation 'com.github.jenly1314.WeChatQRCode:opencv-x86_64:2.6.0'

The repository also explains the second half of the decision, which is the Gradle side. Note one small inconsistency worth remembering: the module directory is named opencv-arm64, while the published Maven coordinate is written opencv-armv64. In the module's build.gradle you set the supported shared library architectures with ndk abiFilters, and the README notes that supporting more platforms makes the APK larger. The sample configuration shows the filter for a single architecture with the other three left as a comment.

This is a genuine trade-off and a common source of confusion for newcomers. If you add the base opencv module but no ABI module, you have the Java side of OpenCV and none of the native code. If you add all four ABI modules, your APK carries a copy of the OpenCV runtime for every architecture, which is a lot of megabytes for a library whose only job is reading a barcode. The realistic choice for most products is arm64-v8a for the devices you ship to, plus x86_64 if you distribute on emulators or Chromebooks, and nothing else.

The abiFilters block also matters for a different reason. It filters what ends up in the package, so it is how you make sure the architectures you chose above are the ones that survive into the APK.

compileSdk is a hard floor, and 2.6.0 moved it again

The README has a section of notes, and the first thing in it is the requirement that will break your build if you miss it.

The rules are stated by version. Using v2.5.0 or above requires compileSdk 35 or higher. Using v2.1.0 or above requires compileSdk 34. Using v2.0.0 or above requires compileSdk 33. If your compileSdk is below 33, you should use the v1.x version from the 1.x branch of the repository.

So the library moves its floor every few releases, and each move is a decision about which Android platforms you support. This is normal for a native library in this space, since the OpenCV build it wraps is rebuilt against a newer NDK and platform level each time, but it means your dependency version and your compileSdk are coupled.

The rest of the integration is a Gradle setup that does not involve the library at all beyond the coordinates. The remote repository is added in the project's build.gradle or settings.gradle, and the sample given is mavenCentral(), with the surrounding lines left as a placeholder.

bash
    repositories {
        //...
        mavenCentral()
    }

Two more coordinates complete the optional set, the OpenCV detection and scanning pair and the WeChat detection and scanning pair, each at the same version as the base module.

bash
    implementation 'com.github.jenly1314.WeChatQRCode:opencv-qrcode:2.6.0'
    implementation 'com.github.jenly1314.WeChatQRCode:wechat-qrcode:2.6.0'

The versioning is consistent across modules, which means you can pin one version and mix modules freely, and the README badges show the library published to Maven Central under the group com.github.jenly1314.WeChatQRCode, with an artifact named wechat-qrcode, and also available through JitPack.

Initialisation changed at v2.1.0 and the old call no longer applies

The setup sequence is short, but there is a version fork in it that will send you to the wrong API if you follow an old tutorial.

The README recommends initialising both OpenCV and the WeChatQRCodeDetector in the onCreate method of your MainActivity or your Application.

For OpenCV, the call depends on the version. From v2.1.0 onwards it is:

kotlin
OpenCV.initOpenCV()

and before v2.1.0 it was the asynchronous variant:

kotlin
OpenCV.initAsync(context)

Once OpenCV is initialised, the WeChatQRCodeDetector can be initialised immediately:

kotlin
WeChatQRCodeDetector.init(context)

The reason the initialisation API moved is visible in the names themselves. The older initAsync took a context and loaded the native library asynchronously, which meant the detector could be called before the library was ready. The newer initOpenCV takes no arguments and is synchronous, so by the time it returns, the native library is loaded and the detector can be constructed. That is a better failure mode, and it is the kind of change that justifies a major version bump in the library's own version rather than in the wrapper.

For a team upgrading across that boundary, the checklist is short: the initialisation call changes, the compileSdk floor changes, and the detection result API changed again in v2.6.0, which the README marks as newly added.

Decoding a bitmap, and the result object added in 2.6.0

The actual work is one call. The WeChat detector returns a list of strings, because more than one code can be present in the image, and the README notes that if you only want one code you can take the first element of the list.

kotlin
val results = WeChatQRCodeDetector.detectAndDecode(bitmap)

The OpenCV detector is an instance rather than a static entry point, and the call is the same in shape:

kotlin
val openCVQRCodeDetector = OpenCVQRCodeDetector()
val results = openCVQRCodeDetector.detectAndDecode(bitmap)

Version 2.6.0 added the ability to get position information back with the recognition, which is what you need if you want to highlight the code in the image or crop a region around it. The result object carries the decoded texts and can hand you the four vertex points of the code.

kotlin
val decodeResult = WeChatQRCodeDetector.detectAndDecodeResult(bitmap)
val points = decodeResult.getVertexPoints()

The OpenCV detector gained the same thing, with an extra boolean argument on the result call in the example given.

kotlin
val decodeResult = openCVQRCodeDetector.detectAndDecodeResult(bitmap, true)

There is also an older style call that takes a list of Mat objects to be filled with the corner points, and the README shows that form as an example for getting position information, iterating over the results and reading the coordinates of the four corners of each rectangle.

The practical point for an integrator is that the two detectors share a shape, so the code that consumes the results does not have to know which engine produced them, and the newer result object is the form to prefer in new code because it is the one the maintainer is extending.

Apache-2.0, Maven Central, and a release roughly every few months

The licence is Apache-2.0, with the text in the LICENSE file at the repository root, and the README links the Apache licence page. For a library that ships native binaries, the permissive terms matter more than usual, since you are redistributing prebuilt shared objects inside your APK.

The library is published to Maven Central under the group com.github.jenly1314.WeChatQRCode, and it is also available through JitPack, which is the standard route for a GitHub hosted library. Both are mirrored by the badges at the top of the README, along with a CI status badge for the build workflow and a download badge pointing at a demo APK in the app/release directory of the repository.

The release history is regular. The recent versions are 2.6.0 on 2026-06-17, 2.5.0 on 2026-03-15 and 2.4.0 on 2025-10-21, so roughly one release every two to three months, and the last push was on 2026-09-13. The project is not archived. The CHANGELOG.md at the repository root is where the per version detail lives.

The API level badge says API 23 and above, which is the minimum Android version the published library supports. That is the practical floor for an application that adopts it.

Two things in the repository suggest a project that expects to be read rather than only consumed. The documentation site is built with mkdocs, configured by mkdocs.yml and produced by build_docs.sh, and it is published at jenly1314.github.io/WeChatQRCode. And there is a separate Java branch of the project, linked from the module list, for a Java implementation rather than the Kotlin-flavoured Android one.

The app/ module in the repository is the demo application, provided so you can download the APK and see the effect before you integrate anything, and the GIF in the README root shows the scanning behaviour.

Editorial conclusion

Adopt WeChatQRCode if you are building an Android application that must read WeChat style QR codes, including codes that other decoders struggle with, and if you already ship OpenCV native libraries or are willing to add them. Do not adopt it if a plain QR code is all you need, because the OpenCV based ZXingLite or MLKit alternatives in the same family are a lighter way to do that, and do not adopt it without checking the compileSdk requirement, since version 2.5.0 and above needs compileSdk 35 or higher and anything below 33 forces you onto the old 1.x branch. Before you integrate, decide which ABI native libraries you will ship, because the more architectures you include the larger the APK becomes, and confirm that the WeChatQRCodeDetector API you intend to call exists in the version you pin.

Frequently asked questions

What does the WeChatQRCode library do?

It is a scanning and recognition library that ports the open source WeChat QR code engine from OpenCV and wraps it in a Java API for Android. Detection modules are available for both the WeChat engine and the QR code functionality built into OpenCV.

Which Gradle modules do I need to add for WeChatQRCode?

The base OpenCV module com.github.jenly1314.WeChatQRCode:opencv is required, the four per-architecture modules for armeabi-v7a, arm64-v8a, x86 and x86_64 are optional but at least one is needed, and the detection and scanning modules are optional additions.

How do I initialise WeChatQRCodeDetector?

Initialise OpenCV first, then the detector. From version 2.1.0 the OpenCV call is OpenCV.initOpenCV(), and before that version it was OpenCV.initAsync(context). The detector is then initialised with WeChatQRCodeDetector.init(context).

What compileSdk do I need for WeChatQRCode?

Version 2.5.0 and above requires compileSdk 35 or higher, 2.1.0 and above requires 34, and 2.0.0 and above requires 33. If your compileSdk is below 33, use the v1.x version from the 1.x branch.

How do I get the position of a decoded QR code?

Version 2.6.0 added detectAndDecodeResult, which returns the decoded texts together with the vertex points of the code through getVertexPoints(). An earlier form takes a list of Mat objects that are filled with the four corner coordinates.

Official sources

  1. jenly1314/WeChatQRCode on GitHub
  2. License: Apache-2.0
  3. Project website
  4. README
  5. Releases
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/jenly1314-wechatqrcode.svg)](https://hysenlabs.com/projects/jenly1314-wechatqrcode)

Was this useful?