Android FileProvider 导致 Camera/Gallery 随机崩溃
Android FileProvider Causing Camera/Gallery to Crash at Random
美好的一天。
借助开发人员指南中的帮助,我能够使我的应用程序的照片捕获正常工作。 activity 通常涉及捕获一张或多张图像(类似于照片网格相机拼贴应用程序)。它在大多数时间和大多数设备上都能正常工作,但在我自己的设备 (Android 5.0.1) 上除外。问题是,camera/gallery 应用程序崩溃,在堆栈跟踪中给我一个安全权限拒绝错误,我已经搜索并实施了解决方案,但无济于事。崩溃通常是随机的,但更可能发生在以下情况:
1.我在拍第二张照片
2. 我的相机设置为最高分辨率:13MP(在较低分辨率下几乎不会发生)
虽然在其他情况下很少发生,但它的发生让我抓狂。这是我的代码:
片段
private void dispatchTakePictureIntent(boolean isQuestionImage) {
Intent takePictureIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getActivity().getPackageManager()) != null) {
File photoFile = null;
try {
photoFile = createImageFile(isQuestionImage);
} catch (IOException ex) {
Log.e("photofile part", "Error: "+ex);
}
if (photoFile != null) {
Uri photoURI = FileProvider.getUriForFile(getActivity(),
"com.operator.u_learn.fileprovider", photoFile);
if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP) {
takePictureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
takePictureIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
if(Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
List<ResolveInfo> resolvedIntentActivities = getActivity()
.getPackageManager()
.queryIntentActivities(takePictureIntent, PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo resolvedIntentInfo : resolvedIntentActivities) {
String packageName = resolvedIntentInfo.activityInfo.packageName;
getActivity().grantUriPermission(packageName,
photoURI,
Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
}
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
if(isQuestionImage)
startActivityForResult(takePictureIntent, REQUEST_QUESTION_IMAGE_CAPTURE);
else
startActivityForResult(takePictureIntent, REQUEST_EXPLANATION_IMAGE_CAPTURE);
//revoke permissions after use
if(Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
getActivity().revokeUriPermission(photoURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
}
}
}
AndroidManifest.xml
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.operator.u_learn.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths"></meta-
data>
</provider>
file_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths
xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="my_images"
path="Android/data/com.operator.u_learn/files/Pictures" />
</paths>
这是我得到的错误
E/AndroidRuntime: FATAL EXCEPTION: main
Process:
com.android.gallery3d, PID: 18974
java.lang.SecurityException: Permission Denial: opening
provider android.support.v4.content.FileProvider from
ProcessRecord{3b596555 18974:com.android.gallery3d/u0a42}
(pid=18974, uid=10042) that is not exported from uid 10221
at
android.os.Parcel.readException(Parcel.java:1540)
at
android.os.Parcel.readException(Parcel.java:1493)
根据我的经验,您的相机模块已被之前的 Activity 锁定。您可以通过 运行 预览另一个相机应用程序并立即切换到您的相机应用程序预览屏幕来检查它。
可能,最高分辨率可能会使它更频繁地发生,因为它需要更多时间才能发布。
如您所知,Android 设备在制造商+硬件+相机驱动程序+OS+制造商默认相机应用程序组合中有几种不同的实现方式。有些允许通过自动释放以前访问的应用程序(LG Nexus 5)来访问相机 api,而其他一些则崩溃(LG G2 phone)。
要解决此问题,如果我的诊断是正确的,我建议您在启动前添加大约 Thread.sleep(500);
的睡眠计数器。
或者,try-catch Camera.open() 方法。如果它被其他处理器锁定,它可能会给出 RuntimeException
。但根据我的经验,Camera API 非常不可靠,因此让我们在 api 命令的几乎每一行都包含 try-catch 代码。
虽然这个答案不能解决 Gallery 崩溃问题,但 Camera 可以。
美好的一天。
借助开发人员指南中的帮助,我能够使我的应用程序的照片捕获正常工作。 activity 通常涉及捕获一张或多张图像(类似于照片网格相机拼贴应用程序)。它在大多数时间和大多数设备上都能正常工作,但在我自己的设备 (Android 5.0.1) 上除外。问题是,camera/gallery 应用程序崩溃,在堆栈跟踪中给我一个安全权限拒绝错误,我已经搜索并实施了解决方案,但无济于事。崩溃通常是随机的,但更可能发生在以下情况: 1.我在拍第二张照片 2. 我的相机设置为最高分辨率:13MP(在较低分辨率下几乎不会发生)
虽然在其他情况下很少发生,但它的发生让我抓狂。这是我的代码:
片段
private void dispatchTakePictureIntent(boolean isQuestionImage) {
Intent takePictureIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getActivity().getPackageManager()) != null) {
File photoFile = null;
try {
photoFile = createImageFile(isQuestionImage);
} catch (IOException ex) {
Log.e("photofile part", "Error: "+ex);
}
if (photoFile != null) {
Uri photoURI = FileProvider.getUriForFile(getActivity(),
"com.operator.u_learn.fileprovider", photoFile);
if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP) {
takePictureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
takePictureIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
if(Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
List<ResolveInfo> resolvedIntentActivities = getActivity()
.getPackageManager()
.queryIntentActivities(takePictureIntent, PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo resolvedIntentInfo : resolvedIntentActivities) {
String packageName = resolvedIntentInfo.activityInfo.packageName;
getActivity().grantUriPermission(packageName,
photoURI,
Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
}
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
if(isQuestionImage)
startActivityForResult(takePictureIntent, REQUEST_QUESTION_IMAGE_CAPTURE);
else
startActivityForResult(takePictureIntent, REQUEST_EXPLANATION_IMAGE_CAPTURE);
//revoke permissions after use
if(Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
getActivity().revokeUriPermission(photoURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
}
}
}
AndroidManifest.xml
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.operator.u_learn.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths"></meta-
data>
</provider>
file_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths
xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="my_images"
path="Android/data/com.operator.u_learn/files/Pictures" />
</paths>
这是我得到的错误
E/AndroidRuntime: FATAL EXCEPTION: main
Process:
com.android.gallery3d, PID: 18974
java.lang.SecurityException: Permission Denial: opening
provider android.support.v4.content.FileProvider from
ProcessRecord{3b596555 18974:com.android.gallery3d/u0a42}
(pid=18974, uid=10042) that is not exported from uid 10221
at
android.os.Parcel.readException(Parcel.java:1540)
at
android.os.Parcel.readException(Parcel.java:1493)
根据我的经验,您的相机模块已被之前的 Activity 锁定。您可以通过 运行 预览另一个相机应用程序并立即切换到您的相机应用程序预览屏幕来检查它。
可能,最高分辨率可能会使它更频繁地发生,因为它需要更多时间才能发布。
如您所知,Android 设备在制造商+硬件+相机驱动程序+OS+制造商默认相机应用程序组合中有几种不同的实现方式。有些允许通过自动释放以前访问的应用程序(LG Nexus 5)来访问相机 api,而其他一些则崩溃(LG G2 phone)。
要解决此问题,如果我的诊断是正确的,我建议您在启动前添加大约 Thread.sleep(500);
的睡眠计数器。
或者,try-catch Camera.open() 方法。如果它被其他处理器锁定,它可能会给出 RuntimeException
。但根据我的经验,Camera API 非常不可靠,因此让我们在 api 命令的几乎每一行都包含 try-catch 代码。
虽然这个答案不能解决 Gallery 崩溃问题,但 Camera 可以。