相机意图不保存照片

sga*_*man 19 android android-camera-intent

我以前成功使用过此代码片段,但文件指向SD卡上的某个位置.

final File temp = new File(getCacheDir(), "temp.jpg");
temp.delete();
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(temp));
startActivityForResult(intent, CONFIG.Intents.Actions.SELECT_CAMERA_PHOTO);
Run Code Online (Sandbox Code Playgroud)

但是,当我使用getCacheDir而不是SD卡上的loc时,似乎从未保存过照片.这是缓存目录和图像捕获的限制吗?

Dev*_*red 41

从技术上讲,这是因为使用Camera应用程序捕获图像时不支持写入内部存储.实际上,您可能会注意到logcat中打印的异常Writing to internal storage is not supported.但是,这不起作用的真正原因是因为默认情况下您正在创建一个专用于您的应用程序包的文件而另一个应用程序(即Camera应用程序)无法访问该文件位置,因为它没有权限这样做.外部存储是文件系统中唯一的全局可访问部分.

解决方法是您使用全局(WORLD_WRITEABLE)权限创建文件.通常,这允许Camera应用程序通过传递的Uri访问文件.没有真正的方法可以直接执行此操作File,因此您必须使用可用的方法创建文件Context,然后抓取它的句柄:

//Remove if exists, the file MUST be created using the lines below
File f = new File(getFilesDir(), "Captured.jpg");
f.delete();
//Create new file
FileOutputStream fos = openFileOutput("Captured.jpg", Context.MODE_WORLD_WRITEABLE);
fos.close();
//Get reference to the file
File f = new File(getFilesDir(), "Captured.jpg");
Run Code Online (Sandbox Code Playgroud)

这也限制了您放置文件的位置,因为这些Context方法固有地在根"files"目录中创建文件,并且您无法将其重定向到缓存目录.

HTH

  • 从[here](http://developer.android.com/reference/android/content/Context.html):**MODE_WORLD_WRITEABLE这个常量在API级别17中已弃用.创建世界可写文件非常危险,可能会导致应用程序出现安全漏洞 强烈劝阻;** (6认同)

Har*_*rry 27

我发现的最佳解决方案是:FileProvider(需要support-library-v4)
它使用内部存储! https://developer.android.com/reference/android/support/v4/content/FileProvider.html

  1. 在Application元素中的Manifest中定义FileProvider:

    <provider
          android:name="android.support.v4.content.FileProvider"
          android:authorities="your.package.name.fileprovider"
          android:exported="false"
          android:grantUriPermissions="true" >
          <meta-data
                     android:name="android.support.FILE_PROVIDER_PATHS"
                     android:resource="@xml/image_path" />
    </provider>
    
    Run Code Online (Sandbox Code Playgroud)
  2. 如果必须,将相机功能添加到AndroidManifest.xml的根元素:

    <uses-feature android:name="android.hardware.camera"
    android:required="true" />
    
    Run Code Online (Sandbox Code Playgroud)
  3. 在res/xml/image_path.xml中定义映像路径:

    <paths xmlns:android="http://schemas.android.com/apk/res/android">
    <files-path name="captured_image" path="your/path/"/>
    </paths>
    
    Run Code Online (Sandbox Code Playgroud)
  4. Java的:

    private static final int IMAGE_REQUEST_CODE = 1;
    // your authority, must be the same as in your manifest file 
    private static final String CAPTURE_IMAGE_FILE_PROVIDER = "your.package.name.fileprovider";
    
    Run Code Online (Sandbox Code Playgroud)

4.1捕获意图:

    File path = new File(activity.getFilesDir(), "your/path");
    if (!path.exists()) path.mkdirs();
    File image = new File(path, "image.jpg");
    Uri imageUri = FileProvider.getUriForFile(activity, CAPTURE_IMAGE_FILE_PROVIDER, image);
    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
    startActivityForResult(intent, IMAGE_REQUEST_CODE);
Run Code Online (Sandbox Code Playgroud)

4.2 onActivityResult():

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent intent) {
        if (requestCode == IMAGE_REQUEST_CODE) {
            if (resultCode == Activity.RESULT_OK) {
                File path = new File(getFilesDir(), "your/path");
                if (!path.exists()) path.mkdirs();
                File imageFile = new File(path, "image.jpg");
                // use imageFile to open your image
            }
        }
        super.onActivityResult(requestCode, resultCode, intent);
    }
Run Code Online (Sandbox Code Playgroud)