fast download pausing
* fast download pausing * fix UI thread blocking when calling pause() * check running threads before start the download * fix null pointer exception in onDestroy in the download service, without calling onCreate method (android 8)
This commit is contained in:
parent
9f4a7e664f
commit
e2aa36d083
5 changed files with 241 additions and 118 deletions
|
|
@ -5,6 +5,7 @@ import android.util.Log;
|
|||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InterruptedIOException;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.nio.channels.ClosedByInterruptException;
|
||||
|
|
@ -13,14 +14,16 @@ import us.shandian.giga.util.Utility;
|
|||
|
||||
import static org.schabi.newpipe.BuildConfig.DEBUG;
|
||||
|
||||
public class DownloadInitializer implements Runnable {
|
||||
public class DownloadInitializer extends Thread {
|
||||
private final static String TAG = "DownloadInitializer";
|
||||
final static int mId = 0;
|
||||
|
||||
private DownloadMission mMission;
|
||||
private HttpURLConnection mConn;
|
||||
|
||||
DownloadInitializer(@NonNull DownloadMission mission) {
|
||||
mMission = mission;
|
||||
mConn = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -32,10 +35,12 @@ public class DownloadInitializer implements Runnable {
|
|||
try {
|
||||
mMission.currentThreadCount = mMission.threadCount;
|
||||
|
||||
HttpURLConnection conn = mMission.openConnection(mId, -1, -1);
|
||||
mConn = mMission.openConnection(mId, -1, -1);
|
||||
mMission.establishConnection(mId, mConn);
|
||||
|
||||
if (!mMission.running || Thread.interrupted()) return;
|
||||
|
||||
mMission.length = Utility.getContentLength(conn);
|
||||
mMission.length = Utility.getContentLength(mConn);
|
||||
|
||||
|
||||
if (mMission.length == 0) {
|
||||
|
|
@ -44,7 +49,7 @@ public class DownloadInitializer implements Runnable {
|
|||
}
|
||||
|
||||
// check for dynamic generated content
|
||||
if (mMission.length == -1 && conn.getResponseCode() == 200) {
|
||||
if (mMission.length == -1 && mConn.getResponseCode() == 200) {
|
||||
mMission.blocks = 0;
|
||||
mMission.length = 0;
|
||||
mMission.fallback = true;
|
||||
|
|
@ -56,50 +61,54 @@ public class DownloadInitializer implements Runnable {
|
|||
}
|
||||
} else {
|
||||
// Open again
|
||||
conn = mMission.openConnection(mId, mMission.length - 10, mMission.length);
|
||||
mConn = mMission.openConnection(mId, mMission.length - 10, mMission.length);
|
||||
mMission.establishConnection(mId, mConn);
|
||||
|
||||
int code = conn.getResponseCode();
|
||||
if (!mMission.running || Thread.interrupted()) return;
|
||||
|
||||
if (code == 206) {
|
||||
if (mMission.currentThreadCount > 1) {
|
||||
mMission.blocks = mMission.length / DownloadMission.BLOCK_SIZE;
|
||||
synchronized (mMission.blockState) {
|
||||
if (mConn.getResponseCode() == 206) {
|
||||
if (mMission.currentThreadCount > 1) {
|
||||
mMission.blocks = mMission.length / DownloadMission.BLOCK_SIZE;
|
||||
|
||||
if (mMission.currentThreadCount > mMission.blocks) {
|
||||
mMission.currentThreadCount = (int) mMission.blocks;
|
||||
if (mMission.currentThreadCount > mMission.blocks) {
|
||||
mMission.currentThreadCount = (int) mMission.blocks;
|
||||
}
|
||||
if (mMission.currentThreadCount <= 0) {
|
||||
mMission.currentThreadCount = 1;
|
||||
}
|
||||
if (mMission.blocks * DownloadMission.BLOCK_SIZE < mMission.length) {
|
||||
mMission.blocks++;
|
||||
}
|
||||
} else {
|
||||
// if one thread is solicited don't calculate blocks, is useless
|
||||
mMission.blocks = 1;
|
||||
mMission.fallback = true;
|
||||
mMission.unknownLength = false;
|
||||
}
|
||||
if (mMission.currentThreadCount <= 0) {
|
||||
mMission.currentThreadCount = 1;
|
||||
}
|
||||
if (mMission.blocks * DownloadMission.BLOCK_SIZE < mMission.length) {
|
||||
mMission.blocks++;
|
||||
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "http response code = " + mConn.getResponseCode());
|
||||
}
|
||||
} else {
|
||||
// if one thread is solicited don't calculate blocks, is useless
|
||||
mMission.blocks = 1;
|
||||
// Fallback to single thread
|
||||
mMission.blocks = 0;
|
||||
mMission.fallback = true;
|
||||
mMission.unknownLength = false;
|
||||
mMission.currentThreadCount = 1;
|
||||
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "falling back due http response code = " + mConn.getResponseCode());
|
||||
}
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "http response code = " + code);
|
||||
}
|
||||
} else {
|
||||
// Fallback to single thread
|
||||
mMission.blocks = 0;
|
||||
mMission.fallback = true;
|
||||
mMission.unknownLength = false;
|
||||
mMission.currentThreadCount = 1;
|
||||
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "falling back due http response code = " + code);
|
||||
for (long i = 0; i < mMission.currentThreadCount; i++) {
|
||||
mMission.threadBlockPositions.add(i);
|
||||
mMission.threadBytePositions.add(0L);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (long i = 0; i < mMission.currentThreadCount; i++) {
|
||||
mMission.threadBlockPositions.add(i);
|
||||
mMission.threadBytePositions.add(0L);
|
||||
if (!mMission.running || Thread.interrupted()) return;
|
||||
}
|
||||
|
||||
File file;
|
||||
|
|
@ -112,7 +121,7 @@ public class DownloadInitializer implements Runnable {
|
|||
|
||||
file = new File(file, mMission.name);
|
||||
|
||||
// if the name is used by "something", delete it
|
||||
// if the name is used by another process, delete it
|
||||
if (file.exists() && !file.isFile() && !file.delete()) {
|
||||
mMission.notifyError(DownloadMission.ERROR_FILE_CREATION, null);
|
||||
return;
|
||||
|
|
@ -131,14 +140,16 @@ public class DownloadInitializer implements Runnable {
|
|||
af.seek(mMission.offsets[mMission.current]);
|
||||
af.close();
|
||||
|
||||
if (Thread.interrupted()) return;
|
||||
if (!mMission.running || Thread.interrupted()) return;
|
||||
|
||||
mMission.running = false;
|
||||
break;
|
||||
} catch (InterruptedIOException | ClosedByInterruptException e) {
|
||||
return;
|
||||
} catch (Exception e) {
|
||||
if (e instanceof ClosedByInterruptException) {
|
||||
return;
|
||||
} else if (e instanceof IOException && e.getMessage().contains("Permission denied")) {
|
||||
if (!mMission.running) return;
|
||||
|
||||
if (e instanceof IOException && e.getMessage().contains("Permission denied")) {
|
||||
mMission.notifyError(DownloadMission.ERROR_PERMISSION_DENIED, e);
|
||||
return;
|
||||
}
|
||||
|
|
@ -150,11 +161,26 @@ public class DownloadInitializer implements Runnable {
|
|||
return;
|
||||
}
|
||||
|
||||
//try again
|
||||
Log.e(TAG, "initializer failed, retrying", e);
|
||||
}
|
||||
}
|
||||
|
||||
// hide marquee in the progress bar
|
||||
mMission.done++;
|
||||
|
||||
mMission.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void interrupt() {
|
||||
super.interrupt();
|
||||
|
||||
if (mConn != null) {
|
||||
try {
|
||||
mConn.disconnect();
|
||||
} catch (Exception e) {
|
||||
// nothing to do
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue