Das Flutter-SDK von Hooky
Das Hooky-Gespräch in deiner Flutter-App: eine Dart-API und ein Bubble-Widget, aufgesetzt auf die nativen SDKs von Hooky. Das Gespräch selbst ist das der SDKs für iOS (SwiftUI) und Android (Jetpack Compose): nativ, ohne WebView, in den Farben deiner Website.
HookyBubble auf Android, und das native Gespräch auf dem iPhone, im Dark Mode.Voraussetzungen
- Ab Flutter 3.35 (Dart 3.9).
- Ab Android 7.0 (
minSdk 24, das Minimum von Flutter selbst), kompiliert mitcompileSdk 36. - Ab iOS 15.
- Nur Android und iOS: Im Web und auf dem Desktop tun die Aufrufe nichts.
- Ein Hooky-Konto und eine Website: Ihr öffentlicher Schlüssel steht unter Websites › Bubble installieren, derselbe wie das
data-site-keyder Web-Bubble.
Installation
Das Paket wird aus seinem GitHub-Repository installiert, als Git-Abhängigkeit. In deiner pubspec.yaml:
dependencies:
hooky_sdk:
git:
url: https://github.com/Defdjamel/hooky-flutter
ref: 1.0.0dann flutter pub get. Die nativen SDKs für iOS und Android sind im Paket enthalten: nichts weiter hinzuzufügen, kein weiteres Repository.
iOS
- Das Plugin funktioniert mit Swift Package Manager (in neueren Flutter-Versionen standardmäßig aktiv) und mit CocoaPods: Es baut das mitgelieferte iOS-SDK samt Privacy Manifest.
- Setz das Deployment-Target auf iOS 15.0: in Xcode, Target Runner › General › Minimum Deployments.
- Um die Kamera anzubieten, füg
NSCameraUsageDescriptionzuios/Runner/Info.plisthinzu. Ohne den Eintrag ist die Option einfach ausgeblendet.
Android
Nichts zu deklarieren: Das Android-SDK ist enthalten, mit seinem Gesprächsbildschirm, seinem FileProvider und der Berechtigung INTERNET. Seine Abhängigkeiten (AndroidX, Compose, OkHttp) kommen von google() und mavenCentral(), in Flutter-Projekten schon eingebunden.
Der Quellcode steht unter MIT-Lizenz: github.com/Defdjamel/hooky-flutter.
Loslegen in 3 Zeilen
import 'package:hooky_sdk/hooky_sdk.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
Hooky.configure('DEIN_OEFFENTLICHER_SCHLUESSEL'); // 1. beim Start
runApp(const MeineApp());
}
Scaffold(
floatingActionButton: const HookyBubble(), // 2. die schwebende Bubble
…
);
FilledButton(onPressed: Hooky.open, child: const Text('Schreib uns')); // 3. oder dein eigener Buttonconfigure lädt Name, Farbe und Begrüßungsnachricht der Website, nimmt das gespeicherte Gespräch wieder auf und hält die Live-Verbindung offen, solange die App im Vordergrund ist. Seine benannten Parameter: translation: false entfernt die Übersetzung der Nachrichten des Teams (siehe Nachrichten übersetzen), apiUrl dient nur zum Testen gegen deinen eigenen Server.
Alle Aufrufe geben ein Future zurück und werfen nie einen Fehler: Fehlschläge landen nur in der Konsole, im Debug-Modus. Vor configure warten identify, setAttributes und track, während open, close und reset nichts tun.
Die Bubble
HookyBubble sieht aus wie die native Bubble der jeweiligen Plattform: ein abgerundetes Quadrat mit weichen Schatten auf iOS (60 Punkte), die umrandete Karte mit dem harten Schatten der Web-Bubble auf Android (64 dp). Sie nimmt die Farbe der Website an, trägt ein Badge für Ungelesene und erscheint, sobald configure aufgerufen wurde.
// Als schwebender Button des Scaffold
Scaffold(floatingActionButton: const HookyBubble(), …)
// Irgendwo, in einem Stack
Stack(children: [
const MeinBildschirm(),
const Positioned(right: 20, bottom: 20, child: SafeArea(child: HookyBubble())),
])
// Deine eigene Aktion, eine andere Größe, ein festgelegter Stil
HookyBubble(onPressed: () => analytics.log('chat'), size: 52, style: HookyBubbleStyle.material)Gespräch öffnen und schließen
Hooky.open(); // Vollbild: ein Sheet auf iOS, eine Activity auf Android
Hooky.close(); // schließt es wiederDas Gespräch wird vom nativen SDK gezeichnet: Die Seiten iOS und Android beschreiben, was es kann (Fotos, PDFs, Entwurf, Fehler).
Ungelesene Nachrichten
Die Bubble zeigt ihr Badge schon selbst. Für deine eigenen Buttons ist Hooky.unreadCount zugleich ein ValueListenable<int> und ein Stream<int> (der aktuelle Wert, dann jede Änderung). Er fällt auf 0, sobald sich das Gespräch öffnet.
// Ein Badge auf einem Tab
ValueListenableBuilder<int>(
valueListenable: Hooky.unreadCount,
builder: (context, n, _) => Badge(isLabelVisible: n > 0, label: Text('$n'), child: const Icon(Icons.chat)),
)
// Oder als Stream
Hooky.unreadCount.listen((n) => print('$n ungelesen'));
final jetzt = Hooky.unreadCount.value;Hooky.state (ein ValueListenable<HookyState>) liefert außerdem isConfigured, siteName, siteColor und sitePosition, für deine eigene Oberfläche. Antworten kommen live an, solange die App im Vordergrund ist; Version 1.0.0 schickt deinen Nutzern keine Push-Benachrichtigungen.
Nutzer identifizieren
Deine App weiß, wer angemeldet ist: Sag es Hooky. Dein Team sieht in den Details des Gesprächs den Namen, die E-Mail, deine eigene Nutzer-ID, das Gerät und die Daten, die du mitgibst. Mit einer E-Mail fragt das Gespräch weder nach Vornamen noch nach E-Mail.
// Nach der Anmeldung
Hooky.identify(
name: user.vorname,
email: user.email,
userId: user.id, // deine eigene ID
attributes: {'tarif': 'Pro', 'bestellungen': 3, 'newsletter': true},
);
// Später: mit den bisherigen zusammengeführt
Hooky.setAttributes({'warenkorb': 49.9, 'gutschein': null}); // null löscht einen Schlüssel
// Bei der Abmeldung
Hooky.reset();So funktioniert es
- Noch kein Gespräch: Alles bleibt im Speicher (sogar vor
configure) und wird mit der ersten Nachricht gesendet. Danach wird jede Änderung sofort gesendet, gebündelt (eine einzige Anfrage für alles, was sich in derselben Sekunde ändert). Offline geht sie später raus. nameundemailersetzen die des Gesprächs (nulllöscht sie auf dem Gerät);userId: nulllässt sie unverändert.- Eine
userId, die sich von der des Gesprächs unterscheidet, bedeutet ein anderes Konto auf demselben Gerät: Das Gespräch wird vergessen, wie beireset(). Der neue Nutzer sieht den Verlauf des vorherigen nicht. Hooky.reset()schließt das Gespräch und vergisst Verlauf und Identität. Ruf es bei der Abmeldung auf.
Regeln für die Daten
| Feld | Regel |
|---|---|
| Freie Daten | Eine flache Map: höchstens 50 Schlüssel, insgesamt 8 KB. Neue Schlüssel ersetzen die alten, die übrigen bleiben. |
| Schlüssel | 1 bis 64 Zeichen: Buchstaben, Ziffern, Leerzeichen, _, . und -. Sonst wird er ignoriert. |
| Wert | Ein String (nach 500 Zeichen abgeschnitten), ein num oder ein bool. null löscht den Schlüssel. Alles andere wird verworfen, mit einer Warnung im Debug-Modus. |
userId | Höchstens 200 Zeichen. |
name, email | Der Name: höchstens 100 Zeichen. Die E-Mail: eine gültige Adresse, sonst wird sie ignoriert. |
Hooky räumt auf, was darüber hinausgeht, und lehnt die Nachricht deines Nutzers deswegen nie ab.
Diese Daten sind Angaben, keine Beweise: Der Schlüssel der Website ist öffentlich, und jeder kann ihn nutzen, um einen beliebigen Namen, eine E-Mail oder eine userId seiner Wahl zu senden. Sie helfen deinem Team, die Person einzuordnen, beweisen aber nicht, wer sie ist. Leg dort nie etwas Geheimes ab (Passwort, Token, Kartennummer) und nutze sie nie, um Zugriff zu gewähren oder an einem Konto etwas zu ändern: Prüf immer auf deiner Seite nach.
Stats
Zähl, was in deiner App passiert, wie mit Hooky.track im Web: Die Kacheln erscheinen unter Statistiken, zusammen mit denen der Website. Ruf es direkt auf, nachdem die Aktion geklappt hat.
Hooky.track('anmeldung');
Hooky.track('bestellung', value: 49.9, properties: {'tarif': 'pro', 'plaetze': 3, 'testphase': false});value: ein Betrag oder eine Menge, in der Kachel summiert. Die Properties sind flach (String,num,bool).- Vor
configureaufgerufen, wartet das Event (höchstens 100). Fehler bleiben stumm; offline geht das Event verloren. - Dieselben Regeln wie im Web (Name, höchstens 20 Properties, Limit): siehe Stats in der Seite.
Schick nie personenbezogene Daten (E-Mail, Name, Telefon) in einem Event. Zähl Aktionen, keine Personen.
Nachrichten übersetzen
Dein Nutzer und dein Team schreiben jeweils in ihrer Sprache, wie mit der Web-Bubble (siehe Nachrichten übersetzen).
- Unter einer Nachricht des Teams in einer anderen Sprache als der des Gesprächs (der des Geräts) steht ein dezenter Link Übersetzen. Übersetzt erscheint die Nachricht in der Sprache des Nutzers, mit „Übersetzt aus dem Englischen · Original anzeigen“, um zum ursprünglichen Text zurückzukehren.
- Der Übersetzungsknopf in der Kopfzeile bietet Immer übersetzen an: Die Nachrichten des Teams kommen dann schon übersetzt an. Die Wahl wird auf dem Gerät gespeichert, pro Website-Schlüssel.
- Schlägt eine Übersetzung fehl, erscheint ein kurzer Fehler mit Erneut versuchen. Die Nachrichten des Nutzers werden bei ihm nie übersetzt; dein Team hat seinen eigenen Knopf Übersetzen, im Dashboard und in der Hooky-App.
- Nur Text wird übersetzt, keine Anhänge. Die Übersetzung ist standardmäßig aktiv; um sie aus deiner App zu entfernen:
Hooky.configure('DEIN_OEFFENTLICHER_SCHLUESSEL', translation: false).
Was das SDK sendet
Was die Web-Bubble sendet, und sonst nichts: die Nachrichten und Dateien des Nutzers, Name, E-Mail, ID und die Daten, die du mitgibst, Sprache und Zeitzone des Geräts sowie sein Modell mit der Systemversion („iPhone 17 Pro · iOS 27.0“, „Pixel 8 · Android 15“). Ohne Werbe-ID und ohne Tracking.
- Jede Anfrage trägt
X-Hooky-Client: hooky-flutter/1.0.0undX-Hooky-App: <bundle id oder package> <version> (<build>): Dein Team sieht, dass das Gespräch von „Flutter · com.example.app 1.0 (1)“ kommt. - Das Gesprächs-Token wird vom nativen SDK gespeichert: im Schlüsselbund auf iOS (nur dieses Gerät), in einer privaten, nie gesicherten Datei auf Android.
- Das Plugin bringt ein iOS-Datenschutzmanifest (
PrivacyInfo.xcprivacy) mit, das kein Tracking angibt. - Für deine Store-Einträge gelten die Daten der nativen SDKs: siehe das App Store-Profil (iOS-Seite) und den Abschnitt Datensicherheit bei Google Play (Android-Seite).
Sprache, Dark Mode, Barrierefreiheit
- Sprache
- Die Oberfläche gibt es auf Französisch, Englisch, Spanisch, Portugiesisch, Italienisch und Deutsch. Sie folgt der Sprache des Geräts, standardmäßig Englisch. Die Sprache wird mit der ersten Nachricht gesendet, damit dein Team in der richtigen Sprache und zur richtigen Uhrzeit antwortet.
- Dark Mode
- Gespräch und Bubble folgen dem hellen oder dunklen Modus des Geräts, mit der Farbe deiner Website.
- Barrierefreiheit
- Die Bubble ist für Screenreader ein Button („Chat mit … öffnen“, und die Zahl der ungelesenen Nachrichten); das native Gespräch behält VoiceOver und Dynamic Type auf iOS, TalkBack und die Schriftgröße auf Android.
R8 und ProGuard
Auf Android nichts hinzuzufügen: Das SDK nutzt keine Reflection und bringt eigene Regeln mit.
Fehlerbehebung
- Meine Website hat ihre Adressen eingetragen: Wird die App abgelehnt?
- Nein. Eine App hat keine Adresse: Sie weist sich mit ihrem Header
X-Hooky-Clientaus und kommt auch dann durch, wenn die Website ihre Domains eingetragen hat. Trag unter Websites nichts ein. - „the Hooky plugin is not available on this platform“
- Starte die App nach dem Hinzufügen des Pakets komplett neu (
flutter run), ein Hot Reload reicht nicht. Im Web und auf dem Desktop gibt es das Plugin nicht. - Der iOS-Build schlägt fehl
- Prüf das Deployment-Target (iOS 15.0): Swift Package Manager und CocoaPods lehnen ein niedrigeres ab. Nach einem Versionswechsel des Pakets:
flutter clean, dannflutter pub get. - Die Bubble bleibt in den Standardfarben
- Prüf den öffentlichen Schlüssel der Website (nicht den geheimen Schlüssel
hks_…und keinen API-Schlüsselhka_…) und das Netz. - Offline
- Die Nachricht zeigt den Fehler und bleibt im Eingabefeld;
identifyundsetAttributeswerden später gesendet. Offline gesendetetrack-Events gehen verloren.
Versionsverlauf
- 1.0.0
- Erste Version:
Hooky.configure,identify(mituserIdund freien Daten),setAttributes,open,close,track,reset,unreadCountundstatelive, das WidgetHookyBubble, die Übersetzung der Nachrichten des Teams (translation), auf den nativen SDKs iOS 1.0.0 und Android 1.0.0.