Flutter-Apps
Das Flutter-SDK relyo_flutter läuft auf iOS (ab 15), Android (ab 8) und Flutter Web mit demselben Code. Es überträgt die Flutter-Oberfläche als Bildfolge: Nur geänderte Bildbereiche werden geschickt, bis zu 10 Bilder pro Sekunde. Eine Berechtigung des Betriebssystems braucht es dafür nicht.
Abhängigkeit
Das Paket liegt nicht auf pub.dev, sondern im Relyo-Repository:
# pubspec.yaml
dependencies:
relyo_flutter:
git:
url: https://github.com/justcode049/Relyo.git
path: packages/flutter-sdk
ref: main # besser: einen festen Commit eintragen
Das Repository ist noch nicht öffentlich. Bis dahin bekommst du den Zugang per E-Mail an [email protected].
Voraussetzung ist Flutter 3.38 oder neuer.
- iOS: Deployment-Target 15.0 (
platform :ios, '15.0'imPodfile). - Android:
android.permission.INTERNETim Manifest; für einen lokalen Server perws://während der Entwicklung zusätzlichandroid:usesCleartextTraffic="true".
Einrichten
import 'package:relyo_flutter/relyo_flutter.dart';
void main() {
Relyo.init(
relayUrl: 'wss://relyo.de',
projectKey: 'pk_deineapp', // entfällt im offenen Dienst
connect: RelyoConnect.lazy,
appVersion: '1.4.0',
);
runApp(RelyoScope(child: const MyApp()));
}
RelyoScope gehört außen um MaterialApp bzw. CupertinoApp und darf nur einmal vorkommen. Die Dialoge des SDK und die Statusleiste liegen in einem eigenen Overlay außerhalb des übertragenen Bereichs und erscheinen deshalb nie im Bild beim Supporter.
Support-Eintrag
Am besten in den Einstellungen, unauffällig am Ende der Liste:
TextButton(
onPressed: () => Relyo.instance.showCode(context),
child: const Text('Support'),
)
showCode zeigt den Code-Dialog, danach führt das SDK durch Freigabe, Session und Ende. Während der Session vergrößert es den oberen Rand der App um die Höhe der Statusleiste (36 Pixel), damit die Leiste keine Bedienelemente verdeckt.
Optionen
| Parameter | Standard | Bedeutung |
|---|---|---|
relayUrl | – | Pflicht. Adresse des Servers, zum Beispiel wss://relyo.de. |
projectKey | – | Projekt-Key der App. Ohne Key ordnet ein Server mit offenem Dienst die App ihrer App-ID zu (Bundle-ID bzw. Package-Name). |
user | – | Angemeldeter Nutzer, RelyoUser(id: …, name: …). Nur zur Anzeige, nicht geprüft. |
connect | RelyoConnect.auto | auto: mit user sofort verbinden, sonst erst bei showCode; eager: immer sofort; lazy: nur bei showCode. |
appVersion | '' | Version der App; erscheint in der Konsole. |
fps | 5 | Ziel-Bildrate, 2 bis 10. Bei knapper Bandbreite regelt das SDK selbst herunter. |
consentText | – | Eigener Erklärtext im Freigabe-Dialog; {agent} wird durch den Namen des Supporters ersetzt. |
Weitere Aufrufe:
Relyo.instance.identify(const RelyoUser(id: 'u_123', name: 'Max M.')); // nach dem Login
Relyo.instance.identify(null); // beim Logout
Relyo.instance.end(); // Session beenden, sonst „Beenden“ in der Statusleiste
Vor der ersten Verbindung legt das SDK nichts auf dem Gerät ab, auch keine Kennung.
Maskierung
Maskiert wird auf dem Gerät, bevor ein Bild es verlässt:
- Immer: jedes Feld mit
obscureText: true. RelyoRedact: alles innerhalb dieses Widgets.
RelyoRedact(
child: TextField(decoration: InputDecoration(labelText: 'IBAN')),
)
Maskierte Bereiche werden schwarz übermalt, bevor das Bild kodiert wird. Kann das SDK den Bildschirm einmal nicht vollständig prüfen, schwärzt es das ganze Bild. Ferngesteuerte Eingaben in maskierte Felder lehnt das SDK ab.
Navigation
Damit der Supporter sieht, wo der Nutzer gerade ist, und Zeichnungen beim Seitenwechsel verschwinden:
MaterialApp(
navigatorObservers: [RelyoNavigatorObserver()],
// …
)
Mit GoRouter zusätzlich für Wechsel, die keinen Navigator-Push auslösen (go(), ShellRoute):
final router = GoRouter(observers: [RelyoNavigatorObserver()], routes: [/* … */]);
router.routerDelegate.addListener(() {
Relyo.instance.reportRoute(router.routerDelegate.currentConfiguration.uri.path);
});
Steuerung
Nach der zweiten Freigabe kann der Supporter tippen, wischen und scrollen, Text in das gerade fokussierte Feld schreiben sowie Enter und Rücktaste senden. Jede eigene Berührung des Nutzers oder eine Hardware-Taste beendet die Steuerung sofort.
Grenzen
- Platform-Views (WebView, Karten, Kamera) erscheinen als graue Fläche mit „Eingebettete Ansicht“.
- System-Dialoge (Berechtigungen, Teilen) und die Bildschirmtastatur sind nicht im Bild.
- Ferngesteuerter Text nur in Flutter-Textfeldern (
TextField,CupertinoTextFieldund alles auf Basis vonEditableText). - Geht die App in den Hintergrund, pausiert die Übertragung und läuft beim Zurückkehren weiter.
- Die Dialoge sind bisher nur auf Deutsch.
Testen
Für eigene Widget-Tests ohne Server gibt es package:relyo_flutter/testing.dart mit einem Test-Server im Speicher (RelyoTesting.install, FakeRelyoServer).