Benutzen der Kamera durch Intent und speichern des Bilds unter eigenem Dateinamen

P

pyretta

Ambitioniertes Mitglied
1
Hallo,

ich zermarter mir schon wieder mein Hirn und bin schon fast am Verzweifeln.
Ich möchte mittels eines "Cam-Buttons" in meiner App auf die Kamera zugreifen und ein Bild machen lassen. Das soll in einem speziellen Ordner mit speziellem Dateinamen abgelegt werden.

Die Benutzung der Kamera hab ich schon hinbekommen, nur das mit dem Dateinamen will einfach nicht klappen. Die Kamera-App speichert die Datei stur mit dem timestamp als Dateinamen oder mit einem Zahlencode.

Dann habe ich bei stack-overflow ein cooles Script gefunden, in der Hoffnung es bringt den gewünschten Erfolg, wie in dem Thread beschrieben, aber nun macht der Button einfach gar nix mehr. :blink:

Hier mal der Code:

Code:
Button cam_button = (Button) findViewById(R.id.cam_button);
cam_button.setOnClickListener(new OnClickListener(){
public void onClick(View view) {
PictureCallback myPictureCallback_JPG = new PictureCallback(){
public void onPictureTaken(byte[] arg0, Camera arg1) {
Camera camera = arg1;
int imageNum = 0;
Intent imageIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
File imagesFolder = new File(Environment.getExternalStorageDirectory(), "Bildordner");
imagesFolder.mkdirs(); // <----
String fileName = "bild_" + String.valueOf(imageNum) + ".jpg";
File output = new File(imagesFolder, fileName);
while (output.exists()){
imageNum++;
fileName = "bild_" + String.valueOf(imageNum) + ".jpg";
output = new File(imagesFolder, fileName);
}
Uri uriSavedImage = Uri.fromFile(output);
imageIntent.putExtra(MediaStore.EXTRA_OUTPUT, uriSavedImage);
OutputStream imageFileOS;
try {
imageFileOS = getContentResolver().openOutputStream(uriSavedImage);
imageFileOS.write(arg0);
imageFileOS.flush();
imageFileOS.close();
} 
catch (FileNotFoundException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
startActivityForResult(imageIntent,1);    //meine Adaption, damit ich den Intent nutzen kann.

// Original:      camera.startPreview();   
// funktioniert aber beides nicht.

}};
}
});
Ich hab sicher irgendwo einen Denkfehler, finde ihn aber einfach nicht.

Hier das was mir das LogCat dazu ausgibt, wenn ich den Cam-Button drücke.

04-12 09:29:47.660: I/InputReader(129): dispatchTouch::touch event's action is 0
04-12 09:29:47.660: I/InputDispatcher(129): Delivering touch to current input target: action: 0, channel '40958950 de.appname/activityname (server)'
04-12 09:29:47.746: I/InputReader(129): dispatchTouch::touch event's action is 1
04-12 09:29:47.746: I/InputDispatcher(129): Delivering touch to current input target: action: 1, channel '40958950 de.appname/activityname (server)'
Könnt Ihr mir da weiterhelfen?

Vielen Dank schonmal im Voraus.

Liebe Grüße,
pyretta
 
Zuletzt bearbeitet:
Also, dass der Button wieder funktioniert und die Kamera-App aufruft, hab ich wieder hinbekommen.
Nur das mit dem verflixten Dateinamen nicht.

Immer speichert die Kamera-App das im Ordner "DCIM/Camera" mit dem aktuellen timestamp als Dateinamen.

z.B. 2012-04-12 10.11.43.jpg

Ich hätte aber gerne folgendes:
"DCIM/Bildordnername/Bildname_1.jpg"

mkdirs() müsste doch das Verzeichnis anlegen, oder?

und folgendes müsste doch die Datei unter gewünschtem Dateinamen in dem Ordner ablegen, oder nicht?

Code:
OutputStream imageFileOS;
try {
imageFileOS = getContentResolver().openOutputStream(uriSavedImage);
imageFileOS.write(arg0);
...
*verzweifel*
*Haare rauf*


Hinbekommen, dass der Button wieder geht, habe ich übrigens wie folgt:

Code:
final Intent imageIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);

PictureCallback picture = new PictureCallback(){
public void onPictureTaken(byte[] arg0, Camera arg1) {
Camera camera = arg1;
int imageNum = 0;
File imagesFolder = new File(Environment.getExternalStorageDirectory(), "Bildordner");
imagesFolder.mkdirs(); // <----
String fileName = "bild_" + String.valueOf(imageNum) + ".jpg";
File output = new File(imagesFolder, fileName);
while (output.exists()){
imageNum++;
fileName = "bild_" + String.valueOf(imageNum) + ".jpg";
output = new File(imagesFolder, fileName);
}
Uri uriSavedImage = Uri.fromFile(output);
imageIntent.putExtra(MediaStore.EXTRA_OUTPUT, uriSavedImage);
OutputStream imageFileOS;
try {
imageFileOS = getContentResolver().openOutputStream(uriSavedImage);
imageFileOS.write(arg0);
imageFileOS.flush();
imageFileOS.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
//camera.startPreview();
}
    };
        
Button cam_button = (Button) findViewById(R.id.cam_button);
cam_button.setOnClickListener(new OnClickListener(){
public void onClick(View view) {
startActivityForResult(imageIntent,1);
}});

EDIT: O.K. logisch dass der Button wieder geht, er umgeht ja einfach das "PictureCallback" bzw. "onPictureTaken" :glare:
 
Zuletzt bearbeitet:
HI,

also ich habe noch nie mit Bilder gearbeitet, aber hätte da eine andere Idee.

Du weißt, dass er es an einem bestimmten Ort mit bestimmten Namen speichert.
Danach kannst du doch einfach das Bild verschieben und an dem bestimmten ort löschen... :D

Gruß
 
Hmm, wär auf jeden Fall mal einen Versuch wert.

Danke für deine Antwort IceClaw.

Ich versuch das gleich mal. :)
 
Ich habs jetzt hinbekommen, dass er ein Verzeichnis erstellt und die Bilddatei nach meinen Vorgaben benennt und in das neue Verzeichnis stellt. :thumbsup:

Der Fehler lag wohl darin, dass ich PictureCallback und onPictureTaken verwenden wollte. Damit gings nicht.

Hier is der Code:

Code:
    public void onClick(View view) {
        switch (view.getId()) {
        case R.id.cam_button:            
            Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            File imagesFolder = new File(Environment.getExternalStorageDirectory().getAbsolutePath(), "DCIM/Bilderordner");
            imagesFolder.mkdirs();            
            
            int imageNum = 0;
                        
            String fileName = "Bild_" + String.valueOf(imageNum) + ".jpg";
            File output = new File(imagesFolder, fileName);
            
            while (output.exists()){
                imageNum++;
                fileName = "Bild_" + String.valueOf(imageNum) + ".jpg";
                output = new File(imagesFolder, fileName);
            }
            
            Uri uriSavedImage;
            uriSavedImage = Uri.fromFile(output);            
            Uri output2 = uriSavedImage;
            intent.putExtra(MediaStore.EXTRA_OUTPUT, output2);
            
            startActivityForResult(intent, 2);            

            break;
        }
        
    }
Jetzt hab ich aber neue Probleme:

1. der Ordner wird nicht in der Galerie angezeigt
2. das Bild wird zusätzlich noch im Ordner Camera abgelegt, mit dem timestamp-Dateinamen
3. und ich kann das Bild in "Eigene Dateien" nicht in der Großansicht ansehen.

:blink:

EDIT: Wenn ich auf dem Smartphone händisch irgend ein Bild, das ich schonmal mit der Kamera aufgenommen hatte, in den Bildordner hinein kopiere, dann wird der Ordner auch in der Galerie angezeigt und die Bilder können ganz normal aufgerufen werden...

Versteht das jemand und kanns mir erklären? :mellow:
 
Zuletzt bearbeitet:
Ich dachte, die Galerie versteht vielleicht das Dateiformat der Bilder nicht und denkt das Verzeichnis ist leer. Deshalb wird es nicht in der Galerie aufgeführt und die Bilder auch nicht korrekt angezeigt.

Also hab ich versucht der Datei einen Dateityp mitzugeben.
Code:
intent.putExtra(Media.MIME_TYPE, "image/jpeg");
Hat nichts gebracht.

Habe auch versucht mit ContentValues zu arbeiten und diese zusätzlich zum Dateinamen und Pfad mitzugeben.
Code:
ContentValues values = new ContentValues();
values.put(Media.MIME_TYPE, "image/jpeg");
intent.putExtra(MediaStore.EXTRA_OUTPUT, values);    
intent.putExtra(MediaStore.EXTRA_OUTPUT, output2);
Hat auch nichts gebracht.

Dann dachte ich, o.k., vielleicht kann er die Datei einfach nicht lesen.
Dann hab ich versucht die Datei lesbar zu machen.
Code:
File output = new File(imagesFolder, fileName);
output.canRead();
Hat auch nichts gebracht.

Wollte ja eigentlich "output.setReadable(true);" schreiben, aber das gabs nicht, obwohl das hier aufgeführt wird:
File | Android Developers

Ich bin echt mit meinem Latein am Ende :unsure:

EDIT: Noch eine Info: Wenn ich alle Bilder, die zusätzlich automatisch im Ordner "Kamera" abgespeichert wurden, lösche, dann funktionieren die richtigen Bilder und der Bilderordner wird in der Galerie angezeigt. Also liegt das wohl an der doppelten Speicherung, nehme ich an.
 
Zuletzt bearbeitet:
Hi pyretta,
voreerst muss ich sagen, habe deine Beiträge nicht alle ganz gelesen, werde es aber tun, da mich diese Thema auch interessiert.

Habe vor ein paar Tagen auch mal ein wenig mit der Kamera experementiert und folgendes geschaft..:
Bild machen und in einem speziellen Ordner speichern..!
Hatte auch vers. Codeabschnitte im Inet gefunden, aber am Ende habe ich das einfachste benutzt und zwar ohne Uri usw. sodnern einfach mit data.getExtras();

Nun zum Code..:
Irgendeinem Button bei onClick:
Code:
//create new Intent
                    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                    startActivityForResult(intent, IMAGE_ACTIVITY_REQUEST_CODE);
Dann bei onActivityResult:
Code:
@Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            if (requestCode == IMAGE_ACTIVITY_REQUEST_CODE) {
                if (resultCode == RESULT_OK) 
                {
                    
                    // Ordner Erstellen
                    File folder_1 = new File("/sdcard/MyFolder"); 
                    folder_1.mkdir();
                    File folder_2 = new File("/sdcard/MyFolder/Pictures");
                    folder_2.mkdir();
                    
                    // auslesen des gespeicherten Foto
                    Bitmap photo = (Bitmap) data.getExtras().get("data");
                                   
                    
                    // Hier wird später das Photo gespeichert
                    String path = "/sdcard/MyFolder/Pictures/";
                    OutputStream fOut = null;
                    
                    // Name des Photos
                    File file = new File(path, "testical_1"+".jpg");
                    try {
                        fOut = new FileOutputStream(file);
                    } catch (FileNotFoundException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }

                    // JPEG format, 100 % quality
                    photo.compress(Bitmap.CompressFormat.JPEG, 100, fOut);
                    try {
                        fOut.flush();
                        fOut.close();
                        
                        MediaStore.Images.Media.insertImage(getContentResolver(),file.getAbsolutePath(),file.getName(),file.getName());
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
}
Bis hier wurde das Photo in einem gewünschten Verzeichnis in JPEG-format gespeichert..!

Einzige Problem, das wie ich lese du auch hast, das Foto wird zweimal gespeichert und zwar einmal wie gewollt, zweites Mal in der Photogallery.
Hier müsste man irgendwie Android auffordern das Bild garnicht zu speichern, sondern nur zur Activity es zu returnen..!

Probleme mit Grossansicht usw habe ich aber nicht, also wenn ich in meinem Ordner gehe kann ich ohne Probleme mein Foto in Grossansicht sehen wie ein ganz normales Foto.
 
  • Danke
Reaktionen: pyretta
Hallo BFK,

vielen Dank für Deine Antwort.
Dein Code sieht wirklich sehr vielversprechend aus, aber leider meckert Eclipse und schmeisst mit Fehlermeldungen um sich.

Es versteht offensichtlich "IMAGE_ACTIVITY_REQUEST_CODE" und "FileOutputStream" nicht.

Machst du noch irgendwas spezielles?
Importierst oder implementierst du irgendwas?
Oder mal ganz doof gefragt: Welche Android-Version nutzt Du mit dem Code?
Ich versuch die App auf Android 2.2 zu optimieren.

Dein Code sieht, finde ich, um Längen besser aus als meiner, von daher würde ich den schon gerne benutzen.
 
Ahh ja sorry,
hab vergessen, mit "IMAGE_ACTIVITY_REQUEST_CODE" meine ich eigentlich eine static public Variable, damit onActivityResult weiss, dass das Bild wirklich von deiner Activity kommt, deshalb :
Code:
if (requestCode == IMAGE_ACTIVITY_REQUEST_CODE) {

Also hier wird es gecheckt.

Deshalb ganz einfach eine int Variable deklarieren..:
Code:
private int IMAGE_ACTIVITY_REQUEST_CODE = 123456;

Oder halt irgendeine Nummer.

Und FileOutPutStream sollte eclispse eigentlich einfach importieren..:
Code:
import java.io.FileOutputStream;

Und was die version angeht, ich baue für Android 2.1 (ab Android 2.1), also solltest du kein Problem haben..!
 
Code:
......
File  root = new File(Environment.getExternalStorageDirectory() + File.separator + "TEMP" + File.separator);//TEMP oder irgendein Ordnername   
           root.mkdirs();
            File sdDir = new File(root, "Dateiname.jpg");          
            startCameraActivity();
und in der Activity
Code:
Uri outputFileUri = Uri.fromFile(sdDir);
        Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
        intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
        startActivityForResult(intent, 0);
....so funktioniert es bei mir
 
  • Danke
Reaktionen: pyretta
Hallo BFK,

danke dass Du mir noch die zusätzlichen Infos zu Deinem Code gegeben hast.
Dadurch wurden die Fehlermeldungen von Eclipse ausgemerzt und ich konnte die App testen.

Aber leider hat der Code dann folgenden Fehler verursacht, nachdem ich das Bild gespeichert hatte:

04-13 11:24:43.390: E/AndroidRuntime(9902): java.lang.RuntimeException: Failure delivering result ResultInfo{who=18, request=0, result=-1, data=Intent { act=inline-data (has extras) }} to activity {appname/actiticyname}: java.lang.NullPointerException
04-13 11:24:43.390: E/AndroidRuntime(9902): at android.app.ActivityThread.deliverResults(ActivityThread.java:2536)
04-13 11:24:43.390: E/AndroidRuntime(9902): at android.app.ActivityThread.handleSendResult(ActivityThread.java:2578)
04-13 11:24:43.390: E/AndroidRuntime(9902): at android.app.ActivityThread.access$2000(ActivityThread.java:117)
04-13 11:24:43.390: E/AndroidRuntime(9902): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:965)
04-13 11:24:43.390: E/AndroidRuntime(9902): at android.os.Handler.dispatchMessage(Handler.java:99)
04-13 11:24:43.390: E/AndroidRuntime(9902): at android.os.Looper.loop(Looper.java:123)
04-13 11:24:43.390: E/AndroidRuntime(9902): at android.app.ActivityThread.main(ActivityThread.java:3687)
04-13 11:24:43.390: E/AndroidRuntime(9902): at java.lang.reflect.Method.invokeNative(Native Method)
04-13 11:24:43.390: E/AndroidRuntime(9902): at java.lang.reflect.Method.invoke(Method.java:507)
04-13 11:24:43.390: E/AndroidRuntime(9902): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:842)
04-13 11:24:43.390: E/AndroidRuntime(9902): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
04-13 11:24:43.390: E/AndroidRuntime(9902): at dalvik.system.NativeStart.main(Native Method)
04-13 11:24:43.390: E/AndroidRuntime(9902): Caused by: java.lang.NullPointerException
04-13 11:24:43.390: E/AndroidRuntime(9902): at android.graphics.Bitmap.compress(Bitmap.java:584)
04-13 11:24:43.390: E/AndroidRuntime(9902): at activityname.onActivityResult(Tab1_Impfen_F.java:103)
04-13 11:24:43.390: E/AndroidRuntime(9902): at android.app.ActivityGroup.dispatchActivityResult(ActivityGroup.java:119)
04-13 11:24:43.390: E/AndroidRuntime(9902): at android.app.ActivityThread.deliverResults(ActivityThread.java:2532)
04-13 11:24:43.390: E/AndroidRuntime(9902): ... 11 more
Das Bild wurde dann trotzdem in dem Galerie-Ordner "Camera" gespeichert, aber der eigene Ordner wurde nicht angelegt und auch der Dateiname nicht vergeben. :sad:

EDIT: Hab den Fehler gefunden. Wir hatten die wichtige Info "Environment.getExternalStorageDirectory().getAbsolutePath()," vergessen.

Richtig heisst es also (in meinem Fall, da ich nicht auf die SD-Karte sondern in die Galerie speichern will, nur eben mit eigenem Ordner):
Code:
File folder_1 = new File(Environment.getExternalStorageDirectory().getAbsolutePath(), "DCIM/Bilder"); 
 folder_1.mkdir();
Aber leider hat das auch nichts an meinem Problem geändert. Der Ordner taucht immer noch nicht in der Galerie auf, die Bilder (wie Du ja auch sagtest) werden immer noch doppelt gespeichert und ich kann meine richtigen Bilder auch nicht in der Großansicht anzeigen lassen. Vielleicht funktioniert Deine Lösung im Bezug der Bilderanzeige nur, wenn man den Ordner eben nicht in der Galerie speichert. Aber, genau das bräuchte ich leider.

EDIT2: Nope. Habe gerade testhalber ausprobiert den Ordner im rootverzeichnis anzulegen. Gleiches Problem.
Dann habe ich Deinen Vorschlag ausprobiert, und versucht auf die SD-Karte zu speichern. Das lies mein Smartphone abstürzen...
Also meine Theorie, dass es am Speicherort an sich liegt, ist dann wohl auch ausgeräumt. :mellow:


@TdB4711
Dir auch erstmal vielen Dank für deine Antwort.
Dein Code funktioniert zwar, aber damit habe ich trotzdem das Problem, dass das Bild doppelt gespeichert wird und nicht in der Großansicht angezeigt werden kann.
 
Zuletzt bearbeitet:
Hmm, ich versuche gerade die unnötige Datei im Camera-Ordner zu löschen. Aber ich krieg das einfach nicht hin. Aber ich fürchte das ist die Lösung für mein Problem.

Ich habe viele Codeschnippsel bei stack-overflow gefunden, aber die krieg ich nicht richtig in meinen Code eingebunden. Sie funktionieren jedenfalls nicht wie gewollt und beschrieben. :sad:

Folgende Codes hab ich bereits versucht:
android - Built-in Camera, using the extra MediaStore.EXTRA_OUTPUT stores pictures twice (in my folder, and in the default) - Stack Overflow
android - Deleting a gallery image after camera intent photo taken - Stack Overflow

Hat aber nix gebracht. Eher im Gegenteil, die Apps stürzte oft sogar ab.

Dann bin ich hierauf gestoßen:
Taking Photos Simply | Android Developers

Das hab ich auch durchgemacht. Brachte nur einen Absturz.


Mein ganzer Code sieht jetzt wie folgt aus:
Code:
package de.app.package;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import java.io.FileOutputStream;

public class MainActivity extends Activity implements OnClickListener{

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);        
        
        Button cam_button = (Button) findViewById(R.id.cam_button);
        cam_button.setOnClickListener(this);
        
    }
    
    
    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    final int IMAGE_ACTIVITY_REQUEST_CODE = 0;
    
    public void onClick(View view) {    
        
        switch (view.getId()) {
        case R.id.cam_button:
            startActivityForResult(intent, IMAGE_ACTIVITY_REQUEST_CODE);
            break;}
        }
        
        @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            
            if (requestCode == IMAGE_ACTIVITY_REQUEST_CODE) {
                if (resultCode == RESULT_OK) 
                {
                    
                    // Ordner Erstellen
                   final File folder_1 = new File(Environment.getExternalStorageDirectory().getAbsolutePath(), "Bilder"); 
                    folder_1.mkdir();
                    
                    // auslesen des gespeicherten Foto
                    Bitmap photo = (Bitmap) data.getExtras().get("data");
                                   
                    
                    // Hier wird später das Photo gespeichert
                    OutputStream fOut = null;
                    
                    // Name des Photos
                    int imageNum = 0;
                    String fileName = "Bild_" + String.valueOf(imageNum) + ".jpg";
                    File file = new File(folder_1, fileName);
                    while (file.exists()){
                        imageNum++;
                        fileName = "Bild_" + String.valueOf(imageNum) + ".jpg";
                        file = new File(folder_1, fileName);
                    }
                    
                    try {
                        fOut = new FileOutputStream(file);
                    } catch (FileNotFoundException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }

                    // JPEG format, 100 % quality
                    photo.compress(Bitmap.CompressFormat.JPEG, 100, fOut);
                    try {
                        fOut.flush();
                        fOut.close();
                        
                        MediaStore.Images.Media.insertImage(getContentResolver(),file.getAbsolutePath(),file.getName(),file.getName());
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    
                    
                }
                
            } 
        } }

Im Manifest hab ich natürlich folgende Permissons hinterlegt:
Code:
<uses-permission android:name="android.permission.CAMERA"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

Mit dem obigen Code kann ich jetzt folgendes:
1. Aus meiner App heraus die Kamera aufrufen.
2. Ein Bild machen.
3. Ein Verzeichnis anlegen und dem Bild einen Dateinamen verpassen.
4. Das Bild im Verzeichnis ablegen.

So weit so gut.

Was es leider noch zusätzlich macht:
1. Das Originalbild im Ordner "DCIM/Camera" mit dem timestamp als Dateinamen ablegen (z.B. 2012-04-13 16.00.23.jpg) und lediglich eine Kopie des Bilds mit meinem angegebenen Dateinamen (z.B. Bild_1.jpg) in meinem angegebenen Ordner (z.B. Bilder) erstellen.
2. Das Bild_1.jpg kann nicht in der Großansicht angezeigt werden.
3. Der Ordner Bilder taucht nicht in der Galery auf.

Wenn Ihr mir da weiterhelfen könntet wär echt toll.
Danke schon mal im Voraus.
 
Hi pyretta,
Ok das mit der doppelten Datei habe ich noch nicht gesucht, werden wir aber schon finden, könnte theoretisch nicht so schwer sein.

Erklär mir aber kurz was meisnt du mit Gallery..?

Willst du dass dein erstellter Ordner, der die Bilder beinhaltet in der App "Galery" erscheint..?
Da erscheinen doch alle Ordner die ein Bild beinhalten oder irre ich mich..?

Dass dein Bild nicht in Grossansicht angezeigt wird, verstehe ich irgendwie auch nicht..!
Was machst du da genau..? Logischerweise öffnest du eine Filemanager-App, navigierst zur gewünschten Datei, drückst auf die Datei, wirst aufgefordert eine App zu benutzen um das Bild zu öffnen. Was passeiret aber dann..?

Und so wie ich das verstanden habe, willst du ja deine Bilder nicht auf die SD speichern, sondern im internen Speicher.
Funktioniert das jetzt, oder kriegst du immer noch einen Absturzt..?
 
  • Danke
Reaktionen: pyretta
Ok, was das Löschen angeht habe ich folgendes ausprobiert von deinem geposteten Link, den meine ich: android - Deleting a gallery image after camera intent photo taken - Stack Overflow
und es scheint zu funken.
Zwar nicht so toll, am besten wäre es das Bild überhaupt nicht zu speichern, aber ok wie es ausieht will Android das Bild immer speichern.

Na egal ich poste mal den Code für das Löschen eines Bildes (wie gesagt nicht von mir, habs aber getestet und es funkt)..:
Code:
/**
 * Gets the last image id from the media store
 * @return
 */
private int getLastImageId(){
    final String[] imageColumns = { MediaStore.Images.Media._ID };
    final String imageOrderBy = MediaStore.Images.Media._ID+" DESC";
    final String imageWhere = null;
    final String[] imageArguments = null;
    Cursor imageCursor = managedQuery(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, imageColumns, imageWhere, imageArguments, imageOrderBy);
    if(imageCursor.moveToFirst()){
        int id = imageCursor.getInt(imageCursor.getColumnIndex(MediaStore.Images.Media._ID));
        imageCursor.close();
        return id;
    }else{
        return 0;
    }
}

Mit dieser Methode bekommt man die ID des letzten gespeicherten Fotos und mit dieser Methode..:

Code:
private void removeImage(int id) {
           ContentResolver cr = getContentResolver();
            cr.delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, MediaStore.Images.Media._ID + "=?", new String[]{ Long.toString(id) } );
    }

löscht man es.

So wie ich lese, funktioniert jedes Handy anders, was das abspeichern angeht.
Und naja um zu verhindern, dass man ein Bild löscht, was garnicht von unserer App entstanden ist, könnte man die erste Methode vor dem Capturen abrufen, die ID irgendwo speichern, später (nach dem Capturen) nochmal abrufen, checken ob die ID wirklich um 1 gestiegen ist und nur wenn es so ist das BIld dann eben löschen.
Das alles sollte funken, wenn die ID auch wirklich immer um 1 erhöht wird. So wie es aussieht funktioniert es aber gerado so, zumind. interpretiere ich es so von meine kurzen Tests.

Ich weiss hört sich nicht sooo gut an, aber habe bis jetzt keine bessere Lösung. Wenn es was einfacheres oder besseres finde, dann poste ich es auch..!
 
  • Danke
Reaktionen: pyretta
Hallo BFK,

vielen vielen Dank für Deine Mühe, Hilfe und Geduld. :smile:
Ich weiss das echt zu schätzen.

Den Code habe ich auch ausprobiert. Aber leider hat der (zumindest so wie ich den eingebunden habe, vielleicht hab ich das auch falsch gemacht) das Bild sogar 3-fach abgespeichert, statt eins der Doppelten zu löschen :blink:.

Im Ordner DCIM/Camera wie folgt:
einmal als "1334562245247.jpg" und einmal als "2012-04-16 09.44.01.jpg"

In meinem Ordner DCIM/Bilder wie gewollt als Bild_0.jpg

Der Witz ist, mein Ordner wird nicht in der Galerie angezeigt und das Album "Kamera", das den Ordner "DCIM/Camera" repräsentiert, zeigt auch nur eins der dort gespeicherten Bilder an.

Achja, mit Galerie meine ich die vorinstallierte App "Galerie", die wie du schon sagtest, eigentlich alle Ordner anzeigen sollte in denen sich Bilder befinden.

Ich vermute einfach mal, dass es an dem neuen Codefragment liegt, denn ohne den speichert es nur die üblichen 2 Dateien ab (DCIM/Camera/2012-04-16 09.44.01.jpg und DCIM/Bilder/Bild_0.jpg).

Hier mal der gesamte Code von A - Z:

Code:
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import java.io.FileOutputStream;

public class ActivityName extends Activity implements OnClickListener {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_layout);        
        Button cam_button = (Button) findViewById(R.id.cam_button);
        cam_button.setOnClickListener(this);
    }
    
    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    final int IMAGE_ACTIVITY_REQUEST_CODE = 0;
    public void onClick(View view) {    
        switch (view.getId()) {
        case R.id.cam_button:
            startActivityForResult(intent, IMAGE_ACTIVITY_REQUEST_CODE);
            break;}
        }
        
        @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            
            if (requestCode == IMAGE_ACTIVITY_REQUEST_CODE) {
                if (resultCode == RESULT_OK) 
                {
                    // Ordner Erstellen
                   final File folder_1 = new File(Environment.getExternalStorageDirectory().getAbsolutePath(), "Bilder"); 
                    folder_1.mkdir();
                    
                    // auslesen des gespeicherten Foto
                    Bitmap photo = (Bitmap) data.getExtras().get("data");                                  
                    
                    // Hier wird später das Photo gespeichert
                    OutputStream fOut = null;
                    
                    // Name des Photos
                    int imageNum = 0;
                    String fileName = "Bild_" + String.valueOf(imageNum) + ".jpg";
                    File file = new File(folder_1, fileName);
                    while (file.exists()){
                        imageNum++;
                        fileName = "Bild_" + String.valueOf(imageNum) + ".jpg";
                        file = new File(folder_1, fileName);
                    }
                    
                    try {
                        fOut = new FileOutputStream(file);
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    }

                    // JPEG format, 100 % quality
                    photo.compress(Bitmap.CompressFormat.JPEG, 100, fOut);
                    try {
                        fOut.flush();
                        fOut.close();                       
                        MediaStore.Images.Media.insertImage(getContentResolver(),file.getAbsolutePath(),file.getName(),file.getName());
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    
                    
                }}
                
            }
    
        
                 // Delete original file from Android's Gallery
             
                    /**
                     * Gets the last image id from the media store
                     * @return
                     */
            
            private int getLastImageId(){                
                        final String[] imageColumns = { MediaStore.Images.Media.DATA, MediaStore.Images.Media.DATE_TAKEN, MediaStore.Images.Media.SIZE, MediaStore.Images.Media._ID };
                        final String imageOrderBy = MediaStore.Images.Media._ID+" DESC";
                        final String imageWhere = MediaStore.Images.Media._ID+">?";
                        final String[] imageArguments = { Integer.toString(herz.tab.impfungen.frau.Tab1_Impfen_F.this.getLastImageId()) };
                        Cursor imageCursor = managedQuery(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, imageColumns, imageWhere, imageArguments, imageOrderBy);
                        if(imageCursor.moveToFirst()){
                            int id = imageCursor.getInt(imageCursor.getColumnIndex(MediaStore.Images.Media._ID));
                            imageCursor.close();    
                            return id;
                        }
                        
                        else{
                            return 0;
                        }
                        
        } 
            private void removeImage(int id) {
                   ContentResolver cr = getContentResolver();
                    cr.delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, MediaStore.Images.Media._ID + "=?", new String[]{ Long.toString(id) } );
            }    
        }
Ich hab auch gelesen, dass es Speicherunterschiede geben soll, je nach dem welches Smartphone man nutzt.
Zum Testen nehme ich mein Galaxy S i9000. Vielleicht liegts ja daran :blink: , was echt schlecht wäre, denn laut den Downloadstatistiken der bisher in den Markt gestellten Apps, haben die meisten genau dieses Smartphone.

Hab ich denn den Code falsch eingebunden?
Eclipse zeigt mir jedenfalls keinerlei Fehler an.

Nur meint es, die Methoden "private int getLastImageId(){...}" und "private void removeImage(int id) {...}" werden nie genutzt und unterkringelt es folglich auch gelb. Das zeigt mir eigentlich, dass das wohl doch an falscher Stelle eingebunden ist. Füg ich den Code allerdings an früherer Stelle ein, kann Eclipse damit überhaupt nichts anfangen und unterstreicht fast alles rot.

Also das mit dem Löschen, scheint aber weiterhin der richtige Weg zu sein. Denn lösche ich die Datei "DCIM/Camera/2012-04-16 09.44.01.jpg", dann wird mein Ordner inklusive Bilddatei in der Galerie angezeigt.

EDIT: Noch ne Info: Wenn ich die App, so wie sie jetzt ist, auf dem Emulator mit den Spezifikationen des LG Optimus 3D ausführe, dann stürzt Smartphone in der Kamera-App ab, bevor ich die Möglichkeit hatte ein Foto zu erstellen. Liegt das jetzt am Emulator, oder kann ich davon ausgehen dass es beim LG tatsächlich zum Absturz kommen würde?
 
Zuletzt bearbeitet:
Also...

Ich hab jetzt nochmal ne Weile rumprobiert und herausgefunden, dass es mit der Galerie dann erst klappt, wenn das Smartphone neu gestartet wurde, also der Medienscan durchgeführt wurde, um die Galerie zu aktualisieren. Das ist ja schon mal was :biggrin: .

Dann habe ich die App mal mit einem Galaxy S2 mit Android 4.0.3 ausprobiert. Dort findet keine Dopplung der Bilddateien statt. Die Datei wird immer sauber in dem Ordner abgespeichert wo hin sie auch soll und nirgens sonst. In der Galerie erscheint sie allerdings auch erst nach einem Neustart.

Jetzt hät ich aber doch noch gerne auf den noch sehr verbreiteten Android 2.3.3 Geräten die Dopplung verhindert bzw. entfernt. :mellow: Das muss doch gehn.
 
Ich habs nun endlich hinbekommen, dank der Hilfe von BFK. Vielen Dank nochmal. :smile:

Mein Fehler, war anzunehmen dass ich keine ArrayList bräuchte um die Dopplung zu löschen. Nope.

Ich habe nun den ganzen Code eingebunden, so funktioniert er auch perfekt. :blushing: (hät mir da einiges sparen können, hät ich das gleich so gemacht)

Dass dann auch alle neuen Bilder in der Galerie erscheinen, hab ich einen Media-Scan initialisiert mit "sendBroadcast".

Nun ist alles so wie es soll. Einziger eventueller Nachteil ist, dass mein Media-Scan immer gleich die ganze SD-Karte scant, nicht etwa nur den benötigten Teil, aber ich denke das ist jetzt eher ein kosmetisches Problem.

Hier jedenfalls für alle Interessierten der vollständige Code:
Code:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.BaseColumns;
import android.provider.MediaStore;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class ActivityName extends Activity implements OnClickListener{
    
    
    int imageNum = 0;
    String fileName = "Bild_" + String.valueOf(imageNum) + ".jpg";
    File path = new File(Environment.getExternalStorageDirectory().getAbsolutePath(), "DCIM/Bilder");
    File output = new File(path, fileName);
    String output_scan = String.valueOf(output);
    Context context;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        Button cam_button = (Button) findViewById(R.id.cam_button);
        cam_button.setOnClickListener(this);
    }     
    public ArrayList<String> GalleryList = new ArrayList<String>();

    private void FillPhotoList()
    {
       // initialize the list!
       GalleryList.clear();
       String[] projection = { MediaStore.Images.ImageColumns.DISPLAY_NAME };
       // intialize the Uri and the Cursor, and the current expected size.
       Cursor c = null; 
       Uri u = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
       //
       // Query the Uri to get the data path.  Only if the Uri is valid.
       if (u != null)
       {
          c = managedQuery(u, projection, null, null, null);
       }

       // If we found the cursor and found a record in it (we also have the id).
       if ((c != null) && (c.moveToFirst())) 
       {
          do 
          {
            // Loop each and add to the list.
            GalleryList.add(c.getString(0));
          }     
          while (c.moveToNext());
       }
    }

    private String getTempFileString()
    {
       // Only one time will we grab this location.
       
       //
       // If this does not exist, we can create it here.
       
       if (!path.exists())
       {
          path.mkdir();
       }
       //
              
       while (output.exists()){
           imageNum++;
           fileName = "Bild_" + String.valueOf(imageNum) + ".jpg";
           output = new File(path , fileName);
           return output.getPath();
       }
      
       return output.getPath();
    }

    public static String sFilePath = ""; 
    public static File CurrentFile = null;
    public static Uri CurrentUri = null;
    
    public int IMAGE_CAPTURE = 0;

    public void setsFilePath(String value)
    {
       // We just updated this value. Set the property first.
       sFilePath = value;
       //
       // initialize these two
       CurrentFile = null;
       CurrentUri = null;
       //
       // If we have something real, setup the file and the Uri.
       if (!sFilePath.equalsIgnoreCase(""))
       {
          CurrentFile = new File(sFilePath);
          CurrentUri = Uri.fromFile(CurrentFile);
       }
    }

    public void startCamera()
    {
       Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
       // Specify the output. This will be unique.
       setsFilePath(getTempFileString());
       //
       intent.putExtra(MediaStore.EXTRA_OUTPUT, CurrentUri);
       //
       // Keep a list for afterwards
       FillPhotoList();
       //
       // finally start the intent and wait for a result.
       startActivityForResult(intent, IMAGE_CAPTURE);
    }

    protected void onActivityResult(int requestCode, int resultCode, Intent data)
    {
       if (requestCode == IMAGE_CAPTURE)
       {
          // based on the result we either set the preview or show a quick toast splash.
          if (resultCode == RESULT_OK)
          {
             // This is ##### ridiculous.  Some versions of Android save
             // to the MediaStore as well.  Not sure why!  We don't know what
             // name Android will give either, so we get to search for this
             // manually and remove it.  
             String[] projection = { MediaStore.Images.ImageColumns.SIZE,
                                     MediaStore.Images.ImageColumns.DISPLAY_NAME,
                                     MediaStore.Images.ImageColumns.DATA,
                                     BaseColumns._ID,};
             //    
             // intialize the Uri and the Cursor, and the current expected size.
             Cursor c = null; 
             Uri u = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
             //
             if (CurrentFile != null)
             {               
                // Query the Uri to get the data path.  Only if the Uri is valid,
                // and we had a valid size to be searching for.
                if ((u != null) && (CurrentFile.length() > 0))
                {
                   c = managedQuery(u, projection, null, null, null);
                }
                //   
                // If we found the cursor and found a record in it (we also have the size).
                if ((c != null) && (c.moveToFirst())) 
                {
                   do 
                   {
                      // Check each area in the gallary we built before.
                      boolean bFound = false;
                      for (String sGallery : GalleryList)
                      {
                         if (sGallery.equalsIgnoreCase(c.getString(1)))
                         {
                            bFound = true;
                            break;
                         }
                      }
                      //       
                      // To here we looped the full gallery.
                      if (!bFound)
                      {
                         // This is the NEW image.  If the size is bigger, copy it.
                         // Then delete it!
                         File f = new File(c.getString(2));

                         // Ensure it's there, check size, and delete!
                         if ((f.exists()) && (CurrentFile.length() < c.getLong(0)) && (CurrentFile.delete()))
                         {
                            // Finally we can stop the copy.
                            try
                            {
                               CurrentFile.createNewFile();
                               FileChannel source = null;
                               FileChannel destination = null;
                               try 
                               {
                                  source = new FileInputStream(f).getChannel();
                                  destination = new FileOutputStream(CurrentFile).getChannel();
                                  destination.transferFrom(source, 0, source.size());
                               }
                               finally 
                               {
                                  if (source != null) 
                                  {
                                     source.close();
                                  }
                                  if (destination != null) 
                                  {
                                     destination.close();
                                  }
                               }
                            }
                            catch (IOException e)
                            {
                               // Could not copy the file over.
                            e.printStackTrace();

                            }
                         }
                         //       
                         ContentResolver cr = getContentResolver();
                         cr.delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 
                            BaseColumns._ID + "=" + c.getString(3), null);
                         break;                        
                      }
                   } 
                   while (c.moveToNext());
                }
             }
          }
       }    
       
       
       
    }  
       
       @Override
       public void onClick(View view) {
           
           switch (view.getId()) {
           case R.id.cam_button:
               startCamera();               
               break;
    }
           

}      

//Medienscan aktivieren, sobald die "zurück-Taste" betätigt wurde (so als Beispiel): 
       @Override
       public void onBackPressed() {
           sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" 
                      + Environment.getExternalStorageDirectory())));           
       } 
       
}
Soweit ich gelesen habe, funktioniert das aber erst ab API 8, sollte aber eigentlich kein Problem sein, angesichts dessen dass kaum noch Smartphones im Umlauf sind mit einer älteren Android-Version. Froyo und Gingerbread sind sowieso momentan (noch) Marktführer.

Ich hoffe ich konnte mit diesem Thread wenigstens anderen Anfängern, die das selbe Problem hatten, ein wenig helfen. Dann ist er nicht ganz umsonst... :blushing:
 
Zuletzt bearbeitet:
Hi pyretta,
Freut mich dass endlich alles klappt..!
:smile:
 

Ähnliche Themen

B
Antworten
6
Aufrufe
1.049
jogimuc
J
R
  • RudolfHagen
Antworten
1
Aufrufe
648
koje71
koje71
B
Antworten
4
Aufrufe
470
bb321
B
Zurück
Oben Unten