← Back to Native mobile foundation team
See how it helps
Mobile native integration
Defines reliable boundaries between cross-platform application code and platform-specific native capabilities.
mobile-native-integration
Team members using this skill
When is it useful?
Use when a feature needs an SDK or device function beyond existing framework APIs.
What does it help you do?
- Chooses the integration mechanism supported by the actual project.
- Specifies typed requests, threading, cancellation and error propagation.
- Updates native manifests and build configuration without losing existing setup.
Try asking this
Integrate a native document scanner with cancellation and explicit errors when the capability is unavailable. Cancel scanning halfway and try it on an unsupported device. Return distinct cancellation and unsupported-capability outcomes without leaving the caller waiting indefinitely.
Detailed documentation
Read the skill’s original instructions, examples and checks in their authored language.
Show less
Native Platform Integration
Encapsulate iOS (Swift / Objective-C / SwiftUI) and Android (Kotlin / Jetpack Compose) platform APIs behind narrow, type-safe interfaces so application screens and domain logic remain portable and testable.
1. Choose the right native integration mechanism
- Check existing SDK & community modules first: before writing custom native code, verify whether an official Expo SDK module, RN community package or Flutter plugin already supports the capability.
- When custom native code is required:
- Expo / React Native:
- Prefer the Expo Modules API (
ModuleDSL in Swift and Kotlin withFunction,AsyncFunction,Events,View) for clean lifecycle hooks and automatic type bridging. - In bare React Native on the New Architecture, define typed Codegen specs (
specs/Native<Name>.tsextendingTurboModulewithTurboModuleRegistry.getEnforcing<Spec>) and Fabric view components.
- Prefer the Expo Modules API (
- Flutter:
- Prefer Pigeon (
@HostApi()/@FlutterApi()) to generate type-safe Dart, Swift and Kotlin contracts without untyped dictionary casting. - When using
MethodChannelorEventChanneldirectly, namespace channel names (com.example.app/<feature>), validate argument maps, and handlePlatformExceptionandMissingPluginException.
- Prefer Pigeon (
- Pure Native (SwiftUI / Jetpack Compose):
- On iOS, isolate hardware/OS frameworks (
AVFoundation,CoreLocation,LocalAuthentication,StoreKit,BackgroundTasks) in@MainActoror actor-isolated service protocols injected into@Observableview models. - On Android, isolate
Context-bound system services,ActivityResultLaunchercontracts andBroadcastReceiverregistrations behind repository/controller interfaces injected via Hilt/Koin/manual DI.
- On iOS, isolate hardware/OS frameworks (
- Expo / React Native:
2. Design a resilient boundary contract
- Single cross-platform wrapper: expose one domain-level TypeScript or Dart module (
biometricVault.ts,documentScanner.dart). UI components must never branch on raw iOSNSErrordomains or AndroidIntentextras. - Capability & simulator fallback: expose an explicit availability check (
isAvailableAsync()) and degrade gracefully on iOS Simulator, Android Emulator without Google Play Services, or older OS versions (if #available(iOS 17, *),Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE). - Threading & lifecycle discipline:
- Never block the iOS main thread (
DispatchQueue.main) or Android main looper (Dispatchers.Main) with file I/O, image transcoding, encryption or synchronous IPC. - Clean up native event emitters,
NotificationCenterobservers,BroadcastReceiverinstances and hardware sessions when the JS/Dart listener detaches or the hostActivity/UIViewControllerpauses.
- Never block the iOS main thread (
3. Native project configuration, manifests and build safety
- iOS (
Info.plist,*.entitlements,Podfile, Xcode):- Add specific
NS...UsageDescriptionkeys for every protected capability, requiredUIBackgroundModes, Associated Domains (applinks:) and Privacy Manifest declarations (PrivacyInfo.xcprivacyrequired reason APIs).
- Add specific
- Android (
AndroidManifest.xml,build.gradle(.kts),proguard-rules.pro):- Declare minimal
<uses-permission>entries,<uses-feature android:required="false" />when hardware is optional (so Google Play does not hide the app on tablets/devices without that sensor), Android 14+android:foregroundServiceTypeattributes, and@Keep/ ProGuard rules for classes serialized across the bridge in release builds.
- Declare minimal
- Expo CNG rule: in managed/prebuild projects, encode all
Info.plist, entitlement andAndroidManifest.xmlchanges inapp.json/app.config.tsor a Config Plugin (withInfoPlist,withAndroidManifest) sonpx expo prebuild --cleanstays reproducible. - Release impact: any native code, Podfile, Gradle or manifest change requires a new binary build (and a
runtimeVersionbump for OTA updates).
Before you finish
- Native bridge wrapped behind a single typed service with simulator and OS fallbacks.
- Heavy native work runs off the main thread; native observers and hardware sessions cleaned up.
- iOS (
Info.plist,PrivacyInfo.xcprivacy, entitlements) and Android (AndroidManifest.xml,foregroundServiceType, ProGuard/R8) configs complete. - Requirement for a new native binary build documented in the handoff.
Included files 2
LICENSE.txtSKILL.md
