从 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);
}

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

  1. Android 7.0 FileProvider 使用说明

    FileProvider FileProvider 这个组件在Android 22.0.0 (也就是 Android 5.0 ) 版本下加入进Android系统,该组件是ContentProvider ...

  2. Android 5.0 到 Android 6.0 + 的深坑之一 之 .so 动态库的适配

    (原创:http://www.cnblogs.com/linguanh) 目录: 前序 一,问题描述 二,为何会如此"无情"? 三,目前存在该问题的知名SDK 四,解决方案,1 对 ...

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

    ------------------------------------------打开音频权限------------------------------------------------ if ...

  4. Android 6.0 动态申请 音频+拍照+相册 权限

    1.音频的权限(包括录音和播放) 1.1.首先要在清单中加上两个权限 <uses-permission android:name="android.permission.WRITE_E ...

  5. centos7.0 可以访问HTML文件,不能访问PHP文件,因为php-fpm没有扩展包

    解决方法 :https://blog.csdn.net/ityang_/article/details/53980190 nginx调用PHP有sock方式和端口方式 1.确认nginx已经调用了ph ...

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

    最近做项目发现Android 8.0+ 更新安装apk时 出现安装失败的情况  总结原因是 缺少安装的权限 Android 8.0 (Android O)为了针对一些流氓软件引导用户安装其他无关应用. ...

  7. 《Thinking in Android 9.0 系统开发源码钻研录》

    最近打算把个人站点的博客文章同步到"博客园"! Thinking in Android -- "系统启动" [启动阶段] [相关文章] 状态 源码版本 init ...

  8. Android 7.0 通过FileProvider共享文件

    一.概述 Android 7.0后,提供了很多新特性,其中最主要的是禁止了通过file://URI直接在文件操作共享文件(该操作会触发FileUriExposedException),而是通过cont ...

  9. Android 7.0+相机、相册、裁剪适配问题

    Android 7.0+相机.相册.裁剪适配问题 在manifest中: <provider android:name="android.support.v4.content.File ...

随机推荐

  1. CentOS 7 升级 Linux 内核

    一.升级内核 1.更新仓库 yum -y update 2.用 ELRepo 仓库 rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org ...

  2. java 日志脱敏框架 sensitive,优雅的打印脱敏日志

    问题 为了保证用户的信息安全,敏感信息需要脱敏. 项目开发过程中,每次处理敏感信息的日志问题感觉很麻烦,大部分都是用工具类单独处理,不利于以后统一管理,很不优雅. 于是,就写了一个基于 java 注解 ...

  3. intellij与eclipse默认快捷键对比

    最近想用intellij,于是找找快捷键.用惯了eclipse,都不太适应intellij的快捷键.慢慢的就适应了常用的快捷键 Idea 与 Eclipse 快捷键的区别,上为Eclipse的快捷键, ...

  4. win10、Ubuntu14.04双系统正确卸载Ubuntu的方法

    参考博客:http://www.cnblogs.com/xia-Autumn/p/6294055.html 问题描述:由于python问题Ubuntu系统崩了,登录之后无法进入桌面.重装桌面时报错,无 ...

  5. 六、Python-字符串编码

      最早的编码为ASCII码(包含0-9.A-Z.a-z.符号(空格.制表符等)),最多支持256个符号(每个符号占1字节) GBK/GB2312:我国制定的中文编码标准,一个字节表示因为字母,两个字 ...

  6. 值得推荐的五大敏捷PHP开发框架

    各位开发者,对于在HTML中混乱使用PHP的人来说,我们给大家推荐几款PHP敏捷开发的框架,以及它们为什么能够流行. 在我们开始之前,先了解敏捷开发是个什么东东. 敏捷是一种软件开发方法,每次开发计划 ...

  7. 全球DDOS安全防护

    转:http://www.safecdn.cn/ https://www.safeidc.cn/llqx.html 全球可视化的DDoS攻击地图:Digital Attack Map 这个项目是源于G ...

  8. 05 JS基础DOM

    JS的window对象定时器: window下一些方法: <script> 弹出 window.alert('hello') 返回布尔值 var ret = window.confirm( ...

  9. 38_redux_counter应用_react版本

    redux的核心API 使用非redux创建: 项目结构: index.js import React from 'react'; import ReactDOM from 'react-dom'; ...

  10. 阅读rocketmq技术内幕、实战与原理杂记 - 设计

    最近正在研究rocketmq,简单记录下设计的不同 互联网系统中Rpc.服务治理.消息中间件基本都是标配,消息中间件能解耦,削峰,高可用并能间接提供达到最终一致性 消息中间件中,消息消费分为最多一次, ...