I tried to take a photo and then to use the photo. Here is what I did.
My device was Nexus 6P (Android 7.1.1).
First, I created a Uri
:
Uri mPicPath = UriUtil.fromFile(this, UriUtil.createTmpFileForPic());
//Uri mPicPath = UriUtil.fromFile(this, UriUtil.createFileForPic());
And then, I started Intent
:
Intent intent = ActivityUtils.getTakePicIntent(mPicPath);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(intent, RequestCode.TAKE_PIC);
}
At last, I handled this Uri
on onActivityResult
:
if (requestCode == RequestCode.TAKE_PIC) {
if (resultCode == RESULT_OK && mPicPath != null) {
Bitmap requireBitmap = BitmapFactory.decodeFile(mPicPath.getPath());
//path is like this: /Download/Android/data/{@applicationId}/files/Pictures/JPEG_20170216_173121268719051242.jpg
requireBitmap.recycle();//Here NPE was thrown.
}
}
At the meantime, Here are UriUtil
:
public class UriUtil {
public static File createFileForPic() throws IOException {
String fileName = "JPEG_" + new SimpleDateFormat("yyyyMMdd_HHmmssSSS", Locale.getDefault()).format(new Date()) + ".jpg";
File storageDic = SPApplication.getInstance().getExternalFilesDir(Environment.DIRECTORY_PICTURES);
return new File(storageDic, fileName);
}
public static File createTmpFileForPic() throws IOException {
String fileName = "JPEG_" + new SimpleDateFormat("yyyyMMdd_HHmmssSSS", Locale.getDefault()).format(new Date());
File storageDic = SPApplication.getInstance().getExternalFilesDir(Environment.DIRECTORY_PICTURES);
return File.createTempFile(fileName, ".jpg", storageDic);
}
public static Uri fromFile(@NonNull Context context, @NonNull File file) {
if (context == null || file == null) {
throw new RuntimeException("context or file can't be null");
}
if (ActivityUtils.requireSDKInt(Build.VERSION_CODES.N)) {
return FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".file_provider", file);
} else {
return Uri.fromFile(file);
}
}
}
and getTakePicIntent(Uri)
:
public static Intent getTakePicIntent(Uri mPicPath) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, mPicPath);
if (!ActivityUtils.requireSDKInt(Build.VERSION_CODES.KITKAT_WATCH)) {//in pre-KitKat devices, manually grant uri permission.
List<ResolveInfo> resInfoList = SPApplication.getInstance().getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo resolveInfo : resInfoList) {
String packageName = resolveInfo.activityInfo.packageName;
SPApplication.getInstance().grantUriPermission(packageName, mPicPath, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
} else {
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
}
return intent;
}
and requireSDKInt
:
public static boolean requireSDKInt(int sdkInt) {
return Build.VERSION.SDK_INT >= sdkInt;
}
Everything worked on different Android API except on Android Nougat(7.x.x). Even 'FileProvider' was provided, 'requireBitmap' always be returned as 'null'.
After logs read, FileNotFoundException
was thrown from BitmapFactory
. It was like:
BitmapFactory: Unable to decode stream: java.io.FileNotFoundException: /Download/Android/data/{@applicationId}/files/Pictures/JPEG_20170216_1744551601425984925.jpg (No such file or directory)
It seems all is clear, but I still can't understand that.
How could it be? Clearly I created a File
! How could I solve that? Any ideas?
After logs read, FileNotFoundException was thrown from BitmapFactory.
. Yes but it will mention the used path too! Why did you omit it?decodeFile(mUri.getPath())
. Please tell the value of mUri.getPath(). All works on 6.0 ? – BorFile.createTempFile
. Do NOT create a temporary file. Only create a file name. The file will be created by the camera app. – BorUri mPicPath
ANDmUri.getPath())
?????? Where does mUri come from? – Borintent.addFlags()
. Are not needed. Not for any Android version. They do always nothing. Confusing code. – BormPicUri.getPath()
is like: "/Download/Android/data/{@applicationId}/files/Pictures/JPEG_20170216_173121268719051242.jpg". EvenUriUtil.createFileForPic()
doesn't work.Intent.FLAG_GRANT_READ_URI_PERMISSION
don't work indeed. And all works on pre-7.0. – Conceivable"/Download/Android/data/{@applicationId}/files/Pictures/........"
That would be an non existend nonsense path. Check if the directorystorageDic
exists before use. A full path can never start with /Download/....SPApplication.getInstance().getExternalFilesDir()
is implemented wrong. – Bor