Skip to content

Commit 62021c8

Browse files
Updates for v0.4.8 (#7)
* Update dependencies to pull in CH SDK 0.4.8; update app as needed. * Integrate with the new record updates method and log responses. * Add in DatabasePassphraseManager and sql cipher * Update readme * Fix typo + incorrect reference to 0.4.4
1 parent 51a6b41 commit 62021c8

File tree

10 files changed

+206
-133
lines changed

10 files changed

+206
-133
lines changed

.idea/compiler.xml

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/gradle.xml

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/misc.xml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 81 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ The CommonHealth Client SDK provides an interface that allows applications to ac
44

55
The CommonHealth Client SDK is in closed beta. If you would like to participate in our beta program, please reach out to info [at] commonhealth.org.
66

7-
While we consider the SDK to be relatively stable, this is pre-release software, so the interfaces are subject to change based on evolving requirements and developer feedback. We're currently investigating way to make it easier to remove configuration dependencies, so if you find anything particularly burdensome or confusing, please let us know.
7+
While we consider the SDK to be relatively stable, this is pre-release software, so the interfaces are subject to change based on evolving requirements and developer feedback. We're currently investigating ways to make it easier to remove configuration dependencies, so if you find anything particularly burdensome or confusing, please let us know by either emailing us or opening a Github issue.
88

99
## Audience
1010
This quick start guide is geared towards participants in our closed beta program. This guide assumes that you have the CommonHealth developer edition installed on your device and you have gone through the enrollment process in the application.
@@ -16,8 +16,8 @@ This quick start guide is geared towards participants in our closed beta program
1616
The CommonHealth Client SDK consists of two modules: commonhealthclient and common. Commonhealthclient contains the bulk of functionality for the SDK, while common types shared between the CommonHealth application and the CommonHealth Client SDK. You'll need to add the following to your application's list of dependencies:
1717

1818
```
19-
implementation "org.thecommonsproject.commonhealth:common:0.4.4"
20-
implementation "org.thecommonsproject.commonhealth:commonhealthclient:0.4.4"
19+
implementation "org.thecommonsproject.commonhealth:common:0.4.8"
20+
implementation "org.thecommonsproject.commonhealth:commonhealthclient:0.4.8"
2121
```
2222

2323
The artifacts currently reside in our organization's bintray repo, but at some point these will be migrated to jcenter. In the mean time, you'll need to add the following maven repository to your list of repositories, typically defined in the project's `gradle.build` file:
@@ -64,7 +64,7 @@ The interapplication data sharing functionality of CommonHealth leverages native
6464
</receiver>
6565
```
6666

67-
Our authorziation process is inspired by OAuth and requires that the `RedirectUriReceiverActivity` receive a redirect from CommonHealth. Applications must define the `interappAuthRedirectScheme`, `interappAuthRedirectHost`, and `interappAuthRedirectPath` manifest placeholders in the app's `build.gradle` file, and the compiled URL must match the `authorizationCallbackUri` in the `CommonHealthStoreConfiguration` object (see below). For example, defining the following manifest placeholders in your `build.gradle` file:
67+
Our authorization process is inspired by OAuth and requires that the `RedirectUriReceiverActivity` receive a redirect from CommonHealth. Applications must define the `interappAuthRedirectScheme`, `interappAuthRedirectHost`, and `interappAuthRedirectPath` manifest placeholders in the app's `build.gradle` file, and the compiled URL must match the `authorizationCallbackUri` in the `CommonHealthStoreConfiguration` object (see below). For example, defining the following manifest placeholders in your `build.gradle` file:
6868

6969
```
7070
manifestPlaceholders.interappAuthRedirectScheme = "org.thecommonsproject.android.commonhealth.sampleapp"
@@ -83,13 +83,30 @@ The client application must initialize the `CommonHealthStore` singleton by prov
8383
For development, you can use the following to create the `CommonHealthStoreConfiguration` object:
8484

8585
```
86+
val notificationPreferences = NotificationPreferences(
87+
subscribedNotificationTypes = setOf(
88+
CommonHealthNotificationType.AUTHORIZATION_FLOW_COMPLETED_WITH_RESULT
89+
),
90+
subscriber = { notification ->
91+
when(notification) {
92+
is CommonHealthNotification.AuthorizationCompleted -> {
93+
when(val response = notification.userResponse) {
94+
is CommonHealthAuthorizationActivityResponse.Failure -> { }
95+
is CommonHealthAuthorizationActivityResponse.Success -> { }
96+
is CommonHealthAuthorizationActivityResponse.UserCanceled -> { }
97+
}
98+
}
99+
}
100+
}
101+
)
86102
val configuration = CommonHealthStoreConfiguration(
87103
appId = BuildConfig.APPLICATION_ID,
88104
commonHealthAppId = "org.thecommonsproject.android.phr.developer",
89105
developerModeEnabled = true,
90106
attestationServiceConfiguration = null,
91107
commonHealthAuthorizationUri = "org.thecommonsproject.android.phr://interapp/auth",
92-
authorizationCallbackUri = "org.thecommonsproject.android.commonhealth.sampleapp://interapp/redirect"
108+
authorizationCallbackUri = "org.thecommonsproject.android.commonhealth.sampleapp://interapp/redirect",
109+
notificationPreferences = notificationPreferences
93110
)
94111
```
95112

@@ -129,13 +146,24 @@ You'll likely notice that many of the interface methods require a `connectionAli
129146

130147
### Check that CommonHealth is available
131148

132-
The `CommonHealthStore` class provides the `isCommonHealthAvailable` method that determines if the CommonHealth application is installed on the user's device and it is set up to share data with client application. The method signature is:
149+
The `CommonHealthStore` class provides the `getCommonHealthAvailability` method that can help determine how (or how not) to interact with CommonHealth:
133150

134151
```
135-
suspend fun isCommonHealthAvailable(context: Context): Boolean
152+
val chStore = CommonHealthStore.getSharedInstance()
153+
val chAvailability = chStore.getCommonHealthAvailability(context)
154+
when(chAvailability) {
155+
CommonHealthAvailability.NOT_INSTALLED -> { } // show install UX
156+
CommonHealthAvailability.ACCOUNT_NOT_CONFIGURED_FOR_SHARING -> { } // this can indicate that a user has disabled sharing entirely or that their device is unsuitable for sharing (ex. device is rooted)
157+
CommonHealthAvailability.AVAILABLE -> { } // Suitable for authorization or querying if consent has been given
158+
}
136159
```
137160

138-
If this method returns false, you may need to instruct the user to install and onboard with the CommonHealth app.
161+
If CommonHealth is not installed, the CommonHealthStore also provides a convenience method to direct a user to Google Play to install it. It is invoked like so:
162+
163+
```
164+
val chInstallIntent = chStore.buildCommonHealthInstallIntent(context)
165+
startActivity(chInstallIntent)
166+
```
139167

140168
### Define the scope of access
141169

@@ -218,7 +246,7 @@ The `inactive` value indicates that the CommonHealth team has deactivated your a
218246

219247
### Authorize
220248

221-
Authorization is performed by launching the `AuthorizationManagementActivity`. To do so, create an intent using the `AuthorizationManagementActivity` static method `createStartForResultIntent`, passing in an authorization request. You then start the activity using the `startActivityForResult` like you typically would for any activity. Note that you will also need to implement the `onActivityResult` method of the calling Activity or Fragment to get the status when `AuthorizationManagementActivity` finishes. `CommonHealthAuthorizationActivityResponse.fromActivityResult` can be used to convert the response into a more developer friendly object.
249+
Authorization is performed by launching the `AuthorizationManagementActivity`. To do so, create an intent using the `AuthorizationManagementActivity` static method `createStartForResultIntent`, passing in an authorization request. You then start the activity using the `startActivity` like you typically would for any activity.
222250

223251
The following sample launches the `AuthorizationManagementActivity`:
224252

@@ -235,48 +263,12 @@ val intent = AuthorizationManagementActivity.createStartForResultIntent(
235263
authorizationRequest
236264
)
237265
238-
startActivityForResult(authIntent, REQUEST_CODE)
266+
startActivity(authIntent)
239267
```
240268

241-
The following sample implements the Fragment's `onActivityResult` method:
269+
This will initiate an authorization and consent flow in CommonHealth.
242270

243-
```
244-
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
245-
when(requestCode) {
246-
CH_AUTH -> {
247-
248-
//process response
249-
when(val response = CommonHealthAuthorizationActivityResponse.fromActivityResult(resultCode, data)) {
250-
null -> super.onActivityResult(requestCode, resultCode, data)
251-
is CommonHealthAuthorizationActivityResponse.Success -> {
252-
Toast.makeText(context, "Authorization Succeeded", Toast.LENGTH_SHORT).show()
253-
}
254-
is CommonHealthAuthorizationActivityResponse.UserCanceled -> {
255-
Toast.makeText(context, "User Canceled", Toast.LENGTH_SHORT).show()
256-
}
257-
is CommonHealthAuthorizationActivityResponse.Failure -> {
258-
val errorMessage = response.errorMessage ?: "Authorization Failed"
259-
Toast.makeText(context, errorMessage, Toast.LENGTH_SHORT).show()
260-
261-
// Optionally take additional action based on exception
262-
when(response.exception) {
263-
is InterappException.ClientApplicationValidationFailed -> { }
264-
is InterappException.AuthError -> { }
265-
else -> { }
266-
}
267-
}
268-
}
269-
270-
updateUI()
271-
return
272-
}
273-
else -> {
274-
updateUI()
275-
super.onActivityResult(requestCode, resultCode, data)
276-
}
277-
}
278-
}
279-
```
271+
The authorization response--a success, cancellation, or error--is communicated back through the NotificationPreferences subscriber object registered in the CommonHealthStoreConfiguration bundle.
280272

281273
See `CategoryListFragment` in this repo for a working implementation.
282274

@@ -295,19 +287,57 @@ suspend fun readSampleQuery(
295287
): List<DataQueryResult>
296288
```
297289

298-
As you can see, the method returns a list of `DataQueryResult` instances. For requests for clinical data, these can be cast to `ClinicalDataQueryResult` instances. Each `ClinicalDataQueryResult` instance contains the following:
290+
As you can see, the method returns a list of `SampleDataQueryResult` instances. For requests for clinical data, these can be cast to `FHIRSampleDataQueryResult` instances. Each `FHIRSampleDataQueryResult` instance contains the following:
299291

300-
- resourceType: DataType.ClinicalResource - the type of the resource
292+
- resourceType: DataType.FHIRResource - the type of the resource
301293
- json: String - JSON string representation of the FHIR resource
302294
- displayText: String - The primary display text computed from the resource by CommonHealth
303-
- secondaryDisplayText: String - The secondary display text computed from the resource by CommonHealth
295+
- secondaryDisplayText: String - The secondary display text computed from the resource by CommonHealth
296+
- chId: UUID - A random, stable identifier for this given resource computed by CommonHealth
297+
- fhirVersion: String - The given FHIR version corresponding to this resource
304298

305299
See `ResourceListFragment` for an example implementation of the data query building and data fetching process.
306300

301+
### Receiving new data or updates to existing data
302+
303+
As part of the NotificationPreferences configuration in the CommonHealthStoreConfiguration, you can subscribe to various notification types:
304+
305+
- CommonHealthNotificationType.AUTHORIZATION_FLOW_COMPLETED_WITH_RESULT - notification containing the authorization response / result
306+
- CommonHealthNotificationType.NEW_DATA_AVAILABLE - notification informing that new data is available
307+
308+
Upon receiving the NEW_DATA_AVAILABLE notification, you can invoke a method on the CommonHealthStore to receive a list of record updates over a given timeframe:
309+
310+
```
311+
@Throws(InterappException::class)
312+
suspend fun getRecordUpdates(
313+
context: Context,
314+
connectionAlias: String,
315+
after: Date? = null,
316+
before: Date? = null
317+
): List<RecordUpdateQueryResult> {
318+
```
319+
320+
The `after` and `before` optional parameters allow you specify an interval of time from which to receive a list of record update events. Each record update event contains:
321+
322+
- CHRecordId: UUID - a stable, random, CH-generated unique identifier for a given record
323+
- updateType: RecordUpdateQueryResult.UpdateType - an enum containing UPDATE_OR_INSERT or DELETION cases
324+
- date: Date - timestamp for the given update
325+
326+
Using these can help you identify when and if you need to pull data from CommonHealth, or if data has been deleted in CommonHealth and should be removed from your local datastore, if persisted.
327+
307328
## Registering with CommonHealth
308329

309330
Registering with CommonHealth is not required to begin testing integrations with CommonHealth. However, if you have a client application that you would like to use in production environments, you'll need to register the application with CommonHealth. This is similar to registering an OAuth client, where you would specify information such as required scope, authorization redirect URI, etc. Please reach out to info [at] commonhealth.org for more information.
310331

332+
## Upgrading from v0.4.4 to v0.4.8
333+
`v0.4.8` introduced a number of large changes and enhancements to the API:
334+
335+
- CommonHealthStoreConfiguration now has a required NotificationPreferences property
336+
- AuthorizationResponses are now communicated as a notification to a subscriber contained in the CommonHealthStoreConfiguration
337+
- A new `getRecordUpdates` method was added to the CommonHealthStore to help determine changes to the data
338+
- A `NEW_DATA_AVAILABLE` notificationType is added to support receiving updates asynchronously from CommonHealth
339+
- The `isCommonHealthAvailable` method was removed in favor of the new `getCommonHealthAvailability`
340+
311341
## Upgrading from v0.4.0 to v0.4.4
312342
`v0.4.4` introduced a small number of changes to the API:
313343

app/build.gradle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,4 +74,7 @@ dependencies {
7474
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
7575
implementation 'androidx.navigation:navigation-fragment-ktx:2.1.0'
7676
implementation 'androidx.navigation:navigation-ui-ktx:2.1.0'
77+
78+
// Database encryption
79+
implementation "net.zetetic:android-database-sqlcipher:$sqlcipherVersion"
7780
}

0 commit comments

Comments
 (0)