web-dev-qa-db-fra.com

MediaStore.EXTRA_OUTPUT rend les données nulles, une autre façon d'enregistrer des photos?

Google propose ce code polyvalent pour prendre des photos via une intention:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    // create Intent to take a picture and return control to the calling application
    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

    fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE); // create a file to save the image
    intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri); // set the image file name

    // start the image capture Intent
    startActivityForResult(intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);
}

Le problème est que si vous êtes comme moi et que vous souhaitez transmettre les photos en tant qu'extras, utilisez EXTRA_OUTPUT s'écoule apparemment avec les données de la photo et fait penser aux actions suivantes que les données d'intention sont nulles.

Il apparaît c'est un gros bug avec Android.

J'essaie de prendre une photo puis de l'afficher sous forme de miniature dans une nouvelle vue. Je voudrais l'avoir enregistré en tant qu'image en taille réelle dans la galerie de l'utilisateur. Quelqu'un sait-il comment spécifier l'emplacement de l'image sans utiliser EXTRA_OUTPUT?

Voici ce que j'ai actuellement:

public void takePhoto(View view) {
    Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

    fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE);
//  takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);

    startActivityForResult(takePictureIntent, CAMERA_REQUEST_CODE);
}

/** 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 */
@SuppressLint("SimpleDateFormat")
private static File getOutputMediaFile(int type){

    File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
              Environment.DIRECTORY_PICTURES), "JoshuaTree");

    if (! mediaStorageDir.exists()){
        if (! mediaStorageDir.mkdirs()){
            Log.d("JoshuaTree", "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;
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == CAMERA_REQUEST_CODE) {
        if (resultCode == RESULT_OK) {
            handleSmallCameraPhoto(data);
        }
    }
}


private void handleSmallCameraPhoto(Intent intent) {
    Bundle extras = intent.getExtras();
    mImageBitmap = (Bitmap) extras.get("data");
    Intent displayIntent = new Intent(this, DisplayPhotoActivity.class);
    displayIntent.putExtra("BitmapImage", mImageBitmap);
    startActivity(displayIntent);
}

}

Si vous avez spécifié MediaStore.EXTRA_OUTPUT, l'image prise sera écrite dans ce chemin et aucune donnée ne sera donnée à onActivityResult. Vous pouvez lire l'image à partir de ce que vous avez spécifié.

Voir une autre même question résolue ici: Appareil photo Android: l'intention de données renvoie null

16
Jeff Liu

Fondamentalement, il existe deux façons de récupérer l'image à partir de la caméra, si vous utilisez pour envoyer une image capturée via des extras d'intention, vous ne pouvez pas la récupérer sur ActivityResult sur intent.getData () 'car elle enregistre les données d'image via des extras.

L'idée est donc:

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);

Et le récupérer sur ActivityResults vérifiant l'intention récupérée:

    @Override  
    public void onActivityResult(int requestCode, int resultCode, Intent intent) {        
    if (resultCode == RESULT_OK) {            
        if (requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE) {                
            if (intent.getData() != null) {                    
                ParcelFileDescriptor parcelFileDescriptor = context.getContentResolver().openFileDescriptor(intent.getData(), "r");    
                      
                FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();                      
                Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor);                     
                parcelFileDescriptor.close();
            } else {                    
                Bitmap imageRetrieved = (Bitmap) intent.getExtras().get("data");              
            }           
        } 
    }
}
1
Ciro Rizzo

Voici comment vous pouvez réaliser ce que vous voulez:

public void onClick(View v) 
  {

    switch(v.getId())

          {

           case R.id.iBCamera:


            File image = new File(appFolderCheckandCreate(), "img" + getTimeStamp() + ".jpg");
            Uri uriSavedImage = Uri.fromFile(image);

            Intent i = new Intent(Android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
            i.putExtra(MediaStore.EXTRA_OUTPUT, uriSavedImage);
            i.putExtra("return-data", true);
            startActivityForResult(i, CAMERA_RESULT);

            break;

           }
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) 
{

    super.onActivityResult(requestCode, resultCode, data);

    switch(requestCode)

          {

          case CAMERA_RESULT:

                       if(resultCode==RESULT_OK)
                          {
                           handleSmallCameraPhoto(uriSavedImage);     
                          }
                     break;

          }

 }

     private void handleSmallCameraPhoto(Uri uri) 
        {
           Bitmap bmp=null;

              try {
                bmp = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri));
                   } 
                   catch (FileNotFoundException e) 
                   {

                 e.printStackTrace();
                }


               Intent displayIntent = new Intent(this, DisplayPhotoActivity.class);
             displayIntent.putExtra("BitmapImage", bmp);
            startActivity(displayIntent);


       }

private String appFolderCheckandCreate(){

    String appFolderPath="";
    File externalStorage = Environment.getExternalStorageDirectory();

    if (externalStorage.canWrite()) 
    {
        appFolderPath = externalStorage.getAbsolutePath() + "/MyApp";
        File dir = new File(appFolderPath);

        if (!dir.exists()) 
        {
              dir.mkdirs();
        }

    }
    else
    {
      showToast("  Storage media not found or is full ! ");
    }

    return appFolderPath;
}



 private String getTimeStamp() {

    final long timestamp = new Date().getTime();

    final Calendar cal = Calendar.getInstance();
                   cal.setTimeInMillis(timestamp);

    final String timeString = new SimpleDateFormat("HH_mm_ss_SSS").format(cal.getTime());


    return timeString;
}

Modifier:

Ajoutez-les au manifeste:

À partir d'Api 19 et supérieur, READ_EXTERNAL_STORAGE doit être déclaré explicitement

     *<uses-permission Android:name="Android.permission.READ_EXTERNAL_STORAGE" />*
     <uses-permission Android:name="Android.permission.WRITE_EXTERNAL_STORAGE" />

vous manifestez.

0
Mohit

Essayez celui-ci Android.provider.MediaStore.EXTRA_OUTPUT Espère résoudre votre bug. Le code suivant fonctionne pour moi:

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE); 
intent.putExtra(Android.provider.MediaStore.EXTRA_OUTPUT, fileUri); 
startActivityForResult(intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);

J'étais confronté au même problème, chaque fois que j'obtenais la valeur NULL lors de la récupération de données sur une autre activité avec getIntent().getData() puis résolu en écrivant Android.provider.MediaStore.EXTRA_OUTPUT Complet, cela résolvait mon bogue.

0
NomanJaved