Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Any interest in making it Android friendly? #55

Open
boriguen opened this issue Jan 31, 2019 · 3 comments
Open

Any interest in making it Android friendly? #55

boriguen opened this issue Jan 31, 2019 · 3 comments

Comments

@boriguen
Copy link

Hi team,

I'm trying to use this library in an Android project with minSdkVersion 24. Here is a quick recap of the problems I face:

First, in order to avoid build issues with Apache httpcomponents, I had to exclude things as follow:
implementation('com.here.account:here-oauth-client:0.4.16') {
exclude group: 'org.apache.httpcomponents', module: 'httpclient'
}
And then I ended up using the pure JavaHttpProvider. I naively ran some unit tests and the authentication went through.
Then, I ran an instrumentation test and hit the wall mentioned above. Indeed, the library uses java.util.Base64 while Android only provides android.util.Base64, leading to the runtime issue: java.lang.NoClassDefFoundError: Failed resolution of: Ljava/util/Base64. I have found it in OAuth1Signer and SignatureCalculator.

My current workaround to get going is to copy those classes and make the small one-line changes to have them work with Android. I now use the Apache Base64 implementation in module 'commons-codec:commons-codec:1.10'.

I now have class AndroidOAuth1Signer.java:

import org.apache.commons.codec.binary.Base64;
.
.
String nonce = new String(Base64.encodeBase64(bytes)).substring(0, NONCE_LENGTH);

And class AndroidSignatureCalculator.java:

import org.apache.commons.codec.binary.Base64;
.
.
byte[] keyBytes = Base64.decodeBase64(key);
.
.
return new String(Base64.encodeBase64(signedBytes));
.
.
Plus a few more replacements

So I'm using those two classes above via third class ClientAuthorizationRequestProviderFromAndroidProperties.java:

package com.here.account.android;

import com.here.account.auth.OAuth1ClientCredentialsProvider;
import com.here.account.auth.provider.FromProperties;
import com.here.account.http.HttpProvider;
import com.here.account.util.SettableSystemClock;

import java.util.Properties;

/**
 * ClientAuthorizationRequestProviderFromAndroidProperties is the class allowing HERE AAA from given
 * properties.
 *
 * It does override getClientAuthorizer() in order to use classes
 * like AndroidOAuth1Signer and AndroidSignatureCalculator specifically modified for Android usage.
 *
 * @author guenebau
 * @since 1.0.0
 */
public class ClientAuthorizationRequestProviderFromAndroidProperties extends FromProperties {
    /**
     * The OAuth 1 signer created from properties.
     */
    private final AndroidOAuth1Signer mOAuth1Signer;

    /**
     * Class constructor.
     *
     * @param properties the properties containing credentials related values.
     */
    public ClientAuthorizationRequestProviderFromAndroidProperties(Properties properties) {
        super(new SettableSystemClock(), properties);
        mOAuth1Signer = new AndroidOAuth1Signer(
                getClock(),
                properties.getProperty(OAuth1ClientCredentialsProvider.FromProperties.ACCESS_KEY_ID_PROPERTY),
                properties.getProperty(OAuth1ClientCredentialsProvider.FromProperties.ACCESS_KEY_SECRET_PROPERTY));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public HttpProvider.HttpRequestAuthorizer getClientAuthorizer() {
        return mOAuth1Signer;
    }
}

It does work well and I can get authorization from HERE Account.

So please let me know if there is any Android friendly direction you would like to explore.

Thanks,

Boris

@kenmccracken
Copy link
Contributor

Hi Boris,

Thank you for your interest in making here-aaa-java-sdk builds be Android friendly. However, your proposed patch of using apache commons-codec may not be possible. Previous versions of this library used apache commons-codec. This library caused conflicts with dependencies pulled in for certain use cases. So, we had to switch to java.util.Base64 in #35 .

Does your Android-friendly requirement affect build time or only runtime? One possibility could be to create a Base64 interface in this project, allowing the developer to inject the Base64 implementation of choice, while keeping this project building with and using java.util.Base64 by default. However, for an Android environment, you could inject an alternate implementation of the Base64 interface using the your library of choice (commons-codec or android.util.Base64).

Regards,
-Ken

@boriguen
Copy link
Author

boriguen commented Feb 8, 2019

Hi Ken,

Thanks for the feedback. The issue happens at runtime since I guess, my build classpath includes the Java SDK. I could likely make the classpath stricter.

Anyways, I like the idea of injecting the Base64 implementation of choice at runtime.

Thanks,

Boris

@kenmccracken
Copy link
Contributor

Hi,

What about using Android >= API Level 26, or 8.0? It seems these might support java.util.Base64, according to https://developer.android.com/reference/java/util/Base64

Thanks,
-Ken

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants