Java tutorial
/* * Copyright (C) 2015 pengjianbo(pengjianbosoft@gmail.com), Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package cn.finalteam.okhttpfinal.dm; import android.os.Message; import cn.finalteam.okhttpfinal.OkHttpFinal; import cn.finalteam.sqlitefinal.DbHelper; import cn.finalteam.sqlitefinal.exception.DbException; import cn.finalteam.sqlitefinal.sqlite.WhereBuilder; import cn.finalteam.toolsfinal.FileUtils; import cn.finalteam.toolsfinal.Logger; import cn.finalteam.toolsfinal.StringUtils; import com.squareup.okhttp.OkHttpClient; import com.squareup.okhttp.Request; import com.squareup.okhttp.Response; import java.io.BufferedInputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.RandomAccessFile; /** * Desction: TODO ???? * Author:pengjianbo * Date:15/8/22 ?4:30 */ public class DownloadHttpTask extends Thread { private final int BUFFER_SIZE = 1024 * 8; private int RESULT_NET_ERROR = -1; private int RESULT_OTHER_ERROR = 0; private int RESULT_SUCCESS = 1; // private boolean mInterrupt; private ProgressReportingRandomAccessFile mProgressReportingRandomAccessFile; // private long mPreviousTime; //?? private boolean mUpdateDbFlag; private DownloadInfo mDownloadInfo; private UpdateDownloadDbThread mUpdateDbThread; private DownloadNextTaskListener mDownloadNextTaskListener; private DownloadUIHandler mDownloadUIHandler; private OkHttpClient mOkHttpClient; private DbHelper mDbHelper; public DownloadHttpTask(DownloadInfo downloadInfo, DownloadUIHandler downloadUIHandler, DbHelper dbHelper, DownloadNextTaskListener downloadNextTaskListener) { this.mDownloadInfo = downloadInfo; this.mDownloadUIHandler = downloadUIHandler; this.mDbHelper = dbHelper; this.mOkHttpClient = OkHttpFinal.getOkHttpFinal().getOkHttpClient(); this.mUpdateDbThread = new UpdateDownloadDbThread(); this.mDownloadNextTaskListener = downloadNextTaskListener; } @Override public void run() { super.run(); onPreExecute(); int result = request(); if (result == RESULT_SUCCESS) { mDownloadInfo.setState(DownloadInfo.COMPLETE); } else { mDownloadInfo.setState(DownloadInfo.PAUSE); mInterrupt = true; } mDownloadNextTaskListener.nextTask(); postMessage(); } private int request() { String url = mDownloadInfo.getUrl(); int resultCode = RESULT_SUCCESS; long startPos = 0; String fileName = FileUtils.getUrlFileName(url); File file = new File(mDownloadInfo.getTargetFolder(), fileName); if (StringUtils.isEmpty(mDownloadInfo.getTargetPath())) { mDownloadInfo.setTargetPath(file.getAbsolutePath()); } if (file.exists()) { startPos = file.length(); } else { try { boolean b = file.createNewFile(); if (!b) { resultCode = RESULT_OTHER_ERROR; Logger.e("create new File failure file=" + file.getAbsolutePath()); return resultCode; } } catch (IOException e) { Logger.e(e + " file=" + file.getAbsolutePath()); resultCode = RESULT_OTHER_ERROR; return resultCode; } } // try { mProgressReportingRandomAccessFile = new ProgressReportingRandomAccessFile(file, "rw", startPos); } catch (FileNotFoundException e) { Logger.e(e); resultCode = RESULT_OTHER_ERROR; return resultCode; } Request request = new Request.Builder().url(url).header("RANGE", "bytes=" + startPos + "-")//httpRANGE .build(); // Response response = null; try { response = mOkHttpClient.newCall(request).execute(); } catch (IOException e) { Logger.e(e); resultCode = RESULT_OTHER_ERROR; return resultCode; } if (response == null || !response.isSuccessful()) {//?? if (response != null) { Logger.e("~ code=" + response.code() + "url=" + url); } resultCode = RESULT_NET_ERROR; } else { try { InputStream inputStream = response.body().byteStream(); try { long totalLength = response.body().contentLength(); if (mDownloadInfo.getTotalLength() == 0l) { mDownloadInfo.setTotalLength(totalLength); } //?? if (startPos > mDownloadInfo.getTotalLength()) { FileUtils.deleteFile(mDownloadInfo.getTargetPath()); mDownloadInfo.setProgress(0); mDownloadInfo.setDownloadLength(0); mDownloadInfo.setTotalLength(0); return resultCode; } if (startPos == mDownloadInfo.getTotalLength() && startPos > 0) { publishProgress(100); return resultCode; } //? int bytesCopied = download(inputStream, mProgressReportingRandomAccessFile); if (((startPos + bytesCopied) != mDownloadInfo.getTotalLength()) || mInterrupt) { // resultCode = RESULT_OTHER_ERROR; return resultCode; } } catch (Exception e) { e.printStackTrace(); resultCode = RESULT_OTHER_ERROR; return resultCode; } } catch (IOException e) { e.printStackTrace(); resultCode = RESULT_OTHER_ERROR; return resultCode; } } return resultCode; } /** * * @param input * @param out * @return * @throws Exception */ public int download(InputStream input, RandomAccessFile out) throws Exception { if (input == null || out == null) { return -1; } byte[] buffer = new byte[BUFFER_SIZE]; BufferedInputStream in = new BufferedInputStream(input, BUFFER_SIZE); int count = 0, n = 0; try { out.seek(out.length()); while (!mInterrupt) { n = in.read(buffer, 0, BUFFER_SIZE); if (n == -1) { break; } if (mInterrupt) { throw new RuntimeException("task interrupt"); } out.write(buffer, 0, n); count += n; } } finally { mOkHttpClient = null; try { out.close(); in.close(); input.close(); } catch (Exception e) { Logger.e(e); } } return count; } /** * */ protected void onPreExecute() { mPreviousTime = System.currentTimeMillis(); mDownloadInfo.setState(DownloadInfo.DOWNLOADING); mUpdateDbThread.start(); postMessage(); } /** * UI * @param progress */ public void publishProgress(int progress) { mDownloadInfo.setProgress(progress); if (!mInterrupt) { if (progress == 100) { //? mDownloadInfo.setState(DownloadInfo.COMPLETE); mDownloadNextTaskListener.nextTask(); } else { mDownloadInfo.setState(DownloadInfo.DOWNLOADING); } } mUpdateDbFlag = true; postMessage(); } private void postMessage() { Message msg = mDownloadUIHandler.obtainMessage(); msg.obj = mDownloadInfo; mDownloadUIHandler.sendMessage(msg); } public boolean isInterrupt() { return mInterrupt; } public void setInterrupt(boolean interrupt) { this.mInterrupt = interrupt; if (mInterrupt) { mDownloadInfo.setState(DownloadInfo.PAUSE); postMessage(); mDownloadNextTaskListener.nextTask(); } } /** * */ private final class ProgressReportingRandomAccessFile extends RandomAccessFile { private long lastDownloadLength = 0; private long curDownloadLength = 0; private long lastRefreshUiTime; public ProgressReportingRandomAccessFile(File file, String mode, long lastDownloadLength) throws FileNotFoundException { super(file, mode); this.lastDownloadLength = lastDownloadLength; this.lastRefreshUiTime = System.currentTimeMillis(); } @Override public void write(byte[] buffer, int offset, int count) throws IOException { super.write(buffer, offset, count); //? long downloadLength = lastDownloadLength + count; curDownloadLength += count; lastDownloadLength = downloadLength; mDownloadInfo.setDownloadLength(downloadLength); // long totalTime = (System.currentTimeMillis() - mPreviousTime) / 1000; if (totalTime == 0) { totalTime += 1; } long networkSpeed = curDownloadLength / totalTime; mDownloadInfo.setNetworkSpeed(networkSpeed); // int progress = (int) (downloadLength * 100 / mDownloadInfo.getTotalLength()); mDownloadInfo.setProgress(progress); long curTime = System.currentTimeMillis(); if (curTime - lastRefreshUiTime >= 1000 || progress == 100) { publishProgress(progress); lastRefreshUiTime = System.currentTimeMillis(); } } } /** * ? */ private final class UpdateDownloadDbThread extends Thread { @Override public void run() { super.run(); while (true) { if (mUpdateDbFlag) { mUpdateDbFlag = false; //? try { mDbHelper.update(mDownloadInfo, WhereBuilder.b("url", "=", mDownloadInfo.getUrl()), "progress", "downloadLength", "totalLength", "targetPath"); } catch (DbException e) { Logger.e(e); } } if (mInterrupt) {// break; } } } } }