package cm.android.util; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import android.Manifest.permission; import android.annotation.TargetApi; import android.content.Context; import android.content.pm.PackageManager; import android.content.res.Configuration; import android.os.Build; import android.os.Environment; import android.os.StatFs; import android.os.storage.StorageManager; import java.io.File; import java.util.List; import cm.java.util.IoUtil; import cm.java.util.ObjectUtil; import cm.java.util.Reflect; import cm.java.util.Utils; public class EnvironmentUtil { private static final long REMAIN_SPACE = 5 * 1024 * 1024; private static final Logger logger = LoggerFactory.getLogger(EnvironmentUtil.class); private EnvironmentUtil() { } /** * 判断外部存储已经挂载 */ private static boolean isExternalStorageMounted() { boolean isMounted = Environment.MEDIA_MOUNTED.equals(Environment .getExternalStorageState()); if (!isMounted) { logger.info("ExternalStorageState = " + Environment.getExternalStorageState()); } return isMounted; } /** * Check if external storage is built-in or removable. * * @return True if external storage is removable (like an SD card), false * otherwise. */ @TargetApi(9) public static boolean isExternalStorageRemovable() { if (SdkUtil.hasGingerbread()) { return Environment.isExternalStorageRemovable(); } return true; } public static boolean isExternalStorageReadable() { String state = Environment.getExternalStorageState(); // String state = EnvironmentCompat.getStorageState(); if (Environment.MEDIA_MOUNTED.equals(state) || Environment.MEDIA_MOUNTED_READ_ONLY .equals(state)) { return true; } return false; } /** * 判断外部存储是否可用 */ public static boolean isExternalStorageWritable() { return isExternalStorageMounted(); } /** * 获取手机sdCard根目录 格式(/sdcard/) */ public static File getExternalStorageDirectory() { return Environment.getExternalStorageDirectory(); } @TargetApi(8) public static File getExternalStoragePublicDirectory(String type) { if (!EnvironmentUtil.SdkUtil.hasFroyo()) { File file = new File(EnvironmentUtil.getExternalStorageDirectory(), type); IoUtil.checkDirectory(file); return file; } File file = Environment.getExternalStoragePublicDirectory(type); IoUtil.checkDirectory(file); return file; } /** * Get the external app cache directory. * * @param context The context to use * @return The external cache dir */ public static File getExternalCacheDir(Context context) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO) { File file = context.getExternalCacheDir(); if (file != null) { return file; } } File externalCacheDir = new File(getExternalDir(context), "cache/"); IoUtil.checkDirectory(externalCacheDir); return externalCacheDir; } /** * Get a usable cache directory (external if available, internal otherwise). * * @param context The context to use * @param uniqueName A unique directory name to append to the cache dir * @return The cache dir */ public static File getCacheDir(Context context, String uniqueName) { // Check if media is mounted or storage is built-in, if so, try and use // external cache dir // otherwise use internal cache dir final File cachePathFile = isExternalStorageWritable() ? getExternalCacheDir(context) : context.getCacheDir(); File uniqueCacheDir = cachePathFile; if (uniqueName != null) { uniqueCacheDir = new File(cachePathFile, uniqueName); } IoUtil.checkDirectory(uniqueCacheDir); return uniqueCacheDir; } /** * 获取外部存储目录""/Android/data/"PackageName"/files/"" */ public static File getExternalFilesDir(Context context, String uniqueName) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO) { File file = context.getExternalFilesDir(uniqueName); if (file != null) { return file; } } File externalFilesDir = new File(getExternalDir(context), "files/"); if (!Utils.isEmpty(uniqueName)) { externalFilesDir = new File(externalFilesDir, uniqueName); } IoUtil.checkDirectory(externalFilesDir); return externalFilesDir; } public static File getExternalDir(Context context) { final String filesDir = "Android/data/" + context.getPackageName(); File externalFilesDir = new File(Environment.getExternalStorageDirectory(), filesDir); IoUtil.checkDirectory(externalFilesDir); return externalFilesDir; } /** * 判断是否有足够的空间 */ public static boolean hasEnoughSpace(File file) { long usable = getUsableSpace(file); if (usable > REMAIN_SPACE) { return true; } else { return false; } } /** * Check how much usable space is available at a given path. * * @param path The path to check * @return The space available in bytes */ @TargetApi(9) public static long getUsableSpace(File path) { if (SdkUtil.hasGingerbread()) { return path.getUsableSpace(); } // final StatFs stats = new StatFs(path.getPath()); // return (long) stats.getBlockSize() * (long) // stats.getAvailableBlocks(); return getAvailableSize(path); } /** * 获取存储可用内存大小 */ private static long getAvailableSize(File path) { if (path == null || !path.exists()) { return -1; } try { StatFs statFs = new StatFs(path.getPath()); long availableBlocks = statFs.getAvailableBlocks();// 可用存储块的数量 long blockSize = statFs.getBlockSize();// 每块存储块的大小 long availableSize = availableBlocks * blockSize;// 可用容量 return availableSize; } catch (Exception e) { return -1; } } public static long getTotalSpace(File file) { if (SdkUtil.hasGingerbread()) { return file.getTotalSpace(); } return getTotalSize(file.getAbsolutePath()); } /** * 获取存储总内存大小 */ private static long getTotalSize(String root) { if (root == null || "".equals(root)) { return -1; } try { StatFs statFs = new StatFs(root); long blockCount = statFs.getBlockCount();// 总存储块的数量 long blockSize = statFs.getBlockSize();// 每块存储块的大小 long totalSize = blockCount * blockSize;// 总存储量 return totalSize; } catch (Exception e) { return -1; } } /** * 获取已用存储大小 */ public static long getUsedSize(File root) { long size = getTotalSpace(root) - getUsableSpace(root); if (size >= 0) { return size; } return 0; } // /** // * Returns the default link's IP addresses, if any, taking into account // IPv4 // * and IPv6 style addresses. // * // * @param context // * the application context // * @return the formatted and comma-separated IP addresses, or null if // none. // */ // public static String getDefaultIpAddresses(Context context) { // ConnectivityManager cm = (ConnectivityManager) context // .getSystemService(Context.CONNECTIVITY_SERVICE); // LinkProperties prop = cm.getActiveLinkProperties(); // return formatIpAddresses(prop); // } // // private static String formatIpAddresses(LinkProperties prop) { // if (prop == null) // return null; // Iterator<InetAddress> iter = prop.getAddresses().iterator(); // // If there are no entries, return null // if (!iter.hasNext()) // return null; // // Concatenate all available addresses, comma separated // String addresses = ""; // while (iter.hasNext()) { // addresses += iter.next().getHostAddress(); // if (iter.hasNext()) // addresses += ", "; // } // return addresses; // } // @TargetApi(11) // public static void enableStrictMode() { // if (Utils.hasGingerbread()) { // StrictMode.ThreadPolicy.Builder threadPolicyBuilder = // new StrictMode.ThreadPolicy.Builder() // .detectAll() // .penaltyLog(); // StrictMode.VmPolicy.Builder vmPolicyBuilder = // new StrictMode.VmPolicy.Builder() // .detectAll() // .penaltyLog(); // // if (Utils.hasHoneycomb()) { // threadPolicyBuilder.penaltyFlashScreen(); // vmPolicyBuilder // .setClassInstanceLimit(ImageGridActivity.class, 1) // .setClassInstanceLimit(ImageDetailActivity.class, 1); // } // StrictMode.setThreadPolicy(threadPolicyBuilder.build()); // StrictMode.setVmPolicy(vmPolicyBuilder.build()); // } // } /** * 判断是否是平板 */ public static boolean isTablet(Context context) { return (context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE; } public static boolean hasExternalStoragePermission(Context context) { return hasPermission(context, permission.WRITE_EXTERNAL_STORAGE); } public static boolean hasPermission(Context context, String permission) { int perm = context.checkCallingOrSelfPermission(permission); return perm == PackageManager.PERMISSION_GRANTED; } // @TargetApi(Build.VERSION_CODES.LOLLIPOP) // public static boolean isSupportInternalSdcard(Context context) { // String[] paths = getVolumePaths(context); // if (SdkUtil.hasLollipop()) { // File internalSdcardFile = new File(paths[0]); // boolean removable = Environment.isExternalStorageRemovable(internalSdcardFile); // String state = Environment.getExternalStorageState(internalSdcardFile); // if (Environment.MEDIA_MOUNTED.equals(state) && !removable) { // return true; // } // } // return !EnvironmentUtil.isExternalStorageRemovable(); // } public static String[] getVolumePaths(Context context) { StorageManager storageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE); try { return Reflect.bind(storageManager).call("getVolumePaths"); } catch (Reflect.ReflectException e) { return null; } // ObjectProxy proxy = new ObjectProxy(storageManager); // Method method = proxy.getMethod("getVolumePaths"); // String[] paths = proxy.doMethod(method); // return paths; } /** * 获取外置sdcard目录 */ public static List<File> getExtSdcardDirectory(Context context) { List<File> fileList = ObjectUtil.newArrayList(); File file = getExternalStorageDirectory(); if (EnvironmentUtil.isExternalStorageRemovable()) { fileList.add(file); } String[] array = getVolumePaths(context); for (String dir : array) { if (file.getAbsolutePath().equals(dir)) { continue; } File extSdcard = new File(dir); // if (SdkUtil.hasKitkat()) { // String state = Environment.getStorageState(extSdcard); // if (Environment.MEDIA_MOUNTED.equals(state)) { // fileList.add(extSdcard); // } // } else { //判断该目录是否可写 long usable = getUsableSpace(extSdcard); if (usable > 0) { fileList.add(extSdcard); // } } } return fileList; } /** * 判断SDK版本 */ public static class SdkUtil { public static boolean has(int versionCode) { return Build.VERSION.SDK_INT >= versionCode; } /** * 判断手机系统版本是否为{@link android.os.Build.VERSION_CODES#FROYO}以上 */ public static boolean hasFroyo() { // Can use static final constants like FROYO, declared in later // versions // of the OS since they are inlined at compile time. This is // guaranteed // behavior. return has(Build.VERSION_CODES.FROYO); } /** * 判断手机系统版本是否为{@link android.os.Build.VERSION_CODES#GINGERBREAD}以上 */ public static boolean hasGingerbread() { return has(Build.VERSION_CODES.GINGERBREAD); } /** * 判断手机系统版本是否为{@link android.os.Build.VERSION_CODES#HONEYCOMB}以上 */ public static boolean hasHoneycomb() { return has(11); // return Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB; } /** * 判断手机系统版本是否为{@link android.os.Build.VERSION_CODES#HONEYCOMB_MR1}以上 */ public static boolean hasHoneycombMR1() { return has(12); // return Build.VERSION.SDK_INT >= // Build.VERSION_CODES.HONEYCOMB_MR1; } public static boolean hasJellyBean() { return has(16); // return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN; } public static boolean hasJellyBeanMr1() { return has(17); // return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1; } public static boolean hasJellyBeanMr2() { return has(18); // return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2; } public static boolean hasKitkat() { return has(19); // return Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; } public static boolean hasLollipop() { return has(21); } } }