Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
570 views
in Technique[技术] by (71.8m points)

android - Camera is not saving after taking picture

I can press a button, open up the native camera app, and successfully take a picture. But then when I check the Gallery or Photos native apps on my phone, the picture isn't saved there. I'm very new to Android so it's likely I'm missing something important in my code.

Questions:

1) Where are these pictures being saved?

2) Can I modify the below code somehow to save instead to internal storage, so all pictures taken with my app are private and only accessible through my app?

3) If I wanted to save these pictures to an object, along with some text/other input, what would be the best way? Should I just save a Uri or some identifier to reference the image later, or save the actual BitMap image?

Any help is greatly appreciated, thanks!

Here is my code to take the picture:

mImageButton.setOnClickListener(new View.OnClickListener()
{
    public void onClick(View v)
    {
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        imageUri = CameraUtils.getOutputMediaFileUri(CameraUtils.MEDIA_TYPE_IMAGE);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
        startActivityForResult(intent, REQUEST_IMAGE);
    }
}

CameraUtils class taken straight from Google developer guides:

public static Uri getOutputMediaFileUri(int type)
{
    return Uri.fromFile(getOutputMediaFile(type));
}

public static File getOutputMediaFile(int type)
{
    File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
            Environment.DIRECTORY_PICTURES), "camera");

    if (!mediaStorageDir.exists())
    {
        if (!mediaStorageDir.mkdirs())
        {
            return null;
        }
    }

    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 if(type == MEDIA_TYPE_VIDEO)
    {
        mediaFile = new File(mediaStorageDir.getPath() + File.separator +
                "VID_" + timeStamp + ".mp4");
    }
    else
    {
        return null;
    }

    return mediaFile;
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

1) By looking at the code, I'd expect the pictures to be saved in a directory called 'camera' which would be found in the Pictures folder on your device (external storage). These might not instantly appear in your gallery, however in later versions of Android (Kitkat and maybe jelly-bean though I can't verify that right now) you should be able to open the Photos app and find them somewhere in there. If that is not the case, then launch a file explorer app (example apps are ASTRO File Manager or X-Plore) and browse to the Pictures/camera directory where you should see your images. The next time your media gets re-indexed (phone reboot, or a re-index triggered from elsewhere), you should see these pictures in your gallery/photo apps. If you want to refresh your media programatically, here might help. Finally, make sure you have the READ_EXTERNAL_STORAGE permission in your Android manifest as specified this (Android doc).

2) If you want to save images to be only available to your application, you need to save them to your application's internal data directory. Take a look at this straight from the Android doc. Make sure to use the MODE_PRIVATE flag.

3) For this, you would want to store the file path somewhere accessible to your app. Either you could save your file paths to a text file with some other text data, or you could use a sqlite database. Finally, you could use an ORM like ORMLite for Android to save a java object which might hold data for your picture and have some fields you want to persist (title, description, path, etc). Here and here is an intro on how to get started with SQLite database in Android (straight from the official doc). If you want to use ORMLite, there is plenty of information on their site here. The developer has spent a lot of time answering StackOverflow questions..

All of your questions can be answered with a few simple Google searches. They are very standard and basic things to do in Android, so you should be able to find a plethora of information and tutorials online.

EDIT:

In response to your comment about the second question. This is what I would probably do (or something similar):

Note that I didn't test this. It's from the top of my head. If you have more issues comment here!

Activity code...

mImageButton.setOnClickListener(new View.OnClickListener()
{
    public void onClick(View v)
    {
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        imageUri = CameraUtils.getOutputMediaFileUri(currentActivity, CameraUtils.MEDIA_TYPE_IMAGE);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
        startActivityForResult(intent, REQUEST_IMAGE);
    }
}

public void onActivityResult(int requestCode, int resultCode, Intent data)
{
    if (requestCode == REQUEST_IMAGE)
    {
        if (resultCode == RESULT_OK)
        {
            String pathToInternallyStoredImage = CameraUtils.saveToInternalStorage(this, imageUri);
            // Load the bitmap from the path and display it somewhere, or whatever
        }
        else if (resultCode == RESULT_CANCELED)
        {
            //Cancel code
        }
    }
}

CameraUtils class code...

public static Uri getOutputMediaFileUri(int type)
{
    return Uri.fromFile(getOutputMediaFile(type));
}

public static File getOutputMediaFile(int type)
{
    File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
            Environment.DIRECTORY_PICTURES), "camera");

    createMediaStorageDir(mediaStorageDir);

    return createFile(type, mediaStorageDir);
}

private static File getOutputInternalMediaFile(Context context, int type)
{
    File mediaStorageDir = new File(context.getFilesDir(), "myInternalPicturesDir");

    createMediaStorageDir(mediaStorageDir);

    return createFile(type, mediaStorageDir);
}

private static void createMediaStorageDir(File mediaStorageDir) // Used to be 'private void ...'
{
    if (!mediaStorageDir.exists())
    {
        mediaStorageDir.mkdirs(); // Used to be 'mediaStorage.mkdirs();'
    }
} // Was flipped the other way

private static File createFile(int type, File mediaStorageDir ) // Used to be 'private File ...'
{
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    File mediaFile = null;
    if (type == MEDIA_TYPE_IMAGE)
    {
        mediaFile = new File(mediaStorageDir .getPath() + File.separator +
                "IMG_" + timeStamp + ".jpg");
    }
    else if(type == MEDIA_TYPE_VIDEO)
    {
        mediaFile = new File(mediaStorageDir .getPath() + File.separator +
                "VID_" + timeStamp + ".mp4");
    }
    return mediaFile;
}

public static String saveToInternalStorage(Context context, Uri tempUri)
{
    InputStream in = null;
    OutputStream out = null;

    File sourceExternalImageFile = new File(tempUri.getPath());
    File destinationInternalImageFile = new File(getOutputInternalMediaFile(context).getPath());

    try
    {
        destinationInternalImageFile.createNewFile();

        in = new FileInputStream(sourceExternalImageFile);
        out = new FileOutputStream(destinationInternalImageFile);

        // Transfer bytes from in to out
        byte[] buf = new byte[1024];
        int len;
        while ((len = in.read(buf)) > 0)
        {
            out.write(buf, 0, len);
        }
    }
    catch (IOException e)
    {
        e.printStackTrace();
        //Handle error
    }
    finally
    {
        try {
            if (in != null) {
                in.close();
            }
            if (out != null) {
                in.close();
            }
        } catch (IOException e) {
            // Eh
        }
    }
    return destinationInternalImageFile.getPath();
}

So now you have the path pointing to your internally stored image, which you can then manipulate/load from your onActivityResult.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...