Créer un plugin natif sur mesure pour Capacitor 8 (Swift & Kotlin)
Tutoriel complet pour interfacer vos SDKs natifs matériels avec votre frontend TypeScript via l’API Plugin de Capacitor.
Quand faut-il créer un plugin Capacitor personnalisé ?
L'écosystème open-source propose de nombreux plugins Capacitor (caméra, géolocalisation, notifications), mais sur les projets sur mesure, vous aurez souvent besoin de : - Interfacer un SDK constructeur propriétaire (lecteur RFID, terminal de paiement, scanner de code-barres industriel). - Utiliser une API iOS / Android récente non encore supportée par la communauté. - Accéder aux enclaves matérielles sécurisées (Apple Secure Enclave, Android KeyStore).
1. Définition de l'interface TypeScript
Le contrat entre le code web et le code natif commence toujours par une interface TypeScript stricte :
export interface CustomBiometricPlugin {
authenticate(options: { reason: string }): Promise<{ success: boolean; token?: string }>;
getHardwareStatus(): Promise<{ isAvailable: boolean; biometryType: 'faceID' | 'touchID' | 'none' }>;
}2. Implémentation iOS en Swift 6
Dans le dossier iOS de votre plugin, créez la classe Swift qui implémente le binding :
import Foundation
import Capacitor@objc(CustomBiometricPlugin) public class CustomBiometricPlugin: CAPPlugin { @objc func authenticate(_ call: CAPPluginCall) { let reason = call.getString("reason") ?? "Authentification requise" let context = LAContext() context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason) { success, error in if success { call.resolve(["success": true]) } else { call.reject(error?.localizedDescription ?? "Échec d'authentification") } } } } ```
3. Implémentation Android en Kotlin
Côté Android, nous utilisons les APIs BiometricPrompt :
@CapacitorPlugin(name = "CustomBiometric")
class CustomBiometricPlugin : Plugin() {
@PluginMethod
fun authenticate(call: PluginCall) {
val reason = call.getString("reason", "Authentification requise")
// Implémentation BiometricPrompt native
val ret = JSObject()
ret.put("success", true)
call.resolve(ret)
}
}Avec cette approche, votre code web reste 100% propre et bénéficie d'une puissance native intégrale.