Token sharing guide¶
This guide will walk you through on how to securely transfer authentication data from the phone app to the watch app using Horologist's Auth libraries.
Requirements¶
Horologist Auth library is built on top of Wearable Data Layer API, so your phone and watch apps must:
- have APK signatures and the signature schemes identical;
- the same package name;
Getting started¶
-
Add dependencies
Add the following dependencies to your project’s build.gradle.
For the phone app project:
dependencies { implementation "com.google.android.horologist:horologist-auth-data-phone:<version>" implementation "com.google.android.horologist:horologist-datalayer:<version>" }
For the watch app project:
dependencies { implementation "com.google.android.horologist:horologist-auth-data:<version>" implementation "com.google.android.horologist:horologist-datalayer:<version>" }
-
Add capability to phone app project
On the phone app project, add a
wear.xml
file in theres/values
folder with the following content:<resources xmlns:tools="http://schemas.android.com/tools" tools:keep="@array/android_wear_capabilities"> <string-array name="android_wear_capabilities"> <item>horologist_phone</item> </string-array> </resources>
For more details, see Specify capability names for detecting your apps.
-
Create a
WearDataLayerRegistry
In both projects, create an instance of WearDataLayerRegistry from the datalayer:
val registry = WearDataLayerRegistry.fromContext( application = // application context, coroutineScope = // a coroutine scope )
This class should be created as a singleton in your app.
-
Define the data to be transferred
Define which authentication data that should be transferred from the phone to the watch. It can be a data class with many properties, it can also be a protocol buffer. For this guide, we will pass a simple
String
instance. -
Create a
Serializer
for the dataCreate a DataStore
Serializer
class for the class defined to be transferred from the phone to the watch (String
for this guide):public object TokenSerializer : Serializer<String> { override val defaultValue: String = "" override suspend fun readFrom(input: InputStream): String = InputStreamReader(input).readText() override suspend fun writeTo(t: String, output: OutputStream) { withContext(Dispatchers.IO) { output.write(t.toByteArray()) } } }
This class should preferable be placed in a shared module between the phone and watch projects, but could also be duplicated in both projects.
More information about this serialization in this blog post.
Send authentication data from the phone¶
-
Create a
TokenBundleRepository
on the phone projectCreate an instance of TokenBundleRepository on the phone app project:
val tokenBundleRepository = TokenBundleRepositoryImpl( registry = registry, coroutineScope = // a coroutine scope, serializer = TokenSerializer )
-
Check if the repository is available (optional)
Before using the repository, you can check if it is available to be used on the current device with:
tokenBundleRepository.isAvailable()
If the repository is not available on the device, all the calls to it will fail silently.
See the requirements of Wearable Data Layer API.
-
Send authentication data
The authentication data can be sent from the phone calling
update
:tokenBundleRepository.update("token")
Receive authentication data on the watch¶
-
Create a
TokenBundleRepository
on the watch projectCreate an instance of TokenBundleRepository on the watch app project:
val tokenBundleRepository = TokenBundleRepositoryImpl.create( registry = registry, serializer = TokenSerializer )
-
Receive authentication data
The authentication data can be listened from the watch via the
flow
property:tokenBundleRepository.flow