Android ACTION_IMAGE_CAPTURE Absicht

Lesezeit: 12 Minuten

Android ACTION IMAGE CAPTURE Absicht
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

  1. 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.

  2. 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.

  • auf Galaxy S: intention.getData() gibt null zurück, und außerdem fügt die Kamera-App auf Galaxy s selbst ein neues Foto in die Galerie ein, aber es wird kein URI zurückgegeben. Wenn Sie also ein Foto aus einer Datei in die Galerie einfügen, wird das Foto dupliziert.

    – Arsenij

    30. Juni 2011 um 9:47 Uhr


  • Hey, mein Gerät ist hier nicht aufgeführt und ich habe es auf deine Weise implementiert. Aber meine Anwendung stürzt immer noch ab, ich kenne den Grund nicht. Bitte helfen Sie mir

    – Geetanjali

    2. August 2011 um 6:52 Uhr

  • Verwenden Sie diesen Code auf Droid-X- und Sony Xpheria-Geräten. Beide Geräte geben den Absichtswert als null zurück. auch droidx gibt den Ergebniscode als 0 zurück, während xpheria den Ergebniscode als -1 zurückgibt. Weiß jemand warum das so sein sollte.

    – rOrlig

    28. September 2011 um 20:14 Uhr

  • Der Link zum “gut dokumentierten Fehler”, der am Anfang von Yanokwas Antwort steht, ist falsch. Bei diesem Fehler geht es darum, die Kamera-App ohne aufzurufen putExtra(EXTRA_AUSGABE,…)

    – Frank Harper

    10. April 2012 um 14:42 Uhr

  • code.google.com/p/android/issues/detail?id=1480 Na, wie erklärst du dir das dann?

    – Bleistiftcheck

    10. Mai 2013 um 10:00 Uhr


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.

  • Stell sicher dass du hast <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> in Ihrem Manifest, wenn Sie neuer als Android 1.5 verwenden – verbrachte ein paar Stunden damit, das Kamera-Zeug zu debuggen, und dies war nicht enthalten, sodass meine Speicherungen immer fehlschlugen.

    – Schwanensohn

    8. September 2011 um 21:00 Uhr

  • Das funktioniert gut für mich, aber etwa alle 10 Bilder wird die leere Datei nicht überschrieben und ich habe am Ende eine 0-Byte-Datei, wo das Bild sein sollte. Es ist sehr ärgerlich und war schwer aufzuspüren.

    – joey_g216

    7. Oktober 2011 um 2:12 Uhr

  • Auf einigen Geräten, wie dem Nexus 7 mit Jelly Bean, müssen Sie Environment.getExternalStorageDirectory().getName() ändern, um .getAbsolutePath() anstelle von .getName() zu verwenden.

    – Keith

    18. Juli 2012 um 20:28 Uhr

1646645001 378 Android ACTION IMAGE CAPTURE Absicht
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

  • Das war großartig. Ich muss dies noch auf allen meinen Geräten testen, aber ich gehe davon aus, dass Sie dies bereits ziemlich oft getan haben. Es gibt so viel Lärm zu diesem Thema, und diese spezielle Antwort ist so einfach und sauber. Funktioniert bisher auf Nexus 5, wo ich zum ersten Mal viele Berichte erhielt, dass ACTION_IMAGE_CAPTURE ohne EXTRA_OUTPUT nicht funktionierte. Ich hoffe, das funktioniert auf ganzer Linie, aber so weit, so gut. Vielen Dank

    – Reich

    4. Januar 2014 um 2:56 Uhr

  • @deepwinter – Danke, mein Herr. Ich habe mir die Haare ausgerissen, aber Ihre Content-Resolver-Lösung funktioniert gut bei allen problematischen Szenarien, die ich hatte.

    – Billy Coover

    4. Februar 2014 um 15:44 Uhr

  • Ziemlich spät zu dieser Party, aber das war die einzige Lösung, die für mich funktioniert hat. Vielen Dank!

    – StackJP

    21. Oktober 2014 um 19:58 Uhr

  • kann ich die MediaStore.EXTRA_OUTPUT irgendwie abrufen onActivityResult oder muss ich mir das wirklich selbst merken? Ich müsste es dauerhaft speichern, damit sich meine App sogar daran erinnert, wenn es während der Aufnahme eines Fotos zerstört wird …

    – Abschlussball85

    12. November 2015 um 7:17 Uhr

  • Es funktioniert nicht auf Samsung Galaxy Note 3 mit Lolipop: ava.lang.NullPointerException: Versuchen Sie, die virtuelle Methode „java.lang.String android.net.Uri.getScheme()“ für eine Nullobjektreferenz aufzurufen

    – Igor Janković

    16. August 2016 um 13:56 Uhr


Android ACTION IMAGE CAPTURE Absicht
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.

1646645003 814 Android ACTION IMAGE CAPTURE Absicht
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.

  • Das /sollte/ funktionieren, aber die OK-Taste der Kamera-App tut einfach nichts. Wir haben es geschafft, auf die SD-Karte zu schreiben, daher vermute ich, dass dies ein Problem mit Dateiberechtigungen ist (obwohl ich dachte, dass eine Anwendung automatisch Schreibberechtigungen für ihr persönliches Verzeichnis hat). danke für die Hilfe!

    – Zeichnete

    15. Dezember 2009 um 22:34 Uhr

  • Ihre App hat Schreibrechte für ihr persönliches Verzeichnis – die Kamera-App (die das Bild aufnimmt) nicht. Sie könnten die Datei jedoch in das onActivityResult verschieben, da sich diese in Ihrer App befindet. Alternativ könnten Sie selbst eine Kamera-Aktivität implementieren, aber das erscheint übertrieben.

    – Reto Meier

    15. Dezember 2009 um 22:36 Uhr

  • Das Wiederherstellen der Kamera-App scheint ein üblicher, aber mühsamer Ansatz zu sein … Wenn wir getDir (“images”, MODE_WORLD_WRITEABLE) verwenden, gilt diese Berechtigung nicht für Dateien, die wir in diesem Verzeichnis erstellen sollen?

    – Zeichnete

    15. Dezember 2009 um 22:42 Uhr

  • Nicht unbedingt. Die Berechtigung gilt für den Ordner, nicht unbedingt für die darin enthaltenen Dateien.

    – Reto Meier

    15. Dezember 2009 um 22:54 Uhr

  • Ich habe den Code mit Android-Geräten mit Android 2.2 und neuer getestet und alle haben das Bild im angegebenen Pfad gespeichert. Ich denke also, dass dies das Standardverhalten sein sollte, um Bilder zu erhalten.

    – Janusz

    30. April 2013 um 15:04 Uhr

Android ACTION IMAGE CAPTURE Absicht
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.

  • Das /sollte/ funktionieren, aber die OK-Taste der Kamera-App tut einfach nichts. Wir haben es geschafft, auf die SD-Karte zu schreiben, daher vermute ich, dass dies ein Problem mit Dateiberechtigungen ist (obwohl ich dachte, dass eine Anwendung automatisch Schreibberechtigungen für ihr persönliches Verzeichnis hat). danke für die Hilfe!

    – Zeichnete

    15. Dezember 2009 um 22:34 Uhr

  • Ihre App hat Schreibrechte für ihr persönliches Verzeichnis – die Kamera-App (die das Bild aufnimmt) nicht. Sie könnten die Datei jedoch in das onActivityResult verschieben, da sich diese in Ihrer App befindet. Alternativ könnten Sie selbst eine Kamera-Aktivität implementieren, aber das erscheint übertrieben.

    – Reto Meier

    15. Dezember 2009 um 22:36 Uhr

  • Das Wiederherstellen der Kamera-App scheint ein üblicher, aber mühsamer Ansatz zu sein … Wenn wir getDir (“images”, MODE_WORLD_WRITEABLE) verwenden, gilt diese Berechtigung nicht für Dateien, die wir in diesem Verzeichnis erstellen sollen?

    – Zeichnete

    15. Dezember 2009 um 22:42 Uhr

  • Nicht unbedingt. Die Berechtigung gilt für den Ordner, nicht unbedingt für die darin enthaltenen Dateien.

    – Reto Meier

    15. Dezember 2009 um 22:54 Uhr

  • Ich habe den Code mit Android-Geräten mit Android 2.2 und neuer getestet und alle haben das Bild im angegebenen Pfad gespeichert. Ich denke also, dass dies das Standardverhalten sein sollte, um Bilder zu erhalten.

    – Janusz

    30. April 2013 um 15:04 Uhr

1646645004 524 Android ACTION IMAGE CAPTURE Absicht
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.

  • Woher kommt die Spalte “_data”? Gibt es dafür keine Konstante?

    – Mathias

    17. März 2011 um 17:29 Uhr

  • ach, es ist developer.android.com/reference/android/provider/… Sie sollten wirklich keine magischen Zeichenfolgen im Code verwenden.

    – Mathias

    18. März 2011 um 9:50 Uhr

964760cookie-checkAndroid ACTION_IMAGE_CAPTURE Absicht

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy