[GH-ISSUE #10] Support for Android below version 8, API 24 #7

Closed
opened 2026-02-28 14:23:59 +03:00 by kerem · 15 comments
Owner

Originally created by @funtax on GitHub (May 4, 2021).
Original GitHub issue: https://github.com/devgianlu/librespot-android/issues/10

Right now, for example java.util.Base64 is available on Android 8+, otherwise there will be an exception like this:

E/AndroidRuntime: FATAL EXCEPTION: Thread-2
Process: xyz.gianlu.librespot.android, PID: 15947
java.lang.NoClassDefFoundError: Failed resolution of: Ljava/util/Base64;
at xyz.gianlu.librespot.common.Utils.toBase64(Utils.java:314)
at xyz.gianlu.librespot.core.Session.authenticatePartial(Session.java:435)
at xyz.gianlu.librespot.core.Session.authenticate(Session.java:333)
at xyz.gianlu.librespot.core.Session.access$600(Session.java:75)
at xyz.gianlu.librespot.core.Session$Builder.create(Session.java:1021)
at xyz.gianlu.librespot.android.LoginActivity$LoginThread.run(LoginActivity.java:96)
Caused by: java.lang.ClassNotFoundException: Didn't find class "java.util.Base64" on path: DexPathList
at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)

We might need to find a workaround if we want to support older Android-versions.

https://stackoverflow.com/questions/47431337/base64-support-for-different-api-levels

Originally created by @funtax on GitHub (May 4, 2021). Original GitHub issue: https://github.com/devgianlu/librespot-android/issues/10 Right now, for example java.util.Base64 is available on Android 8+, otherwise there will be an exception like this: E/AndroidRuntime: FATAL EXCEPTION: Thread-2 Process: xyz.gianlu.librespot.android, PID: 15947 java.lang.NoClassDefFoundError: Failed resolution of: Ljava/util/Base64; at xyz.gianlu.librespot.common.Utils.toBase64(Utils.java:314) at xyz.gianlu.librespot.core.Session.authenticatePartial(Session.java:435) at xyz.gianlu.librespot.core.Session.authenticate(Session.java:333) at xyz.gianlu.librespot.core.Session.access$600(Session.java:75) at xyz.gianlu.librespot.core.Session$Builder.create(Session.java:1021) at xyz.gianlu.librespot.android.LoginActivity$LoginThread.run(LoginActivity.java:96) Caused by: java.lang.ClassNotFoundException: Didn't find class "java.util.Base64" on path: DexPathList[[zip file "/data/app/xyz.gianlu.librespot.android-1/base.apk"],nativeLibraryDirectories=[/data/app/xyz.gianlu.librespot.android-1/lib/arm, /data/app/xyz.gianlu.librespot.android-1/base.apk!/lib/armeabi-v7a, /system/lib, /vendor/lib]] at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56) We might need to find a workaround if we want to support older Android-versions. https://stackoverflow.com/questions/47431337/base64-support-for-different-api-levels
kerem 2026-02-28 14:23:59 +03:00
Author
Owner

@funtax commented on GitHub (May 4, 2021):

Maybe we might use a 3rd-party-library in librespot-java, like this one to be compatible with all platforms?
http://iharder.sourceforge.net/current/java/base64/

<!-- gh-comment-id:831820368 --> @funtax commented on GitHub (May 4, 2021): Maybe we might use a 3rd-party-library in librespot-java, like this one to be compatible with all platforms? http://iharder.sourceforge.net/current/java/base64/
Author
Owner

@funtax commented on GitHub (May 4, 2021):

Or we could use a simple workaround inside the Utils-Class like:

try {
        Class.forName("java.util.Base64");
        ...
    } catch(ClassNotFoundException e) {
        Class.forName("android.util.Base64");
...
    }
<!-- gh-comment-id:831827931 --> @funtax commented on GitHub (May 4, 2021): Or we could use a simple workaround inside the Utils-Class like: ``` try { Class.forName("java.util.Base64"); ... } catch(ClassNotFoundException e) { Class.forName("android.util.Base64"); ... } ```
Author
Owner

@funtax commented on GitHub (May 4, 2021):

I will try to send a PR for the Base64-stuff at librespot-java later.

<!-- gh-comment-id:832151769 --> @funtax commented on GitHub (May 4, 2021): I will try to send a PR for the Base64-stuff at librespot-java later.
Author
Owner

@funtax commented on GitHub (May 5, 2021):

I have changed librespot-java and am using the "Class.forName"-idea to not introduce another non-required dependency.
It's now working on my Android 7 with tremolo-decoder.
Will flash Android 6 on another device and check if it's working there too.

<!-- gh-comment-id:832471732 --> @funtax commented on GitHub (May 5, 2021): I have changed librespot-java and am using the "Class.forName"-idea to not introduce another non-required dependency. It's now working on my Android 7 with tremolo-decoder. Will flash Android 6 on another device and check if it's working there too.
Author
Owner

@funtax commented on GitHub (May 5, 2021):

With the linked PR at librespot-java this is now working fine on my Android 7 with libtremolo.
Will try it on even older versions.

<!-- gh-comment-id:832524547 --> @funtax commented on GitHub (May 5, 2021): With the linked PR at librespot-java this is now working fine on my Android 7 with libtremolo. Will try it on even older versions.
Author
Owner

@funtax commented on GitHub (May 5, 2021):

Android 6 won't work, it for example crashes here:

public static void registerDecoder(@NotNull SuperAudioFormat format, @NotNull Class<? extends Decoder> clazz) {
      ((HashSet)decoders.computeIfAbsent(format, (key) -> {
          return new HashSet(5);
      })).add(clazz);
  }

Pretty sure it's not worth any effort.

@devgianlu I would leave it up to you if you merge my PR at librespot-java, then we seem to have support for Android 7+.
Otherwise you could of course leave it as is and we have support for Android 8+.

<!-- gh-comment-id:832619078 --> @funtax commented on GitHub (May 5, 2021): Android 6 won't work, it for example crashes here: ``` public static void registerDecoder(@NotNull SuperAudioFormat format, @NotNull Class<? extends Decoder> clazz) { ((HashSet)decoders.computeIfAbsent(format, (key) -> { return new HashSet(5); })).add(clazz); } ``` Pretty sure it's not worth any effort. @devgianlu I would leave it up to you if you merge my PR at librespot-java, then we seem to have support for Android 7+. Otherwise you could of course leave it as is and we have support for Android 8+.
Author
Owner

@devgianlu commented on GitHub (May 5, 2021):

Supporting Android 6 would require to remove all lambdas which is not something I am willing to do as it would significantly reduce the code quality. I think Android 7+ support is enough.

<!-- gh-comment-id:832623814 --> @devgianlu commented on GitHub (May 5, 2021): Supporting Android 6 would require to remove all lambdas which is not something I am willing to do as it would significantly reduce the code quality. I think Android 7+ support is enough.
Author
Owner

@mitschwimmer commented on GitHub (May 5, 2021):

@devgianlu I agree that Android 7 is enough. But for the record, it should not be needed to remove lambdas etc. The Android Gradle Plugin >4 can do bytecode transformation for modules and 3rd party libraries. I have to work with Android 6 quite a bit and this feature is a lifesaver. In case you are curious: https://developer.android.com/studio/write/java8-support#library-desugaring

<!-- gh-comment-id:832883945 --> @mitschwimmer commented on GitHub (May 5, 2021): @devgianlu I agree that Android 7 is enough. But for the record, it should not be needed to remove lambdas etc. The Android Gradle Plugin >4 can do bytecode transformation for modules and 3rd party libraries. I have to work with Android 6 quite a bit and this feature is a lifesaver. In case you are curious: https://developer.android.com/studio/write/java8-support#library-desugaring
Author
Owner

@devgianlu commented on GitHub (May 5, 2021):

Oh wow, didn't know that existed. Is it enough to run everything properly or are there additional changes needed?

<!-- gh-comment-id:832885138 --> @devgianlu commented on GitHub (May 5, 2021): Oh wow, didn't know that existed. Is it enough to run everything properly or are there additional changes needed?
Author
Owner

@mitschwimmer commented on GitHub (May 5, 2021):

In our case updating the gradle config as in the documentation was all that was needed.

<!-- gh-comment-id:832887873 --> @mitschwimmer commented on GitHub (May 5, 2021): In our case updating the gradle config as in the documentation was all that was needed.
Author
Owner

@devgianlu commented on GitHub (May 5, 2021):

Nice, can you push that? Possibly lowering the min SDK if needed.

<!-- gh-comment-id:832896228 --> @devgianlu commented on GitHub (May 5, 2021): Nice, can you push that? Possibly lowering the min SDK if needed.
Author
Owner

@mitschwimmer commented on GitHub (May 5, 2021):

Sure, I will push to android-decoder as master is currently non functional due to changes in librespot-java. I will lower the API level to 23 if that works on my test device.

<!-- gh-comment-id:832913823 --> @mitschwimmer commented on GitHub (May 5, 2021): Sure, I will push to android-decoder as master is currently non functional due to changes in librespot-java. I will lower the API level to 23 if that works on my test device.
Author
Owner

@devgianlu commented on GitHub (May 5, 2021):

You need to tell Gradle to refetch the dependencies. It's a bit of a pain to get Android Studio to understand. You might need to invalidate cache and restart too.

<!-- gh-comment-id:832917537 --> @devgianlu commented on GitHub (May 5, 2021): You need to tell Gradle to refetch the dependencies. It's a bit of a pain to get Android Studio to understand. You might need to invalidate cache and restart too.
Author
Owner

@mitschwimmer commented on GitHub (May 5, 2021):

I pushed to android-decoder. Master is broken due to "Decoders.replaceDecoder()" being changed in librespot-lib. Android Studio is a mess sometimes, but this time it is innocent 😄
API level 23 is now possible java syntax wise but it fails to display the player-controls on my device. Maybe you want to give it a go on your Android 6 device? I will not look further into it without anyone asking, enough Android 6 at work 😉

<!-- gh-comment-id:832931735 --> @mitschwimmer commented on GitHub (May 5, 2021): I pushed to android-decoder. Master is broken due to "Decoders.replaceDecoder()" being changed in librespot-lib. Android Studio is a mess sometimes, but this time it is innocent :smile: API level 23 is now possible java syntax wise but it fails to display the player-controls on my device. Maybe you want to give it a go on your Android 6 device? I will not look further into it without anyone asking, enough Android 6 at work :wink:
Author
Owner

@devgianlu commented on GitHub (May 5, 2021):

I pushed to android-decoder. Master is broken due to "Decoders.replaceDecoder()" being changed in librespot-lib. Android Studio is a mess sometimes, but this time it is innocent 😄

Right, will be fixed when I merge #9.

API level 23 is now possible java syntax wise but it fails to display the player-controls on my device. Maybe you want to give it a go on your Android 6 device? I will not look further into it without anyone asking, enough Android 6 at work 😉

Will have a look.

<!-- gh-comment-id:832934289 --> @devgianlu commented on GitHub (May 5, 2021): > I pushed to android-decoder. Master is broken due to "Decoders.replaceDecoder()" being changed in librespot-lib. Android Studio is a mess sometimes, but this time it is innocent 😄 Right, will be fixed when I merge #9. > API level 23 is now possible java syntax wise but it fails to display the player-controls on my device. Maybe you want to give it a go on your Android 6 device? I will not look further into it without anyone asking, enough Android 6 at work 😉 Will have a look.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/librespot-android#7
No description provided.