package com.metis.base.manager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.support.v4.util.ArrayMap;
import android.widget.Toast;
import com.bokecc.sdk.mobile.download.Downloader;
import com.bokecc.sdk.mobile.exception.DreamwinException;
import com.metis.base.module.DownloadTaskImpl;
import com.metis.base.service.DownloadService;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Beak on 2015/10/29.
*/
public class DownloadManager extends AbsManager implements DownloadService.OnDownloadListener {
private static final int WHAT_PROGRESS = 1, WHAT_STATUS = 2, WHAT_EXCEPTION = 3, WHAT_CANCEL = 4;
private static final String KEY_ID = "id", KEY_CURRENT = "current", KEY_TOTAL = "total", KEY_PERCENT = "percent", KEY_SPEED = "speed";
private static DownloadManager sManager = null;
public static synchronized DownloadManager getInstance (Context context) {
if (sManager == null) {
sManager = new DownloadManager(context.getApplicationContext());
}
return sManager;
}
private DownloadService mService = null;
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
if (service instanceof DownloadService.DownloadBinder) {
mService = ((DownloadService.DownloadBinder) service).getService();
mService.setOnDownloadListener(DownloadManager.this);
Toast.makeText(getContext(), "serviceConnected", Toast.LENGTH_SHORT).show();
startTask(getWaitingTask());
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
private ArrayMap<String, DownloadTaskImpl> mTaskQueue = new ArrayMap<>();
private List<OnDownloadCallback> mDownloadCallbackList = new ArrayList<>();
private List<OnTaskQueueChangeCallback> mQueueCallbackList = new ArrayList<>();
private static class IncomingHandler extends Handler {
private final WeakReference<DownloadManager> mService;
IncomingHandler(DownloadManager service) {
mService = new WeakReference<DownloadManager>(service);
}
@Override
public void handleMessage(Message msg)
{
DownloadManager service = mService.get();
if (service != null) {
service.handleMessage(msg);
}
}
}
private IncomingHandler mHandler = null;
private long mLastUpdateTime = 0;
private long mLastCurrent = 0;
private Bundle mUpdateBundle = new Bundle();
private DownloadManager(Context context) {
super(context);
mHandler = new IncomingHandler(this);
}
public boolean isInDownloadingQueue (String id) {
return mTaskQueue.containsKey(id);
}
public void addTask (DownloadTaskImpl task) {
if (isInDownloadingQueue(task.getId())) {
return;
}
mTaskQueue.put(task.getId(), task);
if (!mQueueCallbackList.isEmpty()) {
final int length = mQueueCallbackList.size();
for (int i = 0; i < length; i++) {
mQueueCallbackList.get(i).onTaskAdd(task);
}
}
if (hasWaitingTask()) {
if (mService == null) {
getContext().bindService(new Intent(getContext(), DownloadService.class), mConnection, Context.BIND_AUTO_CREATE);
} else {
startTask(getWaitingTask());
//mService.download();
}
}
}
public DownloadTaskImpl removeTask (String id) {
DownloadTaskImpl task = mTaskQueue.remove(id);
performRemoveCallback(task);
return task;
}
public void pauseTask (DownloadTaskImpl task) {
}
public void pauseTask (String id) {
if (mService != null) {
mService.pause(id);
}
}
public void removeTask (DownloadTaskImpl task) {
mTaskQueue.remove(task.getId());
performRemoveCallback(task);
}
private void performRemoveCallback (DownloadTaskImpl task) {
final int length = mQueueCallbackList.size();
for (int i = 0; i < length; i++) {
mQueueCallbackList.get(i).onTaskRemove(task);
}
}
private void startTask (DownloadTaskImpl task) {
if (task == null) {
return;
}
mService.download(task);
}
public boolean hasWaitingTask () {
final int size = mTaskQueue.size();
if (size == 0) {
return false;
}
for (int i = 0; i < size; i++) {
DownloadTaskImpl task = mTaskQueue.valueAt(i);
if (task.getState() == Downloader.WAIT) {
return true;
}
}
return false;
}
public DownloadTaskImpl getWaitingTask () {
final int length = mTaskQueue.size();
if (length == 0) {
return null;
}
for (int i = 0; i < length; i++) {
DownloadTaskImpl task = mTaskQueue.valueAt(i);
if (task.getState() == Downloader.WAIT) {
return task;
}
}
return null;
}
public DownloadTaskImpl getTaskById (String id) {
if (mTaskQueue.containsKey(id)) {
return mTaskQueue.get(id);
}
return null;
}
private void handleMessage (Message msg) {
String id = null;
switch (msg.what) {
case WHAT_PROGRESS:
Bundle bundle = msg.getData();
id = bundle.getString(KEY_ID);
long current = bundle.getLong(KEY_CURRENT);
long total = bundle.getLong(KEY_TOTAL);
int percent = bundle.getInt(KEY_PERCENT);
int speed = bundle.getInt(KEY_SPEED);
DownloadTaskImpl task = getTaskById(id);
if (task != null) {
task.setPosition(current);
task.setLength(total);
task.setProgress(percent);
task.setSpeed(speed);
}
if (!mDownloadCallbackList.isEmpty()) {
final int length = mDownloadCallbackList.size();
for (int i = 0; i < length; i++) {
mDownloadCallbackList.get(i).onTaskProgress(id, current, total, percent);
}
}
break;
case WHAT_STATUS:
int state = msg.arg1;
id = (String)msg.obj;
switch (state) {
case Downloader.FINISH:
removeTask(id);
break;
}
if (!mDownloadCallbackList.isEmpty()) {
final int length = mDownloadCallbackList.size();
for (int i = 0; i < length; i++) {
OnDownloadCallback callback = mDownloadCallbackList.get(i);
if (state == Downloader.DOWNLOAD) {
callback.onTaskStart(id);
} else if (state == Downloader.FINISH) {
callback.onTaskFinish(id);
} else if (state == Downloader.PAUSE) {
callback.onTaskPause(id);
} else if (state == Downloader.PAUSING) {
callback.onTaskPausing(id);
} else if (state == Downloader.WAIT) {
callback.onTaskWait(id);
}
}
}
break;
case WHAT_CANCEL:
break;
case WHAT_EXCEPTION:
break;
}
}
@Override
public void onProgressUpdate(String id, long current, long total, int percent) {
long now = System.currentTimeMillis();
long delay = now - mLastUpdateTime;
//limit the update duration
if (delay > 1000) {
Message msg = mHandler.obtainMessage();
msg.what = WHAT_PROGRESS;
mUpdateBundle.putString(KEY_ID, id);
mUpdateBundle.putLong(KEY_CURRENT, current);
mUpdateBundle.putLong(KEY_TOTAL, total);
mUpdateBundle.putInt(KEY_PERCENT, percent);
int speed = (int)((current - mLastCurrent) / delay * 1000);
mUpdateBundle.putInt(KEY_SPEED, speed);
msg.setData(mUpdateBundle);
mHandler.sendMessage(msg);
mLastUpdateTime = now;
mLastCurrent = current;
}
}
@Override
public void onStateChanged(String id, int state) {
Message msg = mHandler.obtainMessage();
msg.what = WHAT_STATUS;
msg.arg1 = state;
msg.obj = id;
mHandler.sendMessage(msg);
}
@Override
public void onCancel(String id) {
if (!mDownloadCallbackList.isEmpty()) {
final int length = mDownloadCallbackList.size();
for (int i = 0; i < length; i++) {
mDownloadCallbackList.get(i).onTaskCancel(id);
}
}
}
@Override
public void onException(DreamwinException e, int a) {
if (!mDownloadCallbackList.isEmpty()) {
final int length = mDownloadCallbackList.size();
for (int i = 0; i < length; i++) {
mDownloadCallbackList.get(i).onTaskFailed();
}
}
}
public void registerOnDownloadCallback (OnDownloadCallback callback) {
if (callback == null) {
return;
}
if (mDownloadCallbackList.contains(callback)) {
return;
}
mDownloadCallbackList.add(callback);
}
public void unregisterOnDownloadCallback (OnDownloadCallback callback) {
if (callback == null) {
return;
}
if (!mDownloadCallbackList.contains(callback)) {
return;
}
mDownloadCallbackList.remove(callback);
}
public void registerOnTaskQueueChangeCallback (OnTaskQueueChangeCallback callback) {
if (callback == null) {
return;
}
if (mQueueCallbackList.contains(callback)) {
return;
}
mQueueCallbackList.add(callback);
}
public void unregisterOnTaskQueueChangeCallback (OnTaskQueueChangeCallback callback) {
if (callback == null) {
return;
}
if (!mQueueCallbackList.contains(callback)) {
return;
}
mQueueCallbackList.remove(callback);
}
public interface OnTaskQueueChangeCallback {
public void onTaskAdd (DownloadTaskImpl task);
public void onTaskRemove (DownloadTaskImpl task);
}
public interface OnDownloadCallback {
public void onTaskWait (String id);
public void onTaskStart (String id);
public void onTaskPausing (String id);
public void onTaskPause(String id);
public void onTaskProgress (String id, long current, long total, int percent);
public void onTaskFinish (String id);
public void onTaskFailed ();
public void onTaskCancel (String id);
}
}