Erster Lauf des Einrichtungsskripts auf einem Mac. Xcode brach ab mit "error: Unexpected duplicate tasks", zweimal ValidateEmbeddedBinary auf dieselbe DataMetric360Share.appex. Ursache: addTarget() legt fuer den Typ app_extension selbst schon eine Copy-Phase nach PlugIns am ersten Ziel an. Das Skript fuegte danach eine zweite mit demselben Ziel und derselben Datei hinzu. Die explizite Phase entfaellt jetzt; belegt am erzeugten Projekt: genau eine Phase mit dstSubfolderSpec 13 statt zwei. Alles Uebrige des Skripts lief auf Anhieb: Ziel, Entitlements, URL-Schema, Idempotenz.
5.9 KiB
Tankbeleg aus dem Teilen-Blatt
Ein PDF aus Mail (oder einer anderen App) über Teilen → DataMetric360 direkt als Tankbeleg übernehmen.
Wie es zusammenhängt
Mail ──Teilen──► DataMetric360Share (eigener Prozess)
│
│ PDF → Base64 → UserDefaults der App-Gruppe
│ group.app.datametric360
▼
datametric360://beleg (öffnet die App)
│
▼
App.tsx ──holt ab──► Tanken-Seite ──► belegLesen()
Eine Erweiterung ist ein eigener Prozess mit eigenem Dateibereich; der einzige
gemeinsame Boden mit der App ist die App-Gruppe. Der Beleg reist deshalb
Base64-kodiert durch die geteilten UserDefaults — die liest
@capacitor/preferences ohnehin schon, sobald man ihm die Gruppe nennt. Eine
Datei im Gruppen-Container wäre der sauberere Ort, bräuchte auf der App-Seite
aber eigenen nativen Code, also ein zusätzliches Plugin für einen Weg, den es
sonst nicht gäbe.
Der Preis ist eine Größengrenze von 4 MB (grenzeBytes im
ShareViewController). Ein Tankbeleg liegt bei einigen Dutzend Kilobyte; ein
gescanntes Mehrseiten-PDF kann darüber liegen — dann sagt die Erweiterung das,
und der Weg über Beleg hochladen → Datei auswählen in der App bleibt.
Wo was liegt
| Datei | Rolle |
|---|---|
native/teilen/ShareViewController.swift |
nimmt das PDF entgegen, legt es ab, öffnet die App |
native/teilen/Info.plist |
wann DataMetric360 im Teilen-Blatt erscheint (genau ein PDF) |
native/teilen/DataMetric360Share.entitlements |
App-Gruppe für die Erweiterung |
native/App.entitlements |
dieselbe App-Gruppe für die App |
scripts/ios-teilen-einrichten.mjs |
hängt das alles ins erzeugte Xcode-Projekt |
src/daten/geteilterBeleg.ts |
holt den Beleg ab, räumt ihn weg |
src/App.tsx |
prüft beim Start und bei jeder Rückkehr, springt auf Tanken |
src/screens/Tanken.tsx |
nimmt ihn auf und lädt ihn hoch |
companion-app/ios/ ist gitignored und wird von npx cap add ios neu
gebaut. Alles Native muss deshalb unter native/ liegen und bei jedem Bau
eingespielt werden — dieselbe Regel, die schon die Team-Kennung und den
Standort-Schlüssel in ios-signieren.sh getrieben hat.
Einmalig im Apple-Entwicklerportal
Ohne diese drei Schritte schlägt das Signieren fehl (die App-Gruppe muss existieren, bevor ein Profil sie enthalten kann):
- Identifiers → App Groups:
group.app.datametric360anlegen. - Identifiers → App IDs:
app.datametric360.teilenanlegen, Capability App Groups aktivieren, die Gruppe zuordnen. - Bei der bestehenden App-ID
app.datametric360ebenfalls App Groups aktivieren und dieselbe Gruppe zuordnen.
Danach in Xcode einmal die Profile neu ziehen lassen — oder schlicht
ios-signieren.sh laufen lassen, das macht -allowProvisioningUpdates
selbst. Merkposten aus Abschnitt AI: ein zwischengespeichertes altes
Profil wird stillschweigend weiterverwendet. Ändert sich etwas an den
Berechtigungen, das passende .mobileprovision unter
~/Library/Developer/Xcode/UserData/Provisioning Profiles löschen und neu
exportieren.
Bauen
bash scripts/ios-signieren.sh
Der Schritt „Share-Erweiterung einrichten" läuft dort automatisch, vor dem Archivieren.
Wenn das Skript abbricht
ios-teilen-einrichten.mjs bearbeitet die project.pbxproj über das
npm-Paket xcode. Erstmals auf einem Mac gelaufen am 2026-09-02; dabei kam
genau ein Fehler heraus, seither behoben: die Erweiterung wurde zweimal
eingebettet, weil addTarget() für den Typ app_extension von sich aus schon
eine Copy-Phase nach PlugIns anlegt und das Skript eine zweite hinzufügte.
Xcode quittierte das mit error: Unexpected duplicate tasks. Das Anlegen des
Ziels selbst, die Entitlements, das URL-Schema und die Idempotenz funktionierten
auf Anhieb.
Bricht es ab, ist nichts halb eingerichtet (es bricht vor dem Schreiben ab), und dasselbe lässt sich in Xcode von Hand erledigen:
- File → New → Target… → Share Extension, Name
DataMetric360Share, Sprache Swift, „Activate scheme" verneinen. - Die von Xcode erzeugten
ShareViewController.swift,Info.plistund dasMainInterface.storyboardlöschen und stattdessen die Dateien ausnative/teilen/in das Ziel legen (Storyboard wird nicht gebraucht, die Erweiterung hat keine eigene Oberfläche). - Bundle-ID des Ziels auf
app.datametric360.teilensetzen. - Beide Ziele → Signing & Capabilities → + Capability → App Groups,
group.app.datametric360anhaken. - Ziel
DataMetric360Share→ Build Settings → Code Signing Entitlements aufDataMetric360Share/DataMetric360Share.entitlements; ZielAppaufApp/App.entitlements. - Ziel
App→ Build Phases → Embed App Extensions mussDataMetric360Share.appexenthalten. ios/App/App/Info.plist: URL-Schemadatametric360unterCFBundleURLTypeseintragen.
Schritt 7 ist der leiseste: fehlt er, wird der Beleg abgelegt, die App aber nicht geöffnet — er taucht dann erst auf, wenn man die App das nächste Mal von Hand startet.
Prüfen, ob es wirkt
- In Mail ein PDF antippen → Teilen → DataMetric360 muss in der Liste stehen (nur bei genau einem PDF, sonst absichtlich nicht).
- Antippen → die App kommt nach vorn, springt auf Tanken, das Formular ist offen und liest den Beleg („Beleg wird gelesen …").
- Danach ist der Eintrag weg: dieselbe Datei ein zweites Mal zu teilen muss wieder funktionieren, ein bloßes Wechseln in die App darf den Beleg nicht erneut verarbeiten.
Was hier nicht steht
Android. Der Ablauf ist dort ein anderer (intent-filter statt App-Gruppe),
und die Android-Hülle dieses Projekts ist ohnehin nicht in Gebrauch.