
Zeichnete
Wir versuchen, die native Kamera-App zu verwenden, damit der Benutzer ein neues Bild aufnehmen kann. Es funktioniert gut, wenn wir das weglassen EXTRA_OUTPUT extra
und gibt das kleine Bitmap-Bild zurück. Wenn wir jedoch putExtra(EXTRA_OUTPUT,...)
In der Absicht, bevor Sie es starten, funktioniert alles, bis Sie versuchen, in der Kamera-App auf die Schaltfläche “Ok” zu klicken. Der “Ok”-Button tut einfach nichts. Die Kamera-App bleibt geöffnet und nichts hängt sich auf. Wir können es abbrechen, aber die Datei wird nie geschrieben. Was genau müssen wir tun, um zu bekommen ACTION_IMAGE_CAPTURE
das aufgenommene Bild in eine Datei schreiben?
Edit: Das geht über die MediaStore.ACTION_IMAGE_CAPTURE
Absicht, nur um klar zu sein
das ist ein gut dokumentierter Fehler in einigen Versionen von Android. Das heißt, bei Google Experience-Builds von Android funktioniert die Bilderfassung nicht wie dokumentiert. Was ich im Allgemeinen verwendet habe, ist so etwas in einer Utilities-Klasse.
public boolean hasImageCaptureBug() {
// list of known devices that have the bug
ArrayList<String> devices = new ArrayList<String>();
devices.add("android-devphone1/dream_devphone/dream");
devices.add("generic/sdk/generic");
devices.add("vodafone/vfpioneer/sapphire");
devices.add("tmobile/kila/dream");
devices.add("verizon/voles/sholes");
devices.add("google_ion/google_ion/sapphire");
return devices.contains(android.os.Build.BRAND + "https://stackoverflow.com/" + android.os.Build.PRODUCT + "https://stackoverflow.com/"
+ android.os.Build.DEVICE);
}
Wenn ich dann die Bilderfassung starte, erstelle ich eine Absicht, die nach dem Fehler sucht.
Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
if (hasImageCaptureBug()) {
i.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File("/sdcard/tmp")));
} else {
i.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
}
startActivityForResult(i, mRequestCode);
Bei Aktivitäten, zu denen ich zurückkehre, mache ich je nach Gerät verschiedene Dinge.
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
switch (requestCode) {
case GlobalConstants.IMAGE_CAPTURE:
Uri u;
if (hasImageCaptureBug()) {
File fi = new File("/sdcard/tmp");
try {
u = Uri.parse(android.provider.MediaStore.Images.Media.insertImage(getContentResolver(), fi.getAbsolutePath(), null, null));
if (!fi.delete()) {
Log.i("logMarker", "Failed to delete " + fi);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
} else {
u = intent.getData();
}
}
Das erspart Ihnen das Schreiben einer neuen Kamera-App, aber dieser Code ist auch nicht großartig. die großen Probleme sind
-
Sie erhalten niemals Bilder in voller Größe von den Geräten mit dem Fehler. Sie erhalten Bilder mit einer Breite von 512 Pixeln, die in den Bildinhaltsanbieter eingefügt werden. Auf Geräten ohne den Fehler funktioniert alles als Dokument, Sie erhalten ein großes normales Bild.
-
Sie müssen die Liste pflegen. Wie geschrieben, ist es möglich, dass Geräte mit einer Android-Version geflasht werden (z cyanogenmods Builds), die den Fehler behoben hat. In diesem Fall stürzt Ihr Code ab. Die Lösung besteht darin, den gesamten Gerätefingerabdruck zu verwenden.
Ich weiß, dass dies schon einmal beantwortet wurde, aber ich weiß, dass viele Leute darüber stolpern, also werde ich einen Kommentar hinzufügen.
Ich hatte genau das gleiche Problem auf meinem Nexus One. Dies stammte von der Datei, die vor dem Start der Kamera-App nicht auf der Festplatte vorhanden war. Daher habe ich dafür gesorgt, dass die Datei vor dem Start der Kamera-App vorhanden war. Hier ist ein Beispielcode, den ich verwendet habe:
String storageState = Environment.getExternalStorageState();
if(storageState.equals(Environment.MEDIA_MOUNTED)) {
String path = Environment.getExternalStorageDirectory().getName() + File.separatorChar + "Android/data/" + MainActivity.this.getPackageName() + "/files/" + md5(upc) + ".jpg";
_photoFile = new File(path);
try {
if(_photoFile.exists() == false) {
_photoFile.getParentFile().mkdirs();
_photoFile.createNewFile();
}
} catch (IOException e) {
Log.e(TAG, "Could not create file.", e);
}
Log.i(TAG, path);
_fileUri = Uri.fromFile(_photoFile);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE );
intent.putExtra( MediaStore.EXTRA_OUTPUT, _fileUri);
startActivityForResult(intent, TAKE_PICTURE);
} else {
new AlertDialog.Builder(MainActivity.this)
.setMessage("External Storeage (SD Card) is required.\n\nCurrent state: " + storageState)
.setCancelable(true).create().show();
}
Ich erstelle zuerst einen eindeutigen (etwas) Dateinamen mit einem MD5-Hash und lege ihn in den entsprechenden Ordner. Ich überprüfe dann, ob es existiert (sollte nicht, aber es ist eine gute Praxis, es trotzdem zu überprüfen). Wenn es nicht existiert, erhalte ich das übergeordnete Verzeichnis (einen Ordner) und erstelle die Ordnerhierarchie bis zu ihm (deshalb, wenn die Ordner, die zum Speicherort der Datei führen, nicht existieren, werden sie nach dieser Zeile angezeigt. Dann danach Ich erstelle die Datei. Sobald die Datei erstellt ist, erhalte ich den Uri und übergebe ihn an die Absicht, und dann funktioniert die OK-Schaltfläche wie erwartet und alles ist goldrichtig.
Wenn Sie nun in der Kamera-App auf die Schaltfläche „OK“ klicken, ist die Datei am angegebenen Speicherort vorhanden. In diesem Beispiel wäre es /sdcard/Android/data/com.example.myapp/files/234asdioue23498ad.jpg
Es ist nicht erforderlich, die Datei wie oben beschrieben in das „onActivityResult“ zu kopieren.

Tiefwinter
Ich habe eine Reihe von Fotoaufnahmestrategien ausprobiert, und es scheint immer einen Fall, eine Plattform oder bestimmte Geräte zu geben, bei denen einige oder alle der oben genannten Strategien auf unerwartete Weise fehlschlagen. Ich konnte eine Strategie finden, die den folgenden URI-Generierungscode verwendet, der in den meisten, wenn nicht allen Fällen zu funktionieren scheint.
mPhotoUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
new ContentValues());
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, mPhotoUri);
startActivityForResult(intent,CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE_CONTENT_RESOLVER);
Um weiter zur Diskussion beizutragen und Neulingen zu helfen, habe ich eine Beispiel-/Test-App erstellt, die verschiedene Strategien für die Implementierung von Fotoaufnahmen zeigt. Beiträge anderer Implementierungen werden auf jeden Fall ermutigt, zur Diskussion beizutragen.
https://github.com/deepwinter/AndroidCameraTester

Yenchi
Ich hatte das gleiche Problem, bei dem die OK-Taste in der Kamera-App sowohl auf dem Emulator als auch auf dem Nexus One nichts bewirkte.
Das Problem verschwand, nachdem ein sicherer Dateiname angegeben wurde, der ohne Leerzeichen, ohne Sonderzeichen, in MediaStore.EXTRA_OUTPUT
Wenn Sie eine Datei angeben, die sich in einem Verzeichnis befindet, das noch nicht erstellt wurde, müssen Sie sie zuerst erstellen. Die Kamera-App erledigt mkdir nicht für Sie.

Reto Meier
Der von Ihnen beschriebene Workflow sollte so funktionieren, wie Sie ihn beschrieben haben. Es könnte hilfreich sein, wenn Sie uns den Code rund um die Erstellung des Intents zeigen könnten. Im Allgemeinen sollten Sie mit dem folgenden Muster tun können, was Sie versuchen.
private void saveFullImage() {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File file = new File(Environment.getExternalStorageDirectory(), "test.jpg");
outputFileUri = Uri.fromFile(file);
intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
startActivityForResult(intent, TAKE_PICTURE);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if ((requestCode == TAKE_PICTURE) && (resultCode == Activity.RESULT_OK)) {
// Check if the result includes a thumbnail Bitmap
if (data == null) {
// TODO Do something with the full image stored
// in outputFileUri. Perhaps copying it to the app folder
}
}
}
Beachten Sie, dass es sich um die Kamera Aktivität, die die Datei erstellt und speichert, und sie ist nicht wirklich Teil Ihrer Anwendung, sodass sie keine Schreibberechtigung für Ihren Anwendungsordner hat. Um eine Datei in Ihrem App-Ordner zu speichern, erstellen Sie eine temporäre Datei auf der SD-Karte und verschieben Sie sie in Ihren App-Ordner im onActivityResult
Handler.

Praveenkumar
Um Yenchis obigen Kommentar weiterzuverfolgen, wird die OK-Schaltfläche auch nichts bewirken, wenn die Kamera-App nicht in das betreffende Verzeichnis schreiben kann.
Das bedeutet, dass Sie die Datei nicht an einem Ort erstellen können, der nur von Ihrer Anwendung beschreibbar ist (z. B. etwas unter getCacheDir())
Etwas darunter getExternalFilesDir()
sollte aber funktionieren.
Es wäre schön, wenn die Kamera-App eine Fehlermeldung in die Protokolle drucken würde, wenn sie nicht in die angegebenen schreiben könnte EXTRA_OUTPUT
Pfad, aber ich habe keinen gefunden.

Nabel
Um die Kamera auf die SD-Karte schreiben zu lassen, aber in einem neuen Album in der Galerie-App zu behalten, verwende ich Folgendes:
File imageDirectory = new File("/sdcard/signifio");
String path = imageDirectory.toString().toLowerCase();
String name = imageDirectory.getName().toLowerCase();
ContentValues values = new ContentValues();
values.put(Media.TITLE, "Image");
values.put(Images.Media.BUCKET_ID, path.hashCode());
values.put(Images.Media.BUCKET_DISPLAY_NAME,name);
values.put(Images.Media.MIME_TYPE, "image/jpeg");
values.put(Media.DESCRIPTION, "Image capture by camera");
values.put("_data", "/sdcard/signifio/1111.jpg");
uri = getContentResolver().insert( Media.EXTERNAL_CONTENT_URI , values);
Intent i = new Intent("android.media.action.IMAGE_CAPTURE");
i.putExtra(MediaStore.EXTRA_OUTPUT, uri);
startActivityForResult(i, 0);
Bitte beachten Sie, dass Sie jedes Mal einen eindeutigen Dateinamen generieren und die von mir geschriebene 1111.jpg ersetzen müssen. Dies wurde mit Nexus One getestet. Die URI ist in der privaten Klasse deklariert, sodass ich bei Aktivitätsergebnis das Bild bei Bedarf aus der URI in imageView zur Vorschau laden kann.
9647600cookie-checkAndroid ACTION_IMAGE_CAPTURE Absichtyes