Android 打开本地文件兼容7.0

Android 打开本地文件兼容7.0

简介
Android通过文件管理器打开各种格式文件,根据文件后缀名和文件类型,进行统一处理,兼容Android7.0,方便调用。

完整代码:

object OpenFileUtils {

    //这是在网上找到的一些常见的文件后缀名及其对应的MIME类型,使用中有新的后缀可以加入进去
    private val MIMES = arrayOf(
        //      后缀名       MIME类型
        arrayOf(".3gp",     "video/3gpp"),
        arrayOf(".asf",     "video/x-ms-asf"),
        arrayOf(".avi",     "video/x-msvideo"),
        arrayOf(".m4u",     "video/vnd.mpegurl"),
        arrayOf(".m4v",     "video/x-m4v"),
        arrayOf(".mov",     "video/quicktime"),
        arrayOf(".mp4",     "video/mp4"),
        arrayOf(".mpe",     "video/mpeg"),
        arrayOf(".mpeg",    "video/mpeg"),
        arrayOf(".mpg",     "video/mpeg"),
        arrayOf(".mpg4",    "video/mp4"),
        arrayOf(".wav",     "audio/x-wav"),
        arrayOf(".wma",     "audio/x-ms-wma"),
        arrayOf(".wmv",     "audio/x-ms-wmv"),
        arrayOf(".m3u",     "audio/x-mpegurl"),
        arrayOf(".rmvb",    "audio/x-pn-realaudio"),
        arrayOf(".mp2",     "audio/x-mpeg"),
        arrayOf(".mp3",     "audio/x-mpeg"),
        arrayOf(".m4a",     "audio/mp4a-latm"),
        arrayOf(".m4b",     "audio/mp4a-latm"),
        arrayOf(".m4p",     "audio/mp4a-latm"),
        arrayOf(".mpga",    "audio/mpeg"),
        arrayOf(".ogg",     "audio/ogg"),
        arrayOf(".bmp",     "image/bmp"),
        arrayOf(".gif",     "image/gif"),
        arrayOf(".jpeg",    "image/jpeg"),
        arrayOf(".jpg",     "image/jpeg"),
        arrayOf(".png",     "image/png"),
        arrayOf(".prop",    "text/plain"),
        arrayOf(".c",       "text/plain"),
        arrayOf(".rc",      "text/plain"),
        arrayOf(".conf",    "text/plain"),
        arrayOf(".cpp",     "text/plain"),
        arrayOf(".h",       "text/plain"),
        arrayOf(".java",    "text/plain"),
        arrayOf(".htm",     "text/html"),
        arrayOf(".html",    "text/html"),
        arrayOf(".log",     "text/plain"),
        arrayOf(".sh",      "text/plain"),
        arrayOf(".xml",     "text/plain"),
        arrayOf(".txt",     "text/plain"),
        arrayOf(".apk",     "application/vnd.android.package-archive"),
        arrayOf(".mpc",     "application/vnd.mpohun.certificate"),
        arrayOf(".msg",     "application/vnd.ms-outlook"),
        arrayOf(".pps",     "application/vnd.ms-powerpoint"),
        arrayOf(".ppt",     "application/vnd.ms-powerpoint"),
        arrayOf(".wps",     "application/vnd.ms-works"),
        arrayOf(".bin",     "application/octet-stream"),
        arrayOf(".class",   "application/octet-stream"),
        arrayOf(".exe",     "application/octet-stream"),
        arrayOf(".gtar",    "application/x-gtar"),
        arrayOf(".gz",      "application/x-gzip"),
        arrayOf(".js",      "application/x-javascript"),
        arrayOf(".tar",     "application/x-tar"),
        arrayOf(".tgz",     "application/x-compressed"),
        arrayOf(".rar",     "application/x-rar-compressed"),
        arrayOf(".z",       "application/x-compress"),
        arrayOf(".rtf",     "application/rtf"),
        arrayOf(".pdf",     "application/pdf"),
        arrayOf(".zip",     "application/zip"),
        arrayOf(".doc",     "application/msword"),
        arrayOf(".jar",     "application/java-archive"),
        arrayOf("",         "*/*")//所有文件
    )

    /**
     * @param  context 上下文
     * @param  path 文件路径
     */
    fun open(context: Context, path: String) {
        val intent = Intent().apply {
            action = Intent.ACTION_VIEW             //动作,会根据不同的数据类型打开相应的Activity
            addCategory(Intent.CATEGORY_DEFAULT)    //意图,系统默认
            addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) //标签,创建一个新的任务栈存放Activity,在最顶部展示
            addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)//标签,授予目录临时共享权限
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {//Android7.0之后
                //设置数据和类型
                setDataAndType(
                    //7.0后通过FileProvider获取URI
                    FileProvider.getUriForFile(
                        context,
                        "${context.packageName}.provider",  //要与配置文件中authorities属性一致
                        File(path)
                    ),
                    getFileType(path)
                )
            } else {//Android7.0之前
                setDataAndType(Uri.fromFile(File(path)), getFileType(path))
            }
        }
        context.startActivity(intent)
    }

    /**
     * @param  path 文件路径
     * @return type 文件类型
     */
    private fun getFileType(path: String): String {
        //默认类型
        var type = "*/*"
        //获取后缀名前的分隔符"."在path中的位置。
        val index = path.lastIndexOf(".")
        //防止路径不存在"."出现异常
        if (index < 0) {
            return type
        }
        //获取文件的后缀名
        val fileType = path.substring(index).toLowerCase()
        if (fileType.isEmpty()) {
            return type
        }
        //在MIME和文件类型的匹配表中找到对应的MIME类型。
        for (i in MIMES.indices) {
            if (fileType == MIMES[i][0]) {
                type = MIMES[i][1]
            }
        }
        return type
    }

}

常用文件MIME类型:

1、图片            "image/*"
2、视频            "video/*"
3、音频            "audio/*"
4、文本            "text/*"

Android 7.0 FileProvider使用
1、在AndroidManifest.xml文件中声明FileProvider

<application
    ......
    >

    <provider
        android:name="androidx.core.content.FileProvider"//FileProvider类名
        android:authorities="${applicationId}.provider"  //签名认证,要与获取URI时一致
        android:exported="false"                         //是否公开
        android:grantUriPermissions="true">              //设置URI临时访问权限
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"  //固定名称
            android:resource="@xml/file_paths"/>                //配置路径信息
    </provider>

    <activity android:name=".MainActivity">
        ......
    </activity>
</application>

2、在资源文件中配置可访问的文件夹路径
在这里插入图片描述
file_paths.xml代码如下:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <paths>
        <external-path            //Environment.getExternalStorageDirectory()
            name="external-path"  //可自定义 
            path="." />           //设置path="."代表Environment.getExternalStorageDirectory()下所有目录下的文件
                                  //如设置path="image/",则代表Environment.getExternalStorageDirectory()下的image文件夹下的文件
     </paths>
</resources>
注意1:Android7.0后,必须使用FileProvider,否则会报android.os.FileUriExposedException异常

注意2:打开文件时,必须加上addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION),否则会提示无法找到文件

猜你喜欢

转载自blog.csdn.net/summerrse/article/details/107763199