android 7.0+ FileProvider 访问隐私文件 相册、相机、安装应用的适配

从 Android 7.0 开始,Android SDK 中的 StrictMode 策略禁止开发人员在应用外部公开 file:// URI。具体表现为,当我们在应用中使用包含 file:// URI 的 Intent 离开自己的应用时,程序会发生FileUriExposedException 异常

这里我们要使用到的 FileProvider,就是 ContentProvider 的一个特殊子类,帮助我们将访问受限的 file:// URI 转化为可以授权共享的 content:// URI。

首先 要去 Manifest文件里注册FileProvider

 <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="${applicationId}.FileProvider" //此处的属性值后面获取URI用到
            android:grantUriPermissions="true"
            android:exported="false">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths"/>
        </provider>
    </application>

其次在 res 目录下新建一个 xml 文件夹 里边添加一个xml文件 名字比如:path.xml

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="my_images" path="."/> <!-- 此处的name可以随便取--!>

</paths>

元素必须包含一到多个子元素。这些子元素用于指定共享文件的目录路径,必须是这些元素之一:

<files-path>:内部存储空间应用私有目录下的 files/ 目录,等同于 Context.getFilesDir() 所获取的目录路径;

<cache-path>:内部存储空间应用私有目录下的 cache/ 目录,等同于 Context.getCacheDir() 所获取的目录路径;

<external-path>:外部存储空间根目录,等同于 Environment.getExternalStorageDirectory() 所获取的目录路径;

<external-files-path>:外部存储空间应用私有目录下的 files/ 目录,等同于 Context.getExternalFilesDir(null) 所获取的目录路径;

<external-cache-path>:外部存储空间应用私有目录下的 cache/ 目录,等同于 Context.getExternalCacheDir();

获取URI的方法:

 在Android7.0以下 获取相册图片URI的方式:

Uri uri= Uri.from ( file );

 Android 7.0+获取相册图片的方式:

   //注意此处的 第二个参数必须与 Manifest文件中Provider 的 android:authorities 一致
Uri contentUri = FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID + ".FileProvider", outputFile);

Android 7.0以下 安装应用:

Intent installIntent = new Intent(Intent.ACTION_VIEW);
installIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
installIntent.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive");
startActivity(installIntent);

Android 7.0+ 安装应用:

//采用FileProvider的方式访问文件

File apkFile = new File(getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "app_sample.apk");
Uri apkUri = FileProvider.getUriForFile(this,
BuildConfig.APPLICATION_ID+".FileProvider", apkFile);

Intent installIntent = new Intent(Intent.ACTION_VIEW);
installIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//添加此处 是临时对文件的授权 必须加上此句
installIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
installIntent.setDataAndType(apkUri, "application/vnd.android.package-archive");
startActivity(installIntent);

调用相机的时候:

 public void camera() {
            Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
            tempFile = new File(Environment.getExternalStorageDirectory(),PHOTO_FILE_NAME);
            Uri uri;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                uri = FileProvider.getUriForFile(this, "com.camera.fileprovider",tempFile);                   //此处为Uri临时授权
                intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            } else {
                uri = Uri.fromFile(tempFile);
            }
            intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
            startActivityForResult(intent, PHOTO_REQUEST_CAMERA);
        }

裁剪图片:

public static void cropImageUri(Activity activity, Uri orgUri, Uri desUri, int aspectX, int aspectY, int width, int height, int requestCode) {
    Intent intent = new Intent("com.android.camera.action.CROP");
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {          //此处为Uri临时授权
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    }
    intent.setDataAndType(orgUri, "image/*"); //此处的Uri为 输入Uri用FileProvider的方式获取
    intent.putExtra("crop", "true");
    intent.putExtra("aspectX", aspectX);
    intent.putExtra("aspectY", aspectY);
    intent.putExtra("outputX", width);
    intent.putExtra("outputY", height);
    intent.putExtra("scale", true);
    //将剪切的图片保存到目标Uri中
    intent.putExtra(MediaStore.EXTRA_OUTPUT, desUri);//此处的Uri为输出Uri 需要用Uri.fromFile()的方式获取
    intent.putExtra("return-data", false);
    intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
    intent.putExtra("noFaceDetection", true);
    activity.startActivityForResult(intent, requestCode);
}

原文地址:https://www.cnblogs.com/bimingcong/p/10328429.html

时间: 2024-11-06 03:52:33

android 7.0+ FileProvider 访问隐私文件 相册、相机、安装应用的适配的相关文章

android 6.0权限判断 音频 拍照 相册

------------------------------------------打开音频权限------------------------------------------------ if (PackageManager.PERMISSION_GRANTED == ContextCompat. checkSelfPermission(context, android.Manifest.permission.RECORD_AUDIO)) { }else{ //提示用户开户权限音频 Str

yii2.0 能够访问到文件中但是不能到方法里面

今天在gii生成CRUD的时候碰到一个问题,通过访问能够进入到控制器里面,但是进不到方法里面, 仍然报错,最后把wgroup的访问地址改成w-group,就好了.都忘了原理手册里面有这点的解释了...

Android 8.0+ 更新安装apk失败的问题

最近做项目发现Android 8.0+ 更新安装apk时 出现安装失败的情况  总结原因是 缺少安装的权限 Android 8.0 (Android O)为了针对一些流氓软件引导用户安装其他无关应用.在应用权限设置的"特殊访问权限"中,加入了"安装其他应用"的设置. 简单的方法  可以直接在Manifest.xml中加入下面的权限:(亲测可用) <uses-permissionandroid:name="android.permission.REQU

app在android 6.0或以上平台版本运行过程中请求权限

原文作者:Google 原文地址:http://developer.android.com/intl/zh-cn/training/permissions/requesting.html 原文版权:Creative Commons 2.5 Attribution License 译文作者:Jianan - [email protected] 版本信息:本文基于2016-04-27版本翻译 译文版权:CC BY-NC-ND 4.0,允许复制转载,但必须保留译文作者署名及译文链接,不得演绎和用于商业

Android 5.0 模拟器 emulator无法启动

刚下载的最新的 android 5.0 sdk 和 sys-image , 运行的具体版本是 android 5.0 api level 21,,怀着激动的心情想调试一下我的app,发现android 5.0 的模拟器(emulator )无法启动,地洞后  仅仅是展示了一个黑色的屏幕.. 如果我选择了 google api  版本,再去选择intel x86 cpu的时候,提示警告"his AVD may not work unless you install the Google APIs

我们来一探究竟 Android 7.0 适配中 FileProvider 部分

本文标签: Android7.0 FileProvider 由于 Android 7.0 或更高版本的系统在国内手机市场上的占比不是很高,很多 Android 开发人员并没有做 7.0 适配工作,同时测试人员也容易忽视这方面的兼容问题.这导致 7.0 及以上版本的手机用户在使用到应用部分功能时可能出现 App 崩溃闪退.其中,大部分原因都是由项目中使用到 file:// 类型的 URI 所引发的.本文我们便来一探究竟. Android 7.0 权限变更 为了提高私有目录的安全性,防止应用信息的泄

Android 7.0 适配中 FileProvider 部分总结

本文标签: Android7.0 FileProvider 由于 Android 7.0 或更高版本的系统在国内手机市场上的占比不是很高,很多 Android 开发人员并没有做 7.0 适配工作,同时测试人员也容易忽视这方面的兼容问题.这导致 7.0 及以上版本的手机用户在使用到应用部分功能时可能出现 App 崩溃闪退.其中,大部分原因都是由项目中使用到 file:// 类型的 URI 所引发的.本文我们便来一探究竟. Android 7.0 权限变更 为了提高私有目录的安全性,防止应用信息的泄

关于 Android 7.0 适配中 FileProvider 部分的总结

原文地址:http://yifeng.studio/2017/05/03/android-7-0-compat-fileprovider/ 由于 Android 7.0 或更高版本的系统在国内手机市场上的占比不是很高,很多 Android 开发人员并没有做 7.0 适配工作,同时测试人员也容易忽视这方面的兼容问题.这导致 7.0 及以上版本的手机用户在使用到应用部分功能时可能出现 App 崩溃闪退.其中,大部分原因都是由项目中使用到 file:// 类型的 URI 所引发的.本文我们便来一探究竟

Android 7.0 之后相机/文件读写等权限获取方式改变,导致开启相机闪退

在 Android 7.0 之前 Google 提供的动态申请权限的 API,可以调用相机拍照,访问SDcard等操作都只需要申请对应的权限,如下: <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> 但是 7.0 更新之