我用按钮制作了Simple App,可以在手机上打开相机(API 19),用于扫描文档和裁剪图像。效果很好,但是当我尝试在其他型号的手机(例如API 27)上启动相机时...该应用突然崩溃。
我猜是棒棒糖之后许可发生了变化或过时可能导致此?
我在下面添加了堆栈跟踪,
注意:使用权限Android library Dexter
Edit:我认为ScanActivity在这里不相关,但如果确实如此(错误确实提到了它)Here is ScanActivity
AndoirdManifest
<uses-feature
android:name="android.hardware.camera"
android:required="true" />
<uses-feature
android:name="android.hardware.camera.autofocus"
android:required="false" />
<uses-permission android:name="android.permission.FLASHLIGHT" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
MainActivity
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
camera = findViewById(R.id.open_cam);
//first of all we will ask run time permissions for camera and read and write file
checkPermissions();
camera.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
openCamera();
}
});
}
public void openCamera() {
int preference = ScanConstants.OPEN_CAMERA;
Intent intent = new Intent(this, ScanActivity.class);
intent.putExtra(ScanConstants.OPEN_INTENT_PREFERENCE, preference);
startActivityForResult(intent, OPEN_THING);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK && data != null) {
if (requestCode == OPEN_THING) {
Uri uri = data.getExtras().getParcelable(ScanConstants.SCANNED_RESULT);
Bitmap bitmap = null;
try {
bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), uri);
getContentResolver().delete(uri, null, null);
scannedImageView.setImageBitmap(bitmap);
FileOutputStream outputStream = null;
File sdCard = Environment.getExternalStorageDirectory();
File directory = new File (sdCard.getAbsolutePath() +"/Scan Documents");
directory.mkdir();
String filename = String.format("d.jpg", System.currentTimeMillis());
File outFile = new File(directory, filename);
Toast.makeText(this, "Image Saved Successfully", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
intent.setData(Uri.fromFile(outFile));
sendBroadcast(intent);
try{
outputStream = new FileOutputStream(outFile);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
outputStream.flush();
outputStream.close();
}catch (FileNotFoundException e)
{
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private void checkPermissions()
{
Dexter.withActivity(this)
.withPermissions(
Manifest.permission.CAMERA,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
).withListener(new MultiplePermissionsListener() {
@Override public void onPermissionsChecked(MultiplePermissionsReport report)
{
// check if all permissions are granted
if (report.areAllPermissionsGranted()) {
// do you work now
}
// check for permanent denial of any permission
if (report.isAnyPermissionPermanentlyDenied()) {
// permission is denied permenantly, navigate user to app settings
showSettingsDialog();
}
}
@Override public void onPermissionRationaleShouldBeShown(List<PermissionRequest> permissions, PermissionToken token)
{
token.continuePermissionRequest();
}
}).withErrorListener(new PermissionRequestErrorListener() {
@Override
public void onError(DexterError error) {
Toast.makeText(MainActivity.this, "Error Occured!!!", Toast.LENGTH_SHORT).show();
}
})
.onSameThread()
.check();
}
private void showSettingsDialog()
{
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setTitle("Need Camera and Storage Permissions");
builder.setMessage("This app needs permissions to use this feature you can grant them in app settings");
builder.setPositiveButton("GOTO SETTINGS", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
openSettings();
}
});
builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
builder.show();
}
private void openSettings()
{
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getPackageName(), null);
intent.setData(uri);
startActivityForResult(intent, 101);
}
堆栈跟踪崩溃
2019-11-27 23:34:41.843 15892-15892/com.nabeeltech.myapplication.debug E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.nabeeltech.myapplication.debug, PID: 15892
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.nabeeltech.myapplication.debug/com.scanlibrary.ScanActivity}:
java.lang.SecurityException: UID 10093 does not have permission to content://com.scanlibrary.provider/external_files/scanSample/IMG_20191127_223441.jpg [user 0]
Caused by: java.lang.SecurityException: UID 10093 does not have permission to content://com.scanlibrary.provider/external_files/scanSample/IMG_20191127_223441.jpg [user 0]
好像您试图直接从uri读取位图文件。你应该用FileProvider