android - 7.0系统拍照后,使用系统截图功能,截图保存时崩溃如何解决
ringa_lee
ringa_lee 2017-04-17 17:57:50
0
5
1046
java.lang.SecurityException: Permission Denial: writing android.support.v4.content.FileProvider uri content://com.tianshaokai.demo.fileprovider/camera_photos/temp/1480414713257.jpg from pid=23075, uid=10041 requires the provider be exported, or grantUriPermission()
 public void cropPhoto(File file) {
        cropfile = new File(Environment.getExternalStorageDirectory(), "/temp/" + System.currentTimeMillis() + ".jpg");
        if (!cropfile.getParentFile().exists()) cropfile.getParentFile().mkdirs();
        Uri outputUri = FileProvider.getUriForFile(this, getProvider(), cropfile);
        Uri imageUri = FileProvider.getUriForFile(this, getProvider(), file);//通过FileProvider创建一个content类型的Uri
        Intent intent = new Intent("com.android.camera.action.CROP");
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        intent.setDataAndType(imageUri, "image/*");
        intent.putExtra("crop", "true");
        intent.putExtra("aspectX", 1);
        intent.putExtra("aspectY", 1);
        intent.putExtra("outputX", 300);
        intent.putExtra("outputY", 400);
//        intent.putExtra("scale", true);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, outputUri);
        intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
//        intent.putExtra("noFaceDetection", true); // no face detection
        startActivityForResult(intent, 1002);
 }
file = new File(Environment.getExternalStorageDirectory(), "/temp/" + System.currentTimeMillis() + ".jpg");
        if (!file.getParentFile().exists()) file.getParentFile().mkdirs();
        Uri imageUri = FileProvider.getUriForFile(this, getProvider(), file);//通过FileProvider创建一个content类型的Uri
        Log.d(TAG, "imageUri: " + imageUri);
        Intent intent = new Intent();
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); //添加这一句表示对目标应用临时授权该Uri所代表的文件
        intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);//设置Action为拍照
        intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);//将拍取的照片保存到指定URI
        startActivityForResult(intent, 1001);

现在就是拍照完成后,裁剪 就报最上边的 权限错误,测试机是 7.0 的模拟器

看到大家的回答我补充一下啊,我已经添加了6.0 的 SD卡和摄像头 动态权限,我现在的问题是裁剪完 保存时 报上边的错误。

ringa_lee
ringa_lee

ringa_lee

membalas semua(5)
刘奇

Untuk memintas outputUri foto, anda hanya boleh menggunakan Uri.fromFile, bukan FileProvider.getUriForFile

刘奇

Ya, kebenarannya salah. Selepas 6.0, kebenaran perlu diperoleh secara dinamik.

黄舟

Tiada gesaan sekarang Anda perlu memulakan permohonan kebenaran secara aktif Secara amnya, untuk mengambil gambar, terdapat dua kebenaran untuk kad SD dan kamera. Pengetahuan berkaitan model kebenaran 6.0 boleh ditanya dalam talian. http://www.tuicool.com/articl... Saya menemuinya dalam talian dan anda boleh melihat sama ada ia boleh diselesaikan,

巴扎黑

Pemikiran dan amalan semasa saya:

1 Gunakan FileProvider agar serasi dengan Android N dan ke atas

2. Gunakan fail untuk menyimpan gambar yang diambil dan dipangkas

Langkah:

1. Deklarasikan FileProvider dalam AndroidManifest.xml

<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="包名.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/filepaths" />
    </provider>

2. Cipta direktori xml di bawah res dan buat filepaths.xml dengan kandungan berikut:

<paths>
    <external-path
        name="my_images"
        path="Android/data/包名/files/header/" />
</paths>

Nota: Kelebihan menyimpan dengan laluan ini ialah fail akan dipadamkan apabila aplikasi dinyahpasang fail/header/ ialah laluan tersuai

3. Titik panggilan perlu mengendalikan kebenaran storan luaran (kerana sistem digunakan untuk mengambil gambar, tidak perlu memberikan kebenaran kamera)

int permission = ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (permission != PackageManager.PERMISSION_GRANTED) {
    ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSION_HEAD);
} else {
    //调用拍照或者从相册选取
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    switch (requestCode) {
        case PERMISSION_HEAD:
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            //调用拍照或者从相册选取
        } else {
            //提示:"要使用该功能,必须允许或者在应用访问授权中打开存储空间权限"
        }
        break;
        default:
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        }
    }

4. Pemprosesan URI, laluan telah diisytiharkan dalam filepath.xml, anda perlu menentukan nama fail untuk menyimpan imej (save.jpg)

private Uri getUri() {
    File path = new File(Environment.getExternalStorageDirectory(), "Android/data/包名/files/header");
    if (!path.exists()) {
        path.mkdirs();
    }
    File file = new File(path, "save.jpg");
    //由于一些Android 7.0以下版本的手机在剪裁保存到URI会有问题,所以根据版本处理下兼容性
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        return FileProvider.getUriForFile(context, "com.maidouvr.fileprovider", file);
    } else {
        return Uri.fromFile(file);
    }
}

5. Pemprosesan foto

Uri uri = getUri();
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);

//将存储图片的uri读写权限授权给相机应用
List<ResolveInfo> resInfoList = getActivity().getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo resolveInfo : resInfoList) {
    String packageName = resolveInfo.activityInfo.packageName;
    getActivity().grantUriPermission(packageName, uri , Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
startActivityForResult(Intent.createChooser(intent, "选择拍照工具"), 1001);

6. Pemprosesan pemotongan

Uri uri = getUri();
Intent intent = new Intent("com.android.camera.action.CROP");
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

intent.setDataAndType(uri , "image/*");
intent.putExtra("crop", "true");
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
intent.putExtra("outputX", 500);
intent.putExtra("outputY", 500);
intent.putExtra("scale", true);
intent.putExtra(MediaStore.EXTRA_OUTPUT, getUri());
intent.putExtra("return-data", false);
intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
intent.putExtra("noFaceDetection", true);

//将存储图片的uri读写权限授权给剪裁工具应用
List<ResolveInfo> resInfoList = getActivity().getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo resolveInfo : resInfoList) {
    String packageName = resolveInfo.activityInfo.packageName;
    getActivity().grantUriPermission(packageName, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
startActivityForResult(Intent.createChooser(intent, "选择剪裁工具"), 1002);

Satu perkara terakhir untuk ditambah: Sesetengah telefon mudah alih mungkin mempunyai resultCode sentiasa RESULT_CANCEL selepas pemangkasan, jadi adalah disyorkan untuk menetapkan Mod pelancaran Aktiviti menggunakan fungsi ini kepada singleTask

Peter_Zhu

Pengecualian keselamatan, kebenaran pengguna diperlukan untuk versi 6.0 dan ke atas.

Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan