package usung.com.m.utils;
import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.os.Build;
import android.os.Environment;
import android.util.Log;
import android.widget.Toast;
import com.tbruyelle.rxpermissions2.RxPermissions;
import java.io.File;
import java.io.IOException;
/**
* Descriptions:
* 应用程序在运行的过程中如果需要向手机上保存数据,一般是把数据保存在SDcard中的。
* 大部分应用是直接在SDCard的根目录下创建一个文件夹,然后把数据保存在该文件夹中。
* 这样当该应用被卸载后,这些数据还保留在SDCard中,留下了垃圾数据。
* 如果你想让你的应用被卸载后,与该应用相关的数据也清除掉,该怎么办呢?
*
* SDCard:/storage/emulated/0
* 通过Context.getExternalFilesDir()方法可以获取到 SDCard/Android/data/你的应用包名/files/目录,一般放一些长时间保存的数据(eg:数据库、Shared数据等)
* 通过Context.getExternalCacheDir()方法可以获取到 SDCard/Android/data/你的应用包名/cache/目录,一般存放临时缓存数据
*
* 如果使用上面的方法,当你的应用在被用户卸载后,SDCard/Android/data/你的应用的包名/ 这个目录下的所有文件都会被删除,不会留下垃圾信息。
*
* 而且上面二个目录分别对应 设置->应用->应用详情里面的”清除数据“与”清除缓存“选项
*
* Created by fenghui on 2018/8/31.
*/
public class FileUtils {
static StringTAG ="fenghui";
/**
* 检查 sdCard 是否可用
*
* @return
*/
public static boolean checkSdCard() {
return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
}
/**
* 一般存放临时缓存数据,对应设置中的清除缓存
* /storage/emulated/0/Android/data/usung.com.m/cache
*
* @param context
* @return
*/
public static FilegetExternalCacheDir(Context context) {
final File[] file = {null};
requestPermission(context, () ->file[0] =context.getExternalCacheDir());
return file[0];
}
/**
* 存储在internal storage(就是我们常说的运行内存);这是你app私有的目录,你的shared preference文件、数据库文件都存储在这里。
* 将一些重要的数据库文件以及一些用户配置文件存放在internal storage中
* 路径:data/data/< package name >/files/ eg:/data/user/0/usung.com.m/files
*
* @param context
* @return
*/
public static FilegetFilesDir(Context context) {
return context.getFilesDir();
}
/**
* 获取SD卡根文件夹
* 路径:/storage/emulated/0
*
* @return
*/
public static FilegetEvironmentExternalStorage(Context context) {
final File[] file = {null};
requestPermission(context, () ->file[0] = Environment.getExternalStorageDirectory());
return file[0];
}
/**
* 获取Android给我们提供了特定的目录,比如图片目录、媒体目录等DIRECTORY_MUSIC , DIRECTORY_PICTURES
* /storage/emulated/0/Picture
*
* @param type Environment.DIRECTORY_PICTURES/Environment.DIRECTORY_MUSIC
* @return
*/
public static FilegetAndroidSystemFile(Context context, String type) {
final File[] file = {null};
requestPermission(context, () -> {
file[0] = Environment.getExternalStoragePublicDirectory(type);
Log.i(TAG, "------------- file[0].getPath() ------------" +file[0].getPath());
});
return file[0];
}
/**
* 获取根目录下指定的文件
* /storage/emulated/0/fileName·
*
* @param fileName
* @return
*/
public static FilegetDesignatedFile(Context context, String fileName) {
final File[] file = {null};
requestPermission(context, () ->file[0] = Environment.getExternalStorageDirectory());
return file[0];
}
/**
* 创建文件夹
*
* @param context
* @param parentFilePath 一般为根目录路径
* @param childFileFolderName 要创建的文件夹的名称
* @return
*/
public static void createFileFolder(Context context, String parentFilePath, String childFileFolderName) {
requestPermission(context, () -> {
// // 创建名字为“FengHui”缓存文件夹,路径为“/storage/emulated/0/Android/data/包名/cacke/FengHui”
// File file = new File(context.getExternalCacheDir().getPath(), "FengHui");
File fileFolder =new File(parentFilePath, childFileFolderName);
if (fileFolder.exists()) {
Log.i(TAG, "------------ fileFolder.getPath() ------------ " + fileFolder.getPath() +"不能创建已存在的文件夹");
return;
}
fileFolder.mkdir();
});
}
/**
* 创建指定路径的文件
* @param context
* @param fileFolderPath
* @param fileName
*/
public static void createFile(Context context, String fileFolderPath, String fileName) {
requestPermission(context, () -> {
// // 创建一个路径为 fileFolderPath,文件名为“fenghui_log”的txt文件
// File file = new File(fileFolderPath, "fenghui_log.txt");
File file =new File(fileFolderPath, fileName);
if (file.exists()){
Log.i(TAG, "------------ file.getPath() ------------ " + file.getPath() +"不能创建已存在的文件");
return;
}
try{
file.createNewFile();
}catch (IOException e){
e.printStackTrace();
}
});
}
/**
* 一般放一些长时间保存的数据,对应设置中的清除数据
* app删除时,数据一起删除
* childFileName传null时,返回路径:/storage/emulated/0/Android/data/usung.com.m/files/
* childFileName传Caches时,返回路径:/storage/emulated/0/Android/data/usung.com.m/files/Caches
*
* @param context
* @param childFileName 参数传入为null时,这样默认访问的是files文件夹,我们可以指定子文件夹
* @return
*/
public static FilegetExternalFilesDir(Context context, String childFileName) {
final File[] file = {null};
requestPermission(context, () -> {
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED) || !Environment.isExternalStorageRemovable()) {
file[0] =context.getExternalFilesDir(null); // 此参数 null 可以指定文件夹 childFileName
}else {
file[0] =context.getFilesDir();
}
});
return file[0];
}
interface OnNextListener {
void doNext();
}
/**
* 文件的读写权限申请
* @param context
* @param onNextListener
*/
public static void requestPermission(Context context, OnNextListener onNextListener) {
if (!checkSdCard()){
Toast.makeText(context.getApplicationContext(), "SD卡不可用", Toast.LENGTH_SHORT).show();
return;
}
if (!needCheckPermission()){
onNextListener.doNext();
}else {
RxPermissions rxPermissions =new RxPermissions((Activity) context);
rxPermissions.requestEach(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE)
.subscribe(permission -> {
if (permission.granted) {
onNextListener.doNext();
}else {
if (permission.shouldShowRequestPermissionRationale) {
Toast.makeText(context.getApplicationContext(), "需开启存储权限1", Toast.LENGTH_SHORT).show();
return;
}else {
Toast.makeText(context.getApplicationContext(), "需开启存储权限2", Toast.LENGTH_SHORT).show();
return;
}
}
});
}
}
/**
* 是否需要检查权限
*/
public static boolean needCheckPermission() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;
}
}