Android7.0以上版本打开附件失败问题

简介:

  Android7.0修改了文件权限,导致访问内部文件通过Uri.fromFile(file)构建URI,然后Intent启动意图的方式将不再适用。原因是这种方式构建的uri不够安全。官方建议通过FileProvider,通过文件共享的方式构建URI。 可参考文章快速引入FileProvider

遇到的问题:

  • Failed to find configured root that: 构建URI时就出现了错误,配置的Filepath和文件路径不匹配,匹配即可,也可以使用相对路径:
<external-path name="mintu" path="./" />
  • 打开附件时,提示文件名不存在,但是确定文件是存在的 构建uri时会要求传入文件作为参数,这里可以判断自己的文件是否存在,当确定存在时提示文件名不存在。可以通过配置Inten解决。添加Intent代码:
intent.putExtra(MediaStore.EXTRA_OUTPUT,uri);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

核心代码

//AndroidManifest.xml
  <provider
            android:authorities="com.mintu.dcdb.fileprovider"
            android:name="android.support.v4.content.FileProvider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths"/>
</provider>
//file_paths
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <!--代表外部存储区域的根目录下的文件 Environment.getExternalStorageDirectory()/mintudb目录-->
    <external-path name="mintu" path="." />
    <!--<external-path name="mintu" path="mintudb/" />-->
    <!--<external-files-path name="mintu2" path="mintudb" />-->
    <!--<external-path name="mintu3" path="mintudb" />-->
</paths>
//open
public void openFile(File f, Context context) {
        Log.i(LOGTAG, "正在打开附件打--------" + f.getName()+"。附件大小为"+f.length());
        try {
            String end = f.getName().substring(f.getName().lastIndexOf(".")
                    + 1, f.getName().length()).toLowerCase();
            if(end.equals("amr")){
                AudioRecoderUtils.getInstance().playerStart(f.getAbsolutePath());
            }else {
                Intent intent = new Intent();
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                intent.setAction(android.content.Intent.ACTION_VIEW);
                intent.addCategory("android.intent.category.DEFAULT");
      /* 调用getMIMEType()来取得MimeType */
                String type = getMIMEType(f);
      /* 设置intent的file与MimeType */
                if(Build.VERSION.SDK_INT>=24){
                    Uri contenturi=FileProvider.getUriForFile(context, "com.mintu.dcdb.fileprovider",f);
                    intent.setDataAndType(contenturi,type);
                    intent.putExtra(MediaStore.EXTRA_OUTPUT, contenturi);
                    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                }else{
                    intent.setDataAndType(Uri.fromFile(f), type);
                }
                context.startActivity(intent);
            }
        } catch (Exception e) {
            Log.e(LOGTAG, "打开附件" + f.getName() + "报错了,错误是-----" + e.getMessage());
        }
    }

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏女程序员的日常

STM8S——Flash program memory and data EEPROM

1、简介   STM8S内部的FLASH程序存储器和数据EEPROM是由一组通用寄存器来控制的;所以我们可以通过这些通用寄存器来编程或擦除存储器的内容、设置写保...

30610
来自专栏Android干货

Android项目实战(四十九):Andoird 7.0+相机适配

一、在AndroidManifest.xml 文件中添加 四大组件之一的 <provider>

9900
来自专栏图像识别与深度学习

《Android》Lesson07-隐式Intent***注意:需要把super.onBackPressed();注释掉

208100
来自专栏移动开发

Andorid检测支付宝客户端是否安装

22140
来自专栏Petrichor的专栏

Tmux 使用

[1] 十分钟学会 tmux [2] Tmux使用手册 [3] 第 2 章 配置 tmux

20520
来自专栏上善若水

036android初级篇之Activity的启动模式

你可以通过定义运行模式来定义Activities如何与Task进行交互。定义的两种方式如下:

13430
来自专栏上善若水

025android初级篇之Android am命令的实现

am命令一个重要的调试工具,主要功能包括如下: 启动停止Activity Service,启动Broadcast, 查看管理这些信息。

28960
来自专栏刘望舒

Android解析ActivityManagerService(二)ActivityTask和Activity栈管理

前言 关于AMS,原计划是只写一篇文章来介绍,但是AMS功能繁多,一篇文章的篇幅远远不够。这一篇我们接着来学习与AMS相关的ActivityTask和Activ...

44690
来自专栏吴伟祥

Springboot官方构建下的mvnw.cmd的作用

mvnw 全名是maven wrapper,它的原理是在maven-wrapper.properties文件中记录你要使用的maven版本

22720
来自专栏非著名程序员

我所理解的Intent 和Intent-filter

1.Intent Intent 是一个消息传递对象,可以使用它从其他应用组件请求操作。尽管 Intent 可以通过多种方式促进组件之间的通信,但其基本用例主要包...

21190

扫码关注云+社区

领取腾讯云代金券