对于Android的一些文件,假如我们要实现和电脑上选择打开方式的话,Android上面提供了比较简便的方式。
首先获取文件类型,即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
<providerandroid:name="android.support.v4.content.FileProvider"android:authorities="com.your.app.provider"android:exported="false" //必须为falseandroid:grantUriPermissions="true"><meta-dataandroid: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="/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,改用providerif (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"},{"", "*/*"}};
按照上面的步骤来操作的话,你就可以实现选择打开方式了,不过要记得修改注册FileProvider和provider_paths.xml文件中对应地方的你的应用包名。