Android打开各类文件

341 阅读1分钟

Android打开各类文件

1. 获取文件的MimeType

  1. 方法1
private static String getSuffix(File file) {
    if (file == null || !file.exists() || file.isDirectory()) {
        return null;
    }
    String fileName = file.getName();
    if (fileName.equals("") || fileName.endsWith(".")) {
        return null;
    }
    int index = fileName.lastIndexOf(".");
    if (index != -1) {
        return fileName.substring(index + 1).toLowerCase(Locale.US);
    } else {
        return null;
    }
}
public static String getMimeType(File file){
    String suffix = getSuffix(file);
    if (suffix == null) {
        return "file/*";
    }
    String type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(suffix);
    if (type != null || !type.isEmpty()) {
        return type;
    }
    return "file/*";
}
  1. 方法2
public static String getMimeType(String filePath) {
    MediaMetadataRetriever mmr = new MediaMetadataRetriever();
    String mime = "file/*";
    if (filePath != null) {
        try {
            mmr.setDataSource(filePath);
            mime = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_MIMETYPE);
        } catch (IllegalStateException e) {
            return mime;
        } catch (IllegalArgumentException e) {
            return mime;
        } catch (RuntimeException e) {
            return mime;
        } finally {
            mmr.release();
        }
    }
    return mime;
}
  1. 经验证同一张图片,方法1获取到正确的类型,方法二没有获取到,猜测是图片还没有再媒体库中,待验证.

2. Intent.ACTION_VIEW

@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_VIEW = "android.intent.action.VIEW";

Intent.ACTION_VIEW 比较通用,会根据用户的数据类型打开相应的Activity.

3. 使用Intent.ACTION_VIEW打开指定文件

X:自定义authorities名称
    <provider
        android:name="androidx.core.content.FileProvider"
        android:authorities="X"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/provider_paths"/>
    </provider>
</application>

provider_paths.xml:
<?xml version="1.0" encoding="utf-8"?>
<paths>
    <root-path
        name="root-path"
        path="" />
    <external-path
        name="files_root"
        path="." />
    <external-path
        name="external_storage_root"
        path="." />
    <cache-path
        name="cache_files"
        path="." />
    <external-path path="." name="external_storage_root" /> <!-- 对应Environment.getExternalStorageDirectory() -->
    <cache-path name="cache_files" path="."/> <!-- 对应应用程序内部存储区域的cache子目录中的文件Context.getCacheDir()  -->
    <external-files-path name="external_files" path="."/> <!-- 对应应用程序外部存储区根目录中的文件Context.getExternalFilesDir(null)  -->
    <external-cache-path name="external_cache_files" path="."/> <!-- 对应应用程序外部缓存区域根目录中的文件Context.getExternalCacheDir()  -->
    <files-path name="path_files" path="."/> <!-- 对应应用程序内部存储区域的子目录中的文件Context.getFilesDir() -->
</paths>
try {
    Uri uri = Uri.fromFile(file);
    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){
        uri = FileProvider.getUriForFile(context, 自定义authorities名称, file);
    }
    String type = FileUtil.getMimeType(file);
    Intent in = new Intent(Intent.ACTION_VIEW);
    in.setDataAndTypeAndNormalize(uri, type);
    in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    in.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    context.startActivity(in);
} catch (Exception e) {
    e.printStackTrace();
}

4. android.os.FileUriExposedException

  1. 在Android N及更高版本,不能使用 Uri uri = Uri.fromFile(file); 需要使用 FileProvider.getUriForFile 的形式,通过File获取到Uri.
  2. 参考链接