2

Since I have migrated my app to Android N with FileProvider, I can't see my pictures in phone's gallery (even with version below Android N). So I created a small test app to debug this, without success.

In my Manifest

<uses-permission android:name="android.permission.CAMERA"/>
<uses-feature android:name="android.hardware.camera"/>

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MANAGE_DOCUMENTS"/>

<application
    ...>
    ...


    <provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="${applicationId}.fileprovider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths"></meta-data>
    </provider>
</application>

In file_paths.xml

<paths>
<external-files-path
    name="test_images"
    path="Pictures/TestPictures"/>
</paths>

And I made a small activity that shows last taken picture, to make sure that URI is correct :

private final static int REQUEST_CAMERA = 1102;
public static final String CAMERA_IMAGES_DIR = "TestPictures";
String mOutputFilePath;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            onCamera();
        }
    });
}

public void onCamera() {
    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    if (intent.resolveActivity(getPackageManager()) != null) {
        File photoFile = createImageFile();
        Uri photoURI = FileProvider.getUriForFile(this,
                getPackageName() + ".fileprovider",
                photoFile);
        mOutputFilePath = photoFile.getAbsolutePath();
        intent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
        startActivityForResult(intent, REQUEST_CAMERA);
    }
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == Activity.RESULT_OK && requestCode == REQUEST_CAMERA)
        onCaptureImageResult();
}

private void onCaptureImageResult() {
    if (mOutputFilePath != null) {
        File f = new File(mOutputFilePath);
        Uri finalUri = Uri.fromFile(f);
        galleryAddPic(finalUri);
        ((ImageView) findViewById(R.id.imageView)).setImageURI(finalUri);
    }
}

public File createImageFile() {
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    String imageFileName = "JPEG_" + timeStamp + "_";
    File storageDir = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), CAMERA_IMAGES_DIR + "/");
    if (!storageDir.exists())
        storageDir.mkdir();
    return new File(storageDir, imageFileName + ".jpg");
}

private void galleryAddPic(Uri contentUri) {
    Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, contentUri);
    sendBroadcast(mediaScanIntent);
}

My picture is in my app and in my file browser like expected but I can't see it in photo gallery. I tried to use FileProvider Uri, that's not works too.

A. Ferrand
  • 618
  • 6
  • 19
  • 1
    https://stackoverflow.com/questions/32789157/how-to-write-files-to-external-public-storage-in-android-so-that-they-are-visibl – CommonsWare Apr 10 '17 at 11:24
  • The way to add my photo in the gallery wasn't the problem, but I noticed the directory used in the thread you shared and it helps me to found the solution, thx. – A. Ferrand Apr 10 '17 at 13:48

1 Answers1

4

The problems seems to be the location of the file to add to gallery and not the way to add it.

getExternalFilesDir(Environment.DIRECTORY_PICTURES) doesn't work for media scan but Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) does. However, we can't use the last one with FileProvider, so I need to create a copy of the taken picture in the public directory.

I update my code like :

private void onCaptureImageResult() {
    if (mOutputFilePath != null) {
        File f = new File(mOutputFilePath);
        try {
            File publicFile = copyImageFile(f);
            Uri finalUri = Uri.fromFile(publicFile);
            galleryAddPic(finalUri);
            ((ImageView) findViewById(R.id.imageView)).setImageURI(finalUri);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

public File copyImageFile(File fileToCopy) throws IOException {
    File storageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), CAMERA_IMAGES_DIR + "/");
    if (!storageDir.exists())
        storageDir.mkdir();
    File copyFile = new File(storageDir, fileToCopy.getName());
    copyFile.createNewFile();
    copy(fileToCopy, copyFile);
    return copyFile;
}

public static void copy(File src, File dst) throws IOException {
    InputStream in = new FileInputStream(src);
    OutputStream out = new FileOutputStream(dst);
    byte[] buf = new byte[1024];
    int len;
    while ((len = in.read(buf)) > 0) {
        out.write(buf, 0, len);
    }
    in.close();
    out.close();
}
A. Ferrand
  • 618
  • 6
  • 19