Android中文件缓存

Android 中 文件下载


首先要先创建一个文件缓存的Util类:MultiTaskDownloadManager 要实现 MultiTask 接口类
当时的需求是接口返回给客户端一个链接,然后根据链接地址去缓存文件,

package cn.wostore.gloud.api.download;

import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;

import com.tencent.mm.opensdk.utils.Log;

import java.io.File;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;

import cn.wostore.gloud.MainApplication;
import cn.wostore.gloud.downloads.db.DaoMaster;
import cn.wostore.gloud.downloads.db.DaoSession;
import cn.wostore.gloud.downloads.db.DownloadInfoDao;
import cn.wostore.gloud.utils.Constant;
import cn.wostore.gloud.utils.MathUtil;
import cn.wostore.gloud.utils.SPDownloadUtil;
import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;

public class MultiTaskDownloadManager implements MultiTask {

private static final AtomicReference<MultiTaskDownloadManager> INSTANCE = new AtomicReference<>();
private Map<String, ProgressDownloader> downCalls; //用来存放各个下载的请求
private static String FILE_PATH = Constant.APP_ROOT_PATH + Constant.DOWNLOADS_DIR;
private Map<String, Long> fileContentLengthCache;
private Map<String, File> apkFileCaches;
private DownloadInfoDao downloadInfoDao;


public static MultiTaskDownloadManager getInstance() {
    for (; ; ) {
        MultiTaskDownloadManager current = INSTANCE.get();
        if (current != null) {
            return current;
        }
        current = new MultiTaskDownloadManager();
        if (INSTANCE.compareAndSet(null, current)) {
            return current;
        }
    }
}

private MultiTaskDownloadManager() {
    downCalls = new HashMap<>();
    fileContentLengthCache = new HashMap<>();
    apkFileCaches = new HashMap<>();
    initDownloadDB();
}
 /**
  * 开启缓存
  * */
@Override
public void start(DownloadInfo downloadInfo) {
    if (getDownloadPercent(downloadInfo.getDownloadUrl())[1] == 100) {
        if (getDownloadUrl(downloadInfo.getDownloadUrl())) {
            downCalls.remove(downloadInfo.getDownloadUrl());
        }
        return;
    }
    if (!getDownloadUrl(downloadInfo.getDownloadUrl())) {
        createDownloadUrl(downloadInfo.getDownloadUrl(), downloadInfo);
    }
}


@Override
public void start(String url) {
    if (getDownloadPercent(url)[1] == 100) {
        if (getDownloadUrl(url)) {
            downCalls.remove(url);
        }
        return;
    }
    if (!getDownloadUrl(url)) {
        createDownloadUrl(url, null);
    }
}

 /**
  * 暂停缓存
  * */
@Override
public void stop(String url) {
    if (getDownloadUrl(url)) {
        downCalls.get(url).pause();
        downCalls.remove(url);
    }
}

@Override
public void delete(String url) {
    stop(url);
    File file = getFilePath(url);
    if (file != null && file.exists()) {
        file.delete();
    }
    clearCache(url);
}

/**
* 删除缓存的任务
* */
@Override
public void delete(DownloadInfo info) {
deleteDownloadTask(info);
delete(info.getDownloadUrl());
}

/**
* 删除所有缓存的任务(可用于全选删除)
* /
@Override
public void deleteAll() {
File allFiles = new File(FILE_PATH);
deleteDir(allFiles);
SPDownloadUtil.getInstance().clear();
clearDownloadTasks();
fileContentLengthCache.clear();
apkFileCaches.clear();
Iterator<Map.Entry<String, ProgressDownloader>> iterator = downCalls.entrySet().iterator();
while (iterator.hasNext()) {
iterator.next().getValue().pause();
iterator.remove();
}
}
/
*
* 清除缓存
*/
public void clearCache(String url) {
SPDownloadUtil.getInstance().removeContentLength(url);
if (fileContentLengthCache.containsKey(url)) {
fileContentLengthCache.remove(url);
}
if (apkFileCaches.containsKey(url)) {
apkFileCaches.remove(url);
}
}

/**
* 创建下载地址
*/
private void createDownloadUrl(String url, DownloadInfo info) {
File apkFile = getFilePath(url);
Observable.create(e -> {
ProgressDownloader downloader = new ProgressDownloader(url, apkFile, new ProgressResponseBody.ProgressListener() {
@Override
public void onPreExecute(long contentLength) {
if ((!apkFile.exists() || apkFile.length() == 0) && contentLength > 200) {
SPDownloadUtil.getInstance().saveContentLength(url, contentLength);
fileContentLengthCache.put(url, contentLength);
}
}

            @Override
            public void update(long totalBytes, long contentLength, boolean done) {
                e.onNext(info == null ? url : info);
                if (done && getDownloadUrl(url)) {
                    // 下载完成
                    downCalls.remove(url);
                }
            }

            @Override
            public void onError(Throwable e) {
                if (getDownloadUrl(url)) {
                    downCalls.remove(url);
                }
                clearCache(url);
            }
        });
        downCalls.put(url, downloader);
        downloader.download(apkFile.exists() ? apkFile.length() : 0L);
    }).subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new DownloadObserver());
}

/**
* 获取要下载的地址
/
public boolean getDownloadUrl(String url) {
return downCalls.containsKey(url);
}
/
*
* 获取文件路径
/
public File getFilePath(String url) {
String[] datas = url.split("/");
final String fileName = datas[datas.length - 1];
File pathFile = new File(FILE_PATH);
if (!pathFile.exists()) {
pathFile.mkdirs();
}
File file = new File(FILE_PATH + fileName);
return file;
}
/
*
* 删除缓存到本地的文件目录
*/
private void deleteDir(File file) {
if (!file.exists()) {
return;
}
if (file.isFile()) {
file.delete();
} else {
File[] files = file.listFiles();
if (files == null) {
file.delete();
} else {
for (int i = 0; i < files.length; i++) {
deleteDir(files[i]);
}
file.delete();
}
}
}

/**
 * 获取 当前已下载大小、文件总大小,以及进度(百分比)
 *
 * @param url 下载链接
 * @return 返回结果为一个数据arr(arr[0]已经下载的文件大小 、 arr[1]文件总大小 、 arr[2]文件下载进度 百分比)
 */
public long[] getDownloadPercent(String url) {
    File file;
    if (apkFileCaches.containsKey(url) && apkFileCaches.get(url) != null && apkFileCaches.get(url).exists()) {
        file = apkFileCaches.get(url);
    } else {
        file = getFilePath(url);
        apkFileCaches.put(url, file);
    }
    long contentLength;
    if (fileContentLengthCache.containsKey(url)) {
        contentLength = fileContentLengthCache.get(url);
    } else {
        contentLength = SPDownloadUtil.getInstance().getContentLength(url, 0);
        fileContentLengthCache.put(url, contentLength);
    }
    if (!file.exists() || contentLength == 0) {
        clearCache(url);
        return new long[]{0, 0, 0};
    }
    return new long[]{file.length(), contentLength, (file.length() * 100 / contentLength)};
}

private class DownloadObserver implements Observer<Object> {

    @Override
    public void onSubscribe(Disposable d) {

    }

    @Override
    public void onNext(Object obj) {
        String url;
        DownloadInfo info = null;
        if (obj instanceof DownloadInfo) {
            info = (DownloadInfo) obj;
            url = info.getDownloadUrl();
        } else {
            url = (String) obj;
        }
        long[] s = getDownloadPercent(url);
        if (downloadListener != null) {
            info.setProgress(s[0]);
            info.setContentLenth(s[1]);
            info.setPercent(s[2]);
            downloadListener.onProgress(s[0], s[1], s[2], info);
        }
    }

    @Override
    public void onError(Throwable e) {
        e.printStackTrace();
    }

    @Override
    public void onComplete() {

    }
}


private void initDownloadDB() {
    //初始化 第二个参数随便取名,为数据库的名字
    DaoMaster.DevOpenHelper devOpenHelper = new DaoMaster.DevOpenHelper(MainApplication.getInstance(), "数据库的名称", null);
    DaoMaster daoMaster = new DaoMaster(devOpenHelper.getWritableDatabase());
    DaoSession daoSession = daoMaster.newSession();
    downloadInfoDao = daoSession.getDownloadInfoDao();
}

/**
 * 添加下载任务
 *
 * @param downloadInfo
 */
@Override
public void insertTask(DownloadInfo downloadInfo) {
    downloadInfo.setId(null);//传null可以自增,不用设值
    downloadInfoDao.insert(downloadInfo);
}


/**
 * 获取单个下载任务
 *
 * @param downloadInfo
 * @return
 */
@Override
public DownloadInfo getDownloadInfo(DownloadInfo downloadInfo) {
    List<DownloadInfo> infos = downloadInfoDao.queryBuilder().where(DownloadInfoDao.Properties.DownloadUrl.eq(downloadInfo.getDownloadUrl()))
            .build().list();
    return infos != null && infos.size() > 0 ? infos.get(0) : null;
}

/**
 * 获取下载任务列表
 *
 * @return
 */
@Override
public List<DownloadInfo> getDownloadTasks() {
    return downloadInfoDao.loadAll();
}


/**
 * 清空全部下载任务(sqlite)
 */
private void clearDownloadTasks() {
    downloadInfoDao.deleteAll();
}


/**
 * 删除单个下载任务(sqlite)
 *
 * @param info
 */
private void deleteDownloadTask(DownloadInfo info) {
    DownloadInfo downloadInfo = getDownloadInfo(info);
    if (downloadInfo != null) {
        downloadInfoDao.delete(downloadInfo);
    }
}


/**
 * 单位转换
 *
 * @param sizeInt
 * @return
 */
public String formatSize(long sizeInt) {
    String[] value = new String[2];
    if (sizeInt == 0) {
        return "0MB";
    }
    double b = 1024;
    double kb = b * b;
    double mb = kb * b;
    double gb = mb * b;
    java.text.DecimalFormat df_one = new java.text.DecimalFormat("#0.0");
    java.text.DecimalFormat df_two = new java.text.DecimalFormat("#0.00");
    if (sizeInt < b) {
        return (int) sizeInt + "B";
    } else if (sizeInt < kb) {
        value[0] = String.format("%s", df_two.format(MathUtil.div(sizeInt, b, 2)));
        value[1] = "KB";
    } else if (sizeInt < mb) {
        // 保留两位小数
        value[0] = String.format("%s", df_two.format(MathUtil.div(sizeInt, kb, 2)));
        value[1] = "MB";
    } else if (sizeInt < gb) {
        value[0] = String.format("%s", df_two.format(MathUtil.div(sizeInt, kb, 2)));
        value[1] = "MB";
    } else {
        value[0] = String.format("%s", df_two.format(MathUtil.div(sizeInt, mb, 2)));
        value[1] = "GB";
    }
    return value[0] + value[1];
}


public boolean isAppInstalled(Context context, String url) {
    String[] urls = url.split("/");
    String pkgName = null;
    PackageInfo packageInfo;
    try {
        if (urls[urls.length - 1].indexOf("_") > -1) {
            pkgName = urls[urls.length - 1].split("_")[1].substring(0, urls[urls.length - 1].split("_")[1].length() - 4);
        } else {
            pkgName = urls[urls.length - 1].substring(0, urls[urls.length - 1].length() - 4);
        }
        packageInfo = context.getPackageManager().getPackageInfo(pkgName, 0);
    } catch (PackageManager.NameNotFoundException e) {
        packageInfo = null;
        e.printStackTrace();
    }
    //没有安装APK
    return packageInfo != null;
}

private DownloadListener downloadListener;

public void setDownloadListener(DownloadListener downloadListener) {
    this.downloadListener = downloadListener;
}

public interface DownloadListener {
    void onProgress(long current, long total, long percent, DownloadInfo info);
}

}
这样就可以实现自己要实现的效果了

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值