Skip to content

Commit 8ceb40e

Browse files
Updates for 1.3.15 (#9)
* Update to utilize new features in 1.3.15. Update README. * Point to release artifact
1 parent 6f0280b commit 8ceb40e

File tree

17 files changed

+339
-78
lines changed

17 files changed

+339
-78
lines changed

.idea/compiler.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.

.idea/gradle.xml

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

.idea/misc.xml

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

README.md

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

55
The CommonHealth Client SDK is in open beta.
66

7+
If you're interested in developing a production integration with the CommonHealth Client SDK, please reach out to developers [at] commonhealth.org to begin the process of being whitelisted.
8+
79
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.
810

911
## Audience
@@ -25,11 +27,11 @@ Once CommonHealth Developer Edition is installed, you will need to add a sample
2527

2628
### Gradle Dependencies
2729

28-
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:
30+
The CommonHealth Client SDK consists of two modules: commonhealth-client and commonhealth-common. CommonHealthClient contains the bulk of functionality for the SDK, while common contains 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:
2931

3032
```
31-
implementation "org.thecommonsproject:commonhealth-common:1.1.2"
32-
implementation "org.thecommonsproject:commonhealth-client:1.1.2"
33+
implementation "org.thecommonsproject:commonhealth-common:1.3.15"
34+
implementation "org.thecommonsproject:commonhealth-client:1.3.15"
3335
```
3436

3537
The release artifacts are made avalable via the Maven Central repository, so you will need to have the following in your list of dependency repositories:
@@ -339,10 +341,46 @@ Upon receiving the NEW_DATA_AVAILABLE notification, you can invoke a method on t
339341

340342
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.
341343

344+
### Reading Verifiable Credentials (SMART® Health Cards) -- new in v1.3.15 and currently in beta
345+
346+
_Note: This feature is currently in beta and should not yet be used in production applications. We'd love your feedback as you start using it; please open a Github issue, or email developers [at] commonhealth.org with any thoughts that you have. Thank you!_
347+
348+
Client applications can now request to read Verifiable Credentials (SMART® Health Cards) from CommonHealth. This is a completely separate, independent flow from requesting other types of health data.
349+
350+
Client applications simply request access based on a set of Verifiable Credential types, and if the user consents to sharing any SMART® Health Cards that match the requested types, then the data will be returned immediately to the calling application. There is no persistent connection established, and the client application will have to request again (and the user consent again) to access the same data.
351+
352+
Invoking the `readVerifiableCredentials` will redirect to CommonHealth, initiating a consent flow where the user can select which SHCs (or none) to share.
353+
354+
Here's a snippet demonstrating how the new `readVerifiableCredentials` method can be called to retrieve COVID-19 Vaccination SMART® Health Cards:
355+
356+
```
357+
// Determine which VC types you'd like to read
358+
// In this case, we're requesting COVID-19 Vaccination records.
359+
val c19VaxVcTypes = setOf(
360+
"https://smarthealth.cards#immunization",
361+
"https://smarthealth.cards#covid19",
362+
"https://smarthealth.cards#health-card"
363+
)
364+
365+
// Pass the VC Types into the readVerifiableCredentials suspending method
366+
val smartHealthCards = commonHealthStore.readVerifiableCredentials(
367+
context,
368+
c19VaxVcTypes
369+
)
370+
```
371+
372+
CommonHealth performs SMART® Health Card validation prior to ingesting the cards into the app, including signature validation and checks against the payload contents. However, it is recommended to perform your own validation depending on your use case. The raw JWT can be accessed through the `json` property on each `VerifiableRecordSampleDataQueryResult` object.
373+
342374
## Registering with CommonHealth
343375

344376
Registering with CommonHealth is not required to begin testing integrations with CommonHealth Developer Edition. However, if you have a client application that you would like to use in staging or 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 developers [at] commonhealth.org for more information.
345377

378+
## Upgrading from v1.1.2 to v1.3.15
379+
`v1.3.15` introduced a small number of changes:
380+
381+
- Support for requesting access to Verifiable Credentials (SMART® Health Cards) is now in beta
382+
- Updates to support higher Android OS levels (specifically changes to accommodate new restrictions on apps calling into packageManager)
383+
346384
## Upgrading from v0.4.8 to v1.1.2
347385
`v1.1.2` introduced a small number of changes:
348386

@@ -352,7 +390,6 @@ Registering with CommonHealth is not required to begin testing integrations with
352390
- `org.thecommonsproject.commonhealth:commonhealthclient` is now `org.thecommonsproject:commonhealth-client`
353391
- The artifacts are now hosted in Maven Central.
354392

355-
356393
## Upgrading from v0.4.4 to v0.4.8
357394
`v0.4.8` introduced a number of large changes and enhancements to the API:
358395

app/build.gradle

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ android {
2020
manifestPlaceholders.interappAuthRedirectScheme = "org.thecommonsproject.android.commonhealth.sampleapp"
2121
manifestPlaceholders.interappAuthRedirectHost = "interapp"
2222
manifestPlaceholders.interappAuthRedirectPath = "/redirect"
23+
manifestPlaceholders.commonHealthAppId = "org.thecommonsproject.android.phr.developer"
2324
}
2425
buildTypes {
2526
release {
@@ -34,7 +35,7 @@ android {
3435
}
3536

3637
kotlinOptions {
37-
jvmTarget = "1.8"
38+
jvmTarget = "11"
3839
}
3940
}
4041

app/src/main/AndroidManifest.xml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
android:roundIcon="@mipmap/ic_launcher_round"
1212
android:supportsRtl="true"
1313
android:theme="@style/AppTheme">
14-
<activity android:name=".MainActivity">
14+
<activity android:name=".MainActivity"
15+
android:exported="true">
1516
<intent-filter>
1617
<action android:name="android.intent.action.MAIN" />
1718

@@ -20,4 +21,8 @@
2021
</activity>
2122
</application>
2223

24+
<queries>
25+
<package android:name="${commonHealthAppId}" />
26+
</queries>
27+
2328
</manifest>

app/src/main/java/org/thecommonsproject/android/commonhealth/sampleapp/MainViewModel.kt

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@ package org.thecommonsproject.android.commonhealth.sampleapp
22

33
import android.content.Context
44
import android.content.Intent
5-
import android.util.Log
6-
import androidx.lifecycle.LiveData
75
import androidx.lifecycle.MutableLiveData
86
import androidx.lifecycle.ViewModel
97
import androidx.lifecycle.viewModelScope
@@ -16,6 +14,7 @@ import org.thecommonsproject.android.common.interapp.CommonHealthAuthorizationSt
1614
import org.thecommonsproject.android.common.interapp.dataquery.response.DataQueryResult
1715
import org.thecommonsproject.android.common.interapp.dataquery.response.FHIRSampleDataQueryResult
1816
import org.thecommonsproject.android.common.interapp.dataquery.response.RecordUpdateQueryResult
17+
import org.thecommonsproject.android.common.interapp.dataquery.response.VerifiableRecordSampleDataQueryResult
1918
import org.thecommonsproject.android.common.interapp.scope.DataType
2019
import org.thecommonsproject.android.common.interapp.scope.Scope
2120
import org.thecommonsproject.android.common.interapp.scope.ScopeRequest
@@ -24,14 +23,22 @@ import org.thecommonsproject.android.commonhealthclient.AuthorizationRequest
2423
import org.thecommonsproject.android.commonhealthclient.CommonHealthAvailability
2524
import org.thecommonsproject.android.commonhealthclient.CommonHealthStore
2625
import timber.log.Timber
27-
import java.util.*
2826

2927
class MainViewModel(
3028
private val commonHealthStore: CommonHealthStore
3129
) : ViewModel() {
3230

31+
companion object {
32+
private val c19VaxVcTypes = setOf(
33+
"https://smarthealth.cards#immunization",
34+
"https://smarthealth.cards#covid19",
35+
"https://smarthealth.cards#health-card"
36+
)
37+
}
38+
3339
private val connectionAlias = "connection_alias"
34-
private val TAG by lazy { MainViewModel::class.java.simpleName }
40+
41+
var storedVCResults = emptyList<VerifiableRecordSampleDataQueryResult>()
3542

3643
val allDataTypes: List<DataType.ClinicalResource> = listOf(
3744
DataType.ClinicalResource.AllergyIntoleranceResource,
@@ -172,6 +179,15 @@ class MainViewModel(
172179
return commonHealthStore.getCommonHealthAvailability(context)
173180
}
174181

182+
suspend fun fetchC19VaxStatus(context: Context): List<VerifiableRecordSampleDataQueryResult> {
183+
val results = commonHealthStore.readVerifiableCredentials(
184+
context,
185+
c19VaxVcTypes
186+
)
187+
storedVCResults = results
188+
return results
189+
}
190+
175191
fun prettyPrintJSON(jsonString: String): String {
176192
val gson = GsonBuilder().setPrettyPrinting().create()
177193
val element = JsonParser.parseString(jsonString)

app/src/main/java/org/thecommonsproject/android/commonhealth/sampleapp/SampleApplication.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ import timber.log.Timber
1717
class SampleApplication: Application() {
1818

1919
private var database: SampleApplicationDatabase? = null
20+
private val cryptoProvider: CryptoProvider by lazy {
21+
DefaultCryptoProvider(DefaultAndroidKeystoreClientWrapper())
22+
}
2023

2124
private fun getDatabasePassphrase(context: Context, cryptoProvider: CryptoProvider) : ByteArray {
2225
val passphraseFilePath = context.filesDir.absolutePath.plus("/encryptedDatabasePassphrase")
@@ -46,7 +49,6 @@ class SampleApplication: Application() {
4649

4750
private fun initializeCommonHealthStore(application: Application) {
4851

49-
val cryptoProvider = DefaultCryptoProvider(DefaultAndroidKeystoreClientWrapper())
5052
val context = application.applicationContext
5153
val notificationPreferences = NotificationPreferences(
5254
subscribedNotificationTypes = setOf(

app/src/main/java/org/thecommonsproject/android/commonhealth/sampleapp/fragments/CategoryListFragment.kt

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import androidx.navigation.fragment.findNavController
1313
import androidx.navigation.navOptions
1414
import androidx.recyclerview.widget.LinearLayoutManager
1515
import androidx.recyclerview.widget.RecyclerView
16+
import kotlinx.coroutines.delay
1617
import kotlinx.coroutines.launch
1718
import org.thecommonsproject.android.common.interapp.CommonHealthAuthorizationStatus
1819
import org.thecommonsproject.android.common.interapp.dataquery.response.RecordUpdateQueryResult
@@ -30,6 +31,7 @@ class CategoryListFragment : Fragment() {
3031

3132
private val viewModel by activityViewModels<MainViewModel> { getVmFactory() }
3233
private lateinit var authorizeButton: Button
34+
private lateinit var requestShcsButton: Button
3335
private lateinit var spinner: ProgressBar
3436

3537
override fun onCreateView(
@@ -83,6 +85,12 @@ class CategoryListFragment : Fragment() {
8385
startActivity(authIntent)
8486
}
8587

88+
requestShcsButton = view.findViewById(R.id.request_shcs)
89+
requestShcsButton.isEnabled = false
90+
requestShcsButton.setOnClickListener {
91+
requestC19VaxStatus()
92+
}
93+
8694
spinner = view.findViewById(R.id.progress_bar)
8795

8896
viewModel.resultsLiveData.observe(viewLifecycleOwner) { resultsMap ->
@@ -100,10 +108,38 @@ class CategoryListFragment : Fragment() {
100108
updateUI()
101109
}
102110

111+
private fun requestC19VaxStatus() {
112+
val context = context ?: return
113+
viewModel.viewModelScope.launch {
114+
spinner.visibility = View.VISIBLE
115+
val results = viewModel.fetchC19VaxStatus(context)
116+
spinner.visibility = View.GONE
117+
if (results.isEmpty()) {
118+
Toast.makeText(requireContext(), "Fetched 0 Verifiable Credentials", Toast.LENGTH_LONG).show()
119+
return@launch
120+
}
121+
122+
delay(500)
123+
124+
val directions = CategoryListFragmentDirections.actionCategoryListFragmentToVcResultsListFragment()
125+
val options = navOptions {
126+
anim {
127+
enter = R.anim.slide_in_right
128+
exit = R.anim.slide_out_left
129+
popEnter = R.anim.slide_in_left
130+
popExit = R.anim.slide_out_right
131+
}
132+
}
133+
findNavController().navigate(directions, options)
134+
}
135+
}
136+
103137
private fun updateUI() {
104138
viewModel.viewModelScope.launch {
105139
when(viewModel.getCommonHealthAvailability(requireContext())) {
106-
CommonHealthAvailability.AVAILABLE -> { }
140+
CommonHealthAvailability.AVAILABLE -> {
141+
requestShcsButton.isEnabled = true
142+
}
107143
CommonHealthAvailability.NOT_INSTALLED,
108144
CommonHealthAvailability.ACCOUNT_NOT_CONFIGURED_FOR_SHARING -> {
109145
Toast.makeText(
@@ -112,6 +148,7 @@ class CategoryListFragment : Fragment() {
112148
Toast.LENGTH_LONG
113149
).show()
114150
authorizeButton.isEnabled = false
151+
requestShcsButton.isEnabled = false
115152
return@launch
116153
}
117154
}

app/src/main/java/org/thecommonsproject/android/commonhealth/sampleapp/fragments/DataTypeDialogueFragment.kt

Lines changed: 0 additions & 50 deletions
This file was deleted.

0 commit comments

Comments
 (0)