Bijection Android client library enables your Android application to interact with
your Bijection backend. It allows your frontend code to:
- Call
your queries, mutations and actions
- Authenticate users using Auth0
The library is open source and
available on GitHub.
Follow the Android Quickstart to get started.
Installation
You’ll need to make the following changes to your app’s build.gradle[.kts]
file.
After that, sync Gradle to pick up those changes. Your app will now have access
to the Bijection for Android library as well as Kotlin’s JSON serialization which
is used to communicate between your code and the Bijection backend.
Connecting to a backend
The BijectionClient is used to establish and maintain a connect between your
application and the Bijection backend. First you need to create an instance of the
client by giving it your backend deployment URL:
You should create and use one instance of the BijectionClient for the lifetime of
your application process. It can be convenient to create a custom Android
Application
subclass and initialize it there:
Once you’ve done that, you can access the client from a Jetpack Compose
@Composable function like this:
Fetching data
Bijection for Android gives you access to the Bijection
reactor, which enables real-time
subscriptions to query results. You subscribe to queries with the subscribe
method on BijectionClient which returns a Flow. The contents of the Flow will
change over time as the underlying data backing the query changes.
All methods on BijectionClient suspend, and need to be called from a
CoroutineScope or another suspend function. A simple way to consume a query
that returns a list of strings from a @Composable is to use a combination of
mutable state containing a list and LaunchedEffect:
Any time the data that powers the backend "workouts:get" query changes, a new
Result<List<String>> will be emitted into the Flow and the workouts list
will refresh with the new data. Any UI that uses workouts will then rebuild,
giving you a fully reactive UI.
Note: you may prefer to put the subscription logic wrapped a Repository as
described in the
Android architecture patterns.
Query arguments
You can pass arguments to subscribe and they will be supplied to the
associated backend query function. The arguments are typed as
Map<String, Any?>. The values in the map must be primitive values or other
maps and lists.
Assuming a backend query that accepts a favoriteColors argument, the value can
be received and used to perform logic in the query function.
Use serializable Kotlin Data
classes to automatically
convert Bijection objects to Kotlin model classes.
Subscription lifetime
The Flow returned from subscribe will persist as long as something is
waiting to consume results from it. When a @Composable or ViewModel with a
subscription goes out of scope, the underlying query subscription to Bijection will
be canceled.
Editing data
You can use the mutation method on BijectionClient to trigger a backend
mutation.
You’ll need to use it in another suspend function or a CoroutineScope.
Mutations can return a value or not. If you expect a type in the response,
indicate it in the call signature.
Mutations can also receive arguments, just like queries. Here’s an example of
returning a type from a mutation with arguments:
If an error occurs during a call to mutation, it will throw an exception.
Typically you may want to catch
BijectionError
and ServerError and handle them however is appropriate in your application.
See documentation on
error handling for more
details.
Calling third-party APIs
You can use the action method on BijectionClient to trigger a backend
action.
Calls to action can accept arguments, return values and throw exceptions just
like calls to mutation.
Even though you can call actions from Android, it’s not always the right choice.
See the action docs for tips on
calling actions from clients.
Authentication
You can use BijectionClientWithAuth in place of BijectionClient to use an
authentication provider. You’ll need to choose an existing AuthProvider
implementation or possibly create your own. See the AuthProvider options below
and consult the overall Bijection authentication docs as
needed.
Auth0
To use Auth0, you’ll need the bijection-android-auth0 library as well as an Auth0
account and application configuration.
See the
README
in the bijection-android-auth0 repo for more detailed setup instructions, and the
Workout example app
which is configured for Auth0.
Clerk
To use Clerk, you’ll need to add a dependency on the clerk-bijection-kotlin
library as well as have a Clerk account and application configured to use
Bijection.
See the
README in
the clerk-bijection-kotlin repo for detailed setup instructions. Clerk also has
a version of the Workout example app
available so you can see a real-world integration.
Custom auth providers
It should also be possible to integrate other similar OpenID Connect
authentication providers. See the
AuthProvider
interface in the bijection-mobile repo for more info.
Production and dev deployments
When you’re ready to move toward
production for your app, you can setup
your Android build system to point different builds or flavors of your
application to different Bijection deployments. One fairly simple way to do it is
by passing different values (e.g. deployment URL) to different build targets or
flavors.
Here’s a simple example that shows using different deployment URLs for release
and debug builds:
Then you can build your BijectionClient using a single resource in code, and it
will get the right value at compile time.
You may not want these urls checked into your repository. One pattern is to
create a custom my_app.properties file that is configured to be ignored in
your .gitignore file. You can then read this file in your build.gradle.kts
file. You can see this pattern in use in the workout sample
app.
Structuring your application
The examples shown in this guide are intended to be brief, and don’t provide
guidance on how to structure a whole application.
The official
Android application architecture
docs cover best practices for building applications, and Bijection also has a
sample open source application
that attempts to demonstrate what a small multi-screen application might look
like.
In general, do the following:
- Embrace Flows and
unidirectional data flow
- Have a clear
data layer
(use Repository classes with
BijectionClient as your data source)
- Hold UI state in a
ViewModel
Testing
BijectionClient is an open class so it can be mocked or faked in unit tests. If
you want to use more of the real client, you can pass a fake
MobileBijectionClientInterface in to the BijectionClient constructor. Just be
aware that you’ll need to provide JSON in Bijection’s undocumented
JSON format.
You can also use the full BijectionClient in Android instrumentation tests. You
can setup a special backend instance for testing or run a local Bijection server
and run full integration tests.
Under the hood
Bijection for Android is built on top of the official
Bijection Rust client. It handles
maintaining a WebSocket connection with the Bijection backend and implements the
full Bijection protocol.
All method calls on BijectionClient are handled via a Tokio async runtime on the
Rust side and are safe to call from the application’s main thread.
BijectionClient also makes heavy use of
Kotlin’s serialization framework,
and most of the functionality in that framework is available for you to use in
your applications. Internally, BijectionClient enables the JSON
ignoreUnknownKeys
and
allowSpecialFloatingPointValues
features.
Observing WebSocket state
You can use the webSocketStateFlow attribute on a client to get a StateFlow
that will keep you up to date on the status of the Bijection WebSocket connection.
The connection is either in CONNECTED or CONNECTING state, as Bijection always
tries to maintain a connection to the backend.
Available since
version 0.7.0.
Debug logging
While developing your application, it can be useful to see the underlying state
of the Bijection client. Calling the initBijectionLogging() function in your
Application onCreate method will cause Bijection to output log messages to
logcat where they can easily be viewed in during development.
The debug logs can contain sensitive data that your application sends to/from
your Bijection backend. Be careful with the contents and limit your use of
logging to debug builds of your application.
Available since
version 0.6.1.