Android——使用retrofit实现下载(断点续传、开始、停止)

为 Retrofit 不太熟悉的小伙伴提供便捷通道助力我们共同进步

开启IntentService进行下载,在下载完毕,它会自动关闭服务

public class DownloadIntentService extends IntentService {
    private static final String TAG = "DownloadIntentService";
    private NotificationManager mNotifyManager;
    private String mDownloadFileName;
    private Notification mNotification;
    private int progress;
    private int downcode;
    private RemoteViews remoteViews;
    private int downloadId;
    //retrofit订阅事件的监听
    public static CompositeDisposable compositeDisposable = new CompositeDisposable();

    public DownloadIntentService() {
        super("InitializeService");
    }

    @Override
    public int onStartCommand(@android.support.annotation.Nullable Intent intent, int flags, int startId) {
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public boolean stopService(Intent name) {
        return super.stopService(name);
    }

    @Override
    protected void onHandleIntent(@Nullable Intent intent) {
        String downloadUrl = intent.getExtras().getString("download_url");
        downloadId = intent.getExtras().getInt("download_id");
        mDownloadFileName = intent.getExtras().getString("download_file");
        downcode = intent.getExtras().getInt("downcode");

        Log.d(TAG, "download_url --" + downloadUrl);
        Log.d(TAG, "download_file --" + mDownloadFileName);

        //文件存储地址
        final File file = new File(ConstantCode.APP_ROOT_PATH + ConstantCode.DOWNLOAD_DIR + mDownloadFileName);
        long range = 0;
        progress = 0;
        if (file.exists()) {
            range = SPDownloadUtil.getInstance().get(downloadUrl, 0);
            progress = (int) (range * 100 / file.length());
            if (range == file.length()) {
                installApp(file);
                return;
            }
        }
        Log.d(TAG, "range = " + range);
        
        //下载文件
        remoteViews = new RemoteViews(getPackageName(), R.layout.notify_download);
        remoteViews.setProgressBar(R.id.pb_progress, 100, progress, false);
        remoteViews.setTextViewText(R.id.tv_progress, "已下载" + progress + "%");

        final NotificationCompat.Builder builder =
                new NotificationCompat.Builder(this)
                        .setContent(remoteViews)
                        .setTicker("正在下载")
                        .setSmallIcon(R.drawable.logo);
                        
        mNotification = builder.build();

        mNotifyManager = (NotificationManager)
                getSystemService(Context.NOTIFICATION_SERVICE);
        mNotifyManager.notify(downloadId, mNotification);

        HttpManager.getInstance().downloadFile(getApplication(), range, downloadUrl, mDownloadFileName, new DownloadCallBack() {
            @Override
            public void onProgress(int progress) {
                DialogActivity.appHandler.sendEmptyMessage(progress);
                SPUtils.put(getApplication(), "downProgressRange", progress);
                remoteViews.setProgressBar(R.id.pb_progress, 100, progress, false);
                remoteViews.setTextViewText(R.id.tv_progress, "已下载" + progress + "%");
                mNotifyManager.notify(downloadId, mNotification);
        }
        @Override
        public void onFileLength (String fileLength){
            Log.d(TAG, "文件大小为:" + fileLength);
        }
        @Override
        public void onCompleted () {
            Log.d(TAG, "下载完成");
            SPUtils.put(getApplication(), "downOnce", false);
            SPUtils.put(getApplication(), "downFenish", true);
            SPUtils.put(getApplication(), "downProgressRange", 9999);
            mNotifyManager.cancel(downloadId);
            installApp(file);
        }

        @Override
        public void onError (String msg){
            mNotifyManager.cancel(downloadId);
            Log.d(TAG, "下载发生错误--" + msg);
        }
    });
}

    //安装apk
    private void installApp(File file) {
        DialogActivity.appHandler.sendEmptyMessage(100);
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
        startActivity(intent);
    }

    public void setCompositeDisposable() {
        //暂停下载
        if (!compositeDisposable.isDisposed()) {
            if (compositeDisposable.size() != 0) {
                compositeDisposable.clear();
            }
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }
}

retrofit请求方法:

/*
 * 下载app
 * */
public void downloadFile(Context context, final long range, final String url, final String fileName, final DownloadCallBack downloadCallback) {
    //断点续传时请求的总长度
    File file = new File(ConstantCode.APP_ROOT_PATH + ConstantCode.DOWNLOAD_DIR, fileName);
    String totalLength = "-";
    if (file.exists()) {
        totalLength += file.length();
    }
    changeApiBaseUrl().executeDownload("bytes=" + Long.toString(range) + totalLength, url)
            .subscribe(new Observer<ResponseBody>() {
                @Override
                public void onSubscribe(Disposable d) {
                    DownloadIntentService.compositeDisposable.add(d);
                }

                @Override
                public void onNext(ResponseBody responseBody) {
                    RandomAccessFile randomAccessFile = null;
                    InputStream inputStream = null;
                    long total = range;
                    long responseLength = 0;
                    try {
                        byte[] buf = new byte[2048];
                        int len = 0;
                        //剩余下载的长度
                        responseLength = responseBody.contentLength();

                        inputStream = responseBody.byteStream();
                        String filePath = ConstantCode.APP_ROOT_PATH + ConstantCode.DOWNLOAD_DIR;
                        File file = new File(filePath, fileName);
                        File dir = new File(filePath);
                        if (!dir.exists()) {
                            dir.mkdirs();
                        }
                        randomAccessFile = new RandomAccessFile(file, "rwd");
                        if (range == 0) {
                            randomAccessFile.setLength(responseLength);
                        }
                        randomAccessFile.seek(range);

                        int progress = 0;
                        int lastProgress = 0;

                        while ((len = inputStream.read(buf)) != -1) {
                            randomAccessFile.write(buf, 0, len);
                            total += len;
                            //cun
                            SPDownloadUtil.getInstance().save(url, total);
                            lastProgress = progress;
                            progress = (int) (total * 100 / randomAccessFile.length());
                            if (progress > 0 && progress != lastProgress && progress >= lastProgress) {
                                downloadCallback.onProgress(progress);
                            }
                        }
                        downloadCallback.onCompleted();
                    } catch (Exception e) {
                        Log.d("DownloadIntentService", e.getMessage());
                        downloadCallback.onError(e.getMessage());
                        e.printStackTrace();
                    } finally {
                        try {
                            if (randomAccessFile != null) {
                                randomAccessFile.close();
                            }
                            if (inputStream != null) {
                                inputStream.close();
                            }

                        } catch (Exception e) {
                            e.printStackTrace();
                        }

                    }
                }

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

                @Override
                public void onComplete() {
                }
            });
}

api配置如下内容

@Streaming
@GET
Observable<ResponseBody> executeDownload(@Header("Range") String range, @Url() String url);

开启服务

//开启服务
public void goDownLoad(int code) {
    if (isServiceRunning(DownloadIntentService.class.getName())) {
        Toast.makeText(DialogActivity.this, "正在下载", Toast.LENGTH_SHORT).show();
        return;
    }
    Intent intent = new Intent(getApplicationContext(), DownloadIntentService.class);
    Bundle bundle = new Bundle();
    bundle.putString("download_url", '/' + download_url.substring(download_url.lastIndexOf('/') + 1));
    bundle.putInt("download_id", DOWNLOADAPK_ID);
    bundle.putInt("downcode", code);
    bundle.putString("download_file", download_url.substring(download_url.lastIndexOf('/') + 1));
    intent.putExtras(bundle);
    startService(intent);
}

/**
 * 用来判断服务是否运行.
 *
 * @param className 判断的服务名字
 * @return true 在运行 false 不在运行
 */
private boolean isServiceRunning(String className) {
    boolean isRunning = false;
    ActivityManager activityManager = (ActivityManager) this
            .getSystemService(Context.ACTIVITY_SERVICE);
    List<ActivityManager.RunningServiceInfo> serviceList = activityManager
            .getRunningServices(Integer.MAX_VALUE);
    if (!(serviceList.size() > 0)) {
        return false;
    }
    for (int i = 0; i < serviceList.size(); i++) {
        if (serviceList.get(i).service.getClassName().equals(className) == true) {
            isRunning = true;
            break;
        }
    }
    return isRunning;
}

暂停停止皆可以如此

//关闭服务 停止下载
public void stopFinishSer(){
	 //也就是取消订阅
    if (!DownloadIntentService.compositeDisposable.isDisposed()) {
        if (DownloadIntentService.compositeDisposable.size() != 0) {
            DownloadIntentService.compositeDisposable.clear();
        }
    }
    stopService(intent);
}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
如果要在 Android使用 Retrofit 请求头设置 Range 实现下载测速功能,可以参考以下代码: ```java // 创建 Retrofit 实例 Retrofit retrofit = new Retrofit.Builder() .baseUrl("http://example.com/") .build(); // 定义 API 接口 interface ApiService { @Streaming @GET Call<ResponseBody> downloadFile(@Header("Range") String range, @Url String url); } // 创建 API 实例 ApiService apiService = retrofit.create(ApiService.class); // 下载文件并测速 long start = System.nanoTime(); Call<ResponseBody> call = apiService.downloadFile("bytes=0-1023", "http://example.com/file.zip"); Response<ResponseBody> response = call.execute(); long end = System.nanoTime(); // 计算下载速度 float speed = response.body().contentLength() / ((end - start) / 1e9f); Log.d("DownloadSpeed", "下载速度:" + speed + " B/s"); ``` 上面的代码中,我们使用 Retrofit 创建了一个 API 接口 `ApiService`,其中定义了一个下载文件的方法 `downloadFile()`,它接受两个参数: - `range`:请求头中的 Range 字段,用于指定下载的文件范围; - `url`:要下载的文件的 URL。 在调用 `downloadFile()` 方法时,我们传入了一个范围为 0-1023 的参数,表示只下载文件的前 1KB。下载完成后,我们计算了下载速度(单位为 B/s),并使用 Log 输出了结果。 注意,为了支持大文件下载,我们在 `@GET` 注解中使用了 `@Streaming` 注解,以避免一次性将整个响应体读入内存。同时,为了支持断点续传,我们在请求头中添加了 `Range` 字段。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值