mediquo_flutter
A federated Flutter plugin that integrates the native MediQuo telemedicine SDKs โ chat, video calls and the professional list โ through a clean, plain-Dart API.
๐ค TL;DR โ let the AI handle it
Life's too short to read SDK docs. Paste this into your favorite AI assistant and let it wire MediQuo into your app while you grab a coffee โ:
Integrate the `mediquo_flutter` Flutter package into my project.
Fetch and follow this integration guide exactly:
https://raw.githubusercontent.com/CaioVSR/mediquo_flutter/HEAD/AI_INTEGRATION.md
For the exact API you may also read:
https://pub.dev/documentation/mediquo_flutter/latest/
Then ask me for my apiKey and clientCode and whether I need push notifications,
and implement the integration.
It fetches the full guide (AI_INTEGRATION.md), asks for your
apiKey and clientCode, and writes the integration for you. Prefer doing it by
hand? Everything's below. ๐
- ๐ฉบ Native Android & iOS MediQuo SDKs (native UI, native video stack).
- ๐ iOS integrates via CocoaPods or Swift Package Manager โ no Flutter SPM required.
- ๐งฉ Type-safe platform channel generated with Pigeon.
- ๐ฆ Plain-Dart API (
Futures). - ๐งช 100% unit-test coverage of the Dart layer.
- ๐ No network calls in the app: credentials are produced server-side.
Architecture note. This package bridges the native SDKs (the path the MediQuo Android/iOS docs describe). It is not the WebView widget wrapper.
Quick start
- Get an
apiKey(partner key) and aclientCode(patient CPF, digits only) from your backend โ the app makes no MediQuo network calls. - Add the dependency (see Installation) and do the per-platform native setup.
- Drive everything through a
Mediquoinstance:
final mediquo = Mediquo();
await mediquo.startSession(
MediquoConfiguration.validated(apiKey: apiKey, clientCode: clientCode),
);
await mediquo.openProfessionalList();
Every method returns a Future and throws a MediquoException on failure.
The package holds no state โ the native SDK owns every screen and session.
How authentication works
The plugin never talks to the MediQuo APIs. Patient creation and credentials are a backend responsibility:
- Your backend creates the patient through the MediQuo Patients API and keeps
the patient's
documentNumber(a CPF). - Your app receives two values from your backend:
apiKeyโ the partner API key.clientCodeโ the patientdocumentNumber(CPF, digits only).
- The plugin initialises and authenticates the native SDK with those values.
The native SDKs authenticate by CLIENT_CODE (CPF) โ not by the web widget's JWT access token.
Installation
dependencies:
mediquo_flutter: ^1.0.0
flutter pub get
Requirements
| Platform | Minimum |
|---|---|
| Dart | 3.12 |
| Flutter | 3.44 |
| Android | minSdk 29, compileSdk 35, JDK 17, Kotlin 2.2 |
| iOS | iOS 17, Xcode 26 |
| MediQuo SDK | Android 3.8.1 ยท iOS 26.1.2 |
Platform setup
The native SDKs need host-app configuration that a plugin cannot inject for you.
Android
The MediQuo native SDK lives in a private Maven repository and ships as a
self-contained AAR. Modern Flutter projects resolve repositories centrally
(FAIL_ON_PROJECT_REPOS), so the repo must be declared in your app's Gradle.
-
Add the MediQuo Maven repository to
android/settings.gradle, insidedependencyResolutionManagement.repositories. This is the normal path, not an exception. You add only the repository โ thecom.mediquo:mediquo-sdkdependency itself is declared by this plugin.dependencyResolutionManagement { repositories { google() mavenCentral() maven { url = uri("https://mediquo.jfrog.io/artifactory/android-sdk") } // Add the Vonage Video (TokBox) repo URL MediQuo provides if the build // cannot resolve that transitive dependency. } } -
SDK version โ the plugin pins
com.mediquo:mediquo-sdkto3.8.1by default. Override it only to use a different version published by MediQuo:# android/gradle.properties mediquo.sdkVersion=3.8.1 -
Toolchain โ the SDK is compiled with Kotlin 2.2, so that is the only hard plugin requirement:
Tool Version Kotlin ( org.jetbrains.kotlin.android)2.2.0JDK 17 compileSdk35 or newer minSdk29 You do not need Hilt, KSP or the Compose Gradle plugin, and you must not add a Compose BOM. The AAR is self-contained, and this plugin already supplies the Compose BOM via
api platform(...). (Applying the Compose plugin in an app that has no Compose code fails withIncompatibleComposeRuntimeVersionException.) -
Permissions โ add
CAMERAandRECORD_AUDIO(video calls) and, for push,POST_NOTIFICATIONS(Android 13+) to yourAndroidManifest.xml. The MediQuo Android SDK docs cover the attachmentFileProviderand the colour/font customisation keys.R8/ProGuard rules for the MediQuo SDK's transitive dependencies โ the OpenTok/WebRTC video stack plus MediaPipe, Protobuf, gRPC, Jackson and OSGi โ are bundled with the plugin (
android/consumer-rules.pro) and applied automatically viaconsumerProguardFiles, so aminifyEnabledrelease build needs no MediQuo-specific ProGuard setup. (As with any minified Flutter app you may still need Flutter's own-dontwarn com.google.android.play.core.**for deferred components โ a Flutter concern, not a MediQuo one.)
Verified at build time against
com.mediquo:mediquo-sdk:3.8.1โ a real consumer app compiles with only the above (no Compose/Hilt/KSP plugins) and a release build (R8 /minifyEnabled) succeeds with the bundled rules. Confirm the SDK UI launches at runtime. If a future SDK build ever reports a Hilt/Dagger error, apply the Hilt + KSP plugins and make yourApplication@HiltAndroidAppโ not needed today.
iOS
The MediQuo iOS SDK (MediQuoSDK 26.1.2) ships only as a binary XCFramework. The
plugin bundles it for both dependency managers, so you never add the SDK
yourself โ use whichever your app already uses:
- CocoaPods (default). No extra setup: the plugin's podspec fetches the
MediQuo XCFramework (checksum-pinned to
26.1.2) atpod installand vendors it. Keep Flutter SPM disabled. This is the right path when your app relies on CocoaPods โ for example a OneSignal Notification Service Extension โ where enabling Flutter SPM can clash with prebuilt dynamic frameworks. - Swift Package Manager. If you prefer SPM, enable it
(
flutter config --enable-swift-package-manager) and the plugin'sPackage.swiftpulls the same SDK.
Then, with either dependency manager:
-
Set the iOS deployment target to 17.0 (the SDK's minimum) in your Xcode project.
-
Add the usage descriptions to
Info.plist:<key>NSMicrophoneUsageDescription</key> <string>Required to send voice messages.</string> <key>NSCameraUsageDescription</key> <string>Required to send images and join video calls.</string> -
Set your app's Accent Color for branding and register for APNs if you use push. See the MediQuo iOS SDK docs.
Usage
Create a Mediquo, keep it wherever your app keeps dependencies, and call its
Future-returning methods. Catch MediquoException to surface failures.
import 'package:mediquo_flutter/mediquo_flutter.dart';
final mediquo = Mediquo();
Future<void> startAndOpen(String apiKey, String clientCode) async {
await mediquo.startSession(
MediquoConfiguration.validated(apiKey: apiKey, clientCode: clientCode),
);
await mediquo.openProfessionalList();
}
A complete, runnable sample driven by setState lives in example/.
Push notifications
This package does not fetch push tokens and depends on no Firebase
package โ it only forwards a token you already have to the native SDK. Acquiring
the token is the app's job (typically with
firebase_messaging).
End-to-end flow:
- Your app obtains a token โ FCM on Android; FCM or a raw APNs device token on iOS.
- Your app calls
mediquo.registerPushToken(token)once the patient is authenticated. - The plugin calls the native
registerPushToken. - The MediQuo backend delivers pushes; MediQuo renders them natively (Android
via the bundled
MediquoFirebaseMessagingService, iOS via your notification delegate plusgetSDKViewController(forRemotePush:)).
Who provides what. The per-device token is obtained and registered by your app (the backend can't โ only the device can mint it). The Firebase server credential (a service account) that authorises MediQuo's backend to send pushes is given to MediQuo out-of-band via their portal โ it is never handled by this package and must never be embedded in the app.
final fcmToken = await FirebaseMessaging.instance.getToken();
if (fcmToken != null) {
await mediquo.registerPushToken(MediquoPushToken.fcm(fcmToken));
}
// iOS using a raw APNs token instead of Firebase (pass it as a hex string):
final apnsToken = await FirebaseMessaging.instance.getAPNSToken();
if (apnsToken != null) {
await mediquo.registerPushToken(MediquoPushToken.apns(apnsToken));
}
Open the right screen when a notification is tapped (iOS routes via
getSDKViewController(forRemotePush:); Android deep-links taps natively and
falls back to the professional list):
// e.g. from firebase_messaging's onMessageOpenedApp / getInitialMessage:
await mediquo.openFromNotification(message.data);
The example/ app shows the full wiring (permission request,
getToken, onTokenRefresh).
Android caveat. FCM delivers messages to a single
FirebaseMessagingService. If your app also consumes its own FCM messages, consolidate them into one custom service that forwards MediQuo payloads to the SDK viaMediquoSDK.getInstance()?.onFirebaseMessageReceived(remoteMessage)(native).
Public API
Methods (Mediquo)
| Method | Purpose |
|---|---|
initialize(apiKey) |
initialise the SDK |
authenticate(clientCode) |
authenticate the patient |
startSession(configuration) |
initialise then authenticate |
openProfessionalList() |
present the native UI |
openFromNotification(payload) |
present the screen for a tapped push |
registerPushToken(token) |
register a push token |
logout() |
log the patient out |
Every method returns Future<void> and throws a MediquoException on failure.
The package holds no observable state; model the lifecycle in your own state
management.
Push tokens
MediquoPushToken.fcm(value) or MediquoPushToken.apns(hexValue), passed to
registerPushToken. See Push notifications.
Errors
Failures are thrown as the sealed MediquoException hierarchy
(MediquoInitializationException, MediquoAuthenticationException,
MediquoOpenException, MediquoDeauthenticationException,
MediquoPushRegistrationException, MediquoNotInitializedException,
MediquoPlatformException).
Testing
flutter analyze # clean under very_good_analysis
flutter test --coverage
The Dart layer (models, exceptions, platform interface, method channel and the
Mediquo facade) is fully unit-tested. The native sources follow the documented
MediQuo SDK API.
Documentation
API documentation is generated by dart doc and published on
pub.dev โ start from the
Mediquo class.
License
MIT.
Libraries
- mediquo_flutter
- MediQuo telemedicine integration for Flutter.