最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于android編寫一個下載管理工具類

 更新時間:2025年11月08日 11:04:16   作者:IT樂手  
相信大家在項目開發(fā)的過程中會用到下載相關(guān)的操作,下面小編為大家介紹了一個基于android編寫的工具類,支持下載和取消下載,進度監(jiān)聽功能,有需要的可以了解下

相信大家在項目開發(fā)的過程中會用到下載相關(guān)的操作,下面是我在工作中用到的下載邏輯管理類,支持下載和取消下載,進度監(jiān)聽功能,能滿足大多數(shù)場景需求,希望對大家有幫助

以下是完整代碼:

import android.os.Handler;
import android.os.Looper;

import androidx.annotation.NonNull;
import androidx.lifecycle.MutableLiveData;


import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.SocketException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 描述: 下載管理器
 * 創(chuàng)建者: IT 樂手
 * 日期: 2025/3/27
 */

public class DownloadManager {

    private static final String TAG = "DownloadManager";

    private DownloadManager() {
    }

    private static class SingletonHolder {
        private static final DownloadManager INSTANCE = new DownloadManager();
    }

    public static DownloadManager getInstance() {
        return SingletonHolder.INSTANCE;
    }

    public MutableLiveData<String> unzipModelLiveData = new MutableLiveData<>();

    // 添加當(dāng)前任務(wù)跟蹤
    private final Map<String, DownloadTask> currentTasks = new ConcurrentHashMap<>();

    private final Handler mHandler = new Handler(Looper.getMainLooper());

    public DownloadTask downloadFile(String url, String version, String key, DownloadCallback callback) throws Exception {
        // 檢查是否已有相同任務(wù)正在執(zhí)行
        String taskKey = generateTaskKey(url, key);
        if (currentTasks.containsKey(taskKey)) {
            DownloadTask existingTask = currentTasks.get(taskKey);
            if (existingTask != null && !existingTask.isCanceled) {
                AtotoLogger.e(TAG, "downloadFile: task for " + key + " is already in progress" );
                return existingTask;
            }
        }

        File cacheDir = new File(AppGlobalUtils.getApplication().getExternalFilesDir(null), "model");
        if (!cacheDir.exists()) {
            cacheDir.mkdir();
        }
        String modelDirName = VoskCachedManager.getInstance().getModelByLang(key);
        if (modelDirName == null || modelDirName.isEmpty()) {
            throw new Exception(key + " is not supported");
        }
        File destination = new File(cacheDir, modelDirName + ".zip");
        AtotoLogger.d(TAG, "downloadFile: " + url + " to " + cacheDir.getAbsolutePath() + ", version: " + version + ", destination: " + destination.getAbsolutePath());

        DownloadTask task = downloadFile(url,version, destination, callback);
        currentTasks.put(taskKey, task);
        return task;
    }

    private static @NonNull Map<String, String> buildHeaders() {
        Map<String, String> headers = new HashMap<>();
        headers.put("Authorization", AccountUseCase.getToken());
        headers.put("deviceSeries", DeviceUtil.getPlatform());
        return headers;
    }

    public DownloadTask downloadFile(String url,  String version, File destination, DownloadCallback callback) {
        DownloadTask task = new DownloadTask(url, destination);
        OkHttpClient client = new OkHttpClient();
        Request.Builder requestBuilder = new Request.Builder().url(task.url);
        buildRequestHeader(requestBuilder, buildHeaders());
        Call call = client.newCall(requestBuilder.build());
        task.setCall(call);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(@NonNull Call call, @NonNull IOException e) {
                AtotoLogger.e(TAG, "downloadFile error: " + e);
                removeTask(task);
                mHandler.post(() -> {
                    if (task.isCanceled) {
                        if (callback != null) {
                            callback.onCancel(task.url);
                        }
                    } else {
                        if (callback != null) {
                            callback.onError(task.url, e.getMessage());
                        }
                    }
                });
            }

            @Override
            public void onResponse(@NonNull Call call, @NonNull Response response) {
                // 在開始處理響應(yīng)前檢查取消狀態(tài)
                if (task.isCanceled) {
                    removeTask(task);
                    response.close();
                    AtotoLogger.d(TAG, "downloadFile canceled (before processing): " + task.url);
                    mHandler.post(() -> {
                        if (callback != null) {
                            callback.onCancel(task.url);
                        }
                    });
                    return;
                }

                if (!response.isSuccessful()) {
                    removeTask(task);
                    AtotoLogger.e(TAG, "downloadFile error: " + response.message());
                    mHandler.post(() -> {
                        if (callback != null) {
                            callback.onError(task.url, "Failed to download file: " + response.message());
                        }
                    });
                    return;
                }
                // 已存在文件,直接刪除
                if (destination.exists()) {
                    destination.delete();
                }
                InputStream inputStream = null;
                FileOutputStream outputStream = null;
                boolean downloadSuccess = false;
                boolean shouldUnzip = false;
                try {
                    assert response.body() != null;
                    inputStream = response.body().byteStream();
                    outputStream = new FileOutputStream(destination);
                    byte[] buffer = new byte[2048];
                    long totalBytesRead = 0;
                    long fileSize = response.body().contentLength();
                    int bytesRead;
                    while ((bytesRead = inputStream.read(buffer)) != -1 && !task.isCanceled) {
                        totalBytesRead += bytesRead;
                        outputStream.write(buffer, 0, bytesRead);
                        long finalTotalBytesRead = totalBytesRead;
                        mHandler.post(() -> {
                            if (callback != null) {
                                callback.onProgress(task.url, finalTotalBytesRead, fileSize);
                            }
                        });
                    }
                    if (task.isCanceled) {
                        AtotoLogger.d(TAG, "downloadFile canceled: " + task.url);
                        mHandler.post(() -> {
                            if (callback != null) {
                                callback.onCancel(task.url);
                            }
                        });
                    }
                    else  {
                        downloadSuccess = true;
                        shouldUnzip = true;
                        mHandler.post(() -> {
                            if (callback != null) {
                                callback.onSuccess(task.url, destination.getAbsolutePath());
                            }
                        });
                    }
                } catch (Exception e) {
                    downloadSuccess = false;
                    AtotoLogger.e(TAG, "downloadFile error: " + e);
                    if (task.isCanceled) {
                        mHandler.post(() -> {
                            if (callback != null) {
                                callback.onCancel(task.url);
                            }
                        });
                    } else {
                        mHandler.post(() -> {
                            if (callback != null) {
                                callback.onError(task.url, e.getMessage());
                            }
                        });
                    }
                } finally {
                    try {
                        if (inputStream != null) {
                            inputStream.close();
                        }
                        if (outputStream != null) {
                            outputStream.close();
                        }
                    } catch (IOException e) {
                        // 關(guān)閉流失敗
                        AtotoLogger.e(TAG, e);
                    }
                    // 清理文件:如果取消或失敗,刪除文件
                    if ((task.isCanceled || !downloadSuccess) && destination.exists()) {
                        boolean result = destination.delete();
                        AtotoLogger.d(TAG, "delete file: " + destination.getAbsolutePath() + " result: " + result);
                    }

                    // 只有下載成功且未被取消時才解壓
                    if (shouldUnzip && !task.isCanceled) {
                        // 解壓zip文件
                        startUnZip(destination, version, callback);
                    }

                    removeTask(task);
                }
           }
       });
       return task;
    }

    /**
     * 移除任務(wù)
     */
    private void removeTask(DownloadTask task) {
        currentTasks.values().removeIf(t -> t.url.equals(task.url));
    }

    private void buildRequestHeader(okhttp3.Request.Builder builder, Map<String, String> heads) {
        if (null == heads || heads.isEmpty()) {
            return;
        }
        for (Map.Entry<String, String> entry : heads.entrySet()) {
            builder.addHeader(entry.getKey(), entry.getValue());
        }
    }

    /**
     * 解壓并刪除zip文件
     * @param destination
     */
    private void startUnZip(File destination, String version, DownloadCallback callback) {
        if (destination.exists() && destination.getAbsolutePath().endsWith(".zip")) {
            Thread thread = new Thread(()-> {
                try {
                    FileUnzip.unzipFile(destination, destination.getParentFile(), getFileNameWithoutExtension(destination.getName()));
                } catch (Exception e) {
                    AtotoLogger.e(TAG, e);
                }
                // 寫文件到version.txt
                File modelDir = new File(destination.getParentFile(), getFileNameWithoutExtension(destination.getName()));
                if (modelDir.isDirectory()) {
                    File versionFile = new File(modelDir, "version.txt");
                    FileOutputStream outputStream = null;
                    try {
                        outputStream = new FileOutputStream(versionFile);
                        outputStream.write(version.getBytes());
                        outputStream.flush();
                        unzipModelLiveData.postValue(destination.getName());
                        mHandler.post(()-> {
                            callback.onUnzipFinish(destination.getName());
                        });
                    } catch (IOException e) {
                        AtotoLogger.e(TAG, e);
                    } finally {
                        if (outputStream != null) {
                            try {
                                outputStream.close();
                            } catch (IOException e) {
                                AtotoLogger.e(TAG, e);
                            }
                        }
                    }
                } else {
                    AtotoLogger.d(TAG, "modelDir: " + modelDir.getAbsolutePath() + " is not a directory");
                }

                // 刪除zip文件
                if (destination.exists()) {
                    boolean result = destination.delete();
                    AtotoLogger.d(TAG, "delete file: " + destination.getAbsolutePath() + " result: " + result);
                }
            });
            thread.start();
        }
    }

    private String getFileNameWithoutExtension(String fileName) {
        // 查找最后一個點的位置
        int lastDotIndex = fileName.lastIndexOf(".");

        // 如果存在點,并且點不是第一個字符,去掉后綴
        if (lastDotIndex > 0 && lastDotIndex < fileName.length() - 1) {
            fileName = fileName.substring(0, lastDotIndex);
        }
        return fileName;
    }

    /**
     * 生成任務(wù)唯一標(biāo)識
     */
    private String generateTaskKey(String url, String key) {
        return url + "_" + key;
    }


    public static class DownloadTask {
        private volatile boolean isCanceled = false;
        private String url;
        private File destination;
        private Call call;

        public DownloadTask(String url, File destination) {
            this.url = url;
            this.destination = destination;
        }

        public synchronized void cancel() {
            if (this.call != null) {
                this.call.cancel();
            }
            isCanceled = true;
        }

        public synchronized boolean isCanceled() {
            return isCanceled;
        }

        public void setCall(Call call) {
            this.call = call;
        }
    }


    public interface DownloadCallback {
        void onProgress(String url,long currentSize, long totalSize);
        void onSuccess(String url,String filePath);
        void onUnzipFinish(String unzipFilePath);
        void onError(String url,String error);
        void onCancel(String url);
    }


}

依賴的解壓工具

import com.google.common.io.Files;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

/**
 * 描述:
 * 創(chuàng)建者: IT樂手
 * 日期: 2025/7/23
 */

public class FileUnzip {

    private static final String TAG = "FileUnzip";
    /**
     * 解壓文件
     * @param zipFile 壓縮包
     * @param targetDirectory 解壓的目錄
     * @param destDirName 解壓后的文件夾名稱
     * @throws IOException
     */
    public static void unzipFile(File zipFile, File targetDirectory, String destDirName) throws IOException {
        long start = System.currentTimeMillis();
        int level = 0;
        File oldDir = null;
        try (ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFile))) {
            ZipEntry zipEntry;
            while ((zipEntry = zis.getNextEntry()) != null) {
                File newFile = new File(targetDirectory, zipEntry.getName());
                if (zipEntry.isDirectory()) {
                    if (level == 0) {
                        oldDir = newFile;
                    }
                    newFile.mkdirs();
                    ++level;
                } else {
                    newFile.getParentFile().mkdirs();
                    AtotoLogger.d("unzip file " + newFile.getAbsolutePath());
                    try (FileOutputStream fos = new FileOutputStream(newFile)) {
                        byte[] buffer = new byte[1024];
                        int len;
                        while ((len = zis.read(buffer)) > 0) {
                            fos.write(buffer, 0, len);
                        }
                    }
                    zis.closeEntry();
                }
            }
        }
        if (oldDir != null && oldDir.isDirectory() && oldDir.exists()) {
            File newDir = new File(oldDir.getParentFile(), destDirName);
            AtotoLogger.d("Change oldDir " + oldDir.getAbsolutePath() + " to " + newDir.getAbsolutePath());
            try {
                Files.move(oldDir, newDir);
                AtotoLogger.d("Change success !");
            } catch (Exception e) {
                AtotoLogger.printException(TAG, e);
            }
        }
        AtotoLogger.d(TAG, "unzipFile: " + zipFile.getAbsolutePath() + " to " + targetDirectory.getAbsolutePath() + " cost: " + (System.currentTimeMillis() - start) + "ms");
    }
}

知識擴展

以下是小編為大家整理的一些Android 常用工具類,有需要的可以參考下

1.app相關(guān)輔助類

package utils; 
 
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
 
/** 
 * app相關(guān)輔助類 
 */ 
public class AppUtil { 
    private AppUtil() { 
        /* cannot be instantiated*/ 
        throw new UnsupportedOperationException("cannot be instantiated");
    } 
 
    /** 
     * 獲取應(yīng)用程序名稱 
     * 
     * @param context 
     * @return 
     */ 
    public static String getAppName(Context context) {
 
        PackageManager packageManager = context.getPackageManager();
        try { 
            PackageInfo packageInfo = packageManager.getPackageInfo(context.getPackageName(), 0);
            int labelRes = packageInfo.applicationInfo.labelRes;
            return context.getResources().getString(labelRes);
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        } 
        return null; 
    } 
 
    /** 
     * 獲取應(yīng)用程序版本名稱信息 
     * 
     * @param context 
     * @return 當(dāng)前應(yīng)用的版本名稱 
     */ 
    public static String getVersionName(Context context) {
        try { 
            PackageManager packageManager = context.getPackageManager();
            PackageInfo packageInfo = packageManager.getPackageInfo(
                    context.getPackageName(), 0);
            return packageInfo.versionName;
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        } 
        return null; 
    } 
 
    /** 
     * 獲取應(yīng)用程序的版本Code信息 
     * @param context 
     * @return 版本code 
     */ 
    public static int getVersionCode(Context context) {
        try { 
            PackageManager packageManager = context.getPackageManager();
            PackageInfo packageInfo = packageManager.getPackageInfo(context.getPackageName(), 0);
            return packageInfo.versionCode;
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        } 
        return 0; 
    } 
}

2.文件操作工具類

package utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;

/**
 * 文件操作工具類
 */
public class FileUtil {
    /**
     * 在指定的位置創(chuàng)建指定的文件
     *
     * @param filePath 完整的文件路徑
     * @param mkdir 是否創(chuàng)建相關(guān)的文件夾
     * @throws Exception
     */
    public static void mkFile(String filePath, boolean mkdir) throws Exception {
        File file = new File(filePath);
        file.getParentFile().mkdirs();
        file.createNewFile();
        file = null;
    }

    /**
     * 在指定的位置創(chuàng)建文件夾
     *
     * @param dirPath 文件夾路徑
     * @return 若創(chuàng)建成功,則返回True;反之,則返回False
     */
    public static boolean mkDir(String dirPath) {
        return new File(dirPath).mkdirs();
    }

    /**
     * 刪除指定的文件
     *
     * @param filePath 文件路徑
     *
     * @return 若刪除成功,則返回True;反之,則返回False
     *
     */
    public static boolean delFile(String filePath) {
        return new File(filePath).delete();
    }

    /**
     * 刪除指定的文件夾
     *
     * @param dirPath 文件夾路徑
     * @param delFile 文件夾中是否包含文件
     * @return 若刪除成功,則返回True;反之,則返回False
     *
     */
    public static boolean delDir(String dirPath, boolean delFile) {
        if (delFile) {
            File file = new File(dirPath);
            if (file.isFile()) {
                return file.delete();
            } else if (file.isDirectory()) {
                if (file.listFiles().length == 0) {
                    return file.delete();
                } else {
                    int zfiles = file.listFiles().length;
                    File[] delfile = file.listFiles();
                    for (int i = 0; i < zfiles; i++) {
                        if (delfile[i].isDirectory()) {
                            delDir(delfile[i].getAbsolutePath(), true);
                        }
                        delfile[i].delete();
                    }
                    return file.delete();
                }
            } else {
                return false;
            }
        } else {
            return new File(dirPath).delete();
        }
    }

    /**
     * 復(fù)制文件/文件夾 若要進行文件夾復(fù)制,請勿將目標(biāo)文件夾置于源文件夾中
     * @param source 源文件(夾)
     * @param target 目標(biāo)文件(夾)
     * @param isFolder 若進行文件夾復(fù)制,則為True;反之為False
     * @throws Exception
     */
    public static void copy(String source, String target, boolean isFolder)
            throws Exception {
        if (isFolder) {
            (new File(target)).mkdirs();
            File a = new File(source);
            String[] file = a.list();
            File temp = null;
            for (int i = 0; i < file.length; i++) {
                if (source.endsWith(File.separator)) {
                    temp = new File(source + file[i]);
                } else {
                    temp = new File(source + File.separator + file[i]);
                }
                if (temp.isFile()) {
                    FileInputStream input = new FileInputStream(temp);
                    FileOutputStream output = new FileOutputStream(target + "/" + (temp.getName()).toString());
                    byte[] b = new byte[1024];
                    int len;
                    while ((len = input.read(b)) != -1) {
                        output.write(b, 0, len);
                    }
                    output.flush();
                    output.close();
                    input.close();
                }
                if (temp.isDirectory()) {
                    copy(source + "/" + file[i], target + "/" + file[i], true);
                }
            }
        } else {
            int byteread = 0;
            File oldfile = new File(source);
            if (oldfile.exists()) {
                InputStream inStream = new FileInputStream(source);
                File file = new File(target);
                file.getParentFile().mkdirs();
                file.createNewFile();
                FileOutputStream fs = new FileOutputStream(file);
                byte[] buffer = new byte[1024];
                while ((byteread = inStream.read(buffer)) != -1) {
                    fs.write(buffer, 0, byteread);
                }
                inStream.close();
                fs.close();
            }
        }
    }

    /**
     * 移動指定的文件(夾)到目標(biāo)文件(夾)
     * @param source 源文件(夾)
     * @param target 目標(biāo)文件(夾)
     * @param isFolder 若為文件夾,則為True;反之為False
     * @return
     * @throws Exception
     */
    public static boolean move(String source, String target, boolean isFolder)
            throws Exception {
        copy(source, target, isFolder);
        if (isFolder) {
            return delDir(source, true);
        } else {
            return delFile(source);
        }
    }
}

以上就是基于android編寫一個下載管理工具類的詳細(xì)內(nèi)容,更多關(guān)于android下載管理工具類的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評論

盱眙县| 南乐县| 株洲市| 宁波市| 宁津县| 酉阳| 资源县| 贵州省| 兴隆县| 本溪| 霍州市| 清丰县| 商都县| 怀远县| 阳城县| 桓仁| 龙里县| 宁德市| 上虞市| 冀州市| 临高县| 偏关县| 资阳市| 故城县| 柘城县| 额敏县| 崇仁县| 庆安县| 芦山县| 黎城县| 宁海县| 麻江县| 五家渠市| 潮州市| 天峻县| 绍兴县| 连州市| 府谷县| 宁波市| 东阿县| 社旗县|