android 7.0 因为file://引起的FileUriExposedException异常

 private void dialog() {
        SheetDialog sheetDialog = new SheetDialog(this);
        sheetDialog.setItemClickListener(new SheetDialog.OnSheetDialogListener() {
            @Override
            public void onItemClick(int id, int position) {
                switch (id) {
                    case SheetDialog.TYPE_TAKE_PICTURE:
                        if (PermissionUtils.lacksPermissions(ChatReportActivity.this,
                                PERMISSIONS)) {
                            // 缺少权限时, 进入权限配置页面
                            PermissionsActivity.startActivityForResult(ChatReportActivity.this,
                                    REQUEST_CODE_ASK_CAMERA_PERMISSION, PERMISSIONS);
                        } else {
                            showCameraAction();
                        }
                        break;
                    case SheetDialog.TYPE_SELECT_PHOTO:
                        if (PermissionUtils.lacksPermissions(ChatReportActivity.this,
                                PERMISSIONS)) {
                            // 缺少权限时, 进入权限配置页面
                            PermissionsActivity.startActivityForResult(ChatReportActivity.this,
                                    REQUEST_CODE_ASK_WRITE_PERMISSION, PERMISSIONS_WRITE);
                        } else {
                            goToSelectPicture();
                        }
                        break;
                }
            }
        });
        sheetDialog.show();
    }
调用相机:
private void showCameraAction() {
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        try {
            mTmpFile = FileUtils.createTmpFile(this);
        } catch (IOException e) {
            e.printStackTrace();
        }
        Uri photoOutputUri = FileProvider.getUriForFile(this,
                getPackageName() + ".fileprovider", mTmpFile);
        if (mTmpFile != null && mTmpFile.exists()) {
            intent.putExtra(MediaStore.EXTRA_OUTPUT, photoOutputUri);
            startActivityForResult(intent, REQUEST_CAMERA);
        }
    }

调用相册:

private void goToSelectPicture() {
        Intent intent = new Intent(Intent.ACTION_PICK,
                MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
        intent.setType("image/*");
        startActivityForResult(Intent.createChooser(intent, "选择图片"), REQUEST_GALLERY);
    }
@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        // 拒绝时, 关闭页面, 缺少主要权限, 无法运行
        if (requestCode == REQUEST_CODE_ASK_CAMERA_PERMISSION) {
            if (resultCode == PermissionsActivity.PERMISSIONS_DENIED) {
                Toast.makeText(ChatReportActivity.this, "缺少必要权限", Toast.LENGTH_SHORT).show();
            } else {
                showCameraAction();
            }
            return;
        }

        if (resultCode == RESULT_OK) {
            handleImgRequest(requestCode, data);
        }
    }

配置文件需要加入:

      <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="com.yjtx.fsl.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />
        </provider>

然后在,res目录中,新建一个xml文件,然后创建 file_paths.xml文件。

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <!--<external-path path="Android/data/com.yjtx.fsl/" name="files_root" />-->
    <!--<external-path path="." name="external_storage_root" />-->
    <external-path name="external_files" path="."/>
</paths>
转载:https://www.jianshu.com/p/55b817530fa3

Android 7.0 及以上系统中,直接使用 `file://` 格式的 URI 会触发 `FileUriExposedException` 错误,因为这种方式存在安全风险。解决该问题可采用 `FileProvider` 来生成内容 URI。以下是解决此问题的具体步骤和示例代码: ### 1. 在 `AndroidManifest.xml` 中配置 `FileProvider` 在 `<application>` 标签内添加 `FileProvider` 的配置,示例如下: ```xml <provider android:name="androidx.core.content.FileProvider" android:authorities="com.yourpackage.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider> ``` 其中,`android:authorities` 的值一般为“自己的包名 + fileprovider”,这里假设包名为 `com.yourpackage`。 ### 2. 创建 `file_paths.xml` 文件 在 `res/xml` 目录下创建 `file_paths.xml` 文件,内容如下: ```xml <?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <external-path name="my_images" path="." /> </paths> ``` 这里的 `external-path` 表示外部存储目录,`path="."` 表示允许访问整个外部存储。 ### 3. 修改代码以使用 `FileProvider` 在启动 Activity 时,使用 `FileProvider` 生成内容 URI,示例代码如下: ```java import android.content.Intent; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Environment; import android.provider.MediaStore; import androidx.appcompat.app.AppCompatActivity; import androidx.core.content.FileProvider; import java.io.File; import java.text.SimpleDateFormat; import java.util.Date; public class MainActivity extends AppCompatActivity { private static final int REQUEST_CODE_TAKE_PHOTO = 1; private String mPhotoName; private File mPhoto; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); try { // 生成照片文件名 mPhotoName = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + ".jpg"; // 照片保存路径 File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES); mPhoto = new File(storageDir, mPhotoName); Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); Uri mImageUri; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { // 7.0及以上版本使用FileProvider生成内容URI intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); mImageUri = FileProvider.getUriForFile(this, "com.yourpackage.fileprovider", mPhoto); } else { // 7.0以下版本使用传统的Uri.fromFile方法 mImageUri = Uri.fromFile(mPhoto); } intent.putExtra(MediaStore.EXTRA_OUTPUT, mImageUri); startActivityForResult(intent, REQUEST_CODE_TAKE_PHOTO); } catch (Exception e) { e.printStackTrace(); } } } ``` 在上述代码中,当系统版本为 Android 7.0 及以上时,使用 `FileProvider.getUriForFile` 方法生成内容 URI,并为 Intent 添加 `Intent.FLAG_GRANT_READ_URI_PERMISSION` 标志,以授予其他应用访问该 URI 的权限。 ### 总结 通过以上步骤,将原本的 `file://` 格式的 URI 替换为 `content://` 格式的内容 URI,从而避免 `FileUriExposedException` 错误。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值