123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341 |
- package com.example.myapplication.utils;
- import android.annotation.TargetApi;
- import android.content.Context;
- import android.content.pm.PackageManager;
- import android.os.Build;
- import android.os.Environment;
- import android.os.StatFs;
- import android.text.TextUtils;
- import android.util.Log;
- import com.facebook.stetho.common.LogUtil;
- import com.example.myapplication.BuildConfig;
- import com.jakewharton.disklrucache.DiskLruCache;
- import java.io.File;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.OutputStream;
- import java.security.MessageDigest;
- import java.security.NoSuchAlgorithmException;
- import java.util.ArrayList;
- import java.util.List;
- import static android.os.Environment.MEDIA_MOUNTED;
- /**
- * 用本地的Disk文件来存储各种API数据的结果,在本地利用LRU算法进行文件缓存,缓存文件位于SD卡的<i>("/Android/data/[app_package_name]/cache")</i>目录下
- * <p/>
- */
- public class CacheUtils {
- private static final String TAG = "cunduoduo";
- // Default disk cache size in bytes
- private static final int DEFAULT_DISK_CACHE_SIZE = 1024 * 1024 * 100; // 100MB
- private static final String EXTERNAL_STORAGE_PERMISSION = "android.permission.WRITE_EXTERNAL_STORAGE";
- private static CacheUtils instance;
- private static final int DISK_CACHE_INDEX = 0;
- public static CacheUtils getInstance(Context context) {
- if (instance == null) {
- instance = new CacheUtils(context.getApplicationContext());
- }
- return instance;
- }
- private CacheUtils(Context context) {
- mCacheDir = getCacheDirectory(context);
- initDiskCache(context);
- }
- private DiskLruCache mDiskLruCache;
- private File mCacheDir;
- private final Object mDiskCacheLock = new Object();
- private boolean mDiskCacheStarting = true;
- /**
- * 初始化默认的文件Cache
- */
- public void initDiskCache(Context context) {
- // Set up disk cache
- synchronized (mDiskCacheLock) {
- if (mDiskLruCache == null || mDiskLruCache.isClosed()) {
- // if (getUsableSpace(mCacheDir) > DEFAULT_DISK_CACHE_SIZE) {
- try {
- mDiskLruCache = DiskLruCache.open(mCacheDir, PhoneUtil.getVersionCode(context), 1, DEFAULT_DISK_CACHE_SIZE);
- LogUtil.d("Disk cache initialized");
- } catch (final IOException e) {
- LogUtil.e("initDiskCache - " + e);
- }
- }
- // }
- mDiskCacheStarting = false;
- mDiskCacheLock.notifyAll();
- }
- }
- /**
- * 删除本地的文件Cache,全部清空并删除目录
- */
- public void clearCache(Context context) {
- synchronized (mDiskCacheLock) {
- mDiskCacheStarting = true;
- if (mDiskLruCache != null && !mDiskLruCache.isClosed()) {
- try {
- mDiskLruCache.delete();
- if (BuildConfig.DEBUG) {
- Log.d(TAG, "Disk cache cleared");
- }
- } catch (IOException e) {
- Log.e(TAG, "clearCache - " + e);
- }
- mDiskLruCache = null;
- initDiskCache(context);
- }
- }
- }
- /**
- * Flush文件缓存到文件里
- */
- public void flush() {
- synchronized (mDiskCacheLock) {
- if (mDiskLruCache != null) {
- try {
- mDiskLruCache.flush();
- if (BuildConfig.DEBUG) {
- Log.d(TAG, "Disk cache flushed");
- }
- } catch (IOException e) {
- Log.e(TAG, "flush - " + e);
- }
- }
- }
- }
- /**
- * 关闭文件缓存
- */
- public void close() {
- synchronized (mDiskCacheLock) {
- if (mDiskLruCache != null) {
- try {
- if (!mDiskLruCache.isClosed()) {
- mDiskLruCache.close();
- mDiskLruCache = null;
- // if (BuildConfig.DEBUG) {
- LogUtil.d("Disk cache closed");
- // }
- }
- } catch (IOException e) {
- LogUtil.e("close - " + e);
- }
- }
- }
- }
- /**
- * Check how much usable space is available at a given path.
- *
- * @param path The path to check
- * @return The space available in bytes
- */
- @TargetApi(Build.VERSION_CODES.GINGERBREAD)
- public static long getUsableSpace(File path) {
- final StatFs stats = new StatFs(path.getPath());
- return (long) stats.getBlockSize() * (long) stats.getAvailableBlocks();
- }
- /**
- * 将数据缓存到磁盘缓存中去,以参数data的MD5编码作为文件名,value为文件正文内容
- */
- public void set(final String data, final String value) {
- ThreadPool.getInstance().excute(new Runnable() {
- @Override
- public void run() {
- synchronized (mDiskCacheLock) {
- // Add to disk cache
- if (mDiskLruCache != null) {
- final String key = hashKeyForDisk(data);
- OutputStream out = null;
- try {
- final DiskLruCache.Editor editor = mDiskLruCache.edit(key);
- if (editor != null) {
- out = editor.newOutputStream(DISK_CACHE_INDEX);
- out.write(value.getBytes("UTF-8"));
- editor.commit();
- // out.close();
- }
- } catch (final IOException e) {
- Log.e(TAG, "addStringDataToCache - " + e);
- } catch (Exception e) {
- Log.e(TAG, "addStringDataToCache - " + e);
- } finally {
- try {
- if (out != null) {
- out.close();
- }
- } catch (IOException e) {
- LogUtil.e(e.getLocalizedMessage());
- }
- }
- }
- }
- }
- });
- }
- /**
- * 从文件缓存中获取数据
- */
- public String get(String data) {
- final String key = hashKeyForDisk(data);
- synchronized (mDiskCacheLock) {
- while (mDiskCacheStarting) {
- try {
- mDiskCacheLock.wait();
- } catch (InterruptedException e) {
- LogUtil.e(e.getLocalizedMessage());
- }
- }
- if (mDiskLruCache != null) {
- InputStream inputStream = null;
- try {
- final DiskLruCache.Snapshot snapshot = mDiskLruCache.get(key);
- if (snapshot != null) {
- if (BuildConfig.DEBUG) {
- Log.d(TAG, "Disk cache hit");
- }
- inputStream = snapshot.getInputStream(DISK_CACHE_INDEX);
- if (inputStream != null) {
- byte[] buffer = new byte[inputStream.available()];
- inputStream.read(buffer);
- return new String(buffer, "UTF-8");
- // return EncodingUtils.getString(buffer, "UTF-8");
- }
- }
- } catch (final IOException e) {
- Log.e(TAG, "getFileDataFromCache - " + e);
- } finally {
- try {
- if (inputStream != null) {
- inputStream.close();
- }
- } catch (IOException e) {
- LogUtil.e(e.getLocalizedMessage());
- }
- }
- }
- return null;
- }
- }
- public <T> T getAs(String data, Class<T> dataType) {
- String value = get(data);
- if (!TextUtils.isEmpty(value)) {
- return JsonUtils.jsonObj(value, dataType);
- }
- return null;
- }
- public <T> List<T> getList(String data, Class<T> dataType) {
- String value = get(data);
- if (!TextUtils.isEmpty(value)) {
- return JsonUtils.jsonObjArray(value, dataType);
- }
- return new ArrayList<T>();
- }
- /**
- * 从文件缓存中删除数据
- */
- public void remove(String data) {
- final String key = hashKeyForDisk(data);
- synchronized (mDiskCacheLock) {
- while (mDiskCacheStarting) {
- try {
- mDiskCacheLock.wait();
- } catch (InterruptedException e) {
- LogUtil.e(e.getLocalizedMessage());
- }
- }
- if (mDiskLruCache != null) {
- try {
- mDiskLruCache.remove(key);
- } catch (IOException e) {
- LogUtil.e("removeFromCache - " + e);
- }
- }
- }
- }
- /**
- * Cache的key
- */
- public static String hashKeyForDisk(String key) {
- String cacheKey;
- try {
- final MessageDigest mDigest = MessageDigest.getInstance("MD5");
- mDigest.update(key.getBytes());
- cacheKey = bytesToHexString(mDigest.digest());
- } catch (NoSuchAlgorithmException e) {
- cacheKey = String.valueOf(key.hashCode());
- }
- return cacheKey;
- }
- private static String bytesToHexString(byte[] bytes) {
- // http://stackoverflow.com/questions/332079
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < bytes.length; i++) {
- String hex = Integer.toHexString(0xFF & bytes[i]);
- if (hex.length() == 1) {
- sb.append('0');
- }
- sb.append(hex);
- }
- return sb.toString();
- }
- /**
- * Returns application cache directory. Cache directory will be created on SD card
- * <i>("/Android/data/[app_package_name]/cache")</i> if card is mounted and app has appropriate
- * permission. Else - Android defines cache directory on device's file system.
- *
- * @param context Application context
- * @return Cache {@link File directory}
- */
- public static File getCacheDirectory(Context context) {
- File appCacheDir = null;
- if (MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) && hasExternalStoragePermission(context)) {
- appCacheDir = context.getExternalCacheDir();
- // appCacheDir = getExternalCacheDir(context);
- }
- if (appCacheDir == null) {
- appCacheDir = context.getCacheDir();
- }
- if (appCacheDir == null) {
- Log.w(TAG, "Can't define system cache directory! The app should be re-installed.");
- }
- return appCacheDir;
- }
- private static boolean hasExternalStoragePermission(Context context) {
- int perm = context.checkCallingOrSelfPermission(EXTERNAL_STORAGE_PERMISSION);
- return perm == PackageManager.PERMISSION_GRANTED;
- }
- }
|