web-dev-qa-db-fra.com

Android - Prendre des photos et les enregistrer avec un nom personnalisé dans une destination personnalisée via Intent

J'ai un programme qui ouvre l'appareil photo via Intention de prendre une photo. Cela fonctionne déjà très bien. Cependant, je veux qu'il soit sauvegardé dans un certain dossier avec un certain nom de fichier (le nom de fichier est facultatif mais cela aiderait vraiment).

Alors voici ce que j'ai jusqu'à présent.

Voici la ligne de code qui ouvre la caméra:

//TODO camera stuff.
Intent openCam = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

//The two lines of code below were commented out at first.
//They were eventually added when I tried to save it with a custom name and destination
fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE); // create a file to save the image
openCam.putExtra(MediaStore.EXTRA_OUTPUT, fileUri); // set the image file name

startActivityForResult(openCam, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);

Le gestionnaire de résultats va ici:

//TODO handle result
if (requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE) {
   if (resultCode == RESULT_OK) {
         // Image captured and saved to fileUri specified in the Intent
         Toast.makeText(this, "Image saved to:\n" +
                     data.getData(), Toast.LENGTH_LONG).show();
            System.out.println("I am here");

   } 
   else if (resultCode == RESULT_CANCELED) {
            // User cancelled the image capture
   } 
   else {
            // Image capture failed, advise user
   }
}

Avant d’implémenter les deux méthodes ci-dessous, le code fonctionnait bien. Cependant, il a été enregistré dans le dossier par défaut avec le nom de fichier par défaut (la version de l'horodatage). Le pain grillé affiche "Image enregistrée enregistrée sur: null" car je n’ai pas encore défini cette partie.

Voici donc les méthodes supposées gérer le nom de fichier et la destination personnalisés 

/** Create a file Uri for saving an image or video */
private static Uri getOutputMediaFileUri(int type){
      return Uri.fromFile(getOutputMediaFile(type));
}

/** Create a File for saving an image or video */
private static File getOutputMediaFile(int type){
    // To be safe, you should check that the SDCard is mounted
    // using Environment.getExternalStorageState() before doing this.

    Environment.getExternalStorageState();

    File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
              Environment.DIRECTORY_PICTURES), "MyCameraApp");
    // This location works best if you want the created images to be shared
    // between applications and persist after your app has been uninstalled.

    // Create the storage directory if it does not exist
    if (! mediaStorageDir.exists()){
        if (! mediaStorageDir.mkdirs()){
            Log.d("MyCameraApp", "failed to create directory");
            return null;
        }
    }

    // Create a media file name
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    File mediaFile;
    if (type == MEDIA_TYPE_IMAGE){
        mediaFile = new File(mediaStorageDir.getPath() + File.separator +
        "IMG_"+ timeStamp + ".jpg");
    } else {
        return null;
    }

    return mediaFile;
}

* Ces codes ont été extraits du Guide de l'appareil photo de developer.Android.com.

Le code ci-dessus parvient à ouvrir l'appareil photo, à prendre des photos et à les enregistrer. Cependant, le problème survient lorsque l'utilisateur décide de ne plus prendre de photo et appuie sur la touche Retour. Qu'est-ce qui se passe est que la force de l'application se ferme donnant cette erreur:

10-21 12:44:33.699: E/AndroidRuntime(13016): FATAL EXCEPTION: main
10-21 12:44:33.699: E/AndroidRuntime(13016): Java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=100, result=-1, data=null} to activity {com.AIC.QRCodeScanner/com.AIC.QRCodeScanner.QRCodeScanner}: Java.lang.NullPointerException
10-21 12:44:33.699: E/AndroidRuntime(13016): at Android.app.ActivityThread.deliverResults(ActivityThread.Java:2536)
10-21 12:44:33.699: E/AndroidRuntime(13016): at Android.app.ActivityThread.handleSendResult(ActivityThread.Java:2578)
10-21 12:44:33.699: E/AndroidRuntime(13016): at Android.app.ActivityThread.access$2000(ActivityThread.Java:117)
10-21 12:44:33.699: E/AndroidRuntime(13016): at Android.app.ActivityThread$H.handleMessage(ActivityThread.Java:965)
10-21 12:44:33.699: E/AndroidRuntime(13016): at Android.os.Handler.dispatchMessage(Handler.Java:99)
10-21 12:44:33.699: E/AndroidRuntime(13016): at Android.os.Looper.loop(Looper.Java:123)
10-21 12:44:33.699: E/AndroidRuntime(13016): at Android.app.ActivityThread.main(ActivityThread.Java:3691)
10-21 12:44:33.699: E/AndroidRuntime(13016): at Java.lang.reflect.Method.invokeNative(Native Method)
10-21 12:44:33.699: E/AndroidRuntime(13016): at Java.lang.reflect.Method.invoke(Method.Java:507)
10-21 12:44:33.699: E/AndroidRuntime(13016): at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:847)
10-21 12:44:33.699: E/AndroidRuntime(13016): at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:605)
10-21 12:44:33.699: E/AndroidRuntime(13016): at dalvik.system.NativeStart.main(Native Method)
10-21 12:44:33.699: E/AndroidRuntime(13016): Caused by: Java.lang.NullPointerException
10-21 12:44:33.699: E/AndroidRuntime(13016): at com.AIC.QRCodeScanner.QRCodeScanner.onActivityResult(QRCodeScanner.Java:379)
10-21 12:44:33.699: E/AndroidRuntime(13016): at Android.app.Activity.dispatchActivityResult(Activity.Java:3934)
10-21 12:44:33.699: E/AndroidRuntime(13016): at Android.app.ActivityThread.deliverResults(ActivityThread.Java:2532)
10-21 12:44:33.699: E/AndroidRuntime(13016):    
... 11 more

La ligne vers laquelle il pointe correspond à cette ligne (ligne 379): data.getData(), Toast.LENGTH_LONG

Cependant, les fichiers sont enregistrés dans le dossier /Pictures/MyCameraApp avec les photos Instagram prises.

Les questions sont donc les suivantes: 1. Existe-t-il un moyen de faire fonctionner onActivityResult correctement? Je sais que je peux simplement recourir à startActivity afin de ne pas tuer l'application. 2. Est-il possible de prendre une seule photo avec l'appareil photo? Ainsi, une fois que l'utilisateur a enregistré la photo, l'application revient à l'activité principale. 3. Aussi, puis-je l'enregistrer dans un dossier de mon choix? Je ne suis pas sûr de savoir pourquoi il enregistre les photos dans /Pictures/MyCameraApp. Je souhaite uniquement enregistrer au format /MyCameraApp.

Je pense que je manque quelque chose de simple ici. 

8
Razgriz

Voici le code qui a fait que ça marche:

//camera stuff
Intent imageIntent = new Intent(Android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());

//folder stuff
File imagesFolder = new File(Environment.getExternalStorageDirectory(), "MyImages");
imagesFolder.mkdirs();

File image = new File(imagesFolder, "QR_" + timeStamp + ".png");
Uri uriSavedImage = Uri.fromFile(image);

imageIntent.putExtra(MediaStore.EXTRA_OUTPUT, uriSavedImage);
startActivityForResult(imageIntent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);

Il ouvre l'appareil photo et prend exactement une photo (il revient à l'activité principale une fois que l'utilisateur a enregistré la photo prise. Il enregistre l'image dans le dossier spécifié.

20
Razgriz

Vous pouvez obtenir votre photo dans votre dossier mais pour cela vous devrez passer le nom du fichier avec l'intention en utilisant le code ci-dessous

Intent i = new Intent(Android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
File out = Environment.getExternalStorageDirectory();
out = new File(out, imagename);
i.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(out));
startActivityForResult(i, CAMERA_RESULT);

Le fichier de sortie contient le chemin d'accès complet et le nom du fichier.

Maintenant, gérez la méthode onActivityResult () et vérifiez l’état du résultat si RESULT_OK est obtenu, puis utilisez le nom de fichier que vous avez fourni avec l’intention d’accéder à la photo.

Vous pouvez vous référer Comment obtenir le résultat de la caméra en tant qu'uri dans le dossier de données pour plus d'options.

Modifier

Vous obtenez data.getData() à null car ce sera null si vous transmettez l'URL du fichier avec l'intention. En effet, vous avez déjà le chemin de fichier que vous transmettez avec l’intention, alors pourquoi essayez-vous de le récupérer dans le paquet dans onActivityResult()?

7
Dharmendra

cela peut vous aider

File file=new File(Environment.getExternalStorageDirectory(),"file name");

button.setOnClickListener(new OnClickListener() {

    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub
        opencam();
    }
});

protected void opencam() {
    Intent in = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);    
    in.putExtra(MediaStore.EXTRA_OUTPUT,Uri.fromFile(file));
    startActivityForResult(in,1);
}
0
sachin