Ok+Rxjava+retrofit 기반 단점 전송 다운로드

본 고 는 정지점 속전 다운 로드 를 실현 하 는 구체 적 인 코드 를 공유 하여 여러분 께 참고 하 시기 바 랍 니 다.구체 적 인 내용 은 다음 과 같 습 니 다.
1.Ok+Rxjava 기반 인 터 럽 트 다운로드
2.Ok+Rxjava+Retrofit 기반 인 터 럽 트 다운로드
이전 블 로그 에 서 는Ok+Rxjava 기반 인 터 럽 트 다운로드를 소개 했다.이 글 은 Ok+Rxjava+Retrofit 를 바탕 으로 정지점 전송 다운 로드 를 실현 하 는 것 을 소개 한다.데모 다운로드 주소효과 도 는 이전 사진 과 같다.하하

 제 대체적인 생각 을 말씀 드 리 겠 습 니 다.(이전 편 과 약간 다 릅 니 다)파일 다운로드 url 에 따라 자신 이 정의 한 규칙 에 따라 파일 이름 을 만 들 고 로 컬 같은 경로 에서 이 파일 이 존재 하 는 지 판단 합 니 다.존재 한다 면 파일 크기 가 서버 에서 가 져 온 파일 크기 와 일치 하 는 경우 로 컬 파일 을 덮어 서 다시 다운로드 합 니 다.서버 에서 가 져 온 파일 보다 파일 크기 가 작 으 면 정지점 다운 로드 를 실행 하고 로 컬 파일 길이 부터 다운로드 합 니 다.파일 이 존재 하지 않 으 면 0 바이트 부터 다운로드 합 니 다.
또 다른 것 은 여기 서 파일 다운로드 의 진 도 를 감청 하고 사용자 정의 Downloadinterceptor 를 통 해 우리 의 새로운 DownloadResponse Body 를 설정 하여 우리 의 진도 감청 작업 을 완성 해 야 한 다 는 것 이다.
다음은 위의 주요 코드 입 니 다.
먼저 ResponseBody 를 다시 쓰 겠 습 니 다.

public class DownloadResponseBody extends ResponseBody {
 private ResponseBody responseBody;
 
 //      
 private DownFileCallback downFileCallback;
 
 private BufferedSource bufferedSource;
 private String downUrl;
 
 
 public DownloadResponseBody(ResponseBody responseBody, DownFileCallback downFileCallback, String downUrl) {
 this.responseBody = responseBody;
 this.downFileCallback = downFileCallback;
 this.downUrl = downUrl;
 }
 
 @Override
 public MediaType contentType() {
 return responseBody.contentType();
 }
 
 @Override
 public long contentLength() {
 return responseBody.contentLength();
 }
 
 @Override
 public BufferedSource source() {
 if (bufferedSource == null) {
 bufferedSource = Okio.buffer(source(responseBody.source()));
 }
 return bufferedSource;
 }
 
 private Source source(Source source) {
 return new ForwardingSource(source) {
 long totalBytesRead = 0L;
 File file = new File(DownloadManager.getInstance().getTemporaryName(downUrl));
 
 @Override
 public long read(Buffer sink, long byteCount) throws IOException {
 long bytesRead = super.read(sink, byteCount);
 totalBytesRead += bytesRead != -1 ? bytesRead : 0;
 if (null != downFileCallback) {
 if (bytesRead != -1) {
 long loacalSize = file.length();//        
 long trueTotal = loacalSize + responseBody.contentLength() - totalBytesRead;//      
 downFileCallback.onProgress(trueTotal,loacalSize);
 } else {
 
 }
 
 }
 return bytesRead;
 }
 };
 
 }
}
인 터 셉 터 다시 쓰기

public class Downloadinterceptor implements Interceptor {
 
 private DownFileCallback downFileCallback;
 
 private String downUrl;
 
 public Downloadinterceptor(DownFileCallback listener,String downUrl) {
 this.downFileCallback = listener;
 this.downUrl = downUrl;
 }
 
 @Override
 public Response intercept(Chain chain) throws IOException {
 Response response = chain.proceed(chain.request());
 
 return response.newBuilder()
 .body(new DownloadResponseBody(response.body(), downFileCallback,downUrl))
 .build();
 }
}
그리고 우리 서비스.

public interface HttpService {
 
 /*       Streaming    ,             ,  oom*/
 @Streaming
 @GET
 Observable<ResponseBody> download(@Header("range") String start, @Url String url);
}
다음은 저희 DownloadManager 에서 download 방법 입 니 다.

 /**
 *     
 * @param url     
 * @param downFileCallback       
 */
 public void download(final String url, final DownFileCallback downFileCallback) {
 /*       */
 if (url == null || submap.get(url) != null) {
 return;
 }
 
 Downloadinterceptor interceptor = new Downloadinterceptor(downFileCallback, url);
 okHttpClient = new OkHttpClient.Builder()
 .addInterceptor(interceptor)
 .build();
 Retrofit retrofit = new Retrofit.Builder()
 .client(okHttpClient)
 .baseUrl("http://imtt.dd.qq.com")
 .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
 .build();
 final HttpService httpservice = retrofit.create(HttpService.class);
 
 ProgressDownSubscriber subscriber =
 Observable.just(url)
 .flatMap(new Function<String, ObservableSource<DownloadInfo>>() {
 @Override
 public ObservableSource<DownloadInfo> apply(String s) throws Exception {
 return Observable.just(createDownInfo(s));
 }
 })
 .map(new Function<DownloadInfo, DownloadInfo>() {
 @Override
 public DownloadInfo apply(DownloadInfo s) throws Exception {
 return getRealFileName(s);
 }
 })
 .flatMap(new Function<DownloadInfo, Observable<ResponseBody>>() {
 @Override
 public Observable<ResponseBody> apply(DownloadInfo downInfo) throws Exception {
 return httpservice.download("bytes=" + downInfo.getProgress() + "-", downInfo.getUrl());
 }
 })//  
 .map(new Function<ResponseBody, DownloadInfo>() {
 @Override
 public DownloadInfo apply(ResponseBody responsebody) {
 try {
 return writecache(responsebody, url);
 } catch (IOException e) {
 //*      *//
 e.printStackTrace();
 }
 return null;
 }
 })
 .observeOn(AndroidSchedulers.mainThread())//      
 .subscribeOn(Schedulers.io())//      
 .subscribeWith(new ProgressDownSubscriber<DownloadInfo>() {
 @Override
 public void onNext(DownloadInfo downInfo) {
 downFileCallback.onSuccess(downInfo);
 submap.remove(downInfo.getUrl());
 }
 
 @Override
 public void onError(Throwable t) {
 downFileCallback.onFail(t.getMessage());
 submap.remove(url);
 }
 });
 
 
 submap.put(url, subscriber);
 }
그리고 작업 일시 정지:

 /**
 *     
 */
 public void stop(String url) {
 if (url == null) return;
 if (submap.containsKey(url)) {
 ProgressDownSubscriber subscriber = submap.get(url);
 subscriber.dispose();
 submap.remove(url);
 }
 }
서버 에서 파일 길이 가 져 오기

/**
 *           
 *
 * @param downloadUrl
 * @return
 */
 private long getContentLength(String downloadUrl) {
 Request request = new Request.Builder()
 .url(downloadUrl)
 .build();
 try {
 Response response = mClient.newCall(request).execute();
 if (response != null && response.isSuccessful()) {
 long contentLength = response.body().contentLength();
 response.close();
 return contentLength == 0 ? DownloadInfo.TOTAL_ERROR : contentLength;
 }
 } catch (IOException e) {
 e.printStackTrace();
 }
 return DownloadInfo.TOTAL_ERROR;
 }
서버 에서 파일 길 이 를 가 져 올 때 주의 하 세 요.Android P 이후 api 28 이상 은 명문 네트워크 전송 을 금지 합 니 다.Android Manifest 의 application 태그 에"android:uses CleartextTraffic="true"를 표시 해 야 합 니 다.명문 전송 을 허용 합 니 다.
사용 방법:우선 sd 카드 권한 획득

DownloadManager.getInstance().downloadPath(      ).download(url1, new DownFileCallback() {
 @Override
 public void onSuccess(DownloadInfo info) {
 
 Toast.makeText(MainActivity.this, url1 + "    ", Toast.LENGTH_SHORT).show();
 }
 
 @Override
 public void onFail(String msg) {
 Toast.makeText(MainActivity.this, url1 + "    ", Toast.LENGTH_SHORT).show();
 }
 
 @Override
 public void onProgress(final long totalSize, final long downSize) {
 //       ,        50M,       10M,
 //      onProgress   totalSize      
 //          10M,  40M,downSize          
 //     ,          ,     ,              
 
 runOnUiThread(new Runnable() {
 @Override
 public void run() {
 int progress = (int) (downSize * 100 / totalSize);
 progress1.setProgress(progress);
 }
 });
 }
 });
자,오늘 은 여기까지 입 니 다.여러분 에 게 도움 이 되 었 으 면 좋 겠 습 니 다.이것 은 저 에 게 도 깊 은 인상 을 주 는 노트 입 니 다.
데모 다운로드 주소
github 주소:DownManager  환영 스타
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기