package com.example.ipcplayer.download;
import java.io.Closeable;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import com.example.ipcplayer.http.HttpApi;
import com.example.ipcplayer.utils.FileUtil;
import com.example.ipcplayer.utils.LogUtil;
import com.example.ipcplayer.utils.NetworkUtil;
import com.example.ipcplayer.utils.StorageUtil;
import com.example.ipcplayer.utils.ToastUtil;
import android.content.Context;
public class DownloadRunnable implements Runnable{
private static String TAG = DownloadRunnable.class.getSimpleName();
private String mUrl ;
private Context mContext;
private String mDownloadPath;
private long mTotalSize = 0;
private long mDownloadSize = 0;
private static final int KB = 1024;
private static final int BUFFER_SIZE = 10* KB;
private DownloadInfo mDownloadInfo ;
private static final String DOWNLOADIDLE = "downloadidle";
private static final String DOWNLOADING = "downloading";
private static final String DOWNLOADERROR = "downloaderror";
private static final String DOWNLOADFINISH = "downloadfinish";
private static final String DOWNLOADPAUSE = "downloadpasue";
private static final String DOWNLOADCANCEL = "downloadcancel";
private String mDownloadState = DOWNLOADIDLE;
private DownloadListener mDownloadListener;
private static final int STATUS_HTTP_FORBIDDEN = 12;
private static final int STATUS_HTTP_EXCEPTION = 13;
private static final int STATUS_HTTP_UNAVLIABLE = 14;
private File mDownloadFile ;
private File mTempFile;
private String mFileName;
private long mPreviousFileSize;
private String mFilePath ;
public DownloadRunnable(Context context, String url ,String filePath){
LogUtil.d(TAG + " init object ");
mContext = context;
mUrl = url;
LogUtil.d(TAG + " download url= " + url);
// mDownloadPath = FileUtil.getIPCDownloadDir().getAbsolutePath();
mDownloadPath = filePath;
LogUtil.d(TAG + " download mDirPath= " + mDownloadPath);
mFileName = setFileName();
LogUtil.d(TAG + " mFileName= " + mFileName);
mFilePath = mDownloadPath + File.separator + mFileName;
LogUtil.d(TAG + " mFilePath= " + mFilePath);
mDownloadFile = new File(mDownloadPath,mFileName);
mTempFile = new File(mDownloadPath,mFileName + DownloadConfig.TEMP_TYPE);
mDownloadInfo = new DownloadInfo();
mDownloadInfo.setmUrl(mUrl);
mDownloadInfo.setmFilePath(mFilePath);
}
public String setFileName() {
// TODO Auto-generated method stub
return "try.lrc";
}
@Override
public void run() {
LogUtil.d(TAG + " run ");
// TODO Auto-generated method stub
if(!StorageUtil.isExternalStorageAvailable()){
//do not show toast inside thread ,it'll crash because the looper is null
// ToastUtil.showShortToast(mContext, " SD Card is disable! ");
mDownloadInfo.setmDownloadState(DOWNLOADERROR);
LogUtil.d(TAG + " sdcard is disabled");
return ;
}
try {
createDownloadFile(mDownloadPath);
} catch (Exception e) {
e.printStackTrace();
LogUtil.d(TAG + " create file fail ");
return ;
}
if(NetworkUtil.isNetworkAvailable()){
if(NetworkUtil.isMobileAvailble()){
//pop the notification
LogUtil.d(TAG + " mobile network is connected ");
}
LogUtil.d(TAG + " wifi is connected ");
initFileAndSize();
startDownload(mUrl,mDownloadPath);
}else{
//handle this error
mDownloadInfo.setmDownloadState(DOWNLOADERROR);
mDownloadInfo.setmErrorCode(STATUS_HTTP_UNAVLIABLE);
handleError();
LogUtil.d(TAG + " network is disconnected ");
return ;
}
}
private void createDownloadFile(String path) {
LogUtil.d(TAG + " createDownloadFile ");
// String path = FileUtil.getIPCDownloadDir().getAbsolutePath();
LogUtil.d(TAG + " create dir path = " + path);
File dir = new File(path.trim());
if (!dir.exists()) {
if (dir.mkdirs()) {
LogUtil.d(TAG + " create dir successfully ");
} else {
LogUtil.d(TAG + " create dir failed ");
}
}
if (!mTempFile.exists()) {
try {
if (mTempFile.createNewFile()) {
LogUtil.d(TAG + " create file successfully ");
} else {
LogUtil.d(TAG + " create file failed ");
}
} catch (IOException e) {
// TODO Auto-generated catch block
LogUtil.d(TAG + " create file failed exception = ");
e.printStackTrace();
}
}
}
public DownloadInfo getDownloadInfo(){
LogUtil.d(TAG + " getDownloadInfo ");
return mDownloadInfo;
}
private void initFileAndSize() {
LogUtil.d(TAG + " initFileAndSize ");
mDownloadSize = mTempFile.length();
}
private void startDownload(String url,String downloadPath){
LogUtil.d(TAG + " startDownload ");
HttpResponse response ;
FileOutputStream out = null ;
InputStream in = null;
DefaultHttpClient client ;
HttpGet request ;
HttpEntity reEntity;
try{
request = new HttpGet(url);
client = HttpApi.getDefaultHttpClientSimple();
response = client.execute(request);
int statusCode = response.getStatusLine().getStatusCode();
if(HttpStatus.SC_OK != statusCode && HttpStatus.SC_PARTIAL_CONTENT != statusCode){
mDownloadInfo.setmErrorCode(statusCode);
handleHttpError(statusCode);
return ;
}
reEntity = response.getEntity();
long len = reEntity.getContentLength();
mTotalSize = len ;
// mTotalSize = mDownloadSize + len ;
in = reEntity.getContent();
out = new FileOutputStream(downloadPath+File.separator + mFileName + DownloadConfig.TEMP_TYPE ,true);
if (mDownloadFile.exists()) {
if (getDownloadFileSize() >= mTotalSize) {
mDownloadInfo.setmDownloadState(DOWNLOADFINISH);
handleFinish();
LogUtil.d(TAG + " file already exists then return ; ");
return;
}
}else if(mTempFile.exists()) {
request.setHeader("Range" , "bytes="+mTempFile.length()+"-");
mPreviousFileSize = mTempFile.length();
client = HttpApi.getDefaultHttpClientSimple();
response = client.execute(request);
reEntity = response.getEntity();
in = reEntity.getContent();
}
byte[] buf = new byte[BUFFER_SIZE];
int size ;
while(!isCanceled()){
mDownloadInfo.setmDownloadState(DOWNLOADING);
size = in.read(buf);
if(size > 0){
out.write(buf, 0, size);
mDownloadSize += size;
mDownloadInfo.setmTotalSize(mTotalSize);
mDownloadInfo.setmDownloadSize(mDownloadSize);
updateProgress();
updateFlowManagerment(size);
}else {
in.close();
out.close();
if (mDownloadSize == mTotalSize) {
// update state to successful status
LogUtil.d(TAG + " mTempFile size = "
+ FileUtil.getFileSize(mTempFile));
deleteFile(mDownloadFile);
mTempFile.renameTo(mDownloadFile);
mDownloadInfo.setmDownloadState(DOWNLOADFINISH);
deleteFile(mTempFile);
handleFinish();
}else {
//handle cancel and error
}
break ;
}
}
if(isCanceled()){
//update status
mDownloadInfo.setmDownloadState(DOWNLOADCANCEL);
}
}catch(Exception e){
e.printStackTrace();
//handle error
mDownloadInfo.setmDownloadState(DOWNLOADERROR);
}finally{
try{
if(in != null){
in.close();
}
if(out != null){
out.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
private void deleteFile(File file){
// if(file == null){
// return ;
// }
if (file.exists()) {
if (file.delete()) {
LogUtil.d(TAG + " delete file successfully " + file.toString());
}else{
LogUtil.d(TAG + " delete file failed " + file.toString());
}
}else{
LogUtil.d(TAG + " delete file doesn't exist" );
}
}
private long getDownloadFileSize(){
long size = 0;
try{
size = FileUtil.getFileSize(mDownloadFile);
}catch(Exception e){
LogUtil.d(TAG + " getDownloadFileSize error ");
e.printStackTrace();
}
return size;
}
private void handleError() {
// TODO Auto-generated method stub
mDownloadListener.errorDownload(mDownloadInfo);
}
private void handleFinish() {
mDownloadListener.finishDownload(mDownloadInfo);
}
private void updateFlowManagerment(int size) {
LogUtil.d(TAG + " updateFlowManagerment ");
}
public void setDownloadListener(DownloadListener listener){
mDownloadListener = listener ;
}
private void updateProgress() {
LogUtil.d(TAG + " updateProgress ");
mDownloadListener.updateProgress(mDownloadInfo);
}
private boolean isCanceled() {
LogUtil.d(TAG + " isCanceled ");
return DOWNLOADCANCEL.equals(mDownloadInfo.getmDownloadState());
}
public void cancelDownload(){
mDownloadInfo.setmDownloadState(DOWNLOADCANCEL);
}
public void resumeDownload(){
mDownloadInfo.setmDownloadState(DOWNLOADING);
}
public boolean isDownloading(){
return DOWNLOADING.equals(mDownloadInfo.getmDownloadState());
}
private void handleHttpError(int statusCode) {
LogUtil.d(TAG + " handleHttpError ");
if(HttpStatus.SC_FORBIDDEN == statusCode){
mDownloadInfo.setmErrorCode(STATUS_HTTP_FORBIDDEN);
mDownloadListener.errorDownload(mDownloadInfo);
}else {
mDownloadInfo.setmErrorCode(STATUS_HTTP_EXCEPTION);
mDownloadListener.errorDownload(mDownloadInfo);
}
}
private HttpGet getRequest(String url) {
LogUtil.d(TAG + " getRequest ");
HttpGet httpGet = new HttpGet();
return httpGet;
}
}