Reputation: 3049
Since I had bugs on different devices I decided to changed the whole open camera and save picture code. I have used the exact same code in the Android tutorial.
My code:
private static File createImageFile(Activity activity) throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = activity.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
// Save a file: path for use with ACTION_VIEW intents
photoPath = image.getAbsolutePath();
return image;
}
private static void dispatchTakePictureIntent(Activity activity) {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(activity.getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = MainActivity.createImageFile(activity);
} catch (IOException ex) {
// Error occurred while creating the File
}
// Continue only if the File was successfully created
if (photoFile != null) {
imageUri = FileProvider.getUriForFile(activity,
"com.APPPACKAGE.fileprovider",
photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
activity.startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
}
}
}
On the manifest file:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="18" />
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.APPPACKAGE.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths"/>
</provider>
Using this works great on a Android 6 Marshmallow, on Android 4.4 Kitkat it doesn't. On Kitkat my onActivityResult
i recieve from the camera result = 0
which is RESULT_CANCELLED
.
I've checked if the camera was able to save the photo on the location specified in the file_paths.xml
and it didn't. this folder is filled with 0 bytes files.
What can i do to fix it?
Upvotes: 0
Views: 178
Reputation: 3049
Thanks to @CommonsWare i added this code and it works:
if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP) {
takePictureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
}
else if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.JELLY_BEAN) {
ClipData clip=
ClipData.newUri(activity.getContentResolver(), "A photo", imageUri);
takePictureIntent.setClipData(clip);
takePictureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
}
else {
List<ResolveInfo> resInfoList=
activity.getPackageManager()
.queryIntentActivities(takePictureIntent, PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo resolveInfo : resInfoList) {
String packageName = resolveInfo.activityInfo.packageName;
activity.grantUriPermission(packageName, imageUri,
Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
}
}
Upvotes: 0
Reputation: 1007554
Not all camera apps will support content
as a scheme for the EXTRA_OUTPUT
Uri
. Google's own camera app did not support it until the summer of 2016, for example. And, since we are passing the Uri
via an extra, we have no means of limiting ourselves to camera apps that support content
.
Your main options are:
Reduce your targetSdkVersion
below 24 and stick with Uri.fromFile()
, rather than using FileProvider
Use StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().build());
to disable the FileUriExposedException
, then stick with Uri.fromFile()
, rather than using FileProvider
Scrap your use of ACTION_IMAGE_CAPTURE
entirely, switching to the camera APIs directly or via some helper library (e.g., mine)
Tactically, you might get better results if you use setClipData()
to force granting of permissions on your Uri
.
Upvotes: 1