拍照后相机未保存照片

7
我可以按下按钮,打开本机相机应用程序并成功拍照。但是,当我检查手机上的“图库”或“照片”应用程序时,图片没有保存在那里。我对Android非常陌生,所以我的代码中可能缺少重要部分。
问题:
1)这些照片被保存在哪里?
2)我是否能修改下面的代码以保存到内部存储,以便所有由我的应用程序拍摄的照片都是私有的,并且只能通过我的应用程序访问?
3)如果我想将这些图片与一些文本或其他输入保存到一个对象中,最好的方法是什么?我应该只保存一个`Uri`或某个标识符以后引用该图像,还是保存实际的`BitMap`图像?
非常感谢您的帮助!这是我拍照的代码:
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);
    }
}

下面是直接从Google开发者指南中摘取的CameraUtils类:

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;
}

仅仅拥有相机权限对我来说无法实现保存功能... 当我在相机权限旁边添加了WRITE_EXTERNAL_STORAGE权限时,它才能正常工作。https://developer.android.com/training/data-storage#permissions - Kidus Tekeste
1个回答

5

1) 从代码来看,我预期图片应该保存在设备外部存储的Pictures文件夹下面的一个名为'camera'的目录中。这些图片可能不会立即出现在您的相册中,但在Android的较新版本(Kitkat和也许是jelly-bean,尽管我不能立即验证)中,您应该能够打开照片应用程序并在其中找到它们。如果不是这种情况,则启动一个文件浏览器应用程序(例如ASTRO File Manager或X-Plore)并浏览到Pictures/camera目录,您将在其中看到您的图像。下次您的媒体重新索引(手机重新启动或从其他地方触发的重新索引)时,您应该能够在您的相册/照片应用程序中看到这些图片。如果您想要以编程方式刷新媒体,这里可能有所帮助。最后,请确保您在Android清单中具有READ_EXTERNAL_STORAGE权限,如此文档中所述。

2) 如果您想要保存只供您的应用程序使用的图像,则需要将它们保存在您的应用程序的内部数据目录中。从Android文档中直接查看这里。确保使用MODE_PRIVATE标志。

3) 对于这个问题,您需要将文件路径存储在应用程序可以访问的某个位置。您可以将文件路径与其他文本数据保存到文本文件中,也可以使用sqlite数据库。最后,您可以使用像ORMLite for Android这样的ORM来保存可能包含要持久化的字段(标题、描述、路径等)的图片数据的Java对象。这里这里是有关如何在Android中开始使用SQLite数据库的介绍(直接来自官方文档)。如果您想使用ORMLite,则可以在他们的网站这里上找到大量信息。该开发者花了很多时间回答StackOverflow的问题。

您的所有问题都可以通过一些简单的谷歌搜索来解决。它们是Android中非常标准和基本的操作,因此您应该能够在网上找到大量的信息和教程。

编辑

针对您关于第二个问题的评论。这就是我可能会做的(或类似的事情):

请注意,我没有测试过这个。它来自我的头脑。如果您有更多问题,请在此处发表评论!

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类的代码...

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();
}

现在你有了指向内部存储图像的路径,然后可以从onActivityResult中操作/加载该图像。


1
你的Android清单文件中是否包含以下三个权限?<uses-feature android:name="android.hardware.camera" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> 实际上,你只需要写入权限来保存图片(我相信还需要相机功能)。但通常也会包括读取权限,因为你可能也需要它。
- maraci
1
啊,我想我知道问题出在哪里了。我真傻,没早点意识到这个问题。发生的情况是相机应用程序无法保存到您的内部URI(显然不可能..)。在我的应用程序中,我通过相机意图传递指向外部存储的URI(就像您以前所做的那样),然后在我的onActivityResult中,我打开文件并使用基本的Java IO将其保存到我的应用程序的内部文件夹中。我会编辑我的答案。 - maraci
2
关于权限,使用MediaStore.ACTION_IMAGE_CAPTURE意图时不需要相机权限。 - Alex Cohn
1
@AlexCohn 您是正确的。我对那个评论有误,进行了一些测试和阅读后,现在意识到这一点。谢谢! - maraci
1
是的,抱歉我忘记在onClick方法中进行更改了。 - maraci
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接