Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Dragon Copilot web app for mobile provides APIs for iOS and Android. To maintain consistency in implementation approaches between platforms, both platforms share:
- Common naming conventions:
ApplicationConfig,ApplicationConfigProvider,UserInfo,PatientInfo,VisitInfo. - Common data classes:
ClientTokenProvider,ClientToken,ClientEntraToken,ClientSoFToken. - Session lifecycle methods:
getInstance(),openSession(),closeSession(),clearInstance(). - Multi-patient workflows: Switch patients without re-initialization.
- Token architecture: Offline caching, EIS exchange for partner tokens, validation.
- Theme and language support: Both platforms support appearance and locale changes.
- Ambient recording and dictation events: Available on both platforms.
The two platforms have the following key architectural difference:
- Event handling: iOS uses delegate protocols, Android uses Kotlin flows for event streams.
Architectural differences
1. Event handling
The primary difference between platforms is how they handle events:
| iOS | Android |
|---|---|
| Delegate protocols with optional methods. | Kotlin Flow with sealed class hierarchies. |
AppUiDelegate, AppRecordingDelegate, AppDictationDelegate, AppSettingsDelegate |
event, uiEvent, recordingEvent, dictationEvent flows |
Callback-based: func recordingStarted() |
Flow-based: Flow<AppRecordingUiEvent.RecordingStarted> |
iOS Example:
class MyDelegate: AppRecordingDelegate {
func recordingStarted() {
// Handle recording start
}
}
Android Example:
lifecycleScope.launch {
applicationConfig.recordingEvent.collect { event ->
when (event) {
is AppRecordingUiEvent.RecordingStarted -> { /* Handle */ }
}
}
}
2. Configuration provider structure
| iOS | Android |
|---|---|
Two protocols: ConfigurationProvider + SessionDataProvider |
Single data class: ApplicationConfigProvider |
| Configuration and user info separate from patient/visit | All data in one configuration object |
iOS:
protocol ConfigurationProvider {
func getConfiguration() -> ApplicationConfigProvider
func getAccessTokenProvider() -> AppAccessTokenProvider
func getUser() -> UserInfo
}
protocol SessionDataProvider {
func getPatient() -> PatientInfo
func getVisit() -> VisitInfo
}
Android:
data class ApplicationConfigProvider(
val userInfo: UserInfo?,
val customerId: String?,
val partnerId: String?,
val serverInfo: ServerInfo,
val clientAppInfo: ClientAppInfo,
// ...
)
// Patient and visit provided to openSession()
applicationConfig.openSession(
patientInfo: PatientInfo?,
visitInfo: VisitInfo?
)
3. Token provider callbacks
| iOS | Android |
|---|---|
| Protocol with success and failure callbacks | Listener interface with callbacks |
AppAccessTokenProvider protocol |
AcquireNewTokenListener interface |
iOS:
@objc public protocol AppAccessTokenProvider {
func accessToken(
scopes: [String]?,
forceRefresh: Bool,
onSuccess: @escaping (ClientTokenProvider) -> Void,
onFailure: @escaping (Error) -> Void
)
}
Android:
fun interface AcquireNewTokenListener {
fun acquireNewToken(
scopes: List<String>?,
forceRefresh: Boolean,
onSuccess: (ClientTokenProvider) -> Unit,
onFailure: (Exception) -> Unit
)
}
Platform-specific features
Android-only features
| Feature | Description |
|---|---|
OnLoadingBackPress |
Event when back button is pressed during loading. |
RecordingStopReason |
Detailed stop reasons: USER, SYSTEM_ERROR, MAX_LIMIT_REACHED, AUDIO_INTERRUPTED, INCOMPATIBLE_AUDIO_DEVICE_DETECTED, AUDIO_DEVICE_CHANGED. |
RecordingProgressNotification |
Granular recording progress events: WARN_LIMIT_REACHED, AUDIO_SILENCE_DETECTED, EXTERNAL_AUDIO_DEVICE_DETECTED. |
| Separate flow streams. | Different flows for event, uiEvent, recordingEvent, dictationEvent, internalClientEvent. |
| Required permissions callback. | CheckPermissionCallback for runtime permission requests. |
iOS-only features
| Feature | Description |
|---|---|
UIViewController support. |
openSessionController() for UIKit integration. |
SwiftUI View support. |
openSession() returns SwiftUI View. |
| Protocol-based architecture. | More flexible delegate implementation with optional methods. |
RecordingInterruptionReason |
iOS-specific: systemError, audioInterruption, reachedMaxDuration, incompatibleInputDevice, audioRouteChanged. |
RecordingNotification |
iOS-specific: reachedWarnDuration, audioLoss, externalMicDetected. |
Event mapping reference
Common events across platforms:
| Event type | iOS delegate method | Android flow event |
|---|---|---|
| WebView loaded | webViewLoaded(_ isLoadingDone: Bool) |
AppUiEvent.WebViewLoaded |
| Recording started | recordingStarted() |
AppRecordingUiEvent.RecordingStarted(correlationId) |
| Recording stopped | recordingStopped() |
AppRecordingUiEvent.RecordingStopped(correlationId, reason) |
| Recording failed | recordingFailed() |
AppRecordingUiEvent.RecordingFailed(correlationId, error) |
| Recording interrupted | recordingInterrupted(reason:) |
Captured in RecordingStopped with reason |
| Recording notification | recordingNotification(notification:) |
AppRecordingUiEvent.RecordingProgress(correlationId, notification) |
| Recording uploading | N/A | AppRecordingUiEvent.RecordingUploading(correlationId) |
| Recording uploaded | N/A | AppRecordingUiEvent.RecordingUploaded(correlationId) |
| Dictation started | dictationStarted() |
AppDictationUiEvent.DictationStarted(correlationId) |
| Dictation stopped | dictationStopped() |
AppDictationUiEvent.DictationStopped(correlationId) |
| Theme changed | appearanceThemeChanged(to: String) |
AppSettingsUiEvent.AppearanceChanged(theme: String) |
| Language changed | changeApplicationLanguage(to: String) |
AppSettingsUiEvent.ApplicationLanguageChanged(locale: String) |
| Keep screen on | isIdleTimerDisabled(isOn: Bool) |
AppSettingsUiEvent.KeepScreenOnChanged(isScreenOn: Boolean) |
| Error occurred | N/A | AppUiEvent.ErrorOccurred(error: Exception) |
Migration between platforms
If you're porting an integration from one platform to another, pay attention to the following design considerations:
- Event handling: Convert delegate methods to flow collection or vice versa.
- Configuration: Combine or split configuration and session data providers as needed.
- Platform features: Check for platform-specific events and handle them accordingly.
- UI integration: iOS offers both UIKit (
openSessionController) and SwiftUI (openSession); Android uses Jetpack Compose or traditional Views.
Tip
Both platforms provide optional delegate methods and events. Implement only what your integration needs.