Hey guys! Maybe someone has gone through a similar...
# library-development
r
Hey guys! Maybe someone has gone through a similar thing.. How bad is this? I mean.. it feels pretty hacky, but it's just sooo much more convenient to make users of my library able to write unit tests with no additional setup 😛
Copy code
@SuppressLint("NewApi", "ObsoleteSdkInt")
internal fun ByteArray.toBase64Str(): String {
    // Both these methods (from java util and android util) seem to
    // do exactly the same.
    // The second doesn't work on Unit tests and the first doesn't work
    // on older devices.
    // Also, on unit tests SDK_INT is 0, but we're running on the developer's machine
    // So we can still use java.util in that case

    return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O || Build.VERSION.SDK_INT == 0) {
        java.util.Base64.getUrlEncoder().encodeToString(this)
    } else {
        android.util.Base64.encodeToString(this, Base64.URL_SAFE or Base64.NO_WRAP)
    }
}
either this, or just use java.util if
SDK_INT == 0
, meaning always use the android version on non-tests
e
I wouldn't be a big fan of that approach - running different code in unit tests vs production
but it's base64 which is pretty well understood (outside of padding edge-cases), so maybe it's ok…
r
same..but unfortunately I cannot use the first always on production..I can use it if SDK > O
so there is always (if I go with something like this) a split somewhere
e
personally I'd always use `android.util.Base64`; it forces your unit tests to use Robolectric, but at least that's literally the same code as in the the Android SDK
ideally you could just use
java.util.Base64
and let the Android toolchain desugar it as necessary. unfortunately that's no the case now, but there's a feature request: https://issuetracker.google.com/issues/171293709
r
that's what I have now.. but you know this is a very minor detail and its the only reason why developers have to use roboelectric 😛 (at least for the kinds of tests people tend to do around my library). Seems like a huge waste, you know?
But I get where you're coming from
ideally you could just use
java.util.Base64
and let the Android toolchain desugar it as necessary. unfortunately that's no the case now, but there's a feature request: https://issuetracker.google.com/issues/171293709
Interesting, I'll check this. It's not a solution right now, but it's good to check for sure 🙂
e
alternately, if you've already got it as a dependency, okio.base64 will work regardless of Android/JVM
r
unfortunately, no 😞
e
huh, pretty rare to see an android app without some transitive dependency on retrofit, okhttp, okio, or anything of that sort… but ok
r
I'm not building an app though, I'm building a library 😞
I don't want to force this dependency on my users
The only other thing i can think of is to have these methods behind some interface, have two impl (one uses android, other uses java) then let users of the library opt in explicitly to the java one in tests. Like some static call which replaces the impls used. But it is way less convinient.. new APIs, documentation...and hoping people see that before opening an issue on Github 😅
e
it is possible to use Gradle Module Metadata to give separate variants to JVM and Android consumers. it doesn't help with unit testing though