【GT-安卓应用开发之文件下载实现】

前言:之前有篇文章记录了一下Retrofit,这篇文章也是基于Retrofit实现的。接下来就记录一下,之前做的利用Retrofit实现的文件下载功能。

        首先,定义接口与Retrofit对象

//下载文件
@Streaming
@GET
Call<ResponseBody> downloadFile(@Url String fileUrl);
public static POSTService getDownloadApi() {
    postService = null;
    OkHttpClient client = new OkHttpClient.Builder()
            .retryOnConnectionFailure(true)
            .connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
            .build();
    Retrofit build = new Retrofit.Builder()
            .baseUrl(API_HOST)
            .client(client)
            .build();
    postService  = build.create(POSTService.class);
    return  postService;
}

        然后,定义DownloadUtils类、FileUtils类以及DownloadListener接口

public class DownloadUtils {

    private static final String TAG = "DownloadUtils";

    // 视频下载相关
    protected POSTService mApi;
    private Handler mHandler;
    private Call<ResponseBody> mCall;
    private File mFile;
    private Thread mThread;
    // 下载到本地的文件目录
    private String mFileFolder = Environment.getExternalStorageDirectory() + "/DownloadFile";
    // 下载到本地的文件路径
    private String mFilePath;

    public DownloadUtils() {
        if (mApi == null) {
            mApi = RetrofitBean.getDownloadApi();
        }
        mHandler = new Handler();
    }
public void downloadFile(String url, final DownloadListener downloadListener) {
        //通过Url得到保存到本地的文件名
        String name = url;
        if (FileUtils.createOrExistsDir(mFileFolder)) {
            int i = name.lastIndexOf('/');//一定是找最后一个'/'出现的位置
            if (i != -1) {
                name = name.substring(i);
                mFilePath = mFileFolder + name;
            }
        }
        if (TextUtils.isEmpty(mFilePath)) {
            Log.e(TAG, "downloadVideo: 存储路径为空了");
            return;
        }
        //建立一个文件
        mFile = new File(mFilePath);
        if (FileUtils.createOrExistsFile(mFile)) {
            if (mApi == null) {
                Log.e(TAG, "downloadVideo: 下载接口为空了");
                return;
            }
            mCall = mApi.downloadFile(url);
            mCall.enqueue(new Callback<ResponseBody>() {
                @Override
                public void onResponse(@NonNull Call<ResponseBody> call, @NonNull final Response<ResponseBody> response) {
                    //下载文件放在子线程
                    mThread = new Thread() {
                        @Override
                        public void run() {
                            super.run();
                            //保存到本地
                            writeFile2Disk(response, mFile, downloadListener);
                        }
                    };
                    mThread.start();
                }

                @Override
                public void onFailure(Call<ResponseBody> call, Throwable t) {
                    downloadListener.onFailure("网络错误!");
                }
            });
        }
    }

    private void writeFile2Disk(Response<ResponseBody> response, File file, final DownloadListener downloadListener) {
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                downloadListener.onStart();
            }
        });
        long currentLength = 0;
        OutputStream os = null;

        if (response.body() == null) {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    downloadListener.onFailure("资源错误!");
                }
            });
            return;
        }
        InputStream is = response.body().byteStream();
        final long totalLength = response.body().contentLength();

        try {
            os = new FileOutputStream(file);
            int len;
            byte[] buff = new byte[1024];
            while ((len = is.read(buff)) != -1) {
                os.write(buff, 0, len);
                currentLength += len;
                Log.e(TAG, "当前进度: " + currentLength);
                final long finalCurrentLength = currentLength;
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        downloadListener.onProgress((int) (100 * finalCurrentLength / totalLength));
                        if ((int) (100 * finalCurrentLength / totalLength) == 100) {
                            downloadListener.onFinish(mFilePath);
                        }
                    }
                });
            }
        } catch (FileNotFoundException e) {
            downloadListener.onFailure("未找到文件!");
            e.printStackTrace();
        } catch (IOException e) {
            downloadListener.onFailure("IO错误!");
            e.printStackTrace();
        } finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
public class FileUtils {
    /**
     * 判断文件是否存在
     *
     * @param file 文件
     * @return {@code true}: 存在<br>{@code false}: 不存在
     */
    public static boolean isFileExists(final File file) {
        return file != null && file.exists();
    }

    /**
     * 判断文件是否存在,不存在则判断是否创建成功
     *
     * @param file 文件
     * @return {@code true}: 存在或创建成功<br>{@code false}: 不存在或创建失败
     */
    public static boolean createOrExistsFile(final File file) {
        if (file == null) return false;
        // 如果存在,是文件则返回 true,是目录则返回 false
        if (file.exists()) return file.isFile();
        if (!createOrExistsDir(file.getParentFile())) return false;
        try {
            return file.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 判断目录是否存在,不存在则判断是否创建成功
     *
     * @param file 文件
     * @return {@code true}: 存在或创建成功<br>{@code false}: 不存在或创建失败
     */
    public static boolean createOrExistsDir(final File file) {
        // 如果存在,是目录则返回 true,是文件则返回 false,不存在则返回是否创建成功
        return file != null && (file.exists() ? file.isDirectory() : file.mkdirs());
    }

    /**
     * 判断目录是否存在,不存在则判断是否创建成功
     *
     * @param dirPath 目录路径
     * @return {@code true}: 存在或创建成功<br>{@code false}: 不存在或创建失败
     */
    public static boolean createOrExistsDir(final String dirPath) {
        return createOrExistsDir(getFileByPath(dirPath));
    }

    /**
     * 根据文件路径获取文件
     *
     * @param filePath 文件路径
     * @return 文件
     */
    public static File getFileByPath(final String filePath) {
        return isSpace(filePath) ? null : new File(filePath);
    }

    private static boolean isSpace(final String s) {
        if (s == null) return true;
        for (int i = 0, len = s.length(); i < len; ++i) {
            if (!Character.isWhitespace(s.charAt(i))) {
                return false;
            }
        }
        return true;
    }
}
public interface DownloadListener {
    void onStart();

    void onProgress(int currentLength);

    void onFinish(String localPath);

    void onFailure(String errorInfo);
}

        然后,开始下载

private void downloadFile(String url) {
    DownloadUtils downloadUtils = new DownloadUtils();
    downloadUtils.downloadFile(url, new DownloadListener() {
        @Override
        public void onStart() {
            Log.e(TAG, "onStart: ");
            isDowning = true;
            Toast.makeText(MyApplication.getContextObject(),"正在下载,请稍后",Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onProgress(final int currentLength) {
            Log.e(TAG, "onLoading: " + currentLength);
        }

        @Override
        public void onFinish(String localPath) {
            Log.e(TAG, "onFinish: " + localPath);
            isDowning = false;
            Toast.makeText(MyApplication.getContextObject(),"下载完成",Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onFailure(final String errorInfo) {
            Log.e(TAG, "onFailure: " + errorInfo);
            isDowning = false;
            Toast.makeText(MyApplication.getContextObject(),"下载失败,请重试。。。",Toast.LENGTH_SHORT).show();
        }
    });
}

        上面代码中定义了一个isDowning变量,它的作用是控制一次只会下载一个文件

猜你喜欢

转载自blog.csdn.net/qq_17433217/article/details/81735160
今日推荐