Git Product home page Git Product logo

Comments (12)

reverbel avatar reverbel commented on August 18, 2024 2

Apologies for the very long comment above. Some additional thoughts...

This would be an easy way of making java-stellar-jdk work on Android:

  1. Create refactored versions the Apache jars commons-codec, httpclient, and fluent-hc, with packages org.apache.* renamed to org.apache.android.*.
  2. Create a special version of java-stellar-jdk that uses the renamed (org.apache.android.*) Apache packages instead of the original ones.

Of course this "solution" has two big inconveniences. First, the trouble of keeping parallel versions of Apache projects just to circumvent a silly Android-specific name clashing issue. Second, the trouble of having a special version of java-stellar-jdk for Android.

The second inconvenience could be avoided by using dependency injection, so that java-stellar-jdk is
configured at runtime to depend either on org.apache.* packages or on org.apache.android.* packages.

It appears that the ideal solution for running java-stellar-jdk on Android would be to move away from Apache HttpClient and Commons Codec.

from java-stellar-sdk.

bartekn avatar bartekn commented on August 18, 2024 1

I prepared a JAR file without dependencies: https://www.dropbox.com/s/0z3bu5c67mv9eka/stellar-sdk.jar?dl=0 Please do not use it in production, just check if it works for you and let me know.

from java-stellar-sdk.

overcat avatar overcat commented on August 18, 2024

The project used HttpClient, but it is deprecated in Android SDK 23.
You can check here: https://developer.android.com/sdk/api_diff/23/changes.html

from java-stellar-sdk.

luizjrrd avatar luizjrrd commented on August 18, 2024

@bartekn tried your jar but it didnt worked for me.

Take a look at this: https://developer.android.com/about/versions/marshmallow/android-6.0-changes.html#behavior-apache-http-client

I think we need to update Server.java class (https://github.com/stellar/java-stellar-sdk/blob/master/src/main/java/org/stellar/sdk/Server.java) in order to use HttpUrlConnection (https://developer.android.com/reference/java/net/HttpURLConnection.html)

Could you help me with that?

from java-stellar-sdk.

srayhunter avatar srayhunter commented on August 18, 2024

@SunriseCompany I have committed the fixes for the ability to use Android with the java sdk. Check it out here - https://github.com/srayhunter/java-stellar-sdk

Feedback welcome!

from java-stellar-sdk.

eschgi avatar eschgi commented on August 18, 2024

@srayhunter I have tried your fixes but with no luck. I get apk build errors when i use my own compiled version of the java-stellar-sdk jar. I've build the jar with gradlew.bat build. I have also tried to change the guava dependency from guava to guava-android, but without luck.

Have you maybe a working android sample project?

from java-stellar-sdk.

eschgi avatar eschgi commented on August 18, 2024

@srayhunter I get this error when i build the apk: Error:Execution failed for task ':app:transformResourcesWithMergeJavaResForDebug'.

More than one file was found with OS independent path 'javax/annotation/CheckReturnValue.java'

Someone know what i'm doing wrong?

from java-stellar-sdk.

srayhunter avatar srayhunter commented on August 18, 2024

@eschgi I found a couple issues last night that I will fix today and let you know when those are committed. Thank you for the feedback! Much appreciated.

from java-stellar-sdk.

eschgi avatar eschgi commented on August 18, 2024

@srayhunter Ok perfect. Eventually for the future it would be better to use OkHttp for all http requests. OkHttp supports additionally HTTP/2 and supports also asynchronous programming patterns.

from java-stellar-sdk.

nono3551 avatar nono3551 commented on August 18, 2024

@srayhunter @bartekn
Hello is there any sollution for this issue? I am using newest android studio and compiling project with SDK 26 and this library is not working. I saw that there were some changes in android SDK but is there any way I can make this lib working?

Thank you.

from java-stellar-sdk.

reverbel avatar reverbel commented on August 18, 2024

After spending some time on this issue, I confirm that java-stellar-jdk does not work on Android because it uses Apache classes that cannot be loaded into the Android plataform. The culprit classes live on packages org.apache.http and org.apache.commons.codec.

Surprisingly, the problem shows up even on recent (6.0 and later) versions of Android, after support for the Apache HTTP client was officially removed from the platform (https://developer.android.com/about/versions/marshmallow/android-6.0-changes.html).

What happens on earlier versions of Android is clear. Those versions are bundled with a legacy version of Apache's HttpClient, which depends on Commons Codec. The legacy versions of HttpClient and Codec are loaded as part of the Android platform, taking precedence over any classes in the application's classpath.

java-stellar-jdk does not work with the legacy Apache classes, as it calls HttpClient and Codec methods that do not exist on those ancient classes. Moreover, the legacy classes prevent java-stellar-jdk from using newer versions of those classes. The newer versions of those classes collide with the (pre-loaded) legacy versions. The Android bytecode translator detect the conflicts and does not convert the newer class files into the dex format.

One would expect that this problem would vanish from Android 6.0 (API 23) on, after support to the legacy Apache classes was officially dropped from the platform. However, this did not happen, and here is where things get messy. Even though those classes are not exposed as part of any user-visible Android APIs, it appears that they somehow remain existing within Android and still prevent applications to load newer HttpClient and Codec versions.

To demonstrate the problem, I ran a quick experiment on Android 7.0. My experiment did not use java-stellar-jdk at all. This is the relevant code:

import org.apache.commons.codec.binary.Base64;
...
    public void onClick(View view) {
        String base64Encoded = "...";
        Base64 base64Codec = new Base64();
        byte[] decoded = base64Codec.decode(base64Encoded);
        Snackbar.make(view, "decoded: " + Arrays.toString(decoded),
                      Snackbar.LENGTH_LONG)
                .setAction("Action", null).show();
                }
        }

The code above fails with the following exception:

java.lang.NoSuchMethodError: No virtual method decode(Ljava/lang/String;)[B in class Lorg/apache/commons/codec/binary/Base64; or its super classes (declaration of 'org.apache.commons.codec.binary.Base64' appears in /system/framework/org.apache.http.legacy.boot.jar)
    at com.example.codecandhttptest.MainActivity$1.onClick(MainActivity.java:35)
    at android.view.View.performClick(View.java:6261)
    at android.view.View$PerformClick.run(View.java:23748)
    at android.os.Handler.handleCallback(Handler.java:751)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:154)
    at android.app.ActivityThread.main(ActivityThread.java:6776)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1520)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1410)

The exception above was produced on Android 7.0, by an app that had commons-codec:1.5 as one of the its dependencies:

dependencies {
    ...
    implementation 'commons-codec:commons-codec:1.5'
}

Note the information at the end of the first line of the stack trace above (declaration of 'org.apache.commons.codec.binary.Base64' appears in /system/framework/org.apache.http.legacy.boot.jar). Instead of loading class org.apache.commons.codec.binary.Base64 from commons-codec:1.5, Android 7.0 is still using a legacy version of that class, which has no method decode(String).

To remove any doubt, I ran a second test. Grabbed the source code for commons-codec:1.5, refactored it so that there would be no conflict with the legacy classes anymore (just renamed org.apache.* to org.apache.android.*), and made my quick app use the refactored version of commons-codec:

dependencies {
    ...
    implementation files('libs/commons-codec-1.5-refactored.jar')
}

Now the app ran with no errors, correctly showing the decoded string.

from java-stellar-sdk.

bartekn avatar bartekn commented on August 18, 2024

Fix for Android related-issues is now being reviewed: #72

You can check it out but pulling android branch and running ./gradlew jar to build a JAR.

from java-stellar-sdk.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.