Die .ipa war nicht installierbar, plus QR-Scanner (2026.9.4.8)

Der Erweiterung fehlte CFBundleVersion - eine Pflichtangabe, ohne die iOS
die Installation der ganzen App verweigert ("kann nicht installiert werden").
Verursacht von der Versionsangleichung vom Vortag: das Skript reichte den
Platzhalter $(CURRENT_PROJECT_VERSION) statt einer Zahl weiter, und das per
Skript angelegte Ziel der Erweiterung kennt diese Build-Einstellung nicht.
An den entpackten .ipa nachgemessen, 2026.9.3.3 gegen 2026.9.4.5.

ios-signieren.sh reicht nur noch echte Zahlen weiter, das Gegenlesen der
fertigen .ipa bricht ab statt zu warnen, und abgelegt wird erst danach -
eine Datei, die die Pruefung nicht besteht, darf nicht in auslieferung/
landen.

Dazu:
- Kopfmarke statt Firmierung des Betreibers in der Tankstellen-Zeile
- dritter Suchbegriff: der Name ohne fuehrende Marke. Gemessen: Nominatim
  findet "Shell, Pascalstr. 8, Ingolstadt" nicht, "Pascalstr. 8, Ingolstadt"
  schon - daran blieb die Belegkarte der realen Instanz leer
- der Tankstellen-Verweis zeigt die Tankstelle, statt eine Route zu rechnen
- Cache-Brecher auf .ipa, Symbolen und manifest.plist
- QR-Scanner fuer den Zugangs-Token bei der Ersteinrichtung (jsQR statt
  GoogleMLKit, damit der Xcode-Lauf kein pod install riskiert)

214/214 Tests, Panel als Modul geparst, live gegen audi_ha_test geprueft.
This commit is contained in:
2026-09-04 11:51:44 +02:00
parent d819f2e285
commit 63a45d4ee2
20 changed files with 788 additions and 56 deletions
+10 -5
View File
@@ -60,6 +60,11 @@ mkdir -p "$ZIEL"
cp "$APP/public/symbol-192.png" "$ZIEL/symbol-192.png"
cp "$APP/public/symbol-512.png" "$ZIEL/symbol-512.png"
# Die Adressen tragen die Version als Anhaengsel (?v=...). Sie zeigen sonst bei
# jedem Bau auf dieselbe Zeichenkette, und der Installations-Dienst von iOS haelt
# eine einmal geholte .ipa dann fuer schon bekannt - sichtbar als Wolke mit Pfeil,
# die nie fertig wird, oder als "kann nicht installiert werden". Dieselbe Vorsorge
# trifft das Panel seit jeher fuer sein eigenes Buendel (siehe ota.ts).
cat > "$ZIEL/manifest.plist" <<PLISTENDE
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
@@ -72,15 +77,15 @@ cat > "$ZIEL/manifest.plist" <<PLISTENDE
<array>
<dict>
<key>kind</key><string>software-package</string>
<key>url</key><string>$BASIS/App.ipa</string>
<key>url</key><string>$BASIS/App.ipa?v=$VERSION</string>
</dict>
<dict>
<key>kind</key><string>display-image</string>
<key>url</key><string>$BASIS/symbol-192.png</string>
<key>url</key><string>$BASIS/symbol-192.png?v=$VERSION</string>
</dict>
<dict>
<key>kind</key><string>full-size-image</string>
<key>url</key><string>$BASIS/symbol-512.png</string>
<key>url</key><string>$BASIS/symbol-512.png?v=$VERSION</string>
</dict>
</array>
<key>metadata</key>
@@ -116,7 +121,7 @@ cat > "$ZIEL/index.html" <<HTMLENDE
<main>
<h1>DataMetric360</h1>
<p>Version $VERSION</p>
<a href="itms-services://?action=download-manifest&amp;url=$BASIS/manifest.plist">Installieren</a>
<a href="itms-services://?action=download-manifest&amp;url=$BASIS/manifest.plist?v=$VERSION">Installieren</a>
<p>In Safari oeffnen. Nach dem Antippen fragt iOS einmal nach,<br>danach erscheint die App auf dem Startbildschirm.</p>
</main>
</html>
@@ -133,4 +138,4 @@ echo
# hier zusaetzlich der fertige Link zum Einfuegen in die Safari-Adresszeile;
# der funktioniert unabhaengig davon, ob eine Seite drumherum existiert.
echo "Ohne Seite (z. B. aus dem Repository heraus) direkt in Safari einfuegen:"
echo " itms-services://?action=download-manifest&url=$BASIS/manifest.plist"
echo " itms-services://?action=download-manifest&url=$BASIS/manifest.plist?v=$VERSION"
+49 -5
View File
@@ -126,6 +126,22 @@ for SCHLUESSEL in NSCalendarsWriteOnlyAccessUsageDescription NSCalendarsUsageDes
}
done
# Kamera, fuer den QR-Scanner der Ersteinrichtung.
#
# Gelesen wird der Code in der WebView (jsQR ueber getUserMedia), nicht von
# einem nativen Plugin - siehe den Kopf von src/screens/QrScanner.tsx, warum
# nicht GoogleMLKit. Dieser Schluessel ist trotzdem noetig: ohne ihn beendet
# iOS die App in dem Moment, in dem sie die Kamera anfordert.
echo "==> Kamera-Berechtigung eintragen"
KAMERAGRUND="Liest den QR-Code deines Zugangs-Tokens bei der Ersteinrichtung."
if ! /usr/libexec/PlistBuddy -c "Set :NSCameraUsageDescription $KAMERAGRUND" "$PLIST" 2>/dev/null; then
/usr/libexec/PlistBuddy -c "Add :NSCameraUsageDescription string $KAMERAGRUND" "$PLIST"
fi
/usr/libexec/PlistBuddy -c "Print :NSCameraUsageDescription" "$PLIST" >/dev/null || {
echo "FEHLER: NSCameraUsageDescription liess sich nicht setzen." >&2
exit 1
}
# Share-Erweiterung ins Xcode-Projekt haengen.
#
# Aus demselben Grund wie die Team-Kennung und der Standort-Schluessel oben:
@@ -173,6 +189,18 @@ if ! /usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString $VERSION" "$PLI
/usr/libexec/PlistBuddy -c "Add :CFBundleShortVersionString string $VERSION" "$PLIST"
fi
BUILDNR="$(/usr/libexec/PlistBuddy -c 'Print :CFBundleVersion' "$PLIST" 2>/dev/null || echo 1)"
# In der Info.plist der App steht dort KEINE Zahl, sondern der Platzhalter
# einer Build-Einstellung ($(CURRENT_PROJECT_VERSION), aus dem Capacitor-
# Geruest). Fuer das App-Ziel loest Xcode ihn zu 1 auf - das Ziel der
# Erweiterung kennt die Einstellung aber gar nicht, dort wurde daraus LEER,
# und ein Buendel ohne CFBundleVersion lehnt iOS beim Installieren ab
# ("kann nicht installiert werden"). Genau so ist die .ipa vom 04.09.2026
# unbrauchbar geworden - an der ausgelieferten Datei nachgemessen: App
# CFBundleVersion 1, Erweiterung gar keine. Deshalb hier nur eine echte Zahl
# weiterreichen, sonst die 1.
case "$BUILDNR" in
""|*'$('*|*[!0-9.]*) BUILDNR=1 ;;
esac
# Die Share-Erweiterung MUSS dieselben beiden Nummern tragen wie die App.
#
@@ -265,10 +293,6 @@ xcodebuild -exportArchive \
-exportPath "$AUSGABE" \
-allowProvisioningUpdates
# Die fertige .ipa liegt versioniert unter auslieferung/, weil ios/ gitignored
# ist und das Ergebnis sonst nur auf diesem einen Mac existierte.
mkdir -p "$APP/auslieferung"
cp "$AUSGABE/App.ipa" "$APP/auslieferung/App.ipa"
# Am FERTIGEN Buendel gegenlesen, nicht am Projekt.
#
@@ -280,7 +304,7 @@ cp "$AUSGABE/App.ipa" "$APP/auslieferung/App.ipa"
# Teilen-Blatt).
echo "==> Fertige .ipa gegenlesen"
PRUEF="$(mktemp -d)"
if unzip -q "$APP/auslieferung/App.ipa" -d "$PRUEF"; then
if unzip -q "$AUSGABE/App.ipa" -d "$PRUEF"; then
ERW="$PRUEF/Payload/App.app/PlugIns/DataMetric360Share.appex"
if [ ! -x "$ERW/DataMetric360Share" ] && [ ! -f "$ERW/DataMetric360Share" ]; then
echo " WARNUNG: die Erweiterung hat kein Programm - sie wird nichts tun."
@@ -293,6 +317,19 @@ if unzip -q "$APP/auslieferung/App.ipa" -d "$PRUEF"; then
else
echo " Erweiterung und App tragen beide $APP_V"
fi
# CFBundleVersion ist Pflicht. Fehlt sie in EINEM der beiden Buendel,
# verweigert iOS die Installation der ganzen App - ohne Hinweis darauf,
# woran es liegt. Deshalb hart pruefen, nicht nur warnen.
for ZIEL in "$PRUEF/Payload/App.app" "$ERW"; do
BV="$(/usr/libexec/PlistBuddy -c 'Print :CFBundleVersion' "$ZIEL/Info.plist" 2>/dev/null || echo '')"
case "$BV" in
""|*'$('*)
echo " FEHLER: $(basename "$ZIEL") hat keine brauchbare CFBundleVersion ('$BV')." >&2
echo " iOS wuerde die Installation ablehnen - Bau abgebrochen." >&2
rm -rf "$PRUEF"
exit 1 ;;
esac
done
for ZIEL in "$PRUEF/Payload/App.app" "$ERW"; do
if ! codesign -d --entitlements :- "$ZIEL" 2>/dev/null | grep -q "group.app.datametric360"; then
echo " WARNUNG: $(basename "$ZIEL") ohne App-Gruppe - Teilen kann nichts uebergeben."
@@ -301,6 +338,13 @@ if unzip -q "$APP/auslieferung/App.ipa" -d "$PRUEF"; then
fi
rm -rf "$PRUEF"
# Erst JETZT ablegen. auslieferung/ ist versioniert und wird ausgeliefert -
# eine Datei, die die Pruefung oben nicht besteht, darf dort nicht landen und
# schon gar nicht committet werden. (ios/ ist gitignored, sonst existierte das
# Ergebnis nur auf diesem einen Mac.)
mkdir -p "$APP/auslieferung"
cp "$AUSGABE/App.ipa" "$APP/auslieferung/App.ipa"
# Auslieferung ueber die Luft gleich mitschreiben.
#
# manifest.plist und die Installationsseite hingen bisher an einem zweiten,