sfuhrm / radiobrowser4j

RadioBrowser Java API library
Other
50 stars 8 forks source link

Android related questions #14

Closed green985 closed 9 months ago

green985 commented 1 year ago

I tried this library and after run example code, application crash and print this log. I sought this problem in web, but can't find any solution.

java.lang.RuntimeException: java.lang.ClassNotFoundException: Provider for jakarta.ws.rs.client.ClientBuilder cannot be found at jakarta.ws.rs.client.ClientBuilder.newBuilder(ClientBuilder.java:77) at de.sfuhrm.radiobrowser4j.RestClientFactory.newClient(RestClientFactory.java:27) at de.sfuhrm.radiobrowser4j.RadioBrowser.(RadioBrowser.java:112) at de.sfuhrm.radiobrowser4j.RadioBrowser.(RadioBrowser.java:79) at de.sfuhrm.radiobrowser4j.RadioBrowser.(RadioBrowser.java:131)

Thanks and have a great day.

green985 commented 1 year ago

Update

I change version to 2.0.5 (first android support) and library worked. I don't know why.

Thanks and have a great day.

sfuhrm commented 1 year ago

Thanks for the issue! As far as I understand, 2.2.4 did not work for you (see above), but 2.0.5 worked? In the background I upgraded the used REST library.

I guess the Android environment needs a different approach.

green985 commented 1 year ago

Yeah, you are right. 2.0.5 work no smoothly (have a different bug) but not bad as 2.2.4

Am I open another issue for this (different bug) or wait you for another release ?

sfuhrm commented 1 year ago

Well, this seems to be a more conceptual problem of the library that needs to be worked out, not a simple bug :-(. I find it important to document the problems, but don't expect a solution (before a major release).

As noted in other issues before, it could be possible to get around the ClassNotFoundException if you take the not-found classes out of the Android-build typical obfuscation (see #13 ).

Take a look here: https://developer.android.com/studio/build/shrink-code#keep-code

green985 commented 1 year ago

Yeah, but I work in debug project and not implement proguard or shrink code etc. But I will try and share result in this thread.

Other bug, just list map bug, duplicated key problem. It's nothing compare with that and also just exception when try to get country list.

I can still use library in 2.0.5 version and It's seem to be fine for me.

sfuhrm commented 1 year ago

"Provider for jakarta.ws.rs.client.ClientBuilder cannot be found" looks like there are some /META-INF/services/ files stripped out by the android packaging. I think the file in question will be a text file in the archive named /META-INF/services/jakarta.ws.rs.client.ClientBuilder. If you can put it there, we'll proceed one step.

green985 commented 1 year ago

Hi again, I try your advice but I think nothing change.

exclude 'META-INF/services/jakarta.ws.rs.client.ClientBuilder'

or maybe I do wrong way, I am not familiar with packagingOptions blocks. This line affect nothing, some exception still.

sfuhrm commented 1 year ago

Excludes is the opposite you're wanting:

The set of excluded patterns. Java resources matching any of these patterns do not get packaged in the APK.

I am not used to the resources packaging options myself, sorry.

green985 commented 1 year ago

Yeah, I try all tags for packagingOptions and no result.

Maybe, some of people can guide us. Until that day, I will continue with old library I think.

Bahir commented 1 year ago

"Provider for jakarta.ws.rs.client.ClientBuilder cannot be found" looks like there are some /META-INF/services/ files stripped out by the android packaging. I think the file in question will be a text file in the archive named /META-INF/services/jakarta.ws.rs.client.ClientBuilder. If you can put it there, we'll proceed one step.

I tried to use 2.2.4. Does not work with the same Provider not found problem. And, no, these directory and files are NOT stripped. There is the list of APK META-INF/services directory

com.fasterxml.jackson.core.JsonFactory com.fasterxml.jackson.core.ObjectCodec com.fasterxml.jackson.databind.Module jakarta.ws.rs.client.ClientBuilder jakarta.ws.rs.ext.RuntimeDelegate jakarta.xml.bind.JAXBContext kotlinx.coroutines.CoroutineExceptionHandler kotlinx.coroutines.internal.MainDispatcherFactory org.glassfish.hk2.extension.ServiceLocatorGenerator org.glassfish.jersey.internal.inject.InjectionManagerFactory org.glassfish.jersey.internal.spi.AutoDiscoverable

mraalex commented 1 year ago

I am having the same issue. Even with a simple sample application in Android. I am not an expert on gradle, pro-guard, etc. I think best is you download it an try to find out what the problem is.

https://download.changemystyle.com/radiobrowser4j.zip

sfuhrm commented 1 year ago

@mraalex thanks for the archive ... I'm not managing to import it to Android Studio, it is saying "Error: Module not specified". In Android studios "Edit configuration" dialogue I can't select a module, but I'd guess I would need to select "app". The stackoverflow posts dealing with this topic don't help. On command line I can gradle build it, but this I need to debug it in Android Studio to get a clue.

Is there a way to provide a example without another subproject which seems to confuse gradle / android studio?

Anyone having a quick hint?

mraalex commented 1 year ago

Tap on "Build Variants" on the left and make sure that Module:app is set on the debug version: playStoreFreeDebug

I am using: Android Studio Electric Eel | 2022.1.1 Patch 1 Runtime version: 11.0.15+0-b2043.56-9505619 amd64

If it still does not work you can also create a new project with your Android Studio, integrate the code and see if it is running on your side. Then send me the project.

sfuhrm commented 1 year ago

The Android mystery is solved, thanks to your help, guys! Thanks @mraalex and all other guys for the suggestions.

There needs to be some tweaking to make it run on Android. I am listing them in the following link:

https://github.com/sfuhrm/radiobrowser4j/blob/master/ANDROID.md

Demo

A demo printing radio stations to a full-screen-view is given in the following TAR ball:

radiobrowser4j-android-demo.tar.gz

fourofspades commented 1 year ago

Just came across these same issues with de.sfuhrm:radiobrowser4j:2.5.0

The "fix" relies on turning off codee shrink, minifyEnabled false

My app now bloats to over 2x the size :-(

Is there a way to use this library without turning off minify ?

mraalex commented 1 year ago

I had no minify enabled. The solution from shuhrm worked for me, even with minify.

fourofspades commented 1 year ago

Hmm, interesting, as the demo app linked above has minifyEnabled false, and yes it does build (using both 2.2.5 and 2.5.0), however Proguard is doing very little. if you set minifyEnabled true, it will fail to build. Adding the suggested warnings ignores to proguard-rules.pro it will then build, however using signed release builds will result in runtime crashes.

Adding the suggested keep classes, brings in even more warnings to exclude, and at this point, it's quite a away from looking like it can compile.

Wondering if anyone has a working Proguard they can share for someone that's using minifyEnabled true

mraalex commented 1 year ago

I have tested my signed release build. It works fine with minifyEnabled.

Pro-Guard: -keep class org.glassfish.hk2.utilities. { *; } -keep class org.glassfish.jersey.* { ; } -keep class org.jvnet.hk2.internal. { *; } -keep class de.sfuhrm.radiobrowser4j.* { ; }

build.gradle:

android.packagingOptions.resources.excludes += "*/.md" android.packagingOptions.resources.excludes += "*/.markdown" dependencies { implementation 'de.sfuhrm:radiobrowser4j:2.3.1'; implementation 'org.osgi:org.osgi.framework:1.10.0'; }

code: don't forget to set System property; System.setProperty("jakarta.ws.rs.client.ClientBuilder", "org.glassfish.jersey.client.JerseyClientBuilder"); browser = new RadioBrowser(5000, "Demo agent/1.0");

fourofspades commented 1 year ago

Is that the app linked above? https://github.com/sfuhrm/radiobrowser4j/issues/14#issuecomment-1625387804

mraalex commented 1 year ago

no. It is from another project. Did you try the official sample project from the readme for Android?

fourofspades commented 1 year ago

Using the project in comment #14 (which has all the suggested changes in this thread), both the minified and regular builds will compile, however the minified build crashes when launched.

Process: com.changemystyle.gentlewakeup, PID: 26798 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.changemystyle.gentlewakeup/com.changemystyle.gentlewakeup.FullscreenActivity}: java.lang.RuntimeException: java.lang.ClassNotFoundException: Provider for jakarta.ws.rs.client.ClientBuilder cannot be found

The only change I made was to change minifyEnabled true

fourofspades commented 1 year ago

This is where I am, using the exact same config.

Missing class jakarta.validation.MessageInterpolator$Context (referenced from: void org.glassfish.hk2.utilities.general.internal.MessageInterpolatorImpl$ContextResourceBundle.(jakarta.validation.MessageInterpolator$Context, java.util.Locale) and 2 other contexts) Missing class jakarta.validation.MessageInterpolator (referenced from: jakarta.validation.Validator org.glassfish.hk2.utilities.general.ValidatorUtilities.initializeValidator() and 3 other contexts) Missing class jakarta.validation.Path$Node (referenced from: boolean org.glassfish.hk2.utilities.general.ValidatorUtilities$1.isCascadable(java.lang.Object, jakarta.validation.Path$Node, java.lang.Class, jakarta.validation.Path, java.lang.annotation.ElementType) and 1 other context) Missing class jakarta.validation.Path (referenced from: boolean org.glassfish.hk2.utilities.general.ValidatorUtilities$1.isCascadable(java.lang.Object, jakarta.validation.Path$Node, java.lang.Class, jakarta.validation.Path, java.lang.annotation.ElementType) and 1 other context) Missing class jakarta.validation.TraversableResolver (referenced from: jakarta.validation.TraversableResolver org.glassfish.hk2.utilities.general.ValidatorUtilities.TRAVERSABLE_RESOLVER and 2 other contexts) Missing class jakarta.validation.Validation (referenced from: jakarta.validation.Validator org.glassfish.hk2.utilities.general.ValidatorUtilities.initializeValidator()) Missing class jakarta.validation.Validator (referenced from: jakarta.validation.Validator org.glassfish.hk2.utilities.general.ValidatorUtilities.validator and 4 other contexts) Missing class jakarta.validation.ValidatorContext (referenced from: jakarta.validation.Validator org.glassfish.hk2.utilities.general.ValidatorUtilities.initializeValidator()) Missing class jakarta.validation.ValidatorFactory (referenced from: jakarta.validation.Validator org.glassfish.hk2.utilities.general.ValidatorUtilities.initializeValidator()) Missing class jakarta.validation.metadata.ConstraintDescriptor (referenced from: void org.glassfish.hk2.utilities.general.internal.MessageInterpolatorImpl$ContextResourceBundle.(jakarta.validation.MessageInterpolator$Context, java.util.Locale) and 1 other context) Missing class java.beans.Introspector (referenced from: java.lang.String org.glassfish.hk2.utilities.reflection.BeanReflectionHelper.isAGetter(java.lang.reflect.Method)) Missing class java.lang.Module (referenced from: java.lang.Class javassist.util.proxy.DefineClassHelper.toClass(java.lang.Class, byte[])) Missing class javax.xml.stream.XMLStreamWriter (referenced from: javax.xml.stream.XMLStreamWriter org.glassfish.hk2.utilities.general.DelegatingXMLStreamWriter.writer and 35 other contexts) Missing class lombok.Generated (referenced from: java.lang.Integer de.sfuhrm.radiobrowser4j.AdvancedSearch$AdvancedSearchBuilder.bitrateMax and 154 other contexts) Missing class lombok.NonNull (referenced from: void de.sfuhrm.radiobrowser4j.EndpointDiscovery.(java.lang.String) and 19 other contexts) Missing class org.hibernate.validator.HibernateValidator (referenced from: jakarta.validation.Validator org.glassfish.hk2.utilities.general.ValidatorUtilities.initializeValidator()) Missing class org.osgi.annotation.versioning.ConsumerType (referenced from: org.osgi.framework.BundleListener and 1 other context) Missing class org.osgi.annotation.versioning.ProviderType (referenced from: org.osgi.framework.Bundle and 2 other contexts)

mraalex commented 1 year ago

You are not using the correct sample project. Package com.changemystyle.gentlewakeup is a non-working sample from me.

The official sample project is here: A demo printing radio stations to a full-screen-view is given in the following TAR ball:

radiobrowser4j-android-demo.tar.gz

You should continue from this project and if any issues, integrate the code lines I posted.

Using the project in comment #14 (which has all the suggested changes in this thread), both the minified and regular builds will compile, however the minified build crashes when launched.

Process: com.changemystyle.gentlewakeup, PID: 26798 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.changemystyle.gentlewakeup/com.changemystyle.gentlewakeup.FullscreenActivity}: java.lang.RuntimeException: java.lang.ClassNotFoundException: Provider for jakarta.ws.rs.client.ClientBuilder cannot be found

The only change I made was to change minifyEnabled true

fourofspades commented 1 year ago

Perhaps I am missing something obvious here, and that project doesn't build with minifyEnabled true as it's got an empty Proguard file.

fourofspades commented 1 year ago

Adding the proguard entries you mention (with typos fixes), results in the same errors I am seeing.

-keep class org.glassfish.hk2.utilities.** { *; }
-keep class org.glassfish.jersey.** { *; }
-keep class org.jvnet.hk2.internal.** { *; }
-keep class de.sfuhrm.radiobrowser4j.** { *; }

EDIT; perhaps not typos, but Markdown doing weird things. Added what I am using to a code block.

app.zip

mraalex commented 1 year ago

I am on holidays know for one week. Maybe sfuhrm can help you. I am just a user of the lib. If I come back and you have no solution I can take a look.

fourofspades commented 1 year ago

Had another look at this today, I got something working, with a less aggressive ruleset, (i have only tested voteForStation, listStations, listStations, listStationsBy API calls), however it's working in a shrunk and obfuscated build.

This is my reasonably optimised, working Proguard config, tested against radiobrowser4j 2.5.2, gradle 8.10, Android Studio Giraffe | 2022.3.1 using Java development and Java 1.8 language level.

-keep class org.glassfish.jersey.** { *; }
-keep class org.glassfish.hk2.** { *; }
-keep class org.jvnet.hk2.** { *; }
-keep class de.sfuhrm.radiobrowser4j.** { *; }
-keep class jakarta.inject** { *; }
-keep class jakarta.ws.rs.core** { *; }

-dontwarn jakarta.validation**
-dontwarn java.awt.image**
-dontwarn java.beans.Introspector**
-dontwarn javax.imageio**
-dontwarn javax.xml.stream**
-dontwarn lombok**
-dontwarn java.lang.Module**
-dontwarn java.lang.reflect**
-dontwarn org.glassfish.jersey.server**
-dontwarn org.hibernate.validator**
-dontwarn com.fasterxml.jackson.module.jaxb**
-dontwarn javax.activation**
-dontwarn org.osgi.annotation.versioning**
-dontwarn sun.misc.Contended*

I found this useful. Upload a regular build that's not been through ProGuard and play around in realtime with the ruleset.

https://playground.proguard.com/

sfuhrm commented 1 year ago

Hi guys,

I'm reopening the issue since there are open questions regarding proguard.

In the background the library is using Jersey Client which is using Jackson and JAXB, just to mention the bigger dependencies. It is failry ok to think that this amount of dependencies is not suited for an embedded target like Android.

I have no ready list of classes that need to be defined as exceptions to proguard so everything is working. One strategy that might work is to turn on verbose class loading (don't know whether Android has that) and then only include the classes from this list. But it is probably a quite time consuming task.

@fourofspades does your definition work for you? Does it make sense to already add it to the Android guide?

Stephan

sfuhrm commented 1 year ago

I have renamed this issue to "Android related questions" since it collects many good pointers for Android.

fourofspades commented 1 year ago

Yes, done a fair amount of testing today and it's working well for me.

I guess the only open question is why the shorter configuration worked for some but not for me...

On Sun, 16 Jul 2023, 16:44 Stephan Fuhrmann, @.***> wrote:

Hi guys,

I'm reopening the issue since there are open questions regarding proguard.

In the background the library is using Jersey Client which is using Jackson and JAXB, just to mention the bigger dependencies. It is failry ok to think that this amount of dependencies is not suited for an embedded target like Android.

I have no ready list of classes that need to be defined as exceptions to proguard so everything is working. One strategy that might work is to turn on verbose class loading (don't know whether Android has that) and then only include the classes from this list. But it is probably a quite time consuming task.

@fourofspades https://github.com/fourofspades does your definition work for you? Does it make sense to already add it to the Android guide https://github.com/sfuhrm/radiobrowser4j/blob/master/ANDROID.md?

Stephan

— Reply to this email directly, view it on GitHub https://github.com/sfuhrm/radiobrowser4j/issues/14#issuecomment-1637123394, or unsubscribe https://github.com/notifications/unsubscribe-auth/AOVZNJHF4ZGT47GVBYSCKETXQQD4PANCNFSM6AAAAAAR32ACHM . You are receiving this because you were mentioned.Message ID: @.***>

fourofspades commented 1 year ago

Updated to 2.5.2 and tested the Proguard, tested voting and searching API. it needed a rule tweak, which I changed in the comments above, and I also detailed the exact setup I am using.

fourofspades commented 1 year ago

Had some crashes from users running my app in the wild, using the radiobrowser code on Android. It's not obfuscation related, as it happens in debug on the android emulator. Reverting to 2.5.0 fixes the issue.

Interesting, it's only older devices that have this issue. Most of my bug reports come from Android 7.0 era.

Stack trace:

`

                                                                                                java.lang.NoSuchMethodError: No virtual method getParameterCount()I in class Ljava/lang/reflect/Constructor; or its super classes (declaration of 'java.lang.reflect.Constructor' appears in /system/framework/core-oj.jar)
                                                                                                    at com.fasterxml.jackson.databind.util.ClassUtil$Ctor.getParamCount(ClassUtil.java:1450)
                                                                                                    at com.fasterxml.jackson.databind.introspect.AnnotatedCreatorCollector._findPotentialConstructors(AnnotatedCreatorCollector.java:120)
                                                                                                    at com.fasterxml.jackson.databind.introspect.AnnotatedCreatorCollector.collect(AnnotatedCreatorCollector.java:70)
                                                                                                    at com.fasterxml.jackson.databind.introspect.AnnotatedCreatorCollector.collectCreators(AnnotatedCreatorCollector.java:61)
                                                                                                    at com.fasterxml.jackson.databind.introspect.AnnotatedClass._creators(AnnotatedClass.java:403)
                                                                                                    at com.fasterxml.jackson.databind.introspect.AnnotatedClass.getConstructors(AnnotatedClass.java:308)
                                                                                                    at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector._addCreators(POJOPropertiesCollector.java:613)
                                                                                                    at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector.collectAll(POJOPropertiesCollector.java:426)
                                                                                                    at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector.getPropertyMap(POJOPropertiesCollector.java:386)
                                                                                                    at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector.getProperties(POJOPropertiesCollector.java:233)
                                                                                                    at com.fasterxml.jackson.databind.introspect.BasicBeanDescription._properties(BasicBeanDescription.java:164)
                                                                                                    at com.fasterxml.jackson.databind.introspect.BasicBeanDescription.findProperties(BasicBeanDescription.java:239)
                                                                                                    at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory._findCreatorsFromProperties(BasicDeserializerFactory.java:328)
                                                                                                    at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory._constructDefaultValueInstantiator(BasicDeserializerFactory.java:272)
                                                                                                    at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory.findValueInstantiator(BasicDeserializerFactory.java:223)
                                                                                                    at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.buildBeanDeserializer(BeanDeserializerFactory.java:262)
                                                                                                    at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.createBeanDeserializer(BeanDeserializerFactory.java:151)
                                                                                                    at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer2(DeserializerCache.java:415)
                                                                                                    at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer(DeserializerCache.java:350)
                                                                                                    at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:264)
                                                                                                    at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:244)
                                                                                                    at com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer(DeserializerCache.java:142)
                                                                                                    at com.fasterxml.jackson.databind.DeserializationContext.findRootValueDeserializer(DeserializationContext.java:648)
                                                                                                    at com.fasterxml.jackson.databind.ObjectReader._prefetchRootDeserializer(ObjectReader.java:2430)
                                                                                                    at com.fasterxml.jackson.databind.ObjectReader.forType(ObjectReader.java:771)
                                                                                                    at org.glassfish.jersey.jackson.internal.jackson.jaxrs.base.ProviderBase.readFrom(ProviderBase.java:819)
                                                                                                    at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.invokeReadFrom(ReaderInterceptorExecutor.java:233)
                                                                                                    at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.aroundReadFrom(ReaderInterceptorExecutor.java:212)
                                                                                                    at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:132)
                                                                                                    at org.glassfish.jersey.spi.ContentEncoder.aroundReadFrom(ContentEncoder.java:102)
                                                                                                    at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:132)
                                                                                                    at org.glassfish.jersey.message.internal.MessageBodyFactory.readFrom(MessageBodyFactory.java:1072)
                                                                                                    at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:919)
                                                                                                    at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:853)
                                                                                                    at org.glassfish.jersey.client.ClientResponse.readEntity(ClientResponse.java:298)
                                                                                                    at org.glassfish.jersey.client.InboundJaxrsResponse$1.call(InboundJaxrsResponse.java:93)
                                                                                                    at org.glassfish.jersey.internal.Errors.process(Errors.java:292)
                                                                                                    at org.glassfish.jersey.internal.Errors.process(Errors.java:274)
                                                                                                    at org.glassfish.jersey.internal.Errors.process(Errors.java:205)
                                                                                                    at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:365)
                                                                                                    at org.glassfish.jersey.client.InboundJaxrsResponse.runInScopeIfPossible(InboundJaxrsResponse.java:244)
                                                                                                    at org.glassfish.jersey.client.InboundJaxrsResponse.readEntity(InboundJaxrsResponse.java:90)
                                                                                                    at de.sfuhrm.radiobrowser4j.RadioBrowser.voteForStation(RadioBrowser.java:561)

`

sfuhrm commented 1 year ago

Interesting! The Constructor.getParameterCount() was introduced in JDK 1.8.

Referring to this post, Android 7 had support for JDK 8. I am not sure whether this is correct when I read about your problem, as it would mean the Android is running JDK 7 or older.

I see a dilemma here:

  1. Reverting back to rb4j version 2.5.0 uses jackson 2.13.3 which has several security risks.
  2. The current rb4j version 2.5.2 uses jackson 2.14.1 which has the less security risks, but it breaks with older JDKs than 8.

The target of this library is JDK 8 at the moment. Older really feels wrong.

I'd suggest for antique Android support to Maven-exclude the Jackson stuff in your Application's pom/gradle file and depending on jackson libs 2.13.3.

In the long term the approach using the Jersey-JAXRS-client needs to be replaced by something with less footprint to work smooth with Android.

fourofspades commented 11 months ago

Guess this is the related bug report:

https://github.com/FasterXML/jackson-databind/issues/3702

sfuhrm commented 9 months ago

Just for you info, guys. I've refactored the code a bit to go through 1 class. This way it will be easier to replace the fat dependency towards Jersey / JAX-RS / Jackson with something more lightweight like Okhttp and Gson.

fourofspades commented 9 months ago

That's great news. Was this additional work something you were planning on doing, or are you expecting an android fork?

sfuhrm commented 9 months ago

@fourofspades I am planning an android fork, or a more android-friendly fork. I think reducing the dependency footprint is a good thing anyway.

fourofspades commented 9 months ago

Thanks, that's great news, I'm still on version 2.50 as it was the last version I was able to persuade to work under Android.

sfuhrm commented 9 months ago

A little teaser: This is the (non test) dependencies of the new library. Left is the current version with Jersey and jackson, right is the new version with only GSon. I'll upload an alpha release soon. The library has changed a lot under the hood.

[INFO] Scanning for projects...                 [INFO] Scanning for projects...
[INFO]                              [INFO] 
[INFO] ----------------------< de.sfuhrm:radiobrowser4j >----   [INFO] ----------------------< de.sfuhrm:radiobrowser4j >----
[INFO] Building RadioBrowser4j 2.6.2-SNAPSHOT           [INFO] Building RadioBrowser4j 2.6.2-SNAPSHOT
[INFO]   from pom.xml                       [INFO]   from pom.xml
[INFO] --------------------------------[ jar ]---------------   [INFO] --------------------------------[ jar ]---------------
[INFO]                              [INFO] 
[INFO] --- dependency:3.6.1:tree (default-cli) @ radiobrowser   [INFO] --- dependency:3.6.1:tree (default-cli) @ radiobrowser
[INFO] de.sfuhrm:radiobrowser4j:jar:2.6.2-SNAPSHOT      [INFO] de.sfuhrm:radiobrowser4j:jar:2.6.2-SNAPSHOT
[INFO] +- org.glassfish.jersey.core:jersey-client:jar:3.0.12: | [INFO] +- com.google.code.gson:gson:jar:2.10.1:compile
[INFO] |  +- jakarta.ws.rs:jakarta.ws.rs-api:jar:3.0.0:compil <
[INFO] |  +- org.glassfish.jersey.core:jersey-common:jar:3.0. <
[INFO] |  |  +- jakarta.annotation:jakarta.annotation-api:jar <
[INFO] |  |  \- org.glassfish.hk2:osgi-resource-locator:jar:1 <
[INFO] |  \- jakarta.inject:jakarta.inject-api:jar:2.0.1:comp <
[INFO] +- org.glassfish.jersey.media:jersey-media-json-jackso <
[INFO] |  +- org.glassfish.jersey.ext:jersey-entity-filtering <
[INFO] |  +- com.fasterxml.jackson.core:jackson-annotations:j <
[INFO] |  +- com.fasterxml.jackson.core:jackson-databind:jar: <
[INFO] |  +- com.fasterxml.jackson.module:jackson-module-jaka <
[INFO] |  \- jakarta.xml.bind:jakarta.xml.bind-api:jar:3.0.1: <
[INFO] |     \- com.sun.activation:jakarta.activation:jar:2.0 <
[INFO] +- org.glassfish.jersey.inject:jersey-hk2:jar:3.0.12:c <
[INFO] |  +- org.glassfish.hk2:hk2-locator:jar:3.0.3:compile  <
[INFO] |  |  +- org.glassfish.hk2.external:aopalliance-repack <
[INFO] |  |  +- org.glassfish.hk2:hk2-api:jar:3.0.3:compile   <
[INFO] |  |  \- org.glassfish.hk2:hk2-utils:jar:3.0.3:compile <
[INFO] |  \- org.javassist:javassist:jar:3.29.2-GA:compile    <
[INFO] +- org.slf4j:slf4j-api:jar:2.0.11:compile        [INFO] +- org.slf4j:slf4j-api:jar:2.0.11:compile
[INFO] +- org.slf4j:slf4j-ext:jar:2.0.11:compile        [INFO] +- org.slf4j:slf4j-ext:jar:2.0.11:compile
[INFO] +- org.projectlombok:lombok:jar:1.18.30:provided     [INFO] +- org.projectlombok:lombok:jar:1.18.30:provided
[INFO] |  +- com.fasterxml.jackson.core:jackson-core:jar:2.15 <
[INFO] ------------------------------------------------------   [INFO] ------------------------------------------------------
[INFO] BUILD SUCCESS                        [INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------   [INFO] ------------------------------------------------------
[INFO] Total time:  0.752 s                   | [INFO] Total time:  0.779 s
[INFO] Finished at: 2024-01-12T21:03:21+01:00             | [INFO] Finished at: 2024-01-12T21:03:12+01:00
[INFO] ------------------------------------------------------   [INFO] ------------------------------------------------------
sfuhrm commented 9 months ago

I have release a version 3.0.0 with quite some changes under the hood and some breaking changes in the API. It is marked as a pre-release. It is not using the JAX-RS / Jetty dependencies anymore which caused problems for this issue and Android. It is internally using an URLConnection which is also what the Android recommendations are. For JSON serialization it is now using the more lightweight Gson library from Google.

Since the information in this thread only affects the previous versions, I'm closing the issue. If you find problems with the 3.0.0 version feel free to open new issues! Thank you all for your help and support!

sfuhrm commented 9 months ago

See

https://github.com/sfuhrm/radiobrowser4j/releases/tag/radiobrowser4j-parent-3.0.0

fourofspades commented 9 months ago

Getting excellent results. It's reduced the size of my executable by almost 2Mb, which is great news, the only thing I needed to keep in my Proguard file was:

-dontwarn lombok**
-keep class de.sfuhrm.radiobrowser4j.** { *; }

Tested the following API calls:

Along with endpoint discovery and the the new ConnectionParams.builder. Everything working perfectly.

Many thanks.

sfuhrm commented 9 months ago

@fourofspades thanks for feedback! Let me know if you find bugs.

fourofspades commented 9 months ago

Feels like the last step might be to embed Proguard configuration , so it works with Android out the box, with no additional changes.

sfuhrm commented 9 months ago

@fourofspades is there something that you could provide for that? May be in the form of a PR?

fourofspades commented 9 months ago

Hi, did a bit of research online, and it appears this is one of the differences between a generic jar and an android specific aar library, the aar can include proguard configuration of the library itself, and it's not possible with jar.

As it's only 2 lines to include, it's perhaps easier to update the readme, than mess around with an Android specific library.

sfuhrm commented 9 months ago

@fourofspades thanks for your research! Whatever way suits you, feel free to drop me either the passage for the readme or send a PR which updates it.

sfuhrm commented 9 months ago

@fourofspades PR merged. Thanks!