taking a photo and placing it in the Gallery

2019-09-18 12:47发布

问题:

I have an app which displays its own subclass of SurfaceView with a camera preview, and has its own capture button. I use Camera.takePicture to take the picture, and in the onPictureTaken callback, feed the image data directly into MediaStore.Images.Media.insertImage. (That seemed simpler than writing the image to file and then adding it to the Gallery, but maybe it's a bad idea.)

And the picture shows up in the Gallery! However, it's at the end of the Gallery, which makes it very hard to find. I'd like it to show up at the beginning of the gallery, just like a picture taken with the regular Camera app.

As far as I can tell, the problem is that the stock Camera app names the files as IMG_YYYYMMDD_[time].jpg, while my photos end up as [unix timestamp].jpg. But I don't know how to tell MediaStore to fix that.

Here is the code:

public void capture() {
    mCamera.takePicture(null, null, mPicture);
}

final PictureCallback mPicture = new PictureCallback() {
    public void onPictureTaken(byte[] data, Camera camera) {
         MediaStore.Images.Media.insertImage(getContentResolver(),
                                             BitmapFactory.decodeByteArray(data, 0, data.length),
                                             null, null);
      }
    };

回答1:

The actual solution was to add date metadata. The final result (which still contains an orientation bug) is

final PictureCallback mPicture = new PictureCallback() {

    public void onPictureTaken(byte[] data, Camera camera) {

        // Create a media file name
        String title = "IMG_"+ new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());

        String DCIM = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).toString();
        String DIRECTORY = DCIM + "/Camera";
        String path = DIRECTORY + '/' + title + ".jpg";

        FileOutputStream out = null;
        try {
            out = new FileOutputStream(path);
            out.write(data);
        } catch (Exception e) {
            Log.e("pictureTaken", "Failed to write data", e);
        } finally {
            try {
                out.close();
            } catch (Exception e) {
                Log.e("pictureTaken", "Failed to close file after write", e);
            }
        }

        // Insert into MediaStore.
        ContentValues values = new ContentValues(5);
        values.put(ImageColumns.TITLE, title);
        values.put(ImageColumns.DISPLAY_NAME, title + ".jpg");
        values.put(ImageColumns.DATE_TAKEN, System.currentTimeMillis());
        values.put(ImageColumns.DATA, path);
        // Clockwise rotation in degrees. 0, 90, 180, or 270.
        values.put(ImageColumns.ORIENTATION, activity.getWindowManager().getDefaultDisplay()
                .getRotation() + 90);

        Uri uri = null;
        try {
            uri = activity.getContentResolver().insert(Images.Media.EXTERNAL_CONTENT_URI, values);
        } catch (Throwable th)  {
            // This can happen when the external volume is already mounted, but
            // MediaScanner has not notify MediaProvider to add that volume.
            // The picture is still safe and MediaScanner will find it and
            // insert it into MediaProvider. The only problem is that the user
            // cannot click the thumbnail to review the picture.
            Log.e("pictureTaken", "Failed to write MediaStore" + th);
        }
      }
    };