简体   繁体   English

通过使用FileProvider for Android 7.1.1拍照后,我无法将文件保存到图库

[英]I can't save file to gallery after taking photo by camera by using the FileProvider for Android 7.1.1

I build my app with FileProvider and I want to save the image after I take it. 我使用FileProvider构建我的应用程序,我想在我拿它之后保存图像。 But I can't find the image in the gallery. 但我无法在画廊中找到图像。 I found these source codes from the Android Studio tutorial. 我在Android Studio教程中找到了这些源代码。 I don't know what is the problem. 我不知道是什么问题。 I tried use debugger and I think the createFile() is correct. 我尝试使用调试器,我认为createFile()是正确的。 I also have my bitmap works. 我也有我的位图工作。 It can display the image I take but I can't add the image to the gallery. 它可以显示我拍摄的图像,但我无法将图像添加到图库。

I have this in my Manifest.xml 我在Manifest.xml中有这个

<provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="com.temp.test"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths"/>
</provider>

And in the file_paths.xml I have 在我有的file_paths.xml中

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
       <external-path name="external" path="Android/data/com.temp.test/files/Pictures" />
</paths>

This is how I write the activity 这就是我写活动的方式

private String mCurrentPhotoPath;
private ImageView mImageView;
private ImageButton StartCameraBtn;
private File photoFile = null;

//requestCode
private static final int REQUEST_IMAGE_CAPTURE = 1;

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_photo_note);

    mImageView = (ImageView) findViewById(R.id.imageView);

    StartCameraBtn = (ImageButton) findViewById(R.id.StartCamera);

    StartCameraBtn.setOnClickListener(this);
}
public void onClick(View view)
{
    clearAllFocus();
    switch (view.getId())
    {
        case R.id.StartCamera:
            Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            if (takePictureIntent.resolveActivity(getPackageManager()) != null)
            {
                try
                {
                    photoFile = createFile();
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
                if(photoFile != null){
                    Uri photoURI = FileProvider.getUriForFile(this,
                            "com.temp.test",
                            photoFile);
                    takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
                    startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
                }
            }
            break;
...
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
    mImageView.setImageBitmap(null);

    switch (requestCode)
    {
        case REQUEST_IMAGE_CAPTURE:
            if (resultCode == RESULT_OK)
            {
                setPic();
                galleryAddPic();
            }
            break;
    }
}
private File createFile() throws IOException
{
    // Create an image file name
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    String imageFileName = "JPEG_" + timeStamp + "_";
    File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
    File image = File.createTempFile(
            imageFileName,  /* prefix */
            ".jpg",         /* suffix */
            storageDir      /* directory */
    );

    // Save a file: path for use with ACTION_VIEW intents
    mCurrentPhotoPath = image.getAbsolutePath();
    return image;
}

private void galleryAddPic()
{
    Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
    File f = new File(mCurrentPhotoPath);
    Uri contentUri = Uri.fromFile(f);
    mediaScanIntent.setData(contentUri);
    this.sendBroadcast(mediaScanIntent);
}
private void setPic()
{
    // Get the dimensions of the View
    int targetW = mImageView.getWidth();
    int targetH = mImageView.getHeight();

    // Get the dimensions of the bitmap
    BitmapFactory.Options bmOptions = new BitmapFactory.Options();
    bmOptions.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
    int photoW = bmOptions.outWidth;
    int photoH = bmOptions.outHeight;

    // Determine how much to scale down the image
    int scaleFactor = Math.min(photoW/targetW, photoH/targetH);

    // Decode the image file into a Bitmap sized to fill the View
    bmOptions.inJustDecodeBounds = false;
    bmOptions.inSampleSize = scaleFactor;
    bmOptions.inPurgeable = true;

    Bitmap bitmap = BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
    mImageView.setImageBitmap(bitmap);
}

Please help! 请帮忙! Thank you! 谢谢!

I use debugger to test the galleryaddpic() and the URI has been accessed sucessfully, but I don't know why I can't add it to the gallery. 我使用调试器来测试galleryaddpic()并且已经成功访问​​了URI,但我不知道为什么我无法将它添加到库中。 I can't find the image file in the android VM directory either. 我也找不到android VM目录中的图像文件。 This is the debug log: 这是调试日志:

https://i.stack.imgur.com/JN9uJ.png https://i.stack.imgur.com/JN9uJ.png

I'm using chickendinner as my domian, and keep is the name of my app. 我正在使用chickendinner作为我的domian,而keep是我的应用程序的名称。

Thank you! 谢谢!

Your code handles 你的代码处理

  • write new photo as a jpg-file to the filesystem 将新照片作为jpg文件写入文件系统
  • add new photo to media-db via broadcst Intent.ACTION_MEDIA_SCANNER_SCAN_FILE 通过broadcst Intent.ACTION_MEDIA_SCANNER_SCAN_FILE将新照片添加到media-db
  • create a FileProvider that allow other apps to access private //Android/data/com.temp.test/files/Pictures/... files through a content-uri content://com.temp.test/... 创建一个FileProvider ,允许其他应用程序通过content-uri content://com.temp.test/...访问私人//Android/data/com.temp.test/files/Pictures/...文件content://com.temp.test/...

I assume that the media-db scanner has no read-permission to your app-s private data directory Android/data/com.temp.test/files/Pictures via a file-uri and therefore cannot add the new photo to media-db. 我假设media-db扫描程序没有对你的应用程序的私有数据目录Android/data/com.temp.test/files/Pictures通过文件uri的读取权限,因此无法将新照片添加到media-db 。

Whatsapp and other apps store their received/send photo in public readable internal memory (ie /sdcard/PICTURES/WhatsApp/ ) where the media scanner can read it via file-uri via Intent.ACTION_MEDIA_SCANNER_SCAN_FILE . Whatsapp和其他应用程序将他们收到/发送的照片存储在公共可读的内部存储器(即/ sdcard / PICTURES / WhatsApp /)中,媒体扫描器可以通过文件uri通过Intent.ACTION_MEDIA_SCANNER_SCAN_FILE读取它。

I donot know, if the media scanner can handle content: -uris instead of file uri-s : You can try this: 我不知道,如果媒体扫描仪可以处理content: -uris而不是file uri-s :你可以试试这个:

private void galleryAddPic()
{
    Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
    // assume that mCurrentPhotoPath ="Android/data/com.temp.test/files/Pictures/myTestImage.jpg"
    // can be accessed from outside as "content://com.temp.test/myTestImage.jpg"
    Uri contentUri = Uri.parse("content://com.temp.test/myTestImage.jpg");
    mediaScanIntent.setData(contentUri);
    this.sendBroadcast(mediaScanIntent);
}

Please let us know if this works. 如果有效,请告诉我们。

If this does not work you can try to manually insert a "content://com.temp.test/..." entry into media database. 如果这不起作用,您可以尝试手动将“content://com.temp.test / ...”条目插入媒体数据库。


using public readable internal memory directories should work without a fileprovider 使用public readable internal memory directories应该没有fileprovider

Call this function in onActivityResult. 在onActivityResult中调用此函数。 It worked for me! 它对我有用!

It is in fragment.In activity you can use "this" instead of "getActivity()". 它位于fragment.In活动中,您可以使用“this”而不是“getActivity()”。

private void galleryAddPic() {
        File f = new File(imageFilePath); //set your picture's path

        try {
            MediaStore.Images.Media.insertImage(getActivity().getContentResolver(),
                    f.getAbsolutePath(), f.getName(), null);
            getActivity().sendBroadcast(new Intent(
                    Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(f)));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM