long-term downloads resume

* recovery infrastructure
* bump serialVersionUID of DownloadMission
* misc cleanup in DownloadMission.java
* remove unused/redundant from strings.xml
This commit is contained in:
kapodamy 2019-09-28 18:11:05 -03:00
parent 0cdfa6e377
commit c891f2f1ed
42 changed files with 478 additions and 97 deletions

View file

@ -68,6 +68,7 @@ import java.util.Locale;
import icepick.Icepick; import icepick.Icepick;
import icepick.State; import icepick.State;
import io.reactivex.disposables.CompositeDisposable; import io.reactivex.disposables.CompositeDisposable;
import us.shandian.giga.get.MissionRecoveryInfo;
import us.shandian.giga.io.StoredDirectoryHelper; import us.shandian.giga.io.StoredDirectoryHelper;
import us.shandian.giga.io.StoredFileHelper; import us.shandian.giga.io.StoredFileHelper;
import us.shandian.giga.postprocessing.Postprocessing; import us.shandian.giga.postprocessing.Postprocessing;
@ -762,12 +763,13 @@ public class DownloadDialog extends DialogFragment implements RadioGroup.OnCheck
} }
Stream selectedStream; Stream selectedStream;
Stream secondaryStream = null;
char kind; char kind;
int threads = threadsSeekBar.getProgress() + 1; int threads = threadsSeekBar.getProgress() + 1;
String[] urls; String[] urls;
MissionRecoveryInfo[] recoveryInfo;
String psName = null; String psName = null;
String[] psArgs = null; String[] psArgs = null;
String secondaryStreamUrl = null;
long nearLength = 0; long nearLength = 0;
// more download logic: select muxer, subtitle converter, etc. // more download logic: select muxer, subtitle converter, etc.
@ -786,12 +788,12 @@ public class DownloadDialog extends DialogFragment implements RadioGroup.OnCheck
kind = 'v'; kind = 'v';
selectedStream = videoStreamsAdapter.getItem(selectedVideoIndex); selectedStream = videoStreamsAdapter.getItem(selectedVideoIndex);
SecondaryStreamHelper<AudioStream> secondaryStream = videoStreamsAdapter SecondaryStreamHelper<AudioStream> secondary = videoStreamsAdapter
.getAllSecondary() .getAllSecondary()
.get(wrappedVideoStreams.getStreamsList().indexOf(selectedStream)); .get(wrappedVideoStreams.getStreamsList().indexOf(selectedStream));
if (secondaryStream != null) { if (secondary != null) {
secondaryStreamUrl = secondaryStream.getStream().getUrl(); secondaryStream = secondary.getStream();
if (selectedStream.getFormat() == MediaFormat.MPEG_4) if (selectedStream.getFormat() == MediaFormat.MPEG_4)
psName = Postprocessing.ALGORITHM_MP4_FROM_DASH_MUXER; psName = Postprocessing.ALGORITHM_MP4_FROM_DASH_MUXER;
@ -803,8 +805,8 @@ public class DownloadDialog extends DialogFragment implements RadioGroup.OnCheck
// set nearLength, only, if both sizes are fetched or known. This probably // set nearLength, only, if both sizes are fetched or known. This probably
// does not work on slow networks but is later updated in the downloader // does not work on slow networks but is later updated in the downloader
if (secondaryStream.getSizeInBytes() > 0 && videoSize > 0) { if (secondary.getSizeInBytes() > 0 && videoSize > 0) {
nearLength = secondaryStream.getSizeInBytes() + videoSize; nearLength = secondary.getSizeInBytes() + videoSize;
} }
} }
break; break;
@ -826,13 +828,25 @@ public class DownloadDialog extends DialogFragment implements RadioGroup.OnCheck
return; return;
} }
if (secondaryStreamUrl == null) { if (secondaryStream == null) {
urls = new String[]{selectedStream.getUrl()}; urls = new String[]{
selectedStream.getUrl()
};
recoveryInfo = new MissionRecoveryInfo[]{
new MissionRecoveryInfo(selectedStream)
};
} else { } else {
urls = new String[]{selectedStream.getUrl(), secondaryStreamUrl}; urls = new String[]{
selectedStream.getUrl(), secondaryStream.getUrl()
};
recoveryInfo = new MissionRecoveryInfo[]{
new MissionRecoveryInfo(selectedStream), new MissionRecoveryInfo(secondaryStream)
};
} }
DownloadManagerService.startMission(context, urls, storage, kind, threads, currentInfo.getUrl(), psName, psArgs, nearLength); DownloadManagerService.startMission(
context, urls, storage, kind, threads, currentInfo.getUrl(), psName, psArgs, nearLength, recoveryInfo
);
dismiss(); dismiss();
} }

View file

@ -1,6 +1,7 @@
package us.shandian.giga.get; package us.shandian.giga.get;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import org.schabi.newpipe.streams.io.SharpStream; import org.schabi.newpipe.streams.io.SharpStream;
@ -151,6 +152,20 @@ public class DownloadInitializer extends Thread {
if (!mMission.running || Thread.interrupted()) return; if (!mMission.running || Thread.interrupted()) return;
if (!mMission.unknownLength && mMission.recoveryInfo != null) {
String entityTag = mConn.getHeaderField("ETAG");
String lastModified = mConn.getHeaderField("Last-Modified");
MissionRecoveryInfo recovery = mMission.recoveryInfo[mMission.current];
if (!TextUtils.isEmpty(entityTag)) {
recovery.validateCondition = entityTag;
} else if (!TextUtils.isEmpty(lastModified)) {
recovery.validateCondition = lastModified;// Note: this is less precise
} else {
recovery.validateCondition = null;
}
}
mMission.running = false; mMission.running = false;
break; break;
} catch (InterruptedIOException | ClosedByInterruptException e) { } catch (InterruptedIOException | ClosedByInterruptException e) {

View file

@ -27,7 +27,7 @@ import us.shandian.giga.util.Utility;
import static org.schabi.newpipe.BuildConfig.DEBUG; import static org.schabi.newpipe.BuildConfig.DEBUG;
public class DownloadMission extends Mission { public class DownloadMission extends Mission {
private static final long serialVersionUID = 5L;// last bump: 30 june 2019 private static final long serialVersionUID = 6L;// last bump: 28 september 2019
static final int BUFFER_SIZE = 64 * 1024; static final int BUFFER_SIZE = 64 * 1024;
static final int BLOCK_SIZE = 512 * 1024; static final int BLOCK_SIZE = 512 * 1024;
@ -51,8 +51,9 @@ public class DownloadMission extends Mission {
public static final int ERROR_INSUFFICIENT_STORAGE = 1010; public static final int ERROR_INSUFFICIENT_STORAGE = 1010;
public static final int ERROR_PROGRESS_LOST = 1011; public static final int ERROR_PROGRESS_LOST = 1011;
public static final int ERROR_TIMEOUT = 1012; public static final int ERROR_TIMEOUT = 1012;
public static final int ERROR_RESOURCE_GONE = 1013;
public static final int ERROR_HTTP_NO_CONTENT = 204; public static final int ERROR_HTTP_NO_CONTENT = 204;
public static final int ERROR_HTTP_UNSUPPORTED_RANGE = 206; static final int ERROR_HTTP_FORBIDDEN = 403;
/** /**
* The urls of the file to download * The urls of the file to download
@ -125,6 +126,11 @@ public class DownloadMission extends Mission {
*/ */
public int threadCount = 3; public int threadCount = 3;
/**
* information required to recover a download
*/
public MissionRecoveryInfo[] recoveryInfo;
private transient int finishCount; private transient int finishCount;
public transient boolean running; public transient boolean running;
public boolean enqueued; public boolean enqueued;
@ -132,7 +138,6 @@ public class DownloadMission extends Mission {
public int errCode = ERROR_NOTHING; public int errCode = ERROR_NOTHING;
public Exception errObject = null; public Exception errObject = null;
public transient boolean recovered;
public transient Handler mHandler; public transient Handler mHandler;
private transient boolean mWritingToFile; private transient boolean mWritingToFile;
private transient boolean[] blockAcquired; private transient boolean[] blockAcquired;
@ -197,9 +202,9 @@ public class DownloadMission extends Mission {
} }
/** /**
* Open connection * Opens a connection
* *
* @param threadId id of the calling thread, used only for debug * @param threadId id of the calling thread, used only for debugging
* @param rangeStart range start * @param rangeStart range start
* @param rangeEnd range end * @param rangeEnd range end
* @return a {@link java.net.URLConnection URLConnection} linking to the URL. * @return a {@link java.net.URLConnection URLConnection} linking to the URL.
@ -251,7 +256,7 @@ public class DownloadMission extends Mission {
case 204: case 204:
case 205: case 205:
case 207: case 207:
throw new HttpError(conn.getResponseCode()); throw new HttpError(statusCode);
case 416: case 416:
return;// let the download thread handle this error return;// let the download thread handle this error
default: default:
@ -270,10 +275,6 @@ public class DownloadMission extends Mission {
synchronized void notifyProgress(long deltaLen) { synchronized void notifyProgress(long deltaLen) {
if (!running) return; if (!running) return;
if (recovered) {
recovered = false;
}
if (unknownLength) { if (unknownLength) {
length += deltaLen;// Update length before proceeding length += deltaLen;// Update length before proceeding
} }
@ -344,7 +345,6 @@ public class DownloadMission extends Mission {
if (running) { if (running) {
running = false; running = false;
recovered = true;
if (threads != null) selfPause(); if (threads != null) selfPause();
} }
} }
@ -409,12 +409,13 @@ public class DownloadMission extends Mission {
* Start downloading with multiple threads. * Start downloading with multiple threads.
*/ */
public void start() { public void start() {
if (running || isFinished()) return; if (running || isFinished() || urls.length < 1) return;
// ensure that the previous state is completely paused. // ensure that the previous state is completely paused.
joinForThread(init); int maxWait = 10000;// 10 seconds
joinForThread(init, maxWait);
if (threads != null) { if (threads != null) {
for (Thread thread : threads) joinForThread(thread); for (Thread thread : threads) joinForThread(thread, maxWait);
threads = null; threads = null;
} }
@ -431,6 +432,11 @@ public class DownloadMission extends Mission {
return; return;
} }
if (urls[current] == null) {
doRecover(null);
return;
}
if (blocks == null) { if (blocks == null) {
initializer(); initializer();
return; return;
@ -478,7 +484,6 @@ public class DownloadMission extends Mission {
} }
running = false; running = false;
recovered = true;
if (init != null && init.isAlive()) { if (init != null && init.isAlive()) {
// NOTE: if start() method is running ¡will no have effect! // NOTE: if start() method is running ¡will no have effect!
@ -563,7 +568,7 @@ public class DownloadMission extends Mission {
* Write this {@link DownloadMission} to the meta file asynchronously * Write this {@link DownloadMission} to the meta file asynchronously
* if no thread is already running. * if no thread is already running.
*/ */
private void writeThisToFile() { void writeThisToFile() {
synchronized (LOCK) { synchronized (LOCK) {
if (deleted) return; if (deleted) return;
Utility.writeToFile(metadata, DownloadMission.this); Utility.writeToFile(metadata, DownloadMission.this);
@ -667,6 +672,7 @@ public class DownloadMission extends Mission {
* @return {@code true} is this mission its "healthy", otherwise, {@code false} * @return {@code true} is this mission its "healthy", otherwise, {@code false}
*/ */
public boolean isCorrupt() { public boolean isCorrupt() {
if (urls.length < 1) return false;
return (isPsFailed() || errCode == ERROR_POSTPROCESSING_HOLD) || isFinished(); return (isPsFailed() || errCode == ERROR_POSTPROCESSING_HOLD) || isFinished();
} }
@ -710,6 +716,48 @@ public class DownloadMission extends Mission {
return true; return true;
} }
/**
* Attempts to recover the download
*
* @param fromError exception which require update the url from the source
*/
void doRecover(Exception fromError) {
Log.i(TAG, "Attempting to recover the mission: " + storage.getName());
if (recoveryInfo == null) {
if (fromError == null)
notifyError(ERROR_RESOURCE_GONE, null);
else
notifyError(fromError);
urls = new String[0];// mark this mission as dead
return;
}
if (threads != null) {
for (Thread thread : threads) {
if (thread == Thread.currentThread()) continue;
thread.interrupt();
joinForThread(thread, 0);
}
}
// set the current download url to null in case if the recovery
// process is canceled. Next time start() method is called the
// recovery will be executed, saving time
urls[current] = null;
if (recoveryInfo[current].attempts >= maxRetry) {
recoveryInfo[current].attempts = 0;
notifyError(fromError);
return;
}
threads = new Thread[]{
runAsync(DownloadMissionRecover.mID, new DownloadMissionRecover(this, fromError))
};
}
private boolean deleteThisFromFile() { private boolean deleteThisFromFile() {
synchronized (LOCK) { synchronized (LOCK) {
return metadata.delete(); return metadata.delete();
@ -749,7 +797,13 @@ public class DownloadMission extends Mission {
return who; return who;
} }
private void joinForThread(Thread thread) { /**
* Waits at most {@code millis} milliseconds for the thread to die
*
* @param thread the desired thread
* @param millis the time to wait in milliseconds
*/
private void joinForThread(Thread thread, int millis) {
if (thread == null || !thread.isAlive()) return; if (thread == null || !thread.isAlive()) return;
if (thread == Thread.currentThread()) return; if (thread == Thread.currentThread()) return;
@ -764,7 +818,7 @@ public class DownloadMission extends Mission {
// start() method called quickly after pause() // start() method called quickly after pause()
try { try {
thread.join(10000); thread.join(millis);
} catch (InterruptedException e) { } catch (InterruptedException e) {
Log.d(TAG, "timeout on join : " + thread.getName()); Log.d(TAG, "timeout on join : " + thread.getName());
throw new RuntimeException("A thread is still running:\n" + thread.getName()); throw new RuntimeException("A thread is still running:\n" + thread.getName());
@ -785,9 +839,9 @@ public class DownloadMission extends Mission {
} }
} }
static class Block { public static class Block {
int position; public int position;
int done; public int done;
} }
private static class Lock implements Serializable { private static class Lock implements Serializable {

View file

@ -0,0 +1,222 @@
package us.shandian.giga.get;
import android.util.Log;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.stream.AudioStream;
import org.schabi.newpipe.extractor.stream.StreamExtractor;
import org.schabi.newpipe.extractor.stream.SubtitlesStream;
import org.schabi.newpipe.extractor.stream.VideoStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.nio.channels.ClosedByInterruptException;
import java.util.List;
import static us.shandian.giga.get.DownloadMission.ERROR_RESOURCE_GONE;
public class DownloadMissionRecover extends Thread {
private static final String TAG = "DownloadMissionRecover";
static final int mID = -3;
private final DownloadMission mMission;
private final MissionRecoveryInfo mRecovery;
private final Exception mFromError;
private HttpURLConnection mConn;
DownloadMissionRecover(DownloadMission mission, Exception originError) {
mMission = mission;
mFromError = originError;
mRecovery = mission.recoveryInfo[mission.current];
}
@Override
public void run() {
if (mMission.source == null) {
mMission.notifyError(mFromError);
return;
}
try {
/*if (mMission.source.startsWith(MissionRecoveryInfo.DIRECT_SOURCE)) {
resolve(mMission.source.substring(MissionRecoveryInfo.DIRECT_SOURCE.length()));
return;
}*/
StreamingService svr = NewPipe.getServiceByUrl(mMission.source);
if (svr == null) {
throw new RuntimeException("Unknown source service");
}
StreamExtractor extractor = svr.getStreamExtractor(mMission.source);
extractor.fetchPage();
if (!mMission.running || super.isInterrupted()) return;
String url = null;
switch (mMission.kind) {
case 'a':
for (AudioStream audio : extractor.getAudioStreams()) {
if (audio.average_bitrate == mRecovery.desiredBitrate && audio.getFormat() == mRecovery.format) {
url = audio.getUrl();
break;
}
}
break;
case 'v':
List<VideoStream> videoStreams;
if (mRecovery.desired2)
videoStreams = extractor.getVideoOnlyStreams();
else
videoStreams = extractor.getVideoStreams();
for (VideoStream video : videoStreams) {
if (video.resolution.equals(mRecovery.desired) && video.getFormat() == mRecovery.format) {
url = video.getUrl();
break;
}
}
break;
case 's':
for (SubtitlesStream subtitles : extractor.getSubtitles(mRecovery.format)) {
String tag = subtitles.getLanguageTag();
if (tag.equals(mRecovery.desired) && subtitles.isAutoGenerated() == mRecovery.desired2) {
url = subtitles.getURL();
break;
}
}
break;
default:
throw new RuntimeException("Unknown stream type");
}
resolve(url);
} catch (Exception e) {
if (!mMission.running || e instanceof ClosedByInterruptException) return;
mRecovery.attempts++;
mMission.notifyError(e);
}
}
private void resolve(String url) throws IOException, DownloadMission.HttpError {
if (mRecovery.validateCondition == null) {
Log.w(TAG, "validation condition not defined, the resource can be stale");
}
if (mMission.unknownLength || mRecovery.validateCondition == null) {
recover(url, false);
return;
}
///////////////////////////////////////////////////////////////////////
////// Validate the http resource doing a range request
/////////////////////
try {
mConn = mMission.openConnection(url, mID, mMission.length - 10, mMission.length);
mConn.setRequestProperty("If-Range", mRecovery.validateCondition);
mMission.establishConnection(mID, mConn);
int code = mConn.getResponseCode();
switch (code) {
case 200:
case 413:
// stale
recover(url, true);
return;
case 206:
// in case of validation using the Last-Modified date, check the resource length
long[] contentRange = parseContentRange(mConn.getHeaderField("Content-Range"));
boolean lengthMismatch = contentRange[2] != -1 && contentRange[2] != mMission.length;
recover(url, lengthMismatch);
return;
}
throw new DownloadMission.HttpError(code);
} catch (Exception e) {
if (!mMission.running || e instanceof ClosedByInterruptException) return;
throw e;
} finally {
this.interrupt();
}
}
private void recover(String url, boolean stale) {
Log.i(TAG,
String.format("download recovered name=%s isStale=%s url=%s", mMission.storage.getName(), stale, url)
);
if (url == null) {
mMission.notifyError(ERROR_RESOURCE_GONE, null);
return;
}
mMission.urls[mMission.current] = url;
mRecovery.attempts = 0;
if (stale) {
mMission.resetState(false, false, DownloadMission.ERROR_NOTHING);
}
mMission.writeThisToFile();
if (!mMission.running || super.isInterrupted()) return;
mMission.running = false;
mMission.start();
}
private long[] parseContentRange(String value) {
long[] range = new long[3];
if (value == null) {
// this never should happen
return range;
}
try {
value = value.trim();
if (!value.startsWith("bytes")) {
return range;// unknown range type
}
int space = value.lastIndexOf(' ') + 1;
int dash = value.indexOf('-', space) + 1;
int bar = value.indexOf('/', dash);
// start
range[0] = Long.parseLong(value.substring(space, dash - 1));
// end
range[1] = Long.parseLong(value.substring(dash, bar));
// resource length
value = value.substring(bar + 1);
if (value.equals("*")) {
range[2] = -1;// unknown length received from the server but should be valid
} else {
range[2] = Long.parseLong(value);
}
} catch (Exception e) {
// nothing to do
}
return range;
}
@Override
public void interrupt() {
super.interrupt();
if (mConn != null) {
try {
mConn.disconnect();
} catch (Exception e) {
// nothing to do
}
}
}
}

View file

@ -10,8 +10,10 @@ import java.net.HttpURLConnection;
import java.nio.channels.ClosedByInterruptException; import java.nio.channels.ClosedByInterruptException;
import us.shandian.giga.get.DownloadMission.Block; import us.shandian.giga.get.DownloadMission.Block;
import us.shandian.giga.get.DownloadMission.HttpError;
import static org.schabi.newpipe.BuildConfig.DEBUG; import static org.schabi.newpipe.BuildConfig.DEBUG;
import static us.shandian.giga.get.DownloadMission.ERROR_HTTP_FORBIDDEN;
/** /**
@ -19,7 +21,7 @@ import static org.schabi.newpipe.BuildConfig.DEBUG;
* an error occurs or the process is stopped. * an error occurs or the process is stopped.
*/ */
public class DownloadRunnable extends Thread { public class DownloadRunnable extends Thread {
private static final String TAG = DownloadRunnable.class.getSimpleName(); private static final String TAG = "DownloadRunnable";
private final DownloadMission mMission; private final DownloadMission mMission;
private final int mId; private final int mId;
@ -41,13 +43,7 @@ public class DownloadRunnable extends Thread {
public void run() { public void run() {
boolean retry = false; boolean retry = false;
Block block = null; Block block = null;
int retryCount = 0; int retryCount = 0;
if (DEBUG) {
Log.d(TAG, mId + ":recovered: " + mMission.recovered);
}
SharpStream f; SharpStream f;
try { try {
@ -133,6 +129,17 @@ public class DownloadRunnable extends Thread {
} catch (Exception e) { } catch (Exception e) {
if (!mMission.running || e instanceof ClosedByInterruptException) break; if (!mMission.running || e instanceof ClosedByInterruptException) break;
if (e instanceof HttpError && ((HttpError) e).statusCode == ERROR_HTTP_FORBIDDEN) {
// for youtube streams. The url has expired, recover
f.close();
if (mId == 1) {
// only the first thread will execute the recovery procedure
mMission.doRecover(e);
}
return;
}
if (retryCount++ >= mMission.maxRetry) { if (retryCount++ >= mMission.maxRetry) {
mMission.notifyError(e); mMission.notifyError(e);
break; break;
@ -144,11 +151,7 @@ public class DownloadRunnable extends Thread {
} }
} }
try {
f.close(); f.close();
} catch (Exception err) {
// ¿ejected media storage? ¿file deleted? ¿storage ran out of space?
}
if (DEBUG) { if (DEBUG) {
Log.d(TAG, "thread " + mId + " exited from main download loop"); Log.d(TAG, "thread " + mId + " exited from main download loop");

View file

@ -10,9 +10,11 @@ import java.io.InputStream;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.nio.channels.ClosedByInterruptException; import java.nio.channels.ClosedByInterruptException;
import us.shandian.giga.get.DownloadMission.HttpError;
import us.shandian.giga.util.Utility; import us.shandian.giga.util.Utility;
import static org.schabi.newpipe.BuildConfig.DEBUG; import static org.schabi.newpipe.BuildConfig.DEBUG;
import static us.shandian.giga.get.DownloadMission.ERROR_HTTP_FORBIDDEN;
/** /**
* Single-threaded fallback mode * Single-threaded fallback mode
@ -85,7 +87,7 @@ public class DownloadRunnableFallback extends Thread {
mIs = mConn.getInputStream(); mIs = mConn.getInputStream();
byte[] buf = new byte[64 * 1024]; byte[] buf = new byte[DownloadMission.BUFFER_SIZE];
int len = 0; int len = 0;
while (mMission.running && (len = mIs.read(buf, 0, buf.length)) != -1) { while (mMission.running && (len = mIs.read(buf, 0, buf.length)) != -1) {
@ -103,6 +105,13 @@ public class DownloadRunnableFallback extends Thread {
if (!mMission.running || e instanceof ClosedByInterruptException) return; if (!mMission.running || e instanceof ClosedByInterruptException) return;
if (e instanceof HttpError && ((HttpError) e).statusCode == ERROR_HTTP_FORBIDDEN) {
// for youtube streams. The url has expired, recover
mMission.doRecover(e);
dispose();
return;
}
if (mRetryCount++ >= mMission.maxRetry) { if (mRetryCount++ >= mMission.maxRetry) {
mMission.notifyError(e); mMission.notifyError(e);
return; return;

View file

@ -0,0 +1,79 @@
package us.shandian.giga.get;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.NonNull;
import org.schabi.newpipe.extractor.MediaFormat;
import org.schabi.newpipe.extractor.stream.AudioStream;
import org.schabi.newpipe.extractor.stream.Stream;
import org.schabi.newpipe.extractor.stream.SubtitlesStream;
import org.schabi.newpipe.extractor.stream.VideoStream;
import java.io.Serializable;
public class MissionRecoveryInfo implements Serializable, Parcelable {
private static final long serialVersionUID = 0L;
//public static final String DIRECT_SOURCE = "direct-source://";
public MediaFormat format;
String desired;
boolean desired2;
int desiredBitrate;
transient int attempts = 0;
String validateCondition = null;
public MissionRecoveryInfo(@NonNull Stream stream) {
if (stream instanceof AudioStream) {
desiredBitrate = ((AudioStream) stream).average_bitrate;
desired2 = false;
} else if (stream instanceof VideoStream) {
desired = ((VideoStream) stream).getResolution();
desired2 = ((VideoStream) stream).isVideoOnly();
} else if (stream instanceof SubtitlesStream) {
desired = ((SubtitlesStream) stream).getLanguageTag();
desired2 = ((SubtitlesStream) stream).isAutoGenerated();
} else {
throw new RuntimeException("Unknown stream kind");
}
format = stream.getFormat();
if (format == null) throw new NullPointerException("Stream format cannot be null");
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel parcel, int flags) {
parcel.writeInt(this.format.ordinal());
parcel.writeString(this.desired);
parcel.writeInt(this.desired2 ? 0x01 : 0x00);
parcel.writeInt(this.desiredBitrate);
parcel.writeString(this.validateCondition);
}
private MissionRecoveryInfo(Parcel parcel) {
this.format = MediaFormat.values()[parcel.readInt()];
this.desired = parcel.readString();
this.desired2 = parcel.readInt() != 0x00;
this.desiredBitrate = parcel.readInt();
this.validateCondition = parcel.readString();
}
public static final Parcelable.Creator<MissionRecoveryInfo> CREATOR = new Parcelable.Creator<MissionRecoveryInfo>() {
@Override
public MissionRecoveryInfo createFromParcel(Parcel source) {
return new MissionRecoveryInfo(source);
}
@Override
public MissionRecoveryInfo[] newArray(int size) {
return new MissionRecoveryInfo[size];
}
};
}

View file

@ -177,7 +177,6 @@ public class DownloadManager {
mis.psAlgorithm.setTemporalDir(pickAvailableTemporalDir(ctx)); mis.psAlgorithm.setTemporalDir(pickAvailableTemporalDir(ctx));
} }
mis.recovered = exists;
mis.metadata = sub; mis.metadata = sub;
mis.maxRetry = mPrefMaxRetry; mis.maxRetry = mPrefMaxRetry;
mis.mHandler = mHandler; mis.mHandler = mHandler;

View file

@ -23,6 +23,7 @@ import android.os.Handler;
import android.os.Handler.Callback; import android.os.Handler.Callback;
import android.os.IBinder; import android.os.IBinder;
import android.os.Message; import android.os.Message;
import android.os.Parcelable;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
@ -40,8 +41,11 @@ import org.schabi.newpipe.player.helper.LockManager;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import us.shandian.giga.get.DownloadMission; import us.shandian.giga.get.DownloadMission;
import us.shandian.giga.get.MissionRecoveryInfo;
import us.shandian.giga.io.StoredDirectoryHelper; import us.shandian.giga.io.StoredDirectoryHelper;
import us.shandian.giga.io.StoredFileHelper; import us.shandian.giga.io.StoredFileHelper;
import us.shandian.giga.postprocessing.Postprocessing; import us.shandian.giga.postprocessing.Postprocessing;
@ -73,6 +77,7 @@ public class DownloadManagerService extends Service {
private static final String EXTRA_PATH = "DownloadManagerService.extra.storagePath"; private static final String EXTRA_PATH = "DownloadManagerService.extra.storagePath";
private static final String EXTRA_PARENT_PATH = "DownloadManagerService.extra.storageParentPath"; private static final String EXTRA_PARENT_PATH = "DownloadManagerService.extra.storageParentPath";
private static final String EXTRA_STORAGE_TAG = "DownloadManagerService.extra.storageTag"; private static final String EXTRA_STORAGE_TAG = "DownloadManagerService.extra.storageTag";
private static final String EXTRA_RECOVERY_INFO = "DownloadManagerService.extra.recoveryInfo";
private static final String ACTION_RESET_DOWNLOAD_FINISHED = APPLICATION_ID + ".reset_download_finished"; private static final String ACTION_RESET_DOWNLOAD_FINISHED = APPLICATION_ID + ".reset_download_finished";
private static final String ACTION_OPEN_DOWNLOADS_FINISHED = APPLICATION_ID + ".open_downloads_finished"; private static final String ACTION_OPEN_DOWNLOADS_FINISHED = APPLICATION_ID + ".open_downloads_finished";
@ -365,7 +370,7 @@ public class DownloadManagerService extends Service {
* Start a new download mission * Start a new download mission
* *
* @param context the activity context * @param context the activity context
* @param urls the list of urls to download * @param urls array of urls to download
* @param storage where the file is saved * @param storage where the file is saved
* @param kind type of file (a: audio v: video s: subtitle ?: file-extension defined) * @param kind type of file (a: audio v: video s: subtitle ?: file-extension defined)
* @param threads the number of threads maximal used to download chunks of the file. * @param threads the number of threads maximal used to download chunks of the file.
@ -373,9 +378,11 @@ public class DownloadManagerService extends Service {
* @param source source url of the resource * @param source source url of the resource
* @param psArgs the arguments for the post-processing algorithm. * @param psArgs the arguments for the post-processing algorithm.
* @param nearLength the approximated final length of the file * @param nearLength the approximated final length of the file
* @param recoveryInfo array of MissionRecoveryInfo, in case is required recover the download
*/ */
public static void startMission(Context context, String[] urls, StoredFileHelper storage, char kind, public static void startMission(Context context, String[] urls, StoredFileHelper storage,
int threads, String source, String psName, String[] psArgs, long nearLength) { char kind, int threads, String source, String psName,
String[] psArgs, long nearLength, MissionRecoveryInfo[] recoveryInfo) {
Intent intent = new Intent(context, DownloadManagerService.class); Intent intent = new Intent(context, DownloadManagerService.class);
intent.setAction(Intent.ACTION_RUN); intent.setAction(Intent.ACTION_RUN);
intent.putExtra(EXTRA_URLS, urls); intent.putExtra(EXTRA_URLS, urls);
@ -385,6 +392,7 @@ public class DownloadManagerService extends Service {
intent.putExtra(EXTRA_POSTPROCESSING_NAME, psName); intent.putExtra(EXTRA_POSTPROCESSING_NAME, psName);
intent.putExtra(EXTRA_POSTPROCESSING_ARGS, psArgs); intent.putExtra(EXTRA_POSTPROCESSING_ARGS, psArgs);
intent.putExtra(EXTRA_NEAR_LENGTH, nearLength); intent.putExtra(EXTRA_NEAR_LENGTH, nearLength);
intent.putExtra(EXTRA_RECOVERY_INFO, recoveryInfo);
intent.putExtra(EXTRA_PARENT_PATH, storage.getParentUri()); intent.putExtra(EXTRA_PARENT_PATH, storage.getParentUri());
intent.putExtra(EXTRA_PATH, storage.getUri()); intent.putExtra(EXTRA_PATH, storage.getUri());
@ -404,6 +412,7 @@ public class DownloadManagerService extends Service {
String source = intent.getStringExtra(EXTRA_SOURCE); String source = intent.getStringExtra(EXTRA_SOURCE);
long nearLength = intent.getLongExtra(EXTRA_NEAR_LENGTH, 0); long nearLength = intent.getLongExtra(EXTRA_NEAR_LENGTH, 0);
String tag = intent.getStringExtra(EXTRA_STORAGE_TAG); String tag = intent.getStringExtra(EXTRA_STORAGE_TAG);
Parcelable[] parcelRecovery = intent.getParcelableArrayExtra(EXTRA_RECOVERY_INFO);
StoredFileHelper storage; StoredFileHelper storage;
try { try {
@ -418,10 +427,15 @@ public class DownloadManagerService extends Service {
else else
ps = Postprocessing.getAlgorithm(psName, psArgs); ps = Postprocessing.getAlgorithm(psName, psArgs);
MissionRecoveryInfo[] recovery = new MissionRecoveryInfo[parcelRecovery.length];
for (int i = 0; i < parcelRecovery.length; i++)
recovery[i] = (MissionRecoveryInfo) parcelRecovery[i];
final DownloadMission mission = new DownloadMission(urls, storage, kind, ps); final DownloadMission mission = new DownloadMission(urls, storage, kind, ps);
mission.threadCount = threads; mission.threadCount = threads;
mission.source = source; mission.source = source;
mission.nearLength = nearLength; mission.nearLength = nearLength;
mission.recoveryInfo = recovery;
if (ps != null) if (ps != null)
ps.setTemporalDir(DownloadManager.pickAvailableTemporalDir(this)); ps.setTemporalDir(DownloadManager.pickAvailableTemporalDir(this));

View file

@ -62,7 +62,6 @@ import static android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION;
import static us.shandian.giga.get.DownloadMission.ERROR_CONNECT_HOST; import static us.shandian.giga.get.DownloadMission.ERROR_CONNECT_HOST;
import static us.shandian.giga.get.DownloadMission.ERROR_FILE_CREATION; import static us.shandian.giga.get.DownloadMission.ERROR_FILE_CREATION;
import static us.shandian.giga.get.DownloadMission.ERROR_HTTP_NO_CONTENT; import static us.shandian.giga.get.DownloadMission.ERROR_HTTP_NO_CONTENT;
import static us.shandian.giga.get.DownloadMission.ERROR_HTTP_UNSUPPORTED_RANGE;
import static us.shandian.giga.get.DownloadMission.ERROR_INSUFFICIENT_STORAGE; import static us.shandian.giga.get.DownloadMission.ERROR_INSUFFICIENT_STORAGE;
import static us.shandian.giga.get.DownloadMission.ERROR_NOTHING; import static us.shandian.giga.get.DownloadMission.ERROR_NOTHING;
import static us.shandian.giga.get.DownloadMission.ERROR_PATH_CREATION; import static us.shandian.giga.get.DownloadMission.ERROR_PATH_CREATION;
@ -71,6 +70,7 @@ import static us.shandian.giga.get.DownloadMission.ERROR_POSTPROCESSING;
import static us.shandian.giga.get.DownloadMission.ERROR_POSTPROCESSING_HOLD; import static us.shandian.giga.get.DownloadMission.ERROR_POSTPROCESSING_HOLD;
import static us.shandian.giga.get.DownloadMission.ERROR_POSTPROCESSING_STOPPED; import static us.shandian.giga.get.DownloadMission.ERROR_POSTPROCESSING_STOPPED;
import static us.shandian.giga.get.DownloadMission.ERROR_PROGRESS_LOST; import static us.shandian.giga.get.DownloadMission.ERROR_PROGRESS_LOST;
import static us.shandian.giga.get.DownloadMission.ERROR_RESOURCE_GONE;
import static us.shandian.giga.get.DownloadMission.ERROR_SSL_EXCEPTION; import static us.shandian.giga.get.DownloadMission.ERROR_SSL_EXCEPTION;
import static us.shandian.giga.get.DownloadMission.ERROR_TIMEOUT; import static us.shandian.giga.get.DownloadMission.ERROR_TIMEOUT;
import static us.shandian.giga.get.DownloadMission.ERROR_UNKNOWN_EXCEPTION; import static us.shandian.giga.get.DownloadMission.ERROR_UNKNOWN_EXCEPTION;
@ -430,7 +430,7 @@ public class MissionAdapter extends Adapter<ViewHolder> implements Handler.Callb
switch (mission.errCode) { switch (mission.errCode) {
case 416: case 416:
msg = R.string.error_http_requested_range_not_satisfiable; msg = R.string.error_http_unsupported_range;
break; break;
case 404: case 404:
msg = R.string.error_http_not_found; msg = R.string.error_http_not_found;
@ -443,9 +443,6 @@ public class MissionAdapter extends Adapter<ViewHolder> implements Handler.Callb
case ERROR_HTTP_NO_CONTENT: case ERROR_HTTP_NO_CONTENT:
msg = R.string.error_http_no_content; msg = R.string.error_http_no_content;
break; break;
case ERROR_HTTP_UNSUPPORTED_RANGE:
msg = R.string.error_http_unsupported_range;
break;
case ERROR_PATH_CREATION: case ERROR_PATH_CREATION:
msg = R.string.error_path_creation; msg = R.string.error_path_creation;
break; break;
@ -480,6 +477,9 @@ public class MissionAdapter extends Adapter<ViewHolder> implements Handler.Callb
case ERROR_TIMEOUT: case ERROR_TIMEOUT:
msg = R.string.error_timeout; msg = R.string.error_timeout;
break; break;
case ERROR_RESOURCE_GONE:
msg = R.string.error_download_resource_gone;
break;
default: default:
if (mission.errCode >= 100 && mission.errCode < 600) { if (mission.errCode >= 100 && mission.errCode < 600) {
msgEx = "HTTP " + mission.errCode; msgEx = "HTTP " + mission.errCode;
@ -859,7 +859,7 @@ public class MissionAdapter extends Adapter<ViewHolder> implements Handler.Callb
delete.setVisible(true); delete.setVisible(true);
boolean flag = !mission.isPsFailed(); boolean flag = !mission.isPsFailed() && mission.urls.length > 0;
start.setVisible(flag); start.setVisible(flag);
queue.setVisible(flag); queue.setVisible(flag);
} }

View file

@ -468,7 +468,6 @@
<string name="error_connect_host">لا يمكن الاتصال بالخادم</string> <string name="error_connect_host">لا يمكن الاتصال بالخادم</string>
<string name="error_http_no_content">الخادم لايقوم بإرسال البيانات</string> <string name="error_http_no_content">الخادم لايقوم بإرسال البيانات</string>
<string name="error_http_unsupported_range">الخادم لا يقبل التنزيل المتعدد، إعادة المحاولة مع @string/msg_threads = 1</string> <string name="error_http_unsupported_range">الخادم لا يقبل التنزيل المتعدد، إعادة المحاولة مع @string/msg_threads = 1</string>
<string name="error_http_requested_range_not_satisfiable">عدم استيفاء النطاق المطلوب</string>
<string name="error_http_not_found">غير موجود</string> <string name="error_http_not_found">غير موجود</string>
<string name="error_postprocessing_failed">فشلت المعالجة الاولية</string> <string name="error_postprocessing_failed">فشلت المعالجة الاولية</string>
<string name="clear_finished_download">حذف التنزيلات المنتهية</string> <string name="clear_finished_download">حذف التنزيلات المنتهية</string>

View file

@ -455,7 +455,6 @@
<string name="error_connect_host">Немагчыма злучыцца з серверам</string> <string name="error_connect_host">Немагчыма злучыцца з серверам</string>
<string name="error_http_no_content">Не атрымалася атрымаць дадзеныя з сервера</string> <string name="error_http_no_content">Не атрымалася атрымаць дадзеныя з сервера</string>
<string name="error_http_unsupported_range">Сервер не падтрымлівае шматструменную загрузку, паспрабуйце з @string/msg_threads = 1</string> <string name="error_http_unsupported_range">Сервер не падтрымлівае шматструменную загрузку, паспрабуйце з @string/msg_threads = 1</string>
<string name="error_http_requested_range_not_satisfiable">Запытаны дыяпазон недапушчальны</string>
<string name="error_http_not_found">Не знойдзена</string> <string name="error_http_not_found">Не знойдзена</string>
<string name="error_postprocessing_failed">Пасляапрацоўка не ўдалася</string> <string name="error_postprocessing_failed">Пасляапрацоўка не ўдалася</string>
<string name="clear_finished_download">Ачысціць завершаныя</string> <string name="clear_finished_download">Ачысціць завершаныя</string>

View file

@ -460,7 +460,6 @@
<string name="app_update_notification_content_title">NewPipe 更新可用!</string> <string name="app_update_notification_content_title">NewPipe 更新可用!</string>
<string name="error_path_creation">无法创建目标文件夹</string> <string name="error_path_creation">无法创建目标文件夹</string>
<string name="error_http_unsupported_range">服务器不接受多线程下载, 请使用 @string/msg_threads = 1重试</string> <string name="error_http_unsupported_range">服务器不接受多线程下载, 请使用 @string/msg_threads = 1重试</string>
<string name="error_http_requested_range_not_satisfiable">请求范围无法满足</string>
<string name="msg_pending_downloads">继续进行%s个待下载转移</string> <string name="msg_pending_downloads">继续进行%s个待下载转移</string>
<string name="pause_downloads_on_mobile_desc">切换至移动数据时有用,尽管一些下载无法被暂停</string> <string name="pause_downloads_on_mobile_desc">切换至移动数据时有用,尽管一些下载无法被暂停</string>
<string name="show_comments_title">显示评论</string> <string name="show_comments_title">显示评论</string>

View file

@ -463,7 +463,6 @@ otevření ve vyskakovacím okně</string>
<string name="error_connect_host">Nelze se připojit k serveru</string> <string name="error_connect_host">Nelze se připojit k serveru</string>
<string name="error_http_no_content">Server neposílá data</string> <string name="error_http_no_content">Server neposílá data</string>
<string name="error_http_unsupported_range">Server neakceptuje vícevláknové stahování, opakujte akci s @string/msg_threads = 1</string> <string name="error_http_unsupported_range">Server neakceptuje vícevláknové stahování, opakujte akci s @string/msg_threads = 1</string>
<string name="error_http_requested_range_not_satisfiable">Požadovaný rozsah nelze splnit</string>
<string name="error_http_not_found">Nenalezeno</string> <string name="error_http_not_found">Nenalezeno</string>
<string name="error_postprocessing_failed">Post-processing selhal</string> <string name="error_postprocessing_failed">Post-processing selhal</string>
<string name="clear_finished_download">Vyčistit dokončená stahování</string> <string name="clear_finished_download">Vyčistit dokončená stahování</string>

View file

@ -380,7 +380,6 @@
<string name="error_connect_host">Kan ikke forbinde til serveren</string> <string name="error_connect_host">Kan ikke forbinde til serveren</string>
<string name="error_http_no_content">Serveren sender ikke data</string> <string name="error_http_no_content">Serveren sender ikke data</string>
<string name="error_http_unsupported_range">Serveren accepterer ikke multitrådede downloads; prøv igen med @string/msg_threads = 1</string> <string name="error_http_unsupported_range">Serveren accepterer ikke multitrådede downloads; prøv igen med @string/msg_threads = 1</string>
<string name="error_http_requested_range_not_satisfiable">Det anmodede interval er ikke gyldigt</string>
<string name="error_http_not_found">Ikke fundet</string> <string name="error_http_not_found">Ikke fundet</string>
<string name="error_postprocessing_failed">Efterbehandling fejlede</string> <string name="error_postprocessing_failed">Efterbehandling fejlede</string>
<string name="stop">Stop</string> <string name="stop">Stop</string>

View file

@ -454,7 +454,6 @@
<string name="error_connect_host">Kann nicht mit dem Server verbinden</string> <string name="error_connect_host">Kann nicht mit dem Server verbinden</string>
<string name="error_http_no_content">Der Server sendet keine Daten</string> <string name="error_http_no_content">Der Server sendet keine Daten</string>
<string name="error_http_unsupported_range">Der Server erlaubt kein mehrfädiges Herunterladen wiederhole mit @string/msg_threads = 1</string> <string name="error_http_unsupported_range">Der Server erlaubt kein mehrfädiges Herunterladen wiederhole mit @string/msg_threads = 1</string>
<string name="error_http_requested_range_not_satisfiable">Gewünschter Bereich ist nicht verfügbar</string>
<string name="error_http_not_found">Nicht gefunden</string> <string name="error_http_not_found">Nicht gefunden</string>
<string name="error_postprocessing_failed">Nachbearbeitung fehlgeschlagen</string> <string name="error_postprocessing_failed">Nachbearbeitung fehlgeschlagen</string>
<string name="clear_finished_download">Um fertige Downloads bereinigen</string> <string name="clear_finished_download">Um fertige Downloads bereinigen</string>

View file

@ -456,7 +456,6 @@
<string name="error_connect_host">Αδυναμία σύνδεσης με τον εξυπηρετητή</string> <string name="error_connect_host">Αδυναμία σύνδεσης με τον εξυπηρετητή</string>
<string name="error_http_no_content">Ο εξυπηρετητής δεν μπορεί να στείλει τα δεδομένα</string> <string name="error_http_no_content">Ο εξυπηρετητής δεν μπορεί να στείλει τα δεδομένα</string>
<string name="error_http_unsupported_range">Ο εξυπηρετητής δέν υποστηρίζει πολυνηματικές λήψεις, ξαναπροσπαθήστε με @string/msg_threads = 1</string> <string name="error_http_unsupported_range">Ο εξυπηρετητής δέν υποστηρίζει πολυνηματικές λήψεις, ξαναπροσπαθήστε με @string/msg_threads = 1</string>
<string name="error_http_requested_range_not_satisfiable">Το ζητούμενο εύρος δεν μπορεί να εξυπηρετηθεί</string>
<string name="error_http_not_found">Δεν βρέθηκε</string> <string name="error_http_not_found">Δεν βρέθηκε</string>
<string name="error_postprocessing_failed">Μετεπεξεργασία απέτυχε</string> <string name="error_postprocessing_failed">Μετεπεξεργασία απέτυχε</string>
<string name="clear_finished_download">Εκκαθάριση ολοκληρωμένων λήψεων</string> <string name="clear_finished_download">Εκκαθάριση ολοκληρωμένων λήψεων</string>

View file

@ -444,8 +444,8 @@
<string name="error_ssl_exception">Fallo la conexión segura</string> <string name="error_ssl_exception">Fallo la conexión segura</string>
<string name="error_unknown_host">No se pudo encontrar el servidor</string> <string name="error_unknown_host">No se pudo encontrar el servidor</string>
<string name="error_connect_host">No se puede conectar con el servidor</string> <string name="error_connect_host">No se puede conectar con el servidor</string>
<string name="error_http_no_content">El servidor no está enviando datos</string> <string name="error_http_no_content">El servidor no devolvio datos</string>
<string name="error_http_unsupported_range">El servidor no acepta descargas multiproceso; intente de nuevo con @string/msg_threads = 1</string> <string name="error_http_unsupported_range">El servidor no acepta descargas multi-hilos, intente de nuevo con @string/msg_threads = 1</string>
<string name="error_http_requested_range_not_satisfiable">No se puede satisfacer el intervalo seleccionado</string> <string name="error_http_requested_range_not_satisfiable">No se puede satisfacer el intervalo seleccionado</string>
<string name="error_http_not_found">No encontrado</string> <string name="error_http_not_found">No encontrado</string>
<string name="error_postprocessing_failed">Falló el posprocesamiento</string> <string name="error_postprocessing_failed">Falló el posprocesamiento</string>
@ -453,6 +453,7 @@
<string name="error_insufficient_storage">No hay suficiente espacio disponible en el dispositivo</string> <string name="error_insufficient_storage">No hay suficiente espacio disponible en el dispositivo</string>
<string name="error_progress_lost">Se perdió el progreso porque el archivo fue eliminado</string> <string name="error_progress_lost">Se perdió el progreso porque el archivo fue eliminado</string>
<string name="error_timeout">Tiempo de espera excedido</string> <string name="error_timeout">Tiempo de espera excedido</string>
<string name="error_download_resource_gone">El recurso solicitado ya no esta disponible</string>
<string name="downloads_storage_ask_title">Preguntar dónde descargar</string> <string name="downloads_storage_ask_title">Preguntar dónde descargar</string>
<string name="downloads_storage_ask_summary">Se preguntará dónde guardar cada descarga</string> <string name="downloads_storage_ask_summary">Se preguntará dónde guardar cada descarga</string>
<string name="downloads_storage_ask_summary_kitkat">Se le preguntará dónde guardar cada descarga. <string name="downloads_storage_ask_summary_kitkat">Se le preguntará dónde guardar cada descarga.

View file

@ -457,7 +457,6 @@
<string name="error_connect_host">Serveriga ei saadud ühendust</string> <string name="error_connect_host">Serveriga ei saadud ühendust</string>
<string name="error_http_no_content">Server ei saada andmeid</string> <string name="error_http_no_content">Server ei saada andmeid</string>
<string name="error_http_unsupported_range">Server ei toeta mitmelõimelisi allalaadimisi. Proovi uuesti kasutades @string/msg_threads = 1</string> <string name="error_http_unsupported_range">Server ei toeta mitmelõimelisi allalaadimisi. Proovi uuesti kasutades @string/msg_threads = 1</string>
<string name="error_http_requested_range_not_satisfiable">Taotletud vahemik ei ole rahuldatav</string>
<string name="error_http_not_found">Ei leitud</string> <string name="error_http_not_found">Ei leitud</string>
<string name="error_postprocessing_failed">Järeltöötlemine nurjus</string> <string name="error_postprocessing_failed">Järeltöötlemine nurjus</string>
<string name="clear_finished_download">Eemalda lõpetatud allalaadimised</string> <string name="clear_finished_download">Eemalda lõpetatud allalaadimised</string>

View file

@ -456,7 +456,6 @@
<string name="error_connect_host">Ezin da zerbitzariarekin konektatu</string> <string name="error_connect_host">Ezin da zerbitzariarekin konektatu</string>
<string name="error_http_no_content">Zerbitzariak ez du daturik bidaltzen</string> <string name="error_http_no_content">Zerbitzariak ez du daturik bidaltzen</string>
<string name="error_http_unsupported_range">Zerbitzariak ez ditu hainbat hariko deskargak onartzen, saiatu @string/msg_threads = 1 erabilita</string> <string name="error_http_unsupported_range">Zerbitzariak ez ditu hainbat hariko deskargak onartzen, saiatu @string/msg_threads = 1 erabilita</string>
<string name="error_http_requested_range_not_satisfiable">Eskatutako barrutia ezin da bete</string>
<string name="error_http_not_found">Ez aurkitua</string> <string name="error_http_not_found">Ez aurkitua</string>
<string name="error_postprocessing_failed">Post-prozesuak huts egin du</string> <string name="error_postprocessing_failed">Post-prozesuak huts egin du</string>
<string name="clear_finished_download">Garbitu amaitutako deskargak</string> <string name="clear_finished_download">Garbitu amaitutako deskargak</string>

View file

@ -467,7 +467,6 @@
<string name="saved_tabs_invalid_json">Utilisation des onglets par défaut, erreur lors de la lecture des onglets enregistrés</string> <string name="saved_tabs_invalid_json">Utilisation des onglets par défaut, erreur lors de la lecture des onglets enregistrés</string>
<string name="error_http_unsupported_range">Le serveur naccepte pas les téléchargements multi-fils, veuillez réessayer avec @string/msg_threads = 1</string> <string name="error_http_unsupported_range">Le serveur naccepte pas les téléchargements multi-fils, veuillez réessayer avec @string/msg_threads = 1</string>
<string name="msg_pending_downloads">Continuer vos %s transferts en attente depuis Téléchargement</string> <string name="msg_pending_downloads">Continuer vos %s transferts en attente depuis Téléchargement</string>
<string name="error_http_requested_range_not_satisfiable">Le domaine désiré n\'est pas disponible</string>
<string name="show_comments_title">Afficher les commentaires</string> <string name="show_comments_title">Afficher les commentaires</string>
<string name="show_comments_summary">Désactiver pour ne pas afficher les commentaires</string> <string name="show_comments_summary">Désactiver pour ne pas afficher les commentaires</string>
<string name="autoplay_title">Lecture automatique</string> <string name="autoplay_title">Lecture automatique</string>

View file

@ -461,7 +461,6 @@
<string name="error_connect_host">לא ניתן להתחבר לשרת</string> <string name="error_connect_host">לא ניתן להתחבר לשרת</string>
<string name="error_http_no_content">השרת לא שולח נתונים</string> <string name="error_http_no_content">השרת לא שולח נתונים</string>
<string name="error_http_unsupported_range">"השרת לא מקבל הורדות רב ערוציות, מוטב לנסות שוב עם @string/msg_threads = 1 "</string> <string name="error_http_unsupported_range">"השרת לא מקבל הורדות רב ערוציות, מוטב לנסות שוב עם @string/msg_threads = 1 "</string>
<string name="error_http_requested_range_not_satisfiable">הטווח המבוקש לא מתאים</string>
<string name="error_http_not_found">לא נמצא</string> <string name="error_http_not_found">לא נמצא</string>
<string name="error_postprocessing_failed">העיבוד המאוחר נכשל</string> <string name="error_postprocessing_failed">העיבוד המאוחר נכשל</string>
<string name="clear_finished_download">פינוי ההורדות שהסתיימו</string> <string name="clear_finished_download">פינוי ההורדות שהסתיימו</string>

View file

@ -454,7 +454,6 @@
<string name="error_connect_host">Nije moguće povezati se s serverom</string> <string name="error_connect_host">Nije moguće povezati se s serverom</string>
<string name="error_http_no_content">Server ne šalje podatke</string> <string name="error_http_no_content">Server ne šalje podatke</string>
<string name="error_http_unsupported_range">Poslužitelj ne prihvaća preuzimanja s više niti, pokušaj ponovo s @string/msg_threads = 1</string> <string name="error_http_unsupported_range">Poslužitelj ne prihvaća preuzimanja s više niti, pokušaj ponovo s @string/msg_threads = 1</string>
<string name="error_http_requested_range_not_satisfiable">Traženi raspon nije zadovoljavajući</string>
<string name="error_http_not_found">Nije pronađeno</string> <string name="error_http_not_found">Nije pronađeno</string>
<string name="error_postprocessing_failed">Naknadna obrada nije uspjela</string> <string name="error_postprocessing_failed">Naknadna obrada nije uspjela</string>
<string name="clear_finished_download">Obriši završena preuzimanja</string> <string name="clear_finished_download">Obriši završena preuzimanja</string>

View file

@ -450,7 +450,6 @@
<string name="error_connect_host">Tidak dapat terhubung ke server</string> <string name="error_connect_host">Tidak dapat terhubung ke server</string>
<string name="error_http_no_content">Server tidak mengirim data</string> <string name="error_http_no_content">Server tidak mengirim data</string>
<string name="error_http_unsupported_range">Server tidak menerima unduhan multi-utas, coba lagi dengan @string/msg_threads = 1</string> <string name="error_http_unsupported_range">Server tidak menerima unduhan multi-utas, coba lagi dengan @string/msg_threads = 1</string>
<string name="error_http_requested_range_not_satisfiable">Rentang yang diminta tidak memuaskan</string>
<string name="error_http_not_found">Tidak ditemukan</string> <string name="error_http_not_found">Tidak ditemukan</string>
<string name="error_postprocessing_failed">Pengolahan-pasca gagal</string> <string name="error_postprocessing_failed">Pengolahan-pasca gagal</string>
<string name="clear_finished_download">Hapus unduhan yang sudah selesai</string> <string name="clear_finished_download">Hapus unduhan yang sudah selesai</string>

View file

@ -454,7 +454,6 @@
<string name="error_connect_host">Impossibile connettersi al server</string> <string name="error_connect_host">Impossibile connettersi al server</string>
<string name="error_http_no_content">Il server non invia dati</string> <string name="error_http_no_content">Il server non invia dati</string>
<string name="error_http_unsupported_range">Il server non accetta download multipli, riprovare con @string/msg_threads = 1</string> <string name="error_http_unsupported_range">Il server non accetta download multipli, riprovare con @string/msg_threads = 1</string>
<string name="error_http_requested_range_not_satisfiable">Intervallo richiesto non soddisfatto</string>
<string name="error_http_not_found">Non trovato</string> <string name="error_http_not_found">Non trovato</string>
<string name="error_postprocessing_failed">Post-processing fallito</string> <string name="error_postprocessing_failed">Post-processing fallito</string>
<string name="clear_finished_download">Pulisci i download completati</string> <string name="clear_finished_download">Pulisci i download completati</string>

View file

@ -440,7 +440,6 @@
<string name="error_connect_host">サーバに接続できません</string> <string name="error_connect_host">サーバに接続できません</string>
<string name="error_http_no_content">サーバがデータを送信していません</string> <string name="error_http_no_content">サーバがデータを送信していません</string>
<string name="error_http_unsupported_range">サーバが同時接続ダウンロードを受け付けません。再試行してください @string/msg_threads = 1</string> <string name="error_http_unsupported_range">サーバが同時接続ダウンロードを受け付けません。再試行してください @string/msg_threads = 1</string>
<string name="error_http_requested_range_not_satisfiable">必要な範囲が満たされていません</string>
<string name="error_http_not_found">見つかりません</string> <string name="error_http_not_found">見つかりません</string>
<string name="error_postprocessing_failed">保存処理に失敗しました</string> <string name="error_postprocessing_failed">保存処理に失敗しました</string>
<string name="clear_finished_download">完了済みを一覧から削除します</string> <string name="clear_finished_download">完了済みを一覧から削除します</string>

View file

@ -451,7 +451,6 @@
<string name="error_connect_host">서버에 접속할 수 없습니다</string> <string name="error_connect_host">서버에 접속할 수 없습니다</string>
<string name="error_http_no_content">서버가 데이터를 전송하지 않고 있습니다</string> <string name="error_http_no_content">서버가 데이터를 전송하지 않고 있습니다</string>
<string name="error_http_unsupported_range">서버가 다중 스레드 다운로드를 받아들이지 않습니다, @string/msg_threads = 1 를 사용해 다시 시도해보세요</string> <string name="error_http_unsupported_range">서버가 다중 스레드 다운로드를 받아들이지 않습니다, @string/msg_threads = 1 를 사용해 다시 시도해보세요</string>
<string name="error_http_requested_range_not_satisfiable">요청된 HTTP 범위가 충분하지 않습니다</string>
<string name="error_http_not_found">HTTP 찾을 수 없습니다</string> <string name="error_http_not_found">HTTP 찾을 수 없습니다</string>
<string name="error_postprocessing_failed">후처리 작업이 실패하였습니다</string> <string name="error_postprocessing_failed">후처리 작업이 실패하였습니다</string>
<string name="clear_finished_download">완료된 다운로드 비우기</string> <string name="clear_finished_download">완료된 다운로드 비우기</string>

View file

@ -450,7 +450,6 @@
<string name="error_connect_host">Tidak dapat menyambung ke server</string> <string name="error_connect_host">Tidak dapat menyambung ke server</string>
<string name="error_http_no_content">Server tidak menghantar data</string> <string name="error_http_no_content">Server tidak menghantar data</string>
<string name="error_http_unsupported_range">Server tidak menerima muat turun berbilang thread, cuba lagi dengan @string/msg_threads = 1</string> <string name="error_http_unsupported_range">Server tidak menerima muat turun berbilang thread, cuba lagi dengan @string/msg_threads = 1</string>
<string name="error_http_requested_range_not_satisfiable">Julat yang diminta tidak memuaskan</string>
<string name="error_http_not_found">Tidak ditemui</string> <string name="error_http_not_found">Tidak ditemui</string>
<string name="error_postprocessing_failed">Pemprosesan-pasca gagal</string> <string name="error_postprocessing_failed">Pemprosesan-pasca gagal</string>
<string name="clear_finished_download">Hapuskan senarai muat turun yang selesai</string> <string name="clear_finished_download">Hapuskan senarai muat turun yang selesai</string>

View file

@ -454,7 +454,6 @@
<string name="error_connect_host">Kan geen verbinding maken met de server</string> <string name="error_connect_host">Kan geen verbinding maken met de server</string>
<string name="error_http_no_content">De server verzendt geen gegevens</string> <string name="error_http_no_content">De server verzendt geen gegevens</string>
<string name="error_http_unsupported_range">De server aanvaardt geen meerdradige downloads, probeert het opnieuw met @string/msg_threads = 1</string> <string name="error_http_unsupported_range">De server aanvaardt geen meerdradige downloads, probeert het opnieuw met @string/msg_threads = 1</string>
<string name="error_http_requested_range_not_satisfiable">Gevraagd bereik niet beschikbaar</string>
<string name="error_http_not_found">Niet gevonden</string> <string name="error_http_not_found">Niet gevonden</string>
<string name="error_postprocessing_failed">Nabewerking mislukt</string> <string name="error_postprocessing_failed">Nabewerking mislukt</string>
<string name="clear_finished_download">Voltooide downloads wissen</string> <string name="clear_finished_download">Voltooide downloads wissen</string>

View file

@ -454,7 +454,6 @@
<string name="error_connect_host">Kan niet met de server verbinden</string> <string name="error_connect_host">Kan niet met de server verbinden</string>
<string name="error_http_no_content">De server verzendt geen gegevens</string> <string name="error_http_no_content">De server verzendt geen gegevens</string>
<string name="error_http_unsupported_range">De server accepteert geen multi-threaded downloads, probeer het opnieuw met @string/msg_threads = 1</string> <string name="error_http_unsupported_range">De server accepteert geen multi-threaded downloads, probeer het opnieuw met @string/msg_threads = 1</string>
<string name="error_http_requested_range_not_satisfiable">Gevraagde bereik niet beschikbaar</string>
<string name="error_http_not_found">Niet gevonden</string> <string name="error_http_not_found">Niet gevonden</string>
<string name="error_postprocessing_failed">Nabewerking mislukt</string> <string name="error_postprocessing_failed">Nabewerking mislukt</string>
<string name="clear_finished_download">Voltooide downloads wissen</string> <string name="clear_finished_download">Voltooide downloads wissen</string>

View file

@ -450,7 +450,6 @@
<string name="error_connect_host">ਸਰਵਰ ਨਾਲ ਜੁੜ ਨਹੀਂ ਸਕਦਾ</string> <string name="error_connect_host">ਸਰਵਰ ਨਾਲ ਜੁੜ ਨਹੀਂ ਸਕਦਾ</string>
<string name="error_http_no_content">ਸਰਵਰ ਨੇ ਡਾਟਾ ਨਹੀਂ ਭੇਜਿਆ</string> <string name="error_http_no_content">ਸਰਵਰ ਨੇ ਡਾਟਾ ਨਹੀਂ ਭੇਜਿਆ</string>
<string name="error_http_unsupported_range">ਸਰਵਰ ਮਲਟੀ-Threaded ਡਾਊਨਲੋਡਸ ਨੂੰ ਸਵੀਕਾਰ ਨਹੀਂ ਕਰਦਾ, ਇਸ ਨਾਲ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ @string/msg_threads = 1</string> <string name="error_http_unsupported_range">ਸਰਵਰ ਮਲਟੀ-Threaded ਡਾਊਨਲੋਡਸ ਨੂੰ ਸਵੀਕਾਰ ਨਹੀਂ ਕਰਦਾ, ਇਸ ਨਾਲ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ @string/msg_threads = 1</string>
<string name="error_http_requested_range_not_satisfiable">ਬੇਨਤੀ ਕੀਤੀ ਸੀਮਾ ਤਸੱਲੀਬਖਸ਼ ਨਹੀਂ ਹੈ</string>
<string name="error_http_not_found">ਨਹੀਂ ਲਭਿਆ</string> <string name="error_http_not_found">ਨਹੀਂ ਲਭਿਆ</string>
<string name="error_postprocessing_failed">Post-processing ਫੇਲ੍ਹ</string> <string name="error_postprocessing_failed">Post-processing ਫੇਲ੍ਹ</string>
<string name="clear_finished_download">ਮੁਕੰਮਲ ਹੋਈਆਂ ਡਾਊਨਲੋਡ ਸਾਫ਼ ਕਰੋ</string> <string name="clear_finished_download">ਮੁਕੰਮਲ ਹੋਈਆਂ ਡਾਊਨਲੋਡ ਸਾਫ਼ ਕਰੋ</string>

View file

@ -456,7 +456,6 @@
<string name="error_connect_host">Nie można połączyć się z serwerem</string> <string name="error_connect_host">Nie można połączyć się z serwerem</string>
<string name="error_http_no_content">Serwer nie wysyła danych</string> <string name="error_http_no_content">Serwer nie wysyła danych</string>
<string name="error_http_unsupported_range">Serwer nie akceptuje pobierania wielowątkowego, spróbuj ponownie za pomocą @string/msg_threads = 1</string> <string name="error_http_unsupported_range">Serwer nie akceptuje pobierania wielowątkowego, spróbuj ponownie za pomocą @string/msg_threads = 1</string>
<string name="error_http_requested_range_not_satisfiable">Niewłaściwy zakres</string>
<string name="error_http_not_found">Nie znaleziono</string> <string name="error_http_not_found">Nie znaleziono</string>
<string name="error_postprocessing_failed">Przetwarzanie końcowe nie powiodło się</string> <string name="error_postprocessing_failed">Przetwarzanie końcowe nie powiodło się</string>
<string name="clear_finished_download">Wyczyść ukończone pobieranie</string> <string name="clear_finished_download">Wyczyść ukończone pobieranie</string>

View file

@ -463,7 +463,6 @@ abrir em modo popup</string>
<string name="error_connect_host">Não foi possível conectar ao servidor</string> <string name="error_connect_host">Não foi possível conectar ao servidor</string>
<string name="error_http_no_content">O servidor não envia dados</string> <string name="error_http_no_content">O servidor não envia dados</string>
<string name="error_http_unsupported_range">O servidor não aceita downloads em multi-thread, tente com @string/msg_threads = 1</string> <string name="error_http_unsupported_range">O servidor não aceita downloads em multi-thread, tente com @string/msg_threads = 1</string>
<string name="error_http_requested_range_not_satisfiable">Intervalo solicitado não aceito</string>
<string name="error_http_not_found">Não encontrado</string> <string name="error_http_not_found">Não encontrado</string>
<string name="error_postprocessing_failed">Falha no pós processamento</string> <string name="error_postprocessing_failed">Falha no pós processamento</string>
<string name="clear_finished_download">Limpar downloads finalizados</string> <string name="clear_finished_download">Limpar downloads finalizados</string>

View file

@ -452,7 +452,6 @@
<string name="error_connect_host">Não é possível ligar ao servidor</string> <string name="error_connect_host">Não é possível ligar ao servidor</string>
<string name="error_http_no_content">O servidor não envia dados</string> <string name="error_http_no_content">O servidor não envia dados</string>
<string name="error_http_unsupported_range">O servidor não aceita transferências de vários processos, tente novamente com @string/msg_threads = 1</string> <string name="error_http_unsupported_range">O servidor não aceita transferências de vários processos, tente novamente com @string/msg_threads = 1</string>
<string name="error_http_requested_range_not_satisfiable">Intervalo solicitado não satisfatório</string>
<string name="error_http_not_found">Não encontrado</string> <string name="error_http_not_found">Não encontrado</string>
<string name="error_postprocessing_failed">Pós-processamento falhado</string> <string name="error_postprocessing_failed">Pós-processamento falhado</string>
<string name="clear_finished_download">Limpar transferências concluídas</string> <string name="clear_finished_download">Limpar transferências concluídas</string>

View file

@ -454,7 +454,6 @@
<string name="error_permission_denied">Доступ запрещён системой</string> <string name="error_permission_denied">Доступ запрещён системой</string>
<string name="error_unknown_host">Сервер не найден</string> <string name="error_unknown_host">Сервер не найден</string>
<string name="error_http_unsupported_range">Сервер не принимает многопоточные загрузки, повторная попытка с @string/msg_threads = 1</string> <string name="error_http_unsupported_range">Сервер не принимает многопоточные загрузки, повторная попытка с @string/msg_threads = 1</string>
<string name="error_http_requested_range_not_satisfiable">Запрашиваемый диапазон недопустим</string>
<string name="error_http_not_found">Не найдено</string> <string name="error_http_not_found">Не найдено</string>
<string name="clear_finished_download">Очистить завершённые</string> <string name="clear_finished_download">Очистить завершённые</string>
<string name="stop">Остановить</string> <string name="stop">Остановить</string>

View file

@ -462,7 +462,6 @@
<string name="error_connect_host">Nepodarilo sa pripojiť k serveru</string> <string name="error_connect_host">Nepodarilo sa pripojiť k serveru</string>
<string name="error_http_no_content">Server neposiela údaje</string> <string name="error_http_no_content">Server neposiela údaje</string>
<string name="error_http_unsupported_range">Server neakceptuje preberanie viacerých vlákien, zopakujte s @string/msg_threads = 1</string> <string name="error_http_unsupported_range">Server neakceptuje preberanie viacerých vlákien, zopakujte s @string/msg_threads = 1</string>
<string name="error_http_requested_range_not_satisfiable">Požadovaný rozsah nie je uspokojivý</string>
<string name="error_http_not_found">Nenájdené</string> <string name="error_http_not_found">Nenájdené</string>
<string name="error_postprocessing_failed">Post-spracovanie zlyhalo</string> <string name="error_postprocessing_failed">Post-spracovanie zlyhalo</string>
<string name="clear_finished_download">Vyčistiť dokončené sťahovania</string> <string name="clear_finished_download">Vyčistiť dokončené sťahovania</string>

View file

@ -449,7 +449,6 @@
<string name="error_connect_host">Sunucuya bağlanılamıyor</string> <string name="error_connect_host">Sunucuya bağlanılamıyor</string>
<string name="error_http_no_content">Sunucu veri göndermiyor</string> <string name="error_http_no_content">Sunucu veri göndermiyor</string>
<string name="error_http_unsupported_range">Sunucu, çok iş parçacıklı indirmeleri kabul etmez, @string/msg_threads = 1 ile yeniden deneyin</string> <string name="error_http_unsupported_range">Sunucu, çok iş parçacıklı indirmeleri kabul etmez, @string/msg_threads = 1 ile yeniden deneyin</string>
<string name="error_http_requested_range_not_satisfiable">İstenen aralık karşılanamıyor</string>
<string name="error_http_not_found">Bulunamadı</string> <string name="error_http_not_found">Bulunamadı</string>
<string name="error_postprocessing_failed">İşlem sonrası başarısız</string> <string name="error_postprocessing_failed">İşlem sonrası başarısız</string>
<string name="clear_finished_download">Tamamlanan indirmeleri temizle</string> <string name="clear_finished_download">Tamamlanan indirmeleri temizle</string>

View file

@ -471,7 +471,6 @@
<string name="saved_tabs_invalid_json">Помилка зчитування збережених вкладок. Використовую типові вкладки.</string> <string name="saved_tabs_invalid_json">Помилка зчитування збережених вкладок. Використовую типові вкладки.</string>
<string name="main_page_content_summary">Вкладки, що відображаються на головній сторінці</string> <string name="main_page_content_summary">Вкладки, що відображаються на головній сторінці</string>
<string name="updates_setting_description">Показувати сповіщення з пропозицією оновити застосунок за наявності нової версії</string> <string name="updates_setting_description">Показувати сповіщення з пропозицією оновити застосунок за наявності нової версії</string>
<string name="error_http_requested_range_not_satisfiable">Запитуваний діапазон неприпустимий</string>
<string name="msg_pending_downloads">Продовжити ваші %s відкладених переміщень із Завантажень</string> <string name="msg_pending_downloads">Продовжити ваші %s відкладених переміщень із Завантажень</string>
<string name="pause_downloads_on_mobile_desc">Корисно під час переходу на мобільні дані, хоча деякі завантаження не можуть бути призупинені</string> <string name="pause_downloads_on_mobile_desc">Корисно під час переходу на мобільні дані, хоча деякі завантаження не можуть бути призупинені</string>
<string name="show_comments_title">Показувати коментарі</string> <string name="show_comments_title">Показувати коментарі</string>

View file

@ -449,7 +449,6 @@
<string name="error_connect_host">Không thế kết nối với máy chủ</string> <string name="error_connect_host">Không thế kết nối với máy chủ</string>
<string name="error_http_no_content">Máy chủ không gửi dữ liệu về</string> <string name="error_http_no_content">Máy chủ không gửi dữ liệu về</string>
<string name="error_http_unsupported_range">Máy chủ không chấp nhận tải đa luồng, thử lại với số luồng = 1</string> <string name="error_http_unsupported_range">Máy chủ không chấp nhận tải đa luồng, thử lại với số luồng = 1</string>
<string name="error_http_requested_range_not_satisfiable">(HTTP) Không thể đáp ứng khoảng dữ liệu đã yêu cầu</string>
<string name="error_http_not_found">Không tìm thấy</string> <string name="error_http_not_found">Không tìm thấy</string>
<string name="error_postprocessing_failed">Xử lý thất bại</string> <string name="error_postprocessing_failed">Xử lý thất bại</string>
<string name="clear_finished_download">Dọn các tải về đã hoàn thành</string> <string name="clear_finished_download">Dọn các tải về đã hoàn thành</string>

View file

@ -447,7 +447,6 @@
<string name="error_connect_host">無法連線到伺服器</string> <string name="error_connect_host">無法連線到伺服器</string>
<string name="error_http_no_content">伺服器沒有傳送資料</string> <string name="error_http_no_content">伺服器沒有傳送資料</string>
<string name="error_http_unsupported_range">伺服器不接受多執行緒下載,請以 @string/msg_threads = 1 重試</string> <string name="error_http_unsupported_range">伺服器不接受多執行緒下載,請以 @string/msg_threads = 1 重試</string>
<string name="error_http_requested_range_not_satisfiable">請求範圍無法滿足</string>
<string name="error_http_not_found">找不到</string> <string name="error_http_not_found">找不到</string>
<string name="error_postprocessing_failed">後處理失敗</string> <string name="error_postprocessing_failed">後處理失敗</string>
<string name="clear_finished_download">清除已結束的下載</string> <string name="clear_finished_download">清除已結束的下載</string>

View file

@ -551,13 +551,13 @@
<string name="error_connect_host">Can not connect to the server</string> <string name="error_connect_host">Can not connect to the server</string>
<string name="error_http_no_content">The server does not send data</string> <string name="error_http_no_content">The server does not send data</string>
<string name="error_http_unsupported_range">The server does not accept multi-threaded downloads, retry with @string/msg_threads = 1</string> <string name="error_http_unsupported_range">The server does not accept multi-threaded downloads, retry with @string/msg_threads = 1</string>
<string name="error_http_requested_range_not_satisfiable">Requested range not satisfiable</string>
<string name="error_http_not_found">Not found</string> <string name="error_http_not_found">Not found</string>
<string name="error_postprocessing_failed">Post-processing failed</string> <string name="error_postprocessing_failed">Post-processing failed</string>
<string name="error_postprocessing_stopped">NewPipe was closed while working on the file</string> <string name="error_postprocessing_stopped">NewPipe was closed while working on the file</string>
<string name="error_insufficient_storage">No space left on device</string> <string name="error_insufficient_storage">No space left on device</string>
<string name="error_progress_lost">Progress lost, because the file was deleted</string> <string name="error_progress_lost">Progress lost, because the file was deleted</string>
<string name="error_timeout">Connection timeout</string> <string name="error_timeout">Connection timeout</string>
<string name="error_download_resource_gone">The solicited resource is not available anymore</string>
<string name="clear_finished_download">Clear finished downloads</string> <string name="clear_finished_download">Clear finished downloads</string>
<string name="confirm_prompt">Are you sure?</string> <string name="confirm_prompt">Are you sure?</string>
<string name="msg_pending_downloads">Continue your %s pending transfers from Downloads</string> <string name="msg_pending_downloads">Continue your %s pending transfers from Downloads</string>