今天跟大家谈谈关于在app开发过程中,整个App路径的统一管理,特别是在android4.4的系统上,app在SD卡的读写权限以及创建子文件夹和文件都受到了android系统本身的限制。    网上关于这块的书写,其实很多,但是自己后面想了想,我个人觉得android app路径应该统一管理在这个目录/storage/sdcard0 or sdcard1/Android/data/<包名>/下,这样可以保证整个SD卡目录的清晰和不混乱!同时,当整个软件被卸载的时候,整个程序安装包名下的所有文件与资料都可以不删除掉,而不会导致多余的卸载残余,影响整个sd卡的目录结构,造成混乱与浪费!    好吧!说了那么多,上我整理的代码(不喜勿喷)AppPathManager.class:
/** * @类描述:app全局统一路径管理类 * @修改备注:所有的安卓开发者都应该按照这个方向走,不要再随意地再SD卡里建立各式各样的文件夹, * 而应该将所有应用数据都在/Android/data/内进行读写 * 。统一的规范并不违背开源的初衷, * 甚至有利于整个生态圈的有序发展。 */public class AppPathManager {    /** * @方法说明:返回多个sd卡的该应用私有数据区的files目录 * @方法名称:getExternalRootFilesCachePath * @return:/storage/sdcard0 or sdcard1/Android/data/<包名>/files * @返回值:StringBuffer */    public static StringBuffer getExternalRootFilesCachePath() {        return new StringBuffer(LynApplication.context.getExternalFilesDir(                Environment.MEDIA_MOUNTED).getAbsolutePath()).append("/");    }    /** * @方法说明:返回多个sd卡下该应用私有数据库的缓存目录 * @方法名称:getExternalRootCachePath * @return:/storage/sdcard0 or sdcard1/Android/data/<包名>/caches * @返回值:StringBuffer */    public static StringBuffer getExternalRootCachePath() {        return new StringBuffer(LynApplication.context.getExternalCacheDir()                .getAbsolutePath()).append("/");    }    /** * @方法说明:图片保存路径(统一默认为:yyyy-MM-dd_HH:mm:ss.jpg, 方便后面自动清除) * @方法名称:getDownloadImagePath * @param type * @return * @返回值:String */    public static String getDownloadImagePath() {        return getExternalRootCachePath()                .append("image/")                .append(DateTime.formatDate(new Date(),                        DateTime.DATE_PATTERN_13)).append(".jpg").toString();    }    /** * @方法说明:Alog日志保存文件地址 * @方法名称:getAlogPath * @return * @返回值:String */    public static String getAlogPath() {        return getExternalRootFilesCachePath().append("Alog/").toString();    }    /** * 这两个方法是通过上下文对象Context获取的,只要应用程序被卸载,这两个目录下的文件都要被清空。 context.getCacheDir() * 获取应用程序自己的缓存目录 context.getExternalCacheDir() 获取应用程序在外部存储的存储目录 */    public static StringBuffer getInternalRootCachePath() {        return new StringBuffer(LynApplication.context.getCacheDir()                .getAbsolutePath()).append("/");    }    /** * @方法说明:外置SD 卡公共目录,这些目录仍然可以切只允许访问,不受权限限制 * @方法名称:getExternalPublicPath * @return * @返回值:StringBuffer */    public static StringBuffer getExternalPublicPath() {        return new StringBuffer(Environment.getExternalStoragePublicDirectory(                Environment.MEDIA_MOUNTED).getAbsolutePath())                .append("/");    }    /** * @方法说明:获取系统的根目录 * @方法名称:getSystemRoot * @return * @返回值:StringBuffer */    public static StringBuffer getSystemRoot() {        return new StringBuffer(Environment.getRootDirectory()                .getAbsolutePath()).append("/");// 获得系统主目录(/system)    }    /** * @方法说明:获取手机存储的WanKeXing根路径 * @方法名称:getRootFilePath * @return * @返回值:StringBuffer */    public static StringBuffer getRootFilePath() {        if (hasSDCard()) {            // 获得外部存储媒体目录(mnt/sdcard or /storage/sdcard0)            return new StringBuffer(Environment.getExternalStorageDirectory()                    .getAbsolutePath()).append("/");        } else {            // 获得data的目录(/data)            return new StringBuffer(Environment.getDataDirectory()                    .getAbsolutePath()).append("/");        }    }    /** * @方法说明:判断SD卡是否存在 * @方法名称:hasSDCard * @return * @返回值:boolean */    public static boolean hasSDCard() {        String status = Environment.getExternalStorageState();        if (!status.equals(Environment.MEDIA_MOUNTED)) {            return false;        }        return true;    }    /** * @方法说明:清理掉十天前一天的缓存图片数据 * @方法名称:delImgCacheFileBeforeWeek * @返回值:void */    public static void delImgCacheFileBeforeWeek() {        String needDelField = DateTime.formatDate(getDateBefore(10),                DateTime.DATE_PATTERN_2);        File file = new File(getExternalRootCachePath().toString());        if (file.exists() && file.isDirectory()) {            File[] list = file.listFiles();            for (File file2 : list) {                String name = file2.getName();                if (name.contains(needDelField)) {                    file2.delete();                }            }        }    }    /** * @方法说明:获取以前的时间 * @方法名称:getDateBefore * @param spanDay * @return * @返回值:Date */    private static Date getDateBefore(int spanDay) {        Date nowtime = new Date();        Calendar now = Calendar.getInstance();        now.setTime(nowtime);        now.set(Calendar.DATE, now.get(Calendar.DATE) - spanDay);        return now.getTime();    }}

补充个日期转换:

    public static final String GROUP_BY_EACH_DAY = "yyyyMMdd";    public static final String GROUP_BY_EACH_DAYSM = "yyyyMMddHHmmss";    public static final String GROUP_BY_EACH_SECOND = "yyyyMMddHHmm";    public final static String TIME_PATTERN = "HH:mm:ss";// 定义标准时间格式    public final static String DATE_PATTERN_1 = "yyyy/MM/dd";// 定义标准日期格式1    public final static String DATE_PATTERN_2 = "yyyy-MM-dd";// 定义标准日期格式2    public final static String DATE_PATTERN_3 = "yyyy/MM/dd HH:mm:ss";// 定义标准日期格式3,带有时间    public final static String DATE_PATTERN_4 = "yyyy/MM/dd HH:mm:ss E";// 定义标准日期格式4,带有时间和星期    public final static String DATE_PATTERN_5 = "yyyy年MM月dd日 HH:mm:ss E";// 定义标准日期格式5,带有时间和星期    public final static String DATE_PATTERN_6 = "yyyy-MM-dd HH:mm:ss";// 定义标准日期格式6,带有时间    public final static String DATE_PATTERN_7 = "yyyy年MM月dd日";// 定义标准日期格式7    public final static String DATE_PATTERN_8 = "yyyy-MM-dd HH:mm";// 定义标准日期格式8,带有时间    public final static String DATE_PATTERN_9 = "yy-MM-dd HH时";// 定义标准日期格式9,带有时间    public final static String DATE_PATTERN_10 = "yy/MM/dd HH:mm";// 定义标准日期格式10,带有时间    public final static String DATE_PATTERN_11 = "yy.MM.dd";// 定义标准日期格式11,带有时间    public final static String DATE_PATTERN_12 = "yyyyMMdd";// 定义标准日期格式12,带有时间    public final static String DATE_PATTERN_13 = "yyyy-MM-dd_HH:mm:ss";// 定义标准日期格式13,带有时间    /** * @方法说明:把一个日期,按照某种格式 格式化输出 * @方法名称:formatDate * @param date日期对象 * @param pattern格式模型 * @return * @返回值:String */    public static String formatDate(Date date, String pattern) {        if (date != null) {            SimpleDateFormat sdf = new SimpleDateFormat(pattern);            return sdf.format(date);        }        return "";    }

根据我个人的习惯用法,我喜欢在整个app的实际开发中,真个app的全局路径还是用以下两个方法就完全ok了:

    /** * @方法说明:返回多个sd卡的该应用私有数据区的files目录 * @方法名称:getExternalRootFilesCachePath * @return:/storage/sdcard0 or sdcard1/Android/data/<包名>/files * @返回值:StringBuffer */    public static StringBuffer getExternalRootFilesCachePath() {        return new StringBuffer(LynApplication.context.getExternalFilesDir(                Environment.MEDIA_MOUNTED).getAbsolutePath()).append("/");    }    /** * @方法说明:返回多个sd卡下该应用私有数据库的缓存目录 * @方法名称:getExternalRootCachePath * @return:/storage/sdcard0 or sdcard1/Android/data/<包名>/caches * @返回值:StringBuffer */    public static StringBuffer getExternalRootCachePath() {        return new StringBuffer(LynApplication.context.getExternalCacheDir()                .getAbsolutePath()).append("/");    }

原因有以下几点:
1、整个app的storage/sdcard0 or sdcard1/Android/data/<包名>/该目录下,分别为caches和files两个文件夹
2、caches可以放些缓存类的文件,如图片缓存等。而files可以放些文件类的东西。这样的好处是统一了app的路径管理,防止了sd的结构混乱。
3、不管在4.4以上系统,在sd卡中都是可以任意读写的。同时当程序被卸载后,该storage/sdcard0 or sdcard1/Android/data/<包名> 目录下的东西都会被清空掉!防止了残留文件在sd卡的存留。这种残余的文件特别是在更新安装的时候,最容易了导致程序的数据错误和app的报错!
总之,app的全局路径在sd卡的管理是很重要的一环!不喜勿喷!若有不足,可以留言!一起学习!谢谢!

更多相关文章

  1. Python3原生编写月份计算工具
  2. Android6.0权限系统
  3. Android实现简单底部导航栏 Android仿微信滑动切换效果
  4. StevGuo系列文章翻译之Android中禁止屏保
  5. Android媒体播放---Media playback(二)
  6. Android动态加载补充 加载SD卡中的SO库
  7. Android中从源码分析关于AsyncTask的使用
  8. Looper,Handler,Message
  9. [Android] - 对话框的小框架 Managed-Dialog

随机推荐

  1. Android项目初始时的文件
  2. 第3章 UI开发的点点滴滴
  3. Android 运行时权限
  4. android 使用AsyncTask代替thread进行网
  5. ROS + Android
  6. Android Bitmap.setDensity(int density)
  7. Android的px、dip、sp的区别
  8. APK文件粗略介绍
  9. android 判断文件是否存在
  10. Android客户端自动更新代码