Permission Denial: MediaDocumentsProvider - java

I am getting the following exception when trying to display a URI. I think it occurs after my activity is stopped and I try to access a viable URI again. There are other questions addressing this problem but I am very confused as to how to apply any solutions to my code since my takePhotoIntent allows for a picture to either be taken or chosen from gallery (found below).
Unable to open content: content://com.android.providers.media.documents/document/image%3A49688
java.lang.SecurityException: Permission Denial: reading com.android.providers.media.MediaDocumentsProvider uri
content://com.android.providers.media.documents/document/image%3A49688 from pid=821, uid=10238 requires android.permission.MANAGE_DOCUMENTS, or grantUriPermission()
My createImageFile and my takePhotoIntent:
private File createImageFile() 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 = "file:" + image.getAbsolutePath();
return image;
}
private void dispatchTakePictureIntent() {
for(int i = 0; i < 4; i++) {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
outputFileUri = Uri.fromFile(photoFile);
} catch (IOException ex) {
Log.w("error","IOException");
}catch (NullPointerException nullEx) {
Log.w("error","NullPointerException");
}
// Camera.
final List<Intent> cameraIntents = new ArrayList<Intent>();
final Intent captureIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
final PackageManager packageManager = getPackageManager();
final List<ResolveInfo> listCam = packageManager.queryIntentActivities(captureIntent, 0);
for (ResolveInfo res : listCam) {
final String packageName = res.activityInfo.packageName;
final Intent intent = new Intent(captureIntent);
intent.setComponent(new ComponentName(res.activityInfo.packageName, res.activityInfo.name));
intent.setPackage(packageName);
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
cameraIntents.add(intent);
}
// Filesystem.
final Intent galleryIntent = new Intent();
galleryIntent.setType("image/*");
galleryIntent.setAction(Intent.ACTION_GET_CONTENT);
// Chooser of filesystem options.
final Intent chooserIntent = Intent.createChooser(galleryIntent, "Select Source");
// Add the camera options.
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, cameraIntents.toArray(new Parcelable[cameraIntents.size()]));
if(id.equals(HAPPY_ID))
startActivityForResult(chooserIntent, REQUEST_HAPPY_PHOTO);
if(id.equals(SURPRISED_ID))
startActivityForResult(chooserIntent, REQUEST_SURPRISED_PHOTO);
if(id.equals(AFRAID_ID))
startActivityForResult(chooserIntent, REQUEST_AFRAID_PHOTO);
if(id.equals(UPSET_ID))
startActivityForResult(chooserIntent, REQUEST_UPSET_PHOTO);
if(id.equals(SAD_ID))
startActivityForResult(chooserIntent, REQUEST_SAD_PHOTO);
}
}
}

Per the Storage Access Framework client documentation:
Use ACTION_GET_CONTENT if you want your app to simply read/import data. With this approach, the app imports a copy of the data, such as an image file.
Use ACTION_OPEN_DOCUMENT if you want your app to have long term, persistent access to documents owned by a document provider. An example would be a photo-editing app that lets users edit images stored in a document provider.
As you are using ACTION_GET_CONTENT, your access to the Uri ends when the component is destroyed (unless you pass the Uri to a new component). You must make a copy of the file from the Uri if you'd like to continue to access it beyond the lifetime of your component or switch to ACTION_OPEN_DOCUMENT and persist permissions (possible only with document Uris).

Related

How to capture photo with existing camera app in android?

I need to take photo using existing camera app and store it. I took this code from here
private File createImageFile() 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
currentPhotoPath = image.getAbsolutePath();
return image;
}
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
// Error occurred while creating the File
...
}
// Continue only if the File was successfully created
if (photoFile != null) {
Uri photoURI = FileProvider.getUriForFile(this,
"com.example.android.fileprovider",
photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
}
}
The problem with this code is
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
is depreciated
Once i enter the camera app a file is created even if the picture is not taken
What changes should i make so that a file will be created only when an image is captured in the camera app?

How to get my saved photos in this file manager in Android Studio

I have some issues with my application, I have code that opening camera and saving taked photos but, i can't locate them when i'm using file manager. Can someone help me?
This is, my code to take photos:
cameraBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mPhotoUri = FileProvider.getUriForFile(MainActivity.this, BuildConfig.APPLICATION_ID + ".provider", createImageFile());
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.setClipData(ClipData.newRawUri("A photo", mPhotoUri));
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
intent.putExtra(MediaStore.EXTRA_OUTPUT, mPhotoUri);
startActivityForResult(intent, ACTIVITY_REQUEST_CODE);
}
});
private File createImageFile() {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = new File(getFilesDir(), "images/");
if (!storageDir.exists()) storageDir.mkdirs();
File image = null;
try {
image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
} catch (IOException e) {
e.printStackTrace();
}
// Save a file: path for use with ACTION_VIEW intents
mCurrentPhotoPath = "file:" + image.getAbsolutePath();
return image;
}
This staff saves photos in: /data/data/com.example.miarkait/files/images
And this is code that opening file manager:
imageBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(Intent.ACTION_GET_CONTENT, android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI);
final int ACTIVITY_SELECT_IMAGE = 1234;
startActivityForResult(i, ACTIVITY_SELECT_IMAGE);
}
});
But in this manager, i can see only photos taken by "original" camera:
RESULT
File(getFilesDir()....
getFilesDir() is your app private storage location.
No other app has access.
Not even file managers.
And you cannot pick it with ACTION_GET_CONTENT.

getExternalStoragePublicDirectory not working, while getExternalFilesDir is

I've managed to finally make the code from Android Developer website work.
The original working code is this:
private File createImageFile() 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 dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
// Error occurred while creating the File
}
// Continue only if the File was successfully created
if (photoFile != null) {
Uri photoURI = FileProvider.getUriForFile(this,
"com.test.testapp.fileprovider",
photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
}
}
}
It's working, this app launches the camera and takes pictures, but when I changed the part "getExternalFilesDir" to "getExternalStoragePublicDirectory", the button doesn't launch the camera app

Saving camera pictures in emulated genymotion not working

I am not able to save pictures in sdcard using Genymotion emulator.
Code for creating the file for the image
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
//File storageDir = Environment.getExternalStoragePublicDirectory(
//Environment.DIRECTORY_PICTURES);
File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
mCurrentPhotoPath = "file:" + image.getAbsolutePath();
// Save a file: path for use with ACTION_VIEW intents
Toast.makeText(AddPhotoActivity.this, mCurrentPhotoPath + "file", Toast.LENGTH_SHORT).show();
return image;
}
The above function is not returning anything. Below function is for Initiating camera intent and click picture.
private void dispatchTakePictureIntent() {
// Toast.makeText(AddPhotoActivity.this, "Hello", Toast.LENGTH_SHORT).show();
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
// Error occurred while creating the File
}
// Continue only if the File was successfully created
if (photoFile != null) {
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(photoFile));
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
}
}
}
The problem is something in File.createTempFile() function I guess.

How to add a new directory to android gallery app

So I am trying to have a directory added to the stock android gallery app, and I can't get it to work. I tried the Stock android approach for that, I have also tried the way that is supplied via AOSP and neither have worked. How might I create a new directory, take a new picture and add it to the gallery. I have the photo saving and everything wokring it's just getting it to display in the Gallery app that isn't working
The way google says to add photos to the gallery is the following way....
private void galleryAddPic() {
Intent mediaScanIntent = new Intent("android.intent.action.MEDIA_SCANNER_SCAN_FILE");
File f = new File(mCurrentPhotoPath);
Uri contentUri = Uri.fromFile(f);
mediaScanIntent.setData(contentUri);
this.sendBroadcast(mediaScanIntent);
}
I personally have it set up for
private void galleryAddPic() {
Intent mediaScanIntent = new Intent("android.intent.action.MEDIA_SCANNER_SCAN_FILE");
File f = new File(mCurrentPhotoPath);
Uri contentUri = Uri.fromFile(f);
mediaScanIntent.setData(contentUri);
Config.context.sendBroadcast(mediaScanIntent);
}
where Config.context is initialized in MainActivity to getApplicationContext();
So I changed my function to the following
private void galleryAddPic(String Location) {
Intent mediaScanIntent = new Intent("android.intent.action.MEDIA_SCANNER_SCAN_FILE");
File f = new File(Location);
Uri contentUri = Uri.fromFile(f);
mediaScanIntent.setData(contentUri);
getActivity().sendBroadcast(mediaScanIntent);
}
And to call the function
galleryAddPic(image.getAbsolutePath());
where image is a File
Not the way I had it
galleryAddPic("file:"+image.getAbsolutePath());

Categories