Embedded GigaGet download manager. First try.
This commit is contained in:
parent
f08b1224c9
commit
4bae12aa55
58 changed files with 3121 additions and 40 deletions
229
app/src/main/java/us/shandian/giga/get/DownloadMission.java
Normal file
229
app/src/main/java/us/shandian/giga/get/DownloadMission.java
Normal file
|
|
@ -0,0 +1,229 @@
|
|||
package us.shandian.giga.get;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.util.Log;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.HashMap;
|
||||
|
||||
import us.shandian.giga.util.Utility;
|
||||
import static org.schabi.newpipe.BuildConfig.DEBUG;
|
||||
|
||||
public class DownloadMission
|
||||
{
|
||||
private static final String TAG = DownloadMission.class.getSimpleName();
|
||||
|
||||
public static interface MissionListener {
|
||||
HashMap<MissionListener, Handler> handlerStore = new HashMap<>();
|
||||
|
||||
public void onProgressUpdate(long done, long total);
|
||||
public void onFinish();
|
||||
public void onError(int errCode);
|
||||
}
|
||||
|
||||
public static final int ERROR_SERVER_UNSUPPORTED = 206;
|
||||
public static final int ERROR_UNKNOWN = 233;
|
||||
|
||||
public String name = "";
|
||||
public String url = "";
|
||||
public String location = "";
|
||||
public long blocks = 0;
|
||||
public long length = 0;
|
||||
public long done = 0;
|
||||
public int threadCount = 3;
|
||||
public int finishCount = 0;
|
||||
public ArrayList<Long> threadPositions = new ArrayList<Long>();
|
||||
public HashMap<Long, Boolean> blockState = new HashMap<Long, Boolean>();
|
||||
public boolean running = false;
|
||||
public boolean finished = false;
|
||||
public boolean fallback = false;
|
||||
public int errCode = -1;
|
||||
public long timestamp = 0;
|
||||
|
||||
public transient boolean recovered = false;
|
||||
|
||||
private transient ArrayList<WeakReference<MissionListener>> mListeners = new ArrayList<WeakReference<MissionListener>>();
|
||||
private transient boolean mWritingToFile = false;
|
||||
|
||||
public boolean isBlockPreserved(long block) {
|
||||
return blockState.containsKey(block) ? blockState.get(block) : false;
|
||||
}
|
||||
|
||||
public void preserveBlock(long block) {
|
||||
synchronized (blockState) {
|
||||
blockState.put(block, true);
|
||||
}
|
||||
}
|
||||
|
||||
public void setPosition(int id, long position) {
|
||||
threadPositions.set(id, position);
|
||||
}
|
||||
|
||||
public long getPosition(int id) {
|
||||
return threadPositions.get(id);
|
||||
}
|
||||
|
||||
public synchronized void notifyProgress(long deltaLen) {
|
||||
if (!running) return;
|
||||
|
||||
if (recovered) {
|
||||
recovered = false;
|
||||
}
|
||||
|
||||
done += deltaLen;
|
||||
|
||||
if (done > length) {
|
||||
done = length;
|
||||
}
|
||||
|
||||
if (done != length) {
|
||||
writeThisToFile();
|
||||
}
|
||||
|
||||
for (WeakReference<MissionListener> ref: mListeners) {
|
||||
final MissionListener listener = ref.get();
|
||||
if (listener != null) {
|
||||
MissionListener.handlerStore.get(listener).post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
listener.onProgressUpdate(done, length);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void notifyFinished() {
|
||||
if (errCode > 0) return;
|
||||
|
||||
finishCount++;
|
||||
|
||||
if (finishCount == threadCount) {
|
||||
onFinish();
|
||||
}
|
||||
}
|
||||
|
||||
private void onFinish() {
|
||||
if (errCode > 0) return;
|
||||
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "onFinish");
|
||||
}
|
||||
|
||||
running = false;
|
||||
finished = true;
|
||||
|
||||
deleteThisFromFile();
|
||||
|
||||
for (WeakReference<MissionListener> ref : mListeners) {
|
||||
final MissionListener listener = ref.get();
|
||||
if (listener != null) {
|
||||
MissionListener.handlerStore.get(listener).post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
listener.onFinish();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void notifyError(int err) {
|
||||
errCode = err;
|
||||
|
||||
writeThisToFile();
|
||||
|
||||
for (WeakReference<MissionListener> ref : mListeners) {
|
||||
final MissionListener listener = ref.get();
|
||||
MissionListener.handlerStore.get(listener).post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
listener.onError(errCode);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void addListener(MissionListener listener) {
|
||||
Handler handler = new Handler(Looper.getMainLooper());
|
||||
MissionListener.handlerStore.put(listener, handler);
|
||||
mListeners.add(new WeakReference<MissionListener>(listener));
|
||||
}
|
||||
|
||||
public synchronized void removeListener(MissionListener listener) {
|
||||
for (Iterator<WeakReference<MissionListener>> iterator = mListeners.iterator();
|
||||
iterator.hasNext(); ) {
|
||||
WeakReference<MissionListener> weakRef = iterator.next();
|
||||
if (listener!=null && listener == weakRef.get())
|
||||
{
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void start() {
|
||||
if (!running && !finished) {
|
||||
running = true;
|
||||
|
||||
if (!fallback) {
|
||||
for (int i = 0; i < threadCount; i++) {
|
||||
if (threadPositions.size() <= i && !recovered) {
|
||||
threadPositions.add((long) i);
|
||||
}
|
||||
new Thread(new DownloadRunnable(this, i)).start();
|
||||
}
|
||||
} else {
|
||||
// In fallback mode, resuming is not supported.
|
||||
threadCount = 1;
|
||||
done = 0;
|
||||
blocks = 0;
|
||||
new Thread(new DownloadRunnableFallback(this)).start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void pause() {
|
||||
if (running) {
|
||||
running = false;
|
||||
recovered = true;
|
||||
|
||||
// TODO: Notify & Write state to info file
|
||||
// if (err)
|
||||
}
|
||||
}
|
||||
|
||||
public void delete() {
|
||||
deleteThisFromFile();
|
||||
new File(location + "/" + name).delete();
|
||||
}
|
||||
|
||||
public void writeThisToFile() {
|
||||
if (!mWritingToFile) {
|
||||
mWritingToFile = true;
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
doWriteThisToFile();
|
||||
mWritingToFile = false;
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
}
|
||||
|
||||
private void doWriteThisToFile() {
|
||||
synchronized (blockState) {
|
||||
Utility.writeToFile(location + "/" + name + ".giga", new Gson().toJson(this));
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteThisFromFile() {
|
||||
new File(location + "/" + name + ".giga").delete();
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue