AndroidServiceClient.setCookie throws exception

I have a token and I’m trying to set it on the AndroidServiceClient however it throws an exception pasted below. Is there a different way to handle this?

this.Client.setCookie("ss-tok", token);

The error occurs JsonServiceClient:

 public void setCookie(String name, String value, Long expiresInSecs) {
        CookieManager cookieManager = (CookieManager)CookieHandler.getDefault();
        HttpCookie cookie = new HttpCookie(name, value);
        if (expiresInSecs != null) {
            cookie.setMaxAge(expiresInSecs);
        }
    // error occurs below
        cookieManager.getCookieStore().getCookies().add(cookie);
    }

E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.test.program, PID: 22798
java.lang.UnsupportedOperationException
    at java.util.Collections$UnmodifiableCollection.add(Collections.java:1097)
    at net.servicestack.client.JsonServiceClient.setCookie(JsonServiceClient.java:568)
    at net.servicestack.client.JsonServiceClient.setCookie(JsonServiceClient.java:558)
    at com.beyond4.daytripperadmin.dto.Data.SetToken(Data.java:14)
    at com.beyond4.daytripperadmin.LoginFragment$LoginWebViewClient$1.onReceiveValue(LoginFragment.java:155)
    at com.beyond4.daytripperadmin.LoginFragment$LoginWebViewClient$1.onReceiveValue(LoginFragment.java:150)
    at uf.onResult(Unknown Source:2)
    at org.chromium.android_webview.AwContents.a(PG:906)
    at aeG.run(Unknown Source:4)
    at android.os.Handler.handleCallback(Handler.java:873)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:193)
    at android.app.ActivityThread.main(ActivityThread.java:6669)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

Where are you initiating the AndroidServiceClient? This answer suggests you can try initializing it in onCreate():

CookieHandler.setDefault(new CookieManager());

I moved it into the activity’s onCreate which uses a singleton class and creates the client. Then later when I get the token I try to set it and it fails. I’ve tried your code as well and it still fails… I’ll keep researching.

By no means am I anything more than a beginner on Android development so take this with a grain of salt. I’m testing on SDK 28:

  • cookieManager.getCookieStore().getCookies().add(cookie) throws an error.

  • URI u = URI.create("https://theurl.com"); cookieManager.getCookieStore().add(null, cookie); seems to add the cookie HOWEVER every call to an authenticated service throws the following error: the input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or an illegal character among the padding characters.

  • The only way I could get an authenticated service to work with a token was to use a RequestFilter and set the Authorization Token via a header like this:

      Client.RequestFilter = new ConnectionFilter() {
              @Override
              public void exec(HttpURLConnection conn) {
                  conn.setRequestProperty("Authorization", "Bearer " + theToken);
              }
          };
    

You may want to test a simple authenticated service (with a token) and try to set a cookie with the current implementation of AndroidServiceClient.

The issue with local cookies should be resolved from v1.0.41.

I’ve also added support for setBearerToken() to be able to configure the Service Client with an Authorization Bearer {Token} HTTP Request Header and the setTokenCookie() typed API which wraps setCookie("ss-tok",...).

There’s also an overload for the AndroidServiceClient which lets you specify an android Context that you can use with:

AndroidServiceClient client = new AndroidServiceClient(baseUrl, getContext());

Which will persist cookies into the App’s SharedPreferences.

As always your support is excellent.

Since you probably only get mostly bugs and negative stuff here, I should say that it literally took me 5 minutes (on my second ever Android app test) to get an Android service stack client up and showing a list of items (non authenticated service). 99.9% of my time has been dedicated to learning the Android bits so a big kudos to Service Stack for making it so easy.

1 Like

Where can I download this? It isn’t listed on the plugin site, under beta nor nightly?

It’s the ServiceStack.Android’s package dependency:

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'net.servicestack:android:1.0.41'
}

net.servicestack:android:1.0.41 should be available

1 Like