引言:大家在做app开发的时候,基本都会保存文件到手机,android存储文件的地方有很多,不像ios一样,只能把文件存储到当前app目录下,并且android手机由于厂家定制了rom,sdcard的路径在不同手机上都会不一样.我这边封装了获取路径的几个方法,放在一个工具类里面.
1.获取扩展存储设备
2.获取sdcard2外部存储空间
3.获取可用的 EMMC 内部存储空间
4.获取其他外部存储可用空间
5.获取内部存储目录
Activity 程序的入口,在oncreate方法里面通过工具类获取文件保存路径,并且打印出来.(还写了一个创建指定大小空文件的方法,有需要的可以调用)
/** * 获取存储路径,并且打印出来 * @author ansen * @create time 2015-09-07 */ public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); String str=FileUtil.getCachePath(); // writeFileSize(str+"/ansen.mp3",50); //在当前目录下创建ansen.mp3文件 文件长度50兆 System.out.println(str); } /** * 创建指定大小的文件.写入空数据 * @param filePath 文件路径 * @param size 文件长度 单位是兆 */ private void writeFileSize(String filePath,int size){ try { RandomAccessFile raf = new RandomAccessFile(filePath,"rw"); raf.seek(raf.length());//每次从文件末尾写入 for (int i = 0; i < size; i++) {//一共写入260兆,想写多大的文件改变这个值就行 byte[] buffer = new byte[1024*1024]; //1次1M,这样内存开的大一些,又不是特别大。 raf.write(buffer); System.out.println("写入1兆..."+i); } raf.close(); } catch (Exception e) { e.printStackTrace(); } } }
文件工具类 封装了一个公共方法,获取文件保存路径,一共可以获取5个路径,依次判断5个路径预留空间是否大于50兆.大于就直接返回路径
/** * 文件工具类 * @author ansen * @create time 2015-09-07 */ public final class FileUtil { private static final String FOLDER_NAME = "ansen";//这里可以换成你的app名称 private static final long MIN_STORAGE=52428800;//50*1024*1024最低50m //缓存路径 public static String getCachePath(){ String path = getSavePath(MIN_STORAGE); if(TextUtils.isEmpty(path)){ return null; } path= path + FOLDER_NAME + "/cache"; makeDir(path); return path; } /** * 获取保存文件路径 * @param saveSize 预留空间 * @return 文件路径 */ private static String getSavePath(long saveSize) { String savePath = null; if (StorageUtil.getExternaltStorageAvailableSpace() > saveSize) {//扩展存储设备>预留空间 savePath = StorageUtil.getExternalStorageDirectory(); File saveFile = new File(savePath); if (!saveFile.exists()) { saveFile.mkdirs(); } else if (!saveFile.isDirectory()) { saveFile.delete(); saveFile.mkdirs(); } } else if (StorageUtil.getSdcard2StorageAvailableSpace() > saveSize) {//sdcard2外部存储空间>预留空间 savePath = StorageUtil.getSdcard2StorageDirectory(); File saveFile = new File(savePath); if (!saveFile.exists()) { saveFile.mkdirs(); } else if (!saveFile.isDirectory()) { saveFile.delete(); saveFile.mkdirs(); } } else if (StorageUtil.getEmmcStorageAvailableSpace() > saveSize) {//可用的 EMMC 内部存储空间>预留空间 savePath = StorageUtil.getEmmcStorageDirectory(); File saveFile = new File(savePath); if (!saveFile.exists()) { saveFile.mkdirs(); } else if (!saveFile.isDirectory()) { saveFile.delete(); saveFile.mkdirs(); } } else if (StorageUtil.getOtherExternaltStorageAvailableSpace()>saveSize) {//其他外部存储可用空间>预留空间 savePath = StorageUtil.getOtherExternalStorageDirectory(); File saveFile = new File(savePath); if (!saveFile.exists()) { saveFile.mkdirs(); } else if (!saveFile.isDirectory()) { saveFile.delete(); saveFile.mkdirs(); } }else if (StorageUtil.getInternalStorageAvailableSpace() > saveSize) {//内部存储目录>预留空间 savePath = StorageUtil.getInternalStorageDirectory() + File.separator; } return savePath; } /** * 创建文件夹 * @param path */ private static void makeDir(String path){ File file = new File(path); if(!file.exists()){ file.mkdirs(); } file = null; } }
封装了获取各种路径的一些方法,供FileUtil类调用.
/** * 封装了获取文件路径的一些方法 * @author ansen * @create time 2015-09-07 */ @SuppressLint("NewApi") public final class StorageUtil { private static String otherExternalStorageDirectory = null; private static int kOtherExternalStorageStateUnknow = -1; private static int kOtherExternalStorageStateUnable = 0; private static int kOtherExternalStorageStateIdle = 1; private static int otherExternalStorageState = kOtherExternalStorageStateUnknow; private static String internalStorageDirectory; public static Context context; public static void init(Context cxt) { context = cxt; } /** get external Storage available space */ public static long getExternaltStorageAvailableSpace() { if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { return 0; } File path = Environment.getExternalStorageDirectory(); StatFs statfs = new StatFs(path.getPath()); long blockSize; if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2){ blockSize = statfs.getBlockSizeLong(); }else { blockSize = statfs.getBlockSize(); } long availableBlocks; if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2){ availableBlocks = statfs.getAvailableBlocksLong(); }else { availableBlocks = statfs.getAvailableBlocks(); } return blockSize * availableBlocks; } public final static String getInternalStorageDirectory() { if (TextUtils.isEmpty(internalStorageDirectory)) { File file = context.getFilesDir(); internalStorageDirectory = file.getAbsolutePath(); if (!file.exists()) file.mkdirs(); String shellScript = "chmod 705 " + internalStorageDirectory; runShellScriptForWait(shellScript); } return internalStorageDirectory; } public static long getInternalStorageAvailableSpace() { String path = getInternalStorageDirectory(); StatFs stat = new StatFs(path); // long blockSize = stat.getBlockSizeLong(); long blockSize; if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2){ blockSize = stat.getBlockSizeLong(); }else { blockSize = stat.getBlockSize(); } // long availableBlocks = stat.getAvailableBlocksLong(); long availableBlocks; if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2){ availableBlocks = stat.getAvailableBlocksLong(); }else { availableBlocks = stat.getAvailableBlocks(); } return blockSize * availableBlocks; } public final static String getExternalStorageDirectory() { return Environment.getExternalStorageDirectory() + File.separator + ""; } /** get sdcard2 external Storage available space */ public static long getSdcard2StorageAvailableSpace() { if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { return 0; } String path = getSdcard2StorageDirectory(); File file = new File(path); if (!file.exists()) return 0; StatFs statfs = new StatFs(path); // long blockSize = statfs.getBlockSizeLong(); long blockSize; if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2){ blockSize = statfs.getBlockSizeLong(); }else { blockSize = statfs.getBlockSize(); } // long availableBlocks = statfs.getAvailableBlocksLong(); long availableBlocks; if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2){ availableBlocks = statfs.getAvailableBlocksLong(); }else { availableBlocks = statfs.getAvailableBlocks(); } return blockSize * availableBlocks; } public final static String getSdcard2StorageDirectory() { return "/mnt/sdcard2/"; } public static boolean runShellScriptForWait(final String cmd)throws SecurityException { ShellThread thread = new ShellThread(cmd); thread.setDaemon(true); thread.start(); int k = 0; while (!thread.isReturn() && k++ < 20) { try { Thread.sleep(50); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if (k >= 20) { thread.interrupt(); } return thread.isSuccess(); } /** 用于执行shell脚本的线程 */ private static class ShellThread extends Thread { private boolean isReturn; private boolean isSuccess; private String cmd; public boolean isReturn() { return isReturn; } public boolean isSuccess() { return isSuccess; } /** * @param cmd shell命令内容 * @param isReturn 线程是否已经返回 * @param isSuccess Process是否执行成功 */ public ShellThread(String cmd) { this.cmd = cmd; } @Override public void run() { try { Runtime runtime = Runtime.getRuntime(); Process proc; try { proc = runtime.exec(cmd); isSuccess = (proc.waitFor() == 0); } catch (IOException e) { e.printStackTrace(); } isSuccess = true; } catch (InterruptedException e) { } isReturn = true; } } /** get EMMC internal Storage available space */ public static long getEmmcStorageAvailableSpace() { String path = getEmmcStorageDirectory(); File file = new File(path); if (!file.exists()) return 0; StatFs statfs = new StatFs(path); // long blockSize = statfs.getBlockSizeLong(); long blockSize; if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2){ blockSize = statfs.getBlockSizeLong(); }else { blockSize = statfs.getBlockSize(); } // long availableBlocks = statfs.getAvailableBlocksLong(); long availableBlocks; if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2){ availableBlocks = statfs.getAvailableBlocksLong(); }else { availableBlocks = statfs.getAvailableBlocks(); } return blockSize * availableBlocks; } public final static String getEmmcStorageDirectory() { return "/mnt/emmc/"; } /** get other external Storage available space */ public static long getOtherExternaltStorageAvailableSpace() { if (!Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED)) { return 0; } if (otherExternalStorageState == kOtherExternalStorageStateUnable) return 0; if (otherExternalStorageDirectory == null) { getOtherExternalStorageDirectory(); } if (otherExternalStorageDirectory == null) return 0; StatFs statfs = new StatFs(otherExternalStorageDirectory); // long blockSize = statfs.getBlockSizeLong(); long blockSize; if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2){ blockSize = statfs.getBlockSizeLong(); }else { blockSize = statfs.getBlockSize(); } // long availableBlocks = statfs.getAvailableBlocksLong(); long availableBlocks; if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2){ availableBlocks = statfs.getAvailableBlocksLong(); }else { availableBlocks = statfs.getAvailableBlocks(); } return blockSize * availableBlocks; } public static String getOtherExternalStorageDirectory() { if (otherExternalStorageState == kOtherExternalStorageStateUnable) return null; if (otherExternalStorageState == kOtherExternalStorageStateUnknow) { FstabReader fsReader = new FstabReader(); if (fsReader.size() <= 0) { otherExternalStorageState = kOtherExternalStorageStateUnable; return null; } List<StorageInfo> storages = fsReader.getStorages(); /* 对于可用空间小于100M的挂载节点忽略掉 */ long availableSpace = 100 << (20); String path = null; for (int i = 0; i < storages.size(); i++) { StorageInfo info = storages.get(i); if (info.getAvailableSpace() > availableSpace) { availableSpace = info.getAvailableSpace(); path = info.getPath(); } } otherExternalStorageDirectory = path; if (otherExternalStorageDirectory != null) { otherExternalStorageState = kOtherExternalStorageStateIdle; } else { otherExternalStorageState = kOtherExternalStorageStateUnable; } if(!TextUtils.isEmpty(otherExternalStorageDirectory)){ if(!otherExternalStorageDirectory.endsWith("/")){ otherExternalStorageDirectory=otherExternalStorageDirectory+"/"; } } } return otherExternalStorageDirectory; } public static class FstabReader { public FstabReader() { init(); } public int size() { return storages == null ? 0 : storages.size(); } public List<StorageInfo> getStorages() { return storages; } final List<StorageInfo> storages = new ArrayList<StorageInfo>(); public void init() { File file = new File("/system/etc/vold.fstab"); if (file.exists()) { FileReader fr = null; BufferedReader br = null; try { fr = new FileReader(file); if (fr != null) { br = new BufferedReader(fr); String s = br.readLine(); while (s != null) { if (s.startsWith("dev_mount")) { /* "s"转义符匹配的内容有:半/全角空格 */ String[] tokens = s.split("\s"); String path = tokens[2]; // mount_point StatFs stat = new StatFs(path); long blockSize; long totalBlocks; long availableBlocks; if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2){ blockSize = stat.getBlockSizeLong(); }else { blockSize = stat.getBlockSize(); } if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2){ totalBlocks = stat.getBlockCountLong(); }else { totalBlocks = stat.getBlockCount(); } if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2){ availableBlocks = stat.getAvailableBlocksLong(); }else { availableBlocks = stat.getAvailableBlocks(); } // if (null != stat&& stat.getAvailableBlocksLong() > 0) { // // long availableSpace = stat.getAvailableBlocksLong()* stat.getBlockSizeLong(); // long totalSpace = stat.getBlockCountLong()* stat.getBlockSizeLong(); if (null != stat&& availableBlocks > 0) { long availableSpace = availableBlocks* blockSize; long totalSpace = totalBlocks* blockSize; StorageInfo storage = new StorageInfo(path, availableSpace, totalSpace); storages.add(storage); } } s = br.readLine(); } } } catch (Exception e) { e.printStackTrace(); } finally { if (fr != null) try { fr.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } if (br != null) try { br.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } } static class StorageInfo implements Comparable<StorageInfo> { private String path; private long availableSpace; private long totalSpace; StorageInfo(String path, long availableSpace, long totalSpace) { this.path = path; this.availableSpace = availableSpace; this.totalSpace = totalSpace; } @Override public int compareTo(StorageInfo another) { if (null == another) return 1; return this.totalSpace - another.totalSpace > 0 ? 1 : -1; } long getAvailableSpace() { return availableSpace; } long getTotalSpace() { return totalSpace; } String getPath() { return path; } } }
最后记得在AndroidManifest.xml中配置读写sdcard权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />