Wahrscheinlich ist das UI fertig, der Profile-Screen hat einen „Upload photo“-Button, und plötzlich ist der einfache Teil gar nicht mehr so einfach. Der eigentliche Image-Selection-Flow umfasst native Permissions, vom OS gesteuerte Interfaces, Rückgabewerte, mit denen viele Entwickler nicht rechnen, und ein paar Build-Details, die erst nach einem echten Build auftauchen.
Hier kommt der Expo Image Picker ins Spiel. Das ist die offizielle Expo-Library, mit der du das System-UI öffnest, um Bilder und Videos aus der Mediathek auszuwählen oder ein Foto mit der Kamera aufzunehmen, wie im Expo Package Repository. In der Praxis heißt das: Du bekommst eine zuverlässige Bridge zu nativem Media-Input, aber kein maßgeschneidertes Media-Erlebnis, das auf jedem Gerät gleich funktioniert.
Dieser Guide ist für die erste Implementierung geschrieben, nicht für die Demo. Er konzentriert sich auf die Entscheidungen, die in der Produktion zählen: Managed- vs. Bare-Workflow-Setup, Permission-Handling ohne böse Überraschungen, sicheres Parsing der Ergebnisse und ein praktisches Upload-Pattern, nachdem der User eine Datei ausgewählt hat. Wenn du mit einem Custom-Native-Setup arbeitest, hilft es auch zu verstehen, wie sich das von den Expo EAS Update Optionen unterscheidet, die Capgo in seinem alternativen Guide vergleicht..
Inhaltsverzeichnis
- Einführung in Expo Image Picker
- Installation und essenzielle Konfiguration
- Zugriff auf Kamera und Mediathek
- Picker-Ergebnisse und Optionen verarbeiten
- Fortgeschrittene Patterns und Plattform-Unterschiede
- Häufige Probleme beheben
Erste Schritte mit Expo Image Picker
Ein Product Manager bittet um Profilfotos. Eine Woche später braucht dieselbe Funktion auch Beleg-Uploads, Kamera-Aufnahmen für Vorfallberichte und Retries, wenn Nutzer die Berechtigung beim ersten Mal verweigern. Bild-Input wächst schnell, weil er native Berechtigungen, OS-eigene UIs, temporäre Dateiverwaltung und Backend-Upload-Flows betrifft.
expo-image-picker ist das Expo SDK-Modul für diese Aufgabe. Es öffnet die Plattform-Picker- oder Kamera-UI und gibt die ausgewählten Medien in einem Format zurück, das dein React Native code verarbeiten kann. Die JavaScript API ist klein. Die eigentliche Herausforderung liegt darin, das native Setup, den Berechtigungs-Flow und die Ergebnisverarbeitung sowohl in Managed- als auch in Bare-Projekten korrekt umzusetzen.
Der Haupt-Trade-off ist einfach. Du lässt iOS und Android ihre eigenen Medien-UIs anzeigen, statt einen Custom-Picker zu bauen. Das führt in der Regel zu besseren Ergebnissen: Nutzer verstehen die System-Screens bereits, Berechtigungs-Prompts verhalten sich so, wie es das OS erwartet, und dein Team muss keine Galerie-Implementierung in JavaScript pflegen.
Behandle dies als eine native Integrationsfunktion mit einer React-Oberfläche.
Diese Denkweise hilft, da die Fehlerquellen selten im Button liegen, der den Picker aufruft. Sie stammen meist aus einem von drei Bereichen:
- Native Konfiguration: fehlendes Plugin-Setup, falsche Berechtigungs-Strings oder ein veralteter Build nach Konfigurationsänderungen
- Laufzeit-Verhalten: Nutzer können den Zugriff verweigern, auf iOS eingeschränkten Bibliothekszugriff gewähren oder den Flow abbrechen, ohne etwas auszuwählen
- Ergebnis-Parsing: die aktuelle API gibt ein
assetsarray, sodass ältere Beispiele, dieresult.uridirekt lesen
Die Workflow-Wahl ändert auch den Setup-Pfad. In einer gemanagten Expo-App liegt der Großteil der nativen Arbeit in der App-Konfiguration und erfordert einen Rebuild, wenn sich diese Konfiguration ändert. In einer Bare-App erhältst du weiterhin das Expo-Modul API, musst aber die zugrunde liegenden iOS- und Android-Projekteinstellungen direkter überprüfen. Wenn dein Team einen Custom Client anstelle von Expo Go verwendet, passt dieser Guide gut zu Capgo’s Alternative zu Expo EAS für Teams, die native Module über Expo Go hinaus testen müssen.
Diese Unterscheidung ist für den Rest des Guides wichtig, denn der Happy Path ist nur die halbe Wahrheit. Eine Picker-Implementierung ist erst dann solide, wenn sie in beiden Workflows funktioniert, plattformspezifische Berechtigungs-Besonderheiten ohne Überraschungen für den User handhabt und eine nutzbare Datei an deinen Upload-Layer übergibt, statt bei einer lokalen Vorschau stehenzubleiben.
Installation und essenzielle Konfiguration
Die Installation braucht nur einen Befehl. Die korrekte native Konfiguration entscheidet darüber, ob der Picker auf einem echten Gerät, in einem Custom Dev Client und in deinem Production Build funktioniert.
expo-image-picker bietet eine React-taugliche API für die Plattform-Picker für Fotos, Videos und Kameraaufnahmen. Der JavaScript-Aufruf ist simpel. Das Setup hingegen nicht, da der Foto- und Kamerazugriff von iOS und Android gesteuert wird, nicht von React Native.

Starte mit dem versionsabhängigen Installer von Expo:
npx expo install expo-image-picker
Nutzt expo install anstatt npm install oder yarn add. Expo gleicht die Paketversion mit deinem SDK ab, was eine häufige Klasse von nativen Kompatibilitätsproblemen vermeidet. Wenn du vergleichst, wie Expo-Module in deinen Release-Prozess passen, hilft dieser Expo-Tooling-Übersicht ist eine nützliche Referenz.
Setup des Managed Workflows
Im Managed Workflow deklarierst du das Plugin in der App-Konfiguration, damit Expo die nativen Änderungen zur Build-Zeit anwenden kann.
Beispiel mit app.json:
{
"expo": {
"plugins": ["expo-image-picker"]
}
}
Das ist das Minimum-Setup. In der Praxis fügen Teams meist auch Berechtigungs-Texte hinzu, besonders auf iOS, wo der System-Prompt erklären sollte, warum die App auf etwas zugreifen muss. Halte die Formulierung spezifisch für die Nutzeraktion. „Profilfoto hochladen“ ist besser als „Medienzugriff erforderlich“.
Ein operatives Detail kostet viel Zeit. Änderungen an plugins, Berechtigungs-Strings oder anderen nativen Konfigurationen erfordern einen Rebuild. Das Neuladen von JavaScript wendet diese Änderungen nicht an. In Expo Go bist du zudem durch das begrenzt, was der Client bereits enthält. In einem Development Build oder Production Build spiegelt das native Projekt deine Konfiguration erst nach einem neuen Build wider.
Details zur Bare React Native-Setup
In einer Bare App ist das Paket API dasselbe, aber du musst mehr vom nativen Projekt selbst überprüfen. Die iOS-Usage-Descriptions sind das Erste, was du prüfen solltest. Wenn dein Flow die Bibliothek öffnen, die Kamera starten oder Video mit Audio aufnehmen kann, braucht deine App die entsprechenden Berechtigungsstrings in Info.plist bevor du neu baust.
Eine praktische Checkliste für Bare-Projekte sieht so aus:
- Installieren
expo-image-pickermitnpx expo install expo-image-picker. - Füge die Plugin-Konfiguration hinzu, wenn dein Projekt Expo Config Plugins verwendet.
- Stelle sicher, dass die iOS-Usage-Descriptions zu den Funktionen passen, die du anbietest.
- Baue die iOS- und Android-Apps nach jeder Änderung der nativen Konfiguration neu.
Fehlender Berechtigungstext sieht oft aus wie ein Runtime-Bug, weil die UI code in Ordnung ist und der Button-Handler ausgeführt wird. Der Fehler liegt tiefer im Stack. Ich prüfe normalerweise Info.plist, die App-Konfiguration und ob der aktuelle Build die neuesten nativen Änderungen enthält, bevor ich das Component code anfasse.
Ein paar Gewohnheiten machen das Setup vorhersehbarer:
- Berechtigungs-Text für die konkrete Aktion schreiben: Nutzer sollten verstehen, warum sie den Prompt sehen.
- Kamera und Bibliothek separat konfigurieren: während der andere weiterhin fehlschlägt.
- Nach nativen Änderungen neu bauen: Hot Reload und Fast Refresh aktualisieren native Berechtigungen nicht.
- Auf dem Gerät testen: Simulator-Verhalten kann Berechtigungs- und Kamera-Probleme verbergen.
Falls der Picker in der Entwicklung funktioniert, aber im TestFlight- oder Play-Store-Build abbricht, ist das in erster Linie ein Konfigurationsproblem. Meistens ist es das auch.
Zugriff auf Kamera und Mediathek
Ein Nutzer tippt auf „Foto hochladen“, erwartet, dass sich Kamera oder Bibliothek öffnen, und deine App hat in diesem Moment genau eine Aufgabe. Die richtige System-UI öffnen, Ablehnung oder Abbruch ohne Screen-Crash behandeln und eine nutzbare lokale Datei-Referenz für Vorschau oder Upload zurückgeben.
Das klingt einfach, bis man sowohl Managed- als auch Bare-Builds auf iOS und Android testet. Der JavaScript-API bleibt kompakt, aber das Runtime-Verhalten hängt weiterhin von OS-Prompts, Geräte-Hardware und der vorherigen Konfiguration deiner nativen Berechtigungen ab.

Eine minimale, aber sichere Komponente
Der Kernablauf ist in Expo-Managed- und Bare-Workflow-Projekten identisch. Fordere die relevante Berechtigung an, starte den Picker, prüfe, ob der Benutzer abgebrochen hat, und lies dann das erste Asset von result.assets.
Eine Basiskomponente sieht so aus:
import { useState } from 'react';
import { View, Button, Image, Alert } from 'react-native';
import * as ImagePicker from 'expo-image-picker';
export default function PhotoInput() {
const [imageUri, setImageUri] = useState<string | null>(null);
const pickFromLibrary = async () => {
const permission = await ImagePicker.requestMediaLibraryPermissionsAsync();
if (!permission.granted) {
Alert.alert('Permission required', 'Please allow photo library access.');
return;
}
const result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ['images'],
allowsEditing: true,
quality: 1,
});
if (result.canceled) return;
const asset = result.assets?.[0];
if (!asset?.uri) return;
setImageUri(asset.uri);
};
const takePhoto = async () => {
const permission = await ImagePicker.requestCameraPermissionsAsync();
if (!permission.granted) {
Alert.alert('Permission required', 'Please allow camera access.');
return;
}
const result = await ImagePicker.launchCameraAsync({
allowsEditing: true,
quality: 1,
});
if (result.canceled) return;
const asset = result.assets?.[0];
if (!asset?.uri) return;
setImageUri(asset.uri);
};
return (
<View>
<Button title="Choose from library" onPress={pickFromLibrary} />
<Button title="Take photo" onPress={takePhoto} />
{imageUri ? (
<Image
source={{ uri: imageUri }}
style={{ width: 200, height: 200 }}
/>
) : null}
</View>
);
}
Drei Details sind hier wichtig.
- Fordere Bibliotheks- und Kameraberechtigungen separat an. Sie scheitern unabhängig voneinander.
- Behandle Abbruch als normale Benutzeraktion, nicht als Fehlerzustand.
- Lies von
assets[0], da der Picker ein Asset-Array zurückgibt und kein oberstesuri.
Bibliotheks- und Kameraabläufe
Beginne mit dem Bibliotheksablauf, wenn du den schnellsten Weg zu einer funktionierenden Funktion suchst. Er ist leichter zu testen, funktioniert in mehr Simulator-Setups und vermeidet Kamera-Hardware-Edge-Cases. Füge Kameraunterstützung hinzu, sobald der Ergebnisverarbeitungspfad stabil ist.
Der Kameraablauf hat in der Entwicklung mehr Fehlerquellen. Die iOS-Simulator-Unterstützung ist begrenzt. Android-Emulatoren geben möglicherweise kein Kameraverhalten wieder, das einem echten Gerät entspricht. In Bare-Projekten können diese Lücken dazu führen, dass du die Komponente code untersuchst, obwohl das eigentliche Problem in der nativen Konfiguration oder der Testumgebung liegt.
Ein sauberes UI-Muster ist es, den Nutzer nach der Quelle zu fragen, bevor der Picker aufgerufen wird API:
const showPickerOptions = () => {
Alert.alert('Upload image', 'Choose a source', [
{ text: 'Camera', onPress: takePhoto },
{ text: 'Photo Library', onPress: pickFromLibrary },
{ text: 'Cancel', style: 'cancel' },
]);
};
Diese Trennung hält jede Funktion fokussiert. Sie erleichtert auch das spätere Hinzufügen von Analytics, Feature Flags oder backend-spezifischen Regeln. Zum Beispiel erlauben manche Teams Uploads aus der Bibliothek für Profilbilder, verlangen aber frische Kameraaufnahmen für die Identitätsverifizierung.
Wenn deine App auch Dateizugriffsmuster außerhalb von Expo unterstützt oder du Konventionen über native Stacks hinweg vergleichst, ist dies Capacitor Foto-Bibliotheks-Referenz ein nützlicher Kontext.
Eine kurze Demo hilft, wenn du diesen Flow Teammitgliedern oder QA zeigst:
Was du vom System-UI erwarten kannst
expo-image-picker öffnet den Plattform-Picker oder die Kamera-UI. Deine App steuert nicht jeden Bildschirm in diesem Flow. Dieser Unterschied ist wichtig, denn „funktioniert auf meinem Gerät“ bedeutet oft „das OS hat den Pfad erlaubt, den ich getestet habe“.
Auf iOS können Nutzer eingeschränkten Bibliothekszugriff statt vollen Zugriffs gewähren. Auf Android kann das Picker-Verhalten je nach OS-Version und Vendor-Skin variieren. In Managed-Workflow-Projekten übernimmt Expo mehr der nativen Verkabelung für dich. In Bare-Workflow-Projekten musst du sicherstellen, dass deine gebaute App die nativen Berechtigungsänderungen enthält, die du vorgenommen hast. Der JavaScript-Aufruf kann in beiden Fällen identisch sein, während das Runtime-Ergebnis unterschiedlich ist.
Ich teste diese Fälle normalerweise, bevor ich die Funktion als fertig markiere:
- erste Berechtigungsanfrage
- verweigerte Berechtigung
- Abbruch durch den Nutzer
- Erfolgreiche Auswahl aus der Bibliothek
- Erfolgreiche Kameraaufnahme auf einem physischen Gerät
- Sofortige Vorschau der zurückgegebenen lokalen URI
Diese Fälle entsprechen direkt dem echten Produktionsverhalten. Sie bereiten auch den nächsten Schritt sauber vor, wenn du die Datei an einen Server, eine Moderations-Pipeline oder einen Publishing-Endpunkt wie den senden musst Instagram-Medien-Publishing API.
Picker-Ergebnisse und Optionen verarbeiten
Das Picker-Ergebnis ist der Teil, der normalerweise echte Produktionslogik erfordert. Die System-UI gibt ein strukturiertes Objekt zurück, nicht nur einen Dateipfad, und kleine Fehler hier führen zu kaputten Previews, leeren Uploads oder Crashes, nachdem ein Nutzer abgebrochen hat.
Das Ergebnisobjekt korrekt lesen
Die Ergebnisstruktur, die in aktuellen Expo-Apps relevant ist, lautet result.assets[0].uri, nicht eine Top-Level- result.uri. Dieses Detail betrifft sowohl Managed- als auch Bare-Workflow-Projekte, da das JavaScript API dasselbe ist, auch wenn das native Setup darunter unterschiedlich ist.
Nutze ein Guard-first-Muster:
const result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ['images'],
allowsEditing: true,
quality: 1,
});
if (result.canceled) {
return;
}
const asset = result.assets?.[0];
if (!asset) {
return;
}
const { uri } = asset;
setImageUri(uri);
Das deckt die beiden häufigsten Fehlerfälle ab. Ein abgebrochener Picker liefert kein Asset zum Lesen, und code result.assets[0] existiert immer, wird zur Laufzeit fehlschlagen.
Sobald du die URI hast, ist das Rendern einer Vorschau unkompliziert:
<Image source={{ uri: imageUri }} style={{ width: 240, height: 240 }} />
Wenn du später hochladen möchtest, behalte das gesamte asset das Objekt drumherum, nicht nur die URI. In der Praxis fileName, mimeType, width, height, und fileSize sind oft nützlich für Validierung, Logging oder einen saubereren Multipart-Request.
Optionen, die das spätere Verhalten ändern
Einige Picker-Optionen beeinflussen mehr als nur den Auswahlbildschirm. Sie bestimmen die Dateigröße, das Bearbeitungsverhalten und was dein Backend akzeptieren muss.
| Option | Typ | Was sich ändert | Typische Nutzung |
|---|---|---|---|
mediaTypes |
Array | Schränkt die Auswahl des Nutzers ein | Die Auswahl auf Bilder beschränken, falls dein API nur Bilder akzeptiert |
allowsEditing |
boolean | Lets the OS offer crop or edit UI where supported | Avatare, quadratische Covers, Belegscans |
quality |
number | Komprimiert unterstützte Bildausgaben | Reduziert Upload-Größe für Mobilnetze |
base64 |
boolean | Fügt kodierte Bilddaten zum Ergebnis hinzu | Nur für Integrationen, die explizit Inline-Bilddaten erfordern |
Einige Trade-offs werden leicht übersehen:
allowsEditingist nützlich, wenn das Bildfeld eine feste Form oder Größe hat. Weniger nützlich, wenn dein Server eine eigene Crop-Pipeline nutzt und du die Originaldatei möchtest.qualitybeeinflusst Upload-Zeit, Speicherdruck und Server-Speicher.quality: 1ist nicht automatisch die richtige Wahl.mediaTypesmuss zu den Backend-Regeln passen. Wenn der Server Videos ablehnt, darf der Picker sie nicht zurückgeben.base64erhöht die Payload-Größe im Speicher. Vermeide dies, außer der Zielservice erfordert es zwingend.
Dieser letzte Punkt ist auf Geräten mit wenig Arbeitsspeicher entscheidend. Eine lokale File-URI ist meist die bessere Übergabe für die Vorschau und den Multipart-Upload. Base64 hat zwar berechtigte Anwendungsfälle, ist aber im Vergleich zur Übergabe einer Dateireferenz sehr kostspielig.
URI vs. Base64
Für die meisten Apps gilt eine einfache Regel:
- Nutzt URI für Vorschauen.
- Nutzt URI für Datei-Uploads.
- Nutzt base64 nur wenn das empfangende System explizit nach kodiertem Inhalt fragt.
Dieses Muster hält die Picker-code schlank und leichter testbar. Es passt auch zu der Art, wie viele Backend-Media-Flows aufgebaut sind, einschließlich von Diensten, die Inhalte schließlich auf externe Plattformen wie die veröffentlichen Instagram-Medien-Publishing API.
Wenn euer Team häufige OTA-Updates ausrollt oder bildlastige Assets über die App-Delivery schickt, wirken sich die hier getroffenen Entscheidungen zur Dateigröße auf den restlichen Pipeline aus. Dieser Guide zu der Optimierung von Bildern für App-Updates ist eine hilfreiche Ergänzung zur Picker-Konfiguration.
Ein sichereres Result-Pattern für echte Apps
Für Demo-code reicht es aus, nur imageUri zu speichern. In Produktion solltest du ein normalisiertes Objekt speichern, damit der nächste Schritt – Preview, Validierung, Upload oder Retry – die rohe Picker-Antwort nicht jedes Mal neu interpretieren muss.
const result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ['images'],
allowsEditing: true,
quality: 0.8,
});
if (result.canceled || !result.assets?.length) {
return;
}
const asset = result.assets[0];
setSelectedImage({
uri: asset.uri,
fileName: asset.fileName ?? 'upload.jpg',
mimeType: asset.mimeType ?? 'image/jpeg',
width: asset.width,
height: asset.height,
fileSize: asset.fileSize ?? null,
});
Das gibt dir in der App eine vorhersehbare Struktur. Es erleichtert außerdem, Managed- und Bare-Projekte aufeinander abzustimmen, da die App-code stabil bleibt, während du native Unterschiede an anderer Stelle ausgleichst.
Ein letzter Check hilft: Aktiviere keine zusätzlichen Result-Felder auf Verdacht. Fordere nur die Daten an, die du wirklich brauchst, und halte den Picker auf die Auswahl fokussiert, statt ihn zu einem allgemeinen File-Processing-Schritt zu machen.
Fortgeschrittene Patterns und Plattform-Unterschiede
Ein Picker-Feature wird meistens genau dann komplex, wenn das erste ausgewählte Bild Retries, Auth-Header, native Permission-Unterschiede und einen echten Upload-Endpoint überstehen muss. expo-image-picker kümmert sich gut um die Auswahl. Den Rest des Features muss deine App übernehmen.

Ein praktisches Upload-Pattern
Für APIs, die einen File-Upload erwarten, FormData ist nach wie vor die sicherste Standardoption. Sie funktioniert mit gängigen Rails-, Node-, Laravel-, Django- und Go-Backends und hält den Picker getrennt von Transport-Aspekten.
async function uploadImage(imageUri: string) {
const formData = new FormData();
formData.append('file', {
uri: imageUri,
name: 'upload.jpg',
type: 'image/jpeg',
} as any);
const response = await fetch('https://your-api.example.com/uploads', {
method: 'POST',
body: formData,
headers: {
Accept: 'application/json',
},
});
if (!response.ok) {
throw new Error('Upload failed');
}
return response.json();
}
Dass code ausreicht, um den Pfad zu validieren, ist gut, aber Produktions-Apps brauchen in der Regel eine weitere Schicht. Leiten Sie name und type wenn möglich aus dem ausgewählten Asset ab, hängen Sie die Auth außerhalb der Picker-Funktion an und trennen Sie den Upload-Status vom Picker-Status, damit eine fehlgeschlagene Anfrage den Nutzer nicht zwingt, die Bibliothek erneut zu öffnen.
Ein paar Checks verhindern die häufigen Fehler, die ich in Reviews sehe:
- Bestätigen Sie, dass die lokale
urivor dem Bauen der Anfrage existiert - Zeigen Sie eine Vorschau vor dem Upload an, damit Nutzer die falsche Datei früh erkennen
- Verhindern Sie wiederholte Taps, während die Anfrage läuft
- Behandeln Sie Netzwerkfehler getrennt von Picker-Abbruch oder Berechtigungsfehlern
- Gehen Sie davon aus, dass die Backend-Validierung große Dateien, nicht unterstützte MIME-Typen oder fehlende Auth ablehnt
Wenn Ihr Backend Base64 statt Multipart erfordert, ist das in der Regel eine Server-Einschränkung, keine Picker-Anforderung. Multipart ist speichereffizienter und auf Mobile leichter nachvollziehbar.
Wo Plattformunterschiede wirklich zählen
Die Picker-UI ist nativ und erbt daher natives Verhalten. Das beeinflusst sowohl, was Nutzer sehen, als auch, was dein code annehmen sollte.
Auf iOS folgen Editier-Flows und Berechtigungsanfragen den Konventionen von Apple. Der eingeschränkte Fotozugriff kann eine engere Auswahl an Assets zurückgeben, als du sie auf einem Gerät mit voller Berechtigung gesehen hast. Auf Android variiert das Picker-Verhalten stärker je nach OS-Version und Hersteller-Skin, insbesondere bei Alben, Dateinamen und der Rückgabe von Kameraaufnahmen. Reine React Native Apps spüren diese Unterschiede direkter, da du mehr der nativen Einrichtung selbst in der Hand hast, aber auch verwaltete Expo-Apps brauchen ein code, das den Picker als plattformabhängig und nicht als perfekt einheitlich behandelt.
Die praktische Regel ist einfach. Verlasse dich auf die Felder, die du validieren kannst, nicht auf identische UIs oder identische Metadaten über Geräte hinweg.
Einige Beispiele sind in echten Apps relevant:
- Bearbeiten und Zuschneiden: Die UI und das Zuschneideverhalten sind auf iOS und Android nicht identisch
- Zurückgegebene Metadaten:
fileName,mimeType, undfileSizekönnen fehlen oder inkonsistent sein, füge daher Fallbacks hinzu - Berechtigungen: Der Fotozugriff auf iOS kann auf ausgewählte Elemente beschränkt sein, während das Verhalten auf Android stärker von der OS-Version und der System-Picker-Unterstützung abhängt
- Kamera-Ausgabe: Aufgenommene Bilder können andere Benennungen, Ausrichtungen oder Komprimierungseigenschaften haben als Bibliotheks-Assets
Wenn dein Team auch außerhalb von Expo arbeitet, bietet dieser DesignStack-App-Entwicklungsführer nützliche Android-Kontexte für Entscheidungen zur Medienverarbeitung, die über eine einzelne Bibliothek hinausgehen.
Unterschiede zwischen Managed und Bare Workflow
An diesem Punkt werden die Setup-Entscheidungen für den Betrieb entscheidend.
Im Managed Workflow liegen Permission-Strings und Plugin-Configs meist in der App-Config; native Änderungen werden erst wirksam, wenn du einen neuen Build erstellst. Das hält die JavaScript-Ebene sauber, bedeutet aber auch, dass ein Config-Fix erst beim nächsten Native Build sichtbar wird. OTA-Updates patchen keine fehlenden nativen Berechtigungen.
Im Bare Workflow hat dieselbe Funktion mehr Einzelteile. Du musst die nativen iOS Usage Descriptions, das Verhalten des Android-Manifests, die Package-Installation und das Rebuild-Timing selbst prüfen. Der Vorteil ist die Kontrolle. Der Preis dafür ist, dass ein Picker-Problem durch die native Konfiguration verursacht sein kann und nicht durch die JavaScript-Aufrufstelle.
Teams, die zwischen Expo und Capacitor wechseln, unterschätzen oft, wie unterschiedlich diese Abstraktionsebenen sind. Capgo hat eine hilfreiche Erklärung dazu, wie Capacitor Plattformunterschiede handhabt, und das ist ein guter Vergleichspunkt, wenn du entscheidest, wie viel natives Setup dein Team selbst übernehmen will.
Meine Präferenz ist in beiden Workflows gleich: Halte code beim Picker schlank, normalisiere das Ergebnis einmalig, nutze für den Upload einen dedizierten API Layer und behandle plattformspezifisches Verhalten als etwas, das explizit konfiguriert und getestet werden muss, statt es mit Annahmen zu glätten.
Häufige Probleme beheben
Die meisten Bugs beim Expo Image Picker lassen sich in wenige Kategorien einteilen. Der schnellste Fix ist meist, die fehlerhafte Ebene zu identifizieren: Config, Permissions, Result Handling oder Rendering.

Schnelle Checks für häufige Fehler
Wenn der Picker nicht geöffnet wird oder Berechtigungen fehlschlagen, prüfe zuerst das native Setup. Bei Bare Apps sind fehlende iOS-Usage-Descriptions eine häufige Ursache.
Wenn die App abstürzt, nachdem ein Benutzer den Picker schließt, überprüfe deine Ergebnisverarbeitung. Viele Implementierungen gehen immer noch von einer direkten URI aus und überspringen die canceled Prüfung.
Ein paar schnelle Zuordnungen helfen:
- Berechtigungsfehler: Prüfe deine App-Konfiguration und nativen Berechtigungsstrings, und baue dann neu.
undefinedImage-URI: Lesequelleresult.assets?.[0]?.uri, nichtresult.uri.- Nach Abbrechen passiert nichts: Das kann korrekt sein. Behandle Abbrechen als No-Op-Zustand.
- Bild wird nicht gerendert: Stelle sicher, dass die URI im State gespeichert und übergeben wurde an
<Image source={{ uri }} />. - Kamera verhält sich im Simulator seltsam: Teste auf einem physischen Gerät, bevor du nach einem Library-Bug suchst.
Eine kurze Produktions-Checkliste
Nutze dies als letzten Durchgang vor dem Release:
- Installation mit Expo-Tooling: Nutzt
npx expo install expo-image-picker. - Native Bausteine konfigurieren: Plugin und benötigte Berechtigungsbeschreibungen hinzufügen.
- Berechtigungen gezielt anfordern: Kamera- und Mediatheken-Flows trennen.
- Jedes Ergebnis absichern: Prüfen
result.canceledund sicher lesenassets[0]. - URI-basierte Uploads bevorzugen: Base64 nur für Sonderfälle verwenden.
- Echte Geräte testen: Besonders für Kameraaufnahme und Berechtigungs-Prompts.
Wenn euer Team Capacitor- oder Electron-Apps neben React Native-Projekten ausliefert, Capgo ist eine Option, um JavaScript-, CSS-, Konfigurations- und Asset-Updates bereitzustellen, ohne bei jeder Änderung auf die Store-Prüfung zu warten. Das ist relevant, wenn bildbezogene Fixes in Ihrer Web-Schicht liegen, z. B. Upload-UI, Validierungsregeln, Texte oder Asset-Handling rund um den Picker-Flow.