zxing: zxing-core 3.4.0 crashes on Android < 7.0 when decoding QR code

I’m using com.google.zxing:core:3.4.0 with com.google.zxing:android-core:3.3.0 and com.google.zxing:android-integration:3.3.0 in an Android app. Everytime I scan a QR code with an Android device with Android < 7.0 (API 24) the app crashes with the following exception:

java.lang.NoSuchMethodError: No interface method sort(Ljava/util/Comparator;)V in class Ljava/util/List; or its super classes (declaration of 'java.util.List' appears in /system/framework/core-libart.jar)
        at com.google.zxing.qrcode.detector.FinderPatternFinder.selectBestPatterns(FinderPatternFinder.java:616)
        at com.google.zxing.qrcode.detector.FinderPatternFinder.find(FinderPatternFinder.java:164)
        at com.google.zxing.qrcode.detector.Detector.detect(Detector.java:81)
        at com.google.zxing.qrcode.QRCodeReader.decode(QRCodeReader.java:77)
        at com.google.zxing.MultiFormatReader.decodeInternal(MultiFormatReader.java:173)
        at com.google.zxing.MultiFormatReader.decodeWithState(MultiFormatReader.java:87)
        at com.google.zxing.client.android.DecodeHandler.decode(DecodeHandler.java:98)
        at com.google.zxing.client.android.DecodeHandler.handleMessage(DecodeHandler.java:59)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:148)
        at com.google.zxing.client.android.DecodeThread.run(DecodeThread.java:112)

It looks like the java.util.List.sort(…) method used in FinderPatternFinder.java:616 is not available on Android < API 24: https://developer.android.com/reference/java/util/List.html#sort(java.util.Comparator<?%2520super%2520E>)

Proposed solution: Use Collections.sort(possibleCenters, moduleComparator) instead of possibleCenters.sort(moduleComparator);

To make things more complicated: Android support for Java8 depends on the Android version. Some language features might be only available on newer Android versions: https://developer.android.com/studio/write/java8-support Requiring Java8 for zxing-core means either checking all used Java8 features if they are available Android < 7.0 or dropping support for Android < 7.0 completely.

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 33 (13 by maintainers)

Commits related to this issue

Most upvoted comments

Resolved in https://github.com/zxing/zxing/commit/4b573da62a175a16c59ef52df55edf08a413f4bf by just using the older library version.

But you’re surely aware that a LOT of other apps besides the one you’re talking about (and of which nobody really cares) depended on your library. Maybe you don’t see it as a bug, but yes, it sucks, and I am also looking for a replacemente due to this.

https://developer.android.com/studio/preview/features/?utm_medium=studio-assistant&utm_source=android-studio#j8-desugar

android {
  defaultConfig {
    // Required when setting minSdkVersion to 20 or lower
    multiDexEnabled true
  }

  compileOptions {
    // Flag to enable support for the new language APIs
    coreLibraryDesugaringEnabled true
    // Sets Java compatibility to Java 8
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
  }
}

D8 compiles a separate library DEX file that contains an implementation of the missing APIs and includes it in your app.

    .line 614
    iget-object v3, v0, Lcom/google/zxing/qrcode/detector/FinderPatternFinder;->possibleCenters:Ljava/util/List;

    sget-object v4, Lcom/google/zxing/qrcode/detector/FinderPatternFinder;->moduleComparator:Lcom/google/zxing/qrcode/detector/FinderPatternFinder$EstimatedModuleComparator;

    invoke-static {v3, v4}, Lj$/util/List$-EL;->sort(Ljava/util/List;Ljava/util/Comparator;)V

Now, we can keep minSdk in 19.

Please read all of the messages above. You can a) use 3.3.x, or b) target API 24.

I think everyone understands what you are saying, its just a matter of following a culture of backwards-comaptibility that has been broken here a little. There are tons of libraries that simply release as a completely different package when major changes like switching to JRE 8 is involved, exactly for these reasons. And on purpose.

ok - that regression really sucks

3 years late, but this thread was fun to read.

No, just use the last 3.3.x version. It’s all but identical.

Yes that’s correct.

hi, please make a compatible codes as android support library can do it. simply check the api level before some ‘feature’ like List.sort(), and fallback to compatbility mode if level arent targeted.

Im fixed it by

FinderPatternFinder.java
...
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
      possibleCenters.sort(moduleComparator);
    }else {
      Collections.sort(possibleCenters, moduleComparator);
    }

And I found List.sort() only in FinderPatternFinder.java, do anyone found it on any file?

and again, if you do so, please, dont increase contrived complexity further more. it was pain to read the codes.

Can I simply change the code to Collections.sort(possibleCenters, moduleComparator) without judging SDK version?

I meet the same problem. Can you use Collections.sort() api instead of List.sort()? As an app developer, we need to compatiable sdk version to 14, but zxing break backwards-comaptibility.

Requires Java 8+. Note: Android apps using this version must target API 24 or higher.

Please read all of the messages above. You can a) use 3.3.x, or b) target API 24.

This statements are a bit misleading. On android the target sdk is something different then the min sdk. And if I haven’t missed some essential part of this discussion the requirement is to have min sdk level of 24, right? See: https://developer.android.com/guide/topics/manifest/uses-sdk-element

Yes, I’m aware of what it requires and did it on purpose. You should probably be finding another library if you can’t target API 24. Or: simply use 3.3.3. These aren’t hard, but, do what you need to do.

There is no bug here…?