Android 打开不同类型的文件及android.os.FileUriExposedException错误处理

原创文章,如有转载,请注明出处:http://blog.csdn.net/myth13141314/article/details/69258555

首先获取文件类型,即MIME类型
  • MIME类型表后面附上
/**
* 根据文件后缀名获得对应的MIME类型。
* @param file
*/
private static String getMIMEType(File file) {

   String type="*/*";
   String fName = file.getName();
   //获取后缀名前的分隔符"."在fName中的位置。
   int dotIndex = fName.lastIndexOf(".");
   if(dotIndex < 0){
       return type;
   }
/* 获取文件的后缀名 */
   String end=fName.substring(dotIndex,fName.length()).toLowerCase();
   if(end=="")return type;
   //在MIME和文件类型的匹配表中找到对应的MIME类型。
   for(int i=0;i<MIME_MapTable.length;i++){ //MIME_MapTable??在这里你一定有疑问,这个MIME_MapTable是什么?
       if(end.equals(MIME_MapTable[i][0]))
           type = MIME_MapTable[i][1];
   }
   return type;
}
通过intent调用系统安装的软件打开文件
Intent intent = new Intent();
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//设置intent的Action属性
intent.setAction(Intent.ACTION_VIEW);
//获取文件file的MIME类型
String type = getMIMEType(file);

intent.setDataAndType(/*uri*/Uri.fromFile(file), type);
//跳转
context.startActivity(intent);

以上就是正常情况下打开文件的方法,但是在Android 7.0的机子上回报android.os.FileUriExposedException错误,原因在于Android 7.0的安全策略变了,解决方法是用provider来实现打开文件
  • 首先是AndroidManifest文件里面注册FileProvider
<provider
     android:name="android.support.v4.content.FileProvider"
     android:authorities="com.your.app.provider"
     android:exported="false"  //必须为false
     android:grantUriPermissions="true">
     <meta-data
         android:name="android.support.FILE_PROVIDER_PATHS"
         android:resource="@xml/provider_paths" /> //需要自己编写xml文件
</provider>
  • provider_paths.xml文件的编写

    这里写图片描述

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">

    <external-path name="external_files" path="."/>// .表示根目录

</paths>
  • 修改打开文件的方法
Uri fileUri = FileProvider.getUriForFile(context, context.getPackageName()+".provider", file);//android 7.0以上
intent.setDataAndType(fileUri, type);
还需要grantUriPermission方法添加权限
private static void grantUriPermission (Context context, Uri fileUri, Intent intent) {
    List<ResolveInfo> resInfoList = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
    for (ResolveInfo resolveInfo : resInfoList) {
        String packageName = resolveInfo.activityInfo.packageName;
        context.grantUriPermission(packageName, fileUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
    }
}
最后打开文件的方法为
/**
* 打开文件
* @param file
*/
public static void openFile(Context context, File file){

   try {
       Intent intent = new Intent();
       intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
       //设置intent的Action属性
       intent.setAction(Intent.ACTION_VIEW);
       //获取文件file的MIME类型
       String type = getMIMEType(file);
       //设置intent的data和Type属性。android 7.0以上crash,改用provider
       if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
           Uri fileUri = FileProvider.getUriForFile(context, context.getPackageName()+".provider", file);//android 7.0以上
           intent.setDataAndType(fileUri, type);
           grantUriPermission(context, fileUri, intent);
       }else {
           intent.setDataAndType(/*uri*/Uri.fromFile(file), type);
       }
       //跳转
       context.startActivity(intent);
   }catch (Exception e){
       e.printStackTrace();
       showAlert(context, "File corrupted, download again please.");
   }

}

最后附上MIME类型表
private static final String[][] MIME_MapTable={
       //{后缀名, MIME类型}
       {".3gp",    "video/3gpp"},
       {".apk",    "application/vnd.android.package-archive"},
       {".asf",    "video/x-ms-asf"},
       {".avi",    "video/x-msvideo"},
       {".bin",    "application/octet-stream"},
       {".bmp",    "image/bmp"},
       {".c",  "text/plain"},
       {".class",  "application/octet-stream"},
       {".conf",   "text/plain"},
       {".cpp",    "text/plain"},
       {".doc",    "application/msword"},
       {".docx",   "application/vnd.openxmlformats-officedocument.wordprocessingml.document"},
       {".xls",    "application/vnd.ms-excel"},
       {".xlsx",   "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"},
       {".exe",    "application/octet-stream"},
       {".gif",    "image/gif"},
       {".gtar",   "application/x-gtar"},
       {".gz", "application/x-gzip"},
       {".h",  "text/plain"},
       {".htm",    "text/html"},
       {".html",   "text/html"},
       {".jar",    "application/java-archive"},
       {".java",   "text/plain"},
       {".jpeg",   "image/jpeg"},
       {".jpg",    "image/jpeg"},
       {".js", "application/x-javascript"},
       {".log",    "text/plain"},
       {".m3u",    "audio/x-mpegurl"},
       {".m4a",    "audio/mp4a-latm"},
       {".m4b",    "audio/mp4a-latm"},
       {".m4p",    "audio/mp4a-latm"},
       {".m4u",    "video/vnd.mpegurl"},
       {".m4v",    "video/x-m4v"},
       {".mov",    "video/quicktime"},
       {".mp2",    "audio/x-mpeg"},
       {".mp3",    "audio/x-mpeg"},
       {".mp4",    "video/mp4"},
       {".mpc",    "application/vnd.mpohun.certificate"},
       {".mpe",    "video/mpeg"},
       {".mpeg",   "video/mpeg"},
       {".mpg",    "video/mpeg"},
       {".mpg4",   "video/mp4"},
       {".mpga",   "audio/mpeg"},
       {".msg",    "application/vnd.ms-outlook"},
       {".ogg",    "audio/ogg"},
       {".pdf",    "application/pdf"},
       {".png",    "image/png"},
       {".pps",    "application/vnd.ms-powerpoint"},
       {".ppt",    "application/vnd.ms-powerpoint"},
       {".pptx",   "application/vnd.openxmlformats-officedocument.presentationml.presentation"},
       {".prop",   "text/plain"},
       {".rc", "text/plain"},
       {".rmvb",   "audio/x-pn-realaudio"},
       {".rtf",    "application/rtf"},
       {".sh", "text/plain"},
       {".tar",    "application/x-tar"},
       {".tgz",    "application/x-compressed"},
       {".txt",    "text/plain"},
       {".wav",    "audio/x-wav"},
       {".wma",    "audio/x-ms-wma"},
       {".wmv",    "audio/x-ms-wmv"},
       {".wps",    "application/vnd.ms-works"},
       {".xml",    "text/plain"},
       {".z",  "application/x-compress"},
       {".zip",    "application/x-zip-compressed"},
       {"",        "*/*"}
};

参考链接


欢迎关注我的公众号,和我一起每天进步一点点!
这里写图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值