Android 内部存储和外部存储

版权声明:本文为【路易斯】原创文章,转载请注明出处! https://blog.csdn.net/RichieZhu/article/details/79427684

这里写图片描述
点击查看大图

点我查看原图

LogicalInternalStorageTool.java

/**
 * Created by classichu on 2018/3/2.
 * <p>
 * 逻辑上的 Internal storage:
 * 1 总是可用的
 * 2 这里的文件默认只能被我们的app所访问。
 * 3 当用户卸载app的时候,系统会把internal内该app相关的文件都清除干净。
 * 4 Internal是我们在想确保不被用户与其他app所访问的最佳存储区域。
 * <p>
 * data 目录
 * <p>
 * 这下面的文件会在用户卸载我们的app时被系统删除
 * <p>
 * Android6.0+支持多用户 /data/user/0/<application package>
 */

public class LogicalInternalStorageTool {

    /**
     * /cache
     *
     * @return
     */
    @Deprecated //功能示例
    public static String getDownloadCacheDirectoryPath() {
        return Environment.getDownloadCacheDirectory().getAbsolutePath();
    }


    /**
     * /system
     */
    @Deprecated //功能示例
    public static String getRootDirectoryPath() {
        return Environment.getRootDirectory().getAbsolutePath();
    }


    /**
     * /data
     */
    @Deprecated //功能示例
    public static String getDataDirectoryPath() {
        return Environment.getDataDirectory().getAbsolutePath();
    }

    /**
     * app 的 internal 目录
     * <p>
     * /data/data/<application package>/files
     * <p>
     * miui等系统应用多开 时候
     * /data/user/0/<application package>/files
     * miui等系统应用多开 时候 小号
     * /data/user/999/<application package>/files
     *
     * @param context
     * @return
     */
    public static String getFilesDirPath(Context context) {
        return context.getFilesDir().getAbsolutePath();
    }

    /**
     * /data/data/<application package>/files/file1
     */
    @Deprecated //功能示例
    public static String getFileStreamPath(Context context) {
        return context.getFileStreamPath("file1").getAbsolutePath();
    }

    /**
     * 对于 Files 目录下的文件,通常不会通过 File 类的方式直接进行读写,而是利用一些封装过的类或函数进行操作
     * /data/data/<application package>/files/file2  的 FileInputStream
     */
    @Deprecated //功能示例
    public static FileInputStream openFileInput(Context context) {
        try {
            return context.openFileInput("file2");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 对于 Files 目录下的文件,通常不会通过 File 类的方式直接进行读写,而是利用一些封装过的类或函数进行操作
     * /data/data/<application package>/files/file2  的 FileOutputStream
     */
    @Deprecated //功能示例
    public static FileOutputStream openFileOutput(Context context) {
        try {
            return context.openFileOutput("file2", Context.MODE_PRIVATE);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 对于 Files 目录下的文件,通常不会通过 File 类的方式直接进行读写,而是利用一些封装过的类或函数进行操作
     * 删除
     */
    @Deprecated //功能示例
    public static boolean deleteFile(Context context) {
        return context.deleteFile("file2");
    }

    /**
     * 对于 Files 目录下的文件,通常不会通过 File 类的方式直接进行读写,而是利用一些封装过的类或函数进行操作
     * 查询
     */
    @Deprecated //功能示例
    public static String[] fileList(Context context) {
        return context.fileList();
    }

    /**
     * app 的 internal 缓存目录
     * <p>
     * /data/data/<application package>/cache
     * miui等系统应用多开 时候
     * /data/user/0/<application package>/cache
     * miui等系统应用多开 时候 小号
     * /data/user/999/<application package>/cache
     *
     * @param context
     * @return
     */
    public static String getCacheDirPath(Context context) {
        return context.getCacheDir().getAbsolutePath();
    }

    /**
     * 检索目录,如果没有,该方法会在 /data/data/application package>/ 目录下生成一个以 app_ 开头的文件夹
     * /data/data/<application package>/app_dir1
     *
     * @param context
     * @return
     */
    @Deprecated //功能示例
    public static String getDirPath(Context context) {
        return context.getDir("dir1", Context.MODE_PRIVATE).getAbsolutePath();
    }

    /**
     * /data/data/<application package>/shared_prefs/sp
     *
     * @param context
     * @return
     */
    @Deprecated //功能示例
    public static SharedPreferences getSharedPreferences(Context context) {
        return context.getSharedPreferences("sp", Context.MODE_PRIVATE);
    }

    @Deprecated //功能示例
    public static boolean deleteSharedPreferences(Context context) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            return context.deleteSharedPreferences("sp");
        }
        return false;
    }

    /**
     * name 是 SQLiteDatabase.openOrCreateDatabase(String name ... 中的name
     *
     * @param context
     * @return
     */
    @Deprecated //功能示例
    public static String getDatabasePath(Context context) {
        return context.getDatabasePath("dbname.db").getAbsolutePath();
    }

    /**
     * /data/data/<application package>
     * @param context
     * @return
     */
    public static String getDataDir(Context context) {
        return ContextCompat.getDataDir(context).getAbsolutePath();
    }
    /**
     * /data/data/<application package>/no_backup
     * @param context
     * @return
     */
    @Deprecated //功能示例
    public static String getNoBackupFilesDirPath(Context context) {
        return ContextCompat.getNoBackupFilesDir(context).getAbsolutePath();
    }
    /**
     * /data/data/<application package>/code_cache
     * @param context
     * @return
     */
    @Deprecated //功能示例
    public static String getCodeCacheDirPath(Context context) {
        return ContextCompat.getCodeCacheDir(context).getAbsolutePath();
    }
}

LogicalExternalStorageTool.java



/**
 * Created by classichu on 2018/3/2.
 * 逻辑上的 External storage
 * LogicalExternalStorage =  PhysicalInternalStorage + PhysicalExternalStorage
 * 1 并不总是可用的,因为用户有时会通过USB存储模式挂载外部存储器,当取下挂载的这部分后,就无法对其进行访问了。
 * 2 是大家都可以访问的,因此保存在这里的文件可能被其他程序访问。
 * 3 当用户卸载我们的app时,系统仅仅会删除external根目录(getExternalFilesDir())下的相关文件。
 * 4 External是在不需要严格的访问权限并且希望这些文件能够被其他app所共享或者是允许用户通过电脑访问时的最佳存储区域。
 * <p>
 * 包括 物理上的内置存储卡( ROM 机身存储空间 )和外置存储卡(内存卡 / micro SD卡 / TF卡)
 * 需要
 * <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
 */

public class LogicalExternalStorageTool {

    /**
     * MEDIA_UNKNOWN
     * MEDIA_REMOVED
     * MEDIA_UNMOUNTED
     * MEDIA_CHECKING
     * MEDIA_NOFS
     * MEDIA_MOUNTED
     * MEDIA_MOUNTED_READ_ONLY
     * MEDIA_SHARED
     * MEDIA_BAD_REMOVAL
     * MEDIA_UNMOUNTABLE
     *
     * @return
     */
    /* Checks if external storage is available for read and write */
    public static boolean isExternalStorageWritable() {
        String state = Environment.getExternalStorageState();
        if (Environment.MEDIA_MOUNTED.equals(state)) {
            return true;
        }
        return false;
    }

    /* Checks if external storage is available to at least read */
    public static boolean isExternalStorageReadable() {
        String state = Environment.getExternalStorageState();
        if (Environment.MEDIA_MOUNTED.equals(state) ||
                Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
            return true;
        }
        return false;
    }

    /**
     * 表示外部存储是否可以物理卸载
     *
     * @return
     */
    @Deprecated //功能示例
    public static boolean isExternalStorageRemovable() {
        return Environment.isExternalStorageRemovable();
    }

    /**
     * 表示外部存储是否可以安装apk
     *
     * @return
     */
    @Deprecated //功能示例
    public static boolean isExternalStorageEmulated() {
        return Environment.isExternalStorageEmulated();
    }

    public static boolean isPhysicalExternalStorageWritable(Context context, String path) {
        try {
            StorageManager sm = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
            Method method = StorageManager.class.getMethod("getVolumeState", String.class);
            String state = (String) method.invoke(sm, path);
            if (state.equals(Environment.MEDIA_MOUNTED)) {
                return true;
            }
            return false;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    public static boolean isPhysicalExternalStorageReadable(Context context, String path) {
        try {
            StorageManager sm = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
            Method method = StorageManager.class.getMethod("getVolumeState", String.class);
            String state = (String) method.invoke(sm, path);
            if (state.equals(Environment.MEDIA_MOUNTED) ||
                    state.equals(Environment.MEDIA_MOUNTED_READ_ONLY)) {
                return true;
            }
            return false;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    private static String[] getLogicalExternalStoragePaths(Context context) {
        try {
            StorageManager sm = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
            Method getVolumePathsMethod = StorageManager.class.getMethod("getVolumePaths");
            //获取所有sd卡路径
            String[] paths = (String[]) getVolumePathsMethod.invoke(sm);
            return paths;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 获取内置内存卡 Physical Internal storage / Physical UnRemovable storage 路径
     * 例: /storage/emulated/0   【/mnt/m_internal_storage】
     * 或
     * /storage/sdcard0
     * <p>
     * {@link LogicalExternalStorageTool#getExternalStorageDirectoryPath()}
     *
     * @param context
     * @return
     */
    public static String getPhysicalInternalStoragePath(Context context) {
        String[] paths = getLogicalExternalStoragePaths(context);
        if (paths != null && paths.length > 0) {
            return paths[0];
        }
        return null;
    }

    /**
     * //获取其他所有可用 外置内存卡 Physical External storage / Physical Removable storage 路径 集合
     * 可能是/mnt/sdcard、/mnt/extsd、/mnt/external_sd 、/mnt/sdcard2
     *
     * @param context
     * @return
     */
    @Deprecated //不常用
    public static List<String> getPhysicalExternalStoragePathList(Context context) {
        String[] paths = getLogicalExternalStoragePaths(context);
        if (paths != null && paths.length > 1) {
            List<String> sdPathList = new ArrayList<>();
            for (int i = 1; i < paths.length; i++) {
                if (isPhysicalExternalStorageReadable(context, paths[i])) {
                    sdPathList.add(paths[i]);
                }
            }
            return sdPathList;
        }
        return null;
    }


    /**
     * 获取第一个外置内存卡 External storage / Removable storage 路径
     * 可能是/mnt/sdcard、/mnt/extsd、/mnt/external_sd 、/mnt/sdcard2
     * <p>
     * 例:
     * /storage/sdcard1  【/mnt/m_external_sd】
     * 真机:
     * /storage/sdcard1     华为 M2-A01W
     * /storage/E8C3-9C76   红米 NOTE 4X
     * /storage/6279-371D   Galaxy Tab S2  SM-T819C
     * /storage/0403-0201   华为 nova 2s
     *
     * @param context
     * @return
     */
    public static String getPhysicalExternalStoragePath(Context context) {
        List<String> removableStoragePathList = getPhysicalExternalStoragePathList(context);
        if (removableStoragePathList != null && removableStoragePathList.size() > 0) {
            return removableStoragePathList.get(0);
        }
        return null;
    }


    /**
     * Public files
     * <p>
     * /storage/emulated/0/Download  【"mnt/sdcard/Download"】
     * 或
     * /storage/sdcard0/Download
     * <p>
     * 其他
     * Environment.DIRECTORY_MUSIC 音乐
     * Environment.DIRECTORY_PODCASTS 音/视频的剪辑片段
     * Environment.DIRECTORY_ALARMS  闹钟的声音
     * Environment.DIRECTORY_RINGTONES  铃声
     * Environment.DIRECTORY_NOTIFICATIONS
     * Environment.DIRECTORY_PICTURES 图片
     * Environment.DIRECTORY_MOVIES 电影
     * Environment.DIRECTORY_DOWNLOADS 下载的内容
     * Environment.DIRECTORY_DCIM 拍摄的照片/视频
     * Environment.DIRECTORY_DOCUMENTS 文档
     *
     * @return
     */
    @Deprecated //功能示例
    public static String getExternalStoragePublicDirectory_DirectoryDownloads() {
        return Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath();
    }

    /**
     * 获取内置存储卡路径
     * /storage/emulated/0
     * 或
     * /storage/sdcard0
     *
     * @return
     */
    public static String getExternalStorageDirectoryPath() {
        return Environment.getExternalStorageDirectory().getAbsolutePath();
    }

    /**
     * /storage/emulated/0/Android/data/<application package>/cache
     * 或
     * /storage/sdcard0/Android/data/<application package>/cache
     * Private files :缓存文件
     * 注意:这下面的文件会在用户卸载我们的app时被系统删除
     * 对应 设置->应用->应用详情里面的"清除缓存"选项
     *
     * @return
     */
    public static String getExternalCacheDirPath(Context context) {
        return context.getExternalCacheDir().getAbsolutePath();
    }

    /**
     * /storage/emulated/0/Android/data/<application package>/files/Download
     * 或
     * /storage/sdcard0/Android/data/<application package>/files/Download
     * Private  files :数据文件
     * 注意:这下面的文件会在用户卸载我们的app时被系统删除
     * 对应 设置->应用->应用详情里面的"清除数据"选项
     * 其他
     * Environment.DIRECTORY_MUSIC 音乐
     * Environment.DIRECTORY_PODCASTS 音/视频的剪辑片段
     * Environment.DIRECTORY_ALARMS  闹钟的声音
     * Environment.DIRECTORY_RINGTONES  铃声
     * Environment.DIRECTORY_NOTIFICATIONS
     * Environment.DIRECTORY_PICTURES 图片
     * Environment.DIRECTORY_MOVIES 电影
     * Environment.DIRECTORY_DOWNLOADS 下载的内容
     * Environment.DIRECTORY_DCIM 拍摄的照片/视频
     * Environment.DIRECTORY_DOCUMENTS 文档
     *
     * @return
     */
    @Deprecated //功能示例
    public static String getExternalFilesDirPath_DirectoryDownloads(Context context) {
        return context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath();
    }

    /**
     * /storage/emulated/0/Android/data/<application package>/files
     * 或
     * /storage/sdcard0/Android/data/<application package>/files
     * Private  files :数据文件
     * 注意:这下面的文件会在用户卸载我们的app时被系统删除
     * 对应 设置->应用->应用详情里面的"清除数据"选项
     *
     * @param context
     * @return
     */
    public static String getExternalFilesDirPath(Context context) {
        return context.getExternalFilesDir(null).getAbsolutePath();
    }

    /**
     * 集合
     *
     * @param context
     * @return
     */
    @Deprecated //功能示例
    public static File[] getExternalFilesDirs(Context context) {
        return ContextCompat.getExternalFilesDirs(context, null);
    }

    /**
     * /storage/emulated/0/Android/data/<application package>/files/file1
     *
     * @param context
     * @return
     */
    @Deprecated //功能示例
    public static String getExternalFilesDirPath_File1(Context context) {
        return context.getExternalFilesDir("file1").getAbsolutePath();
    }

    /**
     * 集合
     *
     * @param context
     * @return
     */
    @Deprecated //功能示例
    public static File[] getExternalFilesDirs_File1(Context context) {
        return ContextCompat.getExternalFilesDirs(context, "file1");
    }

    /**
     * /storage/emulated/0/Android/media/<application package>
     *
     * @param context
     * @return
     */
    @Deprecated //功能示例
    public static File[] getExternalMediaDirs(Context context) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            return context.getExternalMediaDirs();
        }
        return null;
    }

    /**
     * 迅雷下载路径一般在这
     * /storage/emulated/0/Android/obb/<application package>
     * 或
     * /storage/sdcard0/Android/obb/<application package>
     *
     * @param context
     * @return
     */
    @Deprecated //功能示例
    public static String getObbDirPath(Context context) {
        return context.getObbDir().getAbsolutePath();
    }

    /**
     * 集合
     *
     * @param context
     * @return
     */
    @Deprecated //功能示例
    public static File[] getObbDirs(Context context) {
        return ContextCompat.getObbDirs(context);
    }
}

猜你喜欢

转载自blog.csdn.net/RichieZhu/article/details/79427684