package com.wm.remusic.downmusic; /** * Created by wm on 2016/4/12. */ import android.content.Context; import android.content.Intent; import android.net.Uri; import android.text.TextUtils; import android.util.Log; import android.widget.Toast; import com.squareup.okhttp.OkHttpClient; import com.squareup.okhttp.Request; import com.squareup.okhttp.Response; import com.squareup.okhttp.ResponseBody; import com.wm.remusic.provider.DownFileStore; import java.io.BufferedInputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.RandomAccessFile; import java.util.ArrayList; import java.util.List; /** * Created by dzc on 15/11/21. */ public class DownloadTask implements Runnable { private DownloadDBEntity dbEntity; private DownFileStore downFileStore; private OkHttpClient client; private Context mContext; private String id; private long totalSize; private long completedSize; // Download section has been completed // private float percent; // Percent Complete private String url; private String saveDirPath; private RandomAccessFile file; private int UPDATE_SIZE = 50 * 1024; // The database is updated once every 50k private int downloadStatus = DownloadStatus.DOWNLOAD_STATUS_INIT; private String fileName; // File name when saving private String artist; private String temp = ".temp"; private boolean isPreparingDown; private String TAG = "DownloadTask"; private List<DownloadTaskListener> listeners; public DownloadTask(Context context) { mContext = context.getApplicationContext(); listeners = new ArrayList<>(); downFileStore = DownFileStore.getInstance(context); } public DownloadTask(Context context, Builder builder) { // mContext = context.getApplicationContext(); listeners = new ArrayList<>(); downFileStore = DownFileStore.getInstance(context); init(builder); } private void init(Builder builder) { mContext = builder.context; fileName = builder.fileName; artist = builder.art; saveDirPath = builder.saveDirPath; completedSize = builder.completedSize; dbEntity = builder.dbEntity; url = builder.url; totalSize = builder.totalSize; completedSize = builder.completedSize; id = builder.id; downloadStatus = builder.downloadStatus; UPDATE_SIZE = builder.UPDATE_SIZE; listeners = builder.listeners; } public static class Builder { private String url; private String fileName = url; // File name when saving private String art; private String saveDirPath; private Context context; private DownloadDBEntity dbEntity = null; private String id; private long totalSize; private long completedSize; // Download section has been completed private int UPDATE_SIZE = 50 * 1024; // The database is updated once every 50k private int downloadStatus = DownloadStatus.DOWNLOAD_STATUS_INIT; private List<DownloadTaskListener> listeners = new ArrayList<>(); public Builder(Context context) { this.context = context.getApplicationContext(); } public Builder(Context context, String url) { this.url = url; this.context = context.getApplicationContext(); } public Builder setFileName(String fileName) { this.fileName = fileName; return this; } public Builder setArtName(String art) { this.art = art; return this; } public Builder setSaveDirPath(String saveDirPath) { this.saveDirPath = saveDirPath; return this; } public Builder setId(String id) { this.id = id; return this; } public Builder setCache(int UPDATE_SIZE) { this.UPDATE_SIZE = UPDATE_SIZE; return this; } public Builder setCompletedSize(long completedSize) { this.completedSize = completedSize; return this; } public Builder setTotalSize(long totalSize) { this.totalSize = totalSize; return this; } public Builder setDBEntity(DownloadDBEntity dbEntity) { this.dbEntity = dbEntity; downloadStatus = dbEntity.getDownloadStatus(); url = dbEntity.getUrl(); id = dbEntity.getDownloadId(); fileName = dbEntity.getFileName(); art = dbEntity.getArtist(); saveDirPath = dbEntity.getSaveDirPath(); completedSize = dbEntity.getCompletedSize(); totalSize = dbEntity.getTotalSize(); return this; } public Builder setListeners(List<DownloadTaskListener> listeners) { this.listeners = listeners; return this; } public Builder setDownloadStatus(int downloadStatus) { this.downloadStatus = downloadStatus; return this; } public DownloadTask build() { // id = (saveDirPath + fileName).hashCode() + ""; return new DownloadTask(context, this); } } @Override public void run() { Log.e("start", completedSize + ""); downloadStatus = DownloadStatus.DOWNLOAD_STATUS_PREPARE; // id = (saveDirPath + fileName).hashCode() + ""; onPrepare(); InputStream inputStream = null; BufferedInputStream bis = null; try { dbEntity = downFileStore.getDownLoadedList(id); file = new RandomAccessFile(saveDirPath + fileName, "rwd"); if (dbEntity != null) { completedSize = dbEntity.getCompletedSize(); totalSize = dbEntity.getTotalSize(); } if (file.length() < completedSize) { completedSize = file.length(); } long fileLength = file.length(); if (fileLength != 0 && totalSize == fileLength) { downloadStatus = DownloadStatus.DOWNLOAD_STATUS_COMPLETED; totalSize = completedSize = fileLength; dbEntity = new DownloadDBEntity(id, totalSize, completedSize, url, saveDirPath, fileName, artist, downloadStatus); downFileStore.insert(dbEntity); Log.e(TAG, "file is completed , file length = " + fileLength + " file totalsize = " + totalSize); Toast.makeText(mContext, fileName + "已经下载完成", Toast.LENGTH_SHORT).show(); onCompleted(); return; } else if (fileLength > totalSize) { completedSize = 0; totalSize = 0; } downloadStatus = DownloadStatus.DOWNLOAD_STATUS_START; onStart(); Request request = new Request.Builder() .url(url) .header("RANGE", "bytes=" + completedSize + "-")// Http value set breakpoints RANGE .addHeader("Referer", url) .build(); Log.e("comlesize", completedSize + ""); file.seek(completedSize); Response response = client.newCall(request).execute(); ResponseBody responseBody = response.body(); if (responseBody != null) { downloadStatus = DownloadStatus.DOWNLOAD_STATUS_DOWNLOADING; if (totalSize <= 0) totalSize = responseBody.contentLength(); inputStream = responseBody.byteStream(); bis = new BufferedInputStream(inputStream); byte[] buffer = new byte[4 * 1024]; int length = 0; int buffOffset = 0; if (dbEntity == null) { dbEntity = new DownloadDBEntity(id, totalSize, 0L, url, saveDirPath, fileName, artist, downloadStatus); downFileStore.insert(dbEntity); } while ((length = bis.read(buffer)) > 0 && downloadStatus != DownloadStatus.DOWNLOAD_STATUS_CANCEL && downloadStatus != DownloadStatus.DOWNLOAD_STATUS_PAUSE) { file.write(buffer, 0, length); completedSize += length; buffOffset += length; if (buffOffset >= UPDATE_SIZE) { // Update download information database if (totalSize <= 0 || dbEntity.getTotalSize() <= 0) dbEntity.setToolSize(totalSize); buffOffset = 0; dbEntity.setCompletedSize(completedSize); dbEntity.setDownloadStatus(downloadStatus); downFileStore.update(dbEntity); onDownloading(); } } //这两句根据需要自行选择是否注释,注释掉的话由于少了数据库的读取,速度会快一点,但同时如果在下载过程程序崩溃的话,程序不会保存最新的下载进度 dbEntity.setCompletedSize(completedSize); dbEntity.setDownloadStatus(downloadStatus); downFileStore.update(dbEntity); onDownloading(); } } catch (FileNotFoundException e) { downloadStatus = DownloadStatus.DOWNLOAD_STATUS_ERROR; onError(DownloadTaskListener.DOWNLOAD_ERROR_FILE_NOT_FOUND); return; // e.printStackTrace(); } catch (IOException e) { downloadStatus = DownloadStatus.DOWNLOAD_STATUS_ERROR; onError(DownloadTaskListener.DOWNLOAD_ERROR_IO_ERROR); return; } finally { //String nP = fileName.substring(0, path.length() - 5); dbEntity.setCompletedSize(completedSize); dbEntity.setFileName(fileName); downFileStore.update(dbEntity); if (bis != null) try { bis.close(); } catch (IOException e) { e.printStackTrace(); } if (inputStream != null) try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } if (file != null) try { file.close(); } catch (IOException e) { e.printStackTrace(); } } if (totalSize == completedSize) { String path = saveDirPath + fileName; File file = new File(path); Log.e("rename", path.substring(0, path.length() - 5)); boolean c = file.renameTo(new File(path + ".mp3")); Log.e("rename", c + ""); downloadStatus = DownloadStatus.DOWNLOAD_STATUS_COMPLETED; dbEntity.setDownloadStatus(downloadStatus); downFileStore.update(dbEntity); Uri contentUri = Uri.fromFile(new File(saveDirPath + fileName + ".mp3")); Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, contentUri); mContext.sendBroadcast(mediaScanIntent); } switch (downloadStatus) { case DownloadStatus.DOWNLOAD_STATUS_COMPLETED: onCompleted(); break; case DownloadStatus.DOWNLOAD_STATUS_PAUSE: onPause(); break; case DownloadStatus.DOWNLOAD_STATUS_CANCEL: downFileStore.deleteTask(dbEntity.getDownloadId()); File temp = new File(saveDirPath + fileName); if (temp.exists()) temp.delete(); onCancel(); break; } } public String getId() { return id; } public void setId(String id) { this.id = id; } public float getPercent() { if (totalSize == 0) { return 0; } return completedSize * 100 / totalSize; } public void setPreparingDown(boolean b) { isPreparingDown = b; } public boolean getPreparingDown() { return isPreparingDown; } public long getTotalSize() { return totalSize; } public void setTotalSize(long totalSize) { this.totalSize = totalSize; } public long getCompletedSize() { return completedSize; } public void setCompletedSize(long completedSize) { this.completedSize = completedSize; } public String getSaveDirPath() { return saveDirPath; } public void setSaveDirPath(String saveDirPath) { this.saveDirPath = saveDirPath; } public int getDownloadStatus() { return downloadStatus; } public void setDownloadStatus(int downloadStatus) { this.downloadStatus = downloadStatus; } public void setdownFileStore(DownFileStore downFileStore) { this.downFileStore = downFileStore; } public void setDbEntity(DownloadDBEntity dbEntity) { this.dbEntity = dbEntity; } public DownloadDBEntity getDbEntity() { return dbEntity; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public void setHttpClient(OkHttpClient client) { this.client = client; } public String getFileName() { return fileName; } public String getArtistName() { return artist; } public void setFileName(String fileName) { this.fileName = fileName; } public void cancel() { setDownloadStatus(DownloadStatus.DOWNLOAD_STATUS_CANCEL); File temp = new File(saveDirPath + fileName); if (temp.exists()) temp.delete(); } public void pause() { setDownloadStatus(DownloadStatus.DOWNLOAD_STATUS_PAUSE); } private void onPrepare() { if (listeners == null) { return; } for (DownloadTaskListener listener : listeners) { listener.onPrepare(this); } } private void onStart() { if (listeners == null) { return; } for (DownloadTaskListener listener : listeners) { listener.onStart(this); } } private void onDownloading() { if (listeners == null) { return; } for (DownloadTaskListener listener : listeners) { listener.onDownloading(this); } } private void onCompleted() { if (listeners == null) { return; } for (DownloadTaskListener listener : listeners) { listener.onCompleted(this); } } private void onPause() { if (listeners == null) { return; } for (DownloadTaskListener listener : listeners) { listener.onPause(this); } } private void onCancel() { if (listeners == null) { return; } for (DownloadTaskListener listener : listeners) { listener.onCancel(this); } } private void onError(int errorCode) { if (listeners == null) { return; } for (DownloadTaskListener listener : listeners) { listener.onError(this, errorCode); } } public void addDownloadListener(DownloadTaskListener listener) { Log.e("downtask", (listeners == null) + ""); if (listener != null) listeners.add(listener); } /** * if listener is null,clear all listener * * @param listener */ public void removeDownloadListener(DownloadTaskListener listener) { if (listener == null) { listeners.clear(); } else { listeners.remove(listener); } } @Override public boolean equals(Object o) { if (this == o) { return true; } if (!(o instanceof DownloadTask)) { return false; } if (TextUtils.isEmpty(url) || TextUtils.isEmpty(saveDirPath)) { return false; } return url.equals(((DownloadTask) o).url) && saveDirPath.equals(((DownloadTask) o).saveDirPath); } public static DownloadTask parse(DownloadDBEntity entity, Context context) { // DownloadTask task = new DownloadTask(context); DownloadTask task = new Builder(context).setDBEntity(entity).build(); // task.setDownloadStatus(entity.getDownloadStatus()); // task.setId(entity.getDownloadId()); // task.setUrl(entity.getUrl()); // task.setFileName(entity.getFileName()); // task.setSaveDirPath(entity.getSaveDirPath()); // task.setCompletedSize(entity.getCompletedSize()); // task.setDbEntity(entity); // task.setTotalSize(entity.getTotalSize()); return task; } }