code cleanup

* migrate few annotations to androidx
* mission recovery: better error handling (except StreamExtractor.getErrorMessage() method always returns an error)
* post-processing: more detailed progress

[file specific changes]

DownloadMission.java
* remove redundant/boilerplate code (again)
* make few variables volatile
* better file "length" approximation
* use "done" variable to count the amount of bytes downloaded (simplify percent calc in UI code)

Postprocessing.java
* if case of error use "ERROR_POSTPROCESSING" instead of "ERROR_UNKNOWN_EXCEPTION"
* simplify source stream init

DownloadManager.java
* move all "service message sending" code to DownloadMission
* remove not implemented method "notifyUserPendingDownloads()" also his unused strings

DownloadManagerService.java
* use START_STICKY instead of START_NOT_STICKY
* simplify addMissionEventListener()/removeMissionEventListener() methods (always are called from the main thread)

Deleter.java
* better method definition

MissionAdapter.java
* better method definition
* code cleanup
* the UI is now refreshed every 750ms
* simplify download progress calculation
* indicates if the download is actually recovering
* smooth download speed measure
* show estimated remain time

MainFragment.java:
* check if viewPager is null (issued by "Apply changes" feature of Android Studio)
This commit is contained in:
kapodamy 2019-10-09 23:49:23 -03:00
parent ffaaf9d68f
commit fc4a892f45
53 changed files with 554 additions and 622 deletions

View file

@ -2,13 +2,11 @@ package us.shandian.giga.service;
import android.content.Context;
import android.os.Handler;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.DiffUtil;
import android.util.Log;
import android.widget.Toast;
import org.schabi.newpipe.R;
import java.io.File;
import java.io.IOException;
@ -152,6 +150,8 @@ public class DownloadManager {
continue;
}
mis.threads = new Thread[0];
boolean exists;
try {
mis.storage = StoredFileHelper.deserialize(mis.storage, ctx);
@ -170,8 +170,6 @@ public class DownloadManager {
// is Java IO (avoid showing the "Save as..." dialog)
if (exists && mis.storage.isDirect() && !mis.storage.delete())
Log.w(TAG, "Unable to delete incomplete download file: " + sub.getPath());
exists = true;
}
mis.psState = 0;
@ -243,7 +241,6 @@ public class DownloadManager {
boolean start = !mPrefQueueLimit || getRunningMissionsCount() < 1;
if (canDownloadInCurrentNetwork() && start) {
mHandler.sendEmptyMessage(DownloadManagerService.MESSAGE_PROGRESS);
mission.start();
}
}
@ -252,7 +249,6 @@ public class DownloadManager {
public void resumeMission(DownloadMission mission) {
if (!mission.running) {
mHandler.sendEmptyMessage(DownloadManagerService.MESSAGE_PROGRESS);
mission.start();
}
}
@ -261,7 +257,6 @@ public class DownloadManager {
if (mission.running) {
mission.setEnqueued(false);
mission.pause();
mHandler.sendEmptyMessage(DownloadManagerService.MESSAGE_PAUSED);
}
}
@ -274,7 +269,6 @@ public class DownloadManager {
mFinishedMissionStore.deleteMission(mission);
}
mHandler.sendEmptyMessage(DownloadManagerService.MESSAGE_DELETED);
mission.delete();
}
}
@ -291,7 +285,6 @@ public class DownloadManager {
mFinishedMissionStore.deleteMission(mission);
}
mHandler.sendEmptyMessage(DownloadManagerService.MESSAGE_DELETED);
mission.storage = null;
mission.delete();
}
@ -374,35 +367,29 @@ public class DownloadManager {
}
public void pauseAllMissions(boolean force) {
boolean flag = false;
synchronized (this) {
for (DownloadMission mission : mMissionsPending) {
if (!mission.running || mission.isPsRunning() || mission.isFinished()) continue;
if (force) mission.threads = null;// avoid waiting for threads
if (force) {
// avoid waiting for threads
mission.init = null;
mission.threads = new Thread[0];
}
mission.pause();
flag = true;
}
}
if (flag) mHandler.sendEmptyMessage(DownloadManagerService.MESSAGE_PAUSED);
}
public void startAllMissions() {
boolean flag = false;
synchronized (this) {
for (DownloadMission mission : mMissionsPending) {
if (mission.running || mission.isCorrupt()) continue;
flag = true;
mission.start();
}
}
if (flag) mHandler.sendEmptyMessage(DownloadManagerService.MESSAGE_PROGRESS);
}
/**
@ -483,28 +470,18 @@ public class DownloadManager {
boolean isMetered = mPrefMeteredDownloads && mLastNetworkStatus == NetworkState.MeteredOperating;
int running = 0;
int paused = 0;
synchronized (this) {
for (DownloadMission mission : mMissionsPending) {
if (mission.isCorrupt() || mission.isPsRunning()) continue;
if (mission.running && isMetered) {
paused++;
mission.pause();
} else if (!mission.running && !isMetered && mission.enqueued) {
running++;
mission.start();
if (mPrefQueueLimit) break;
}
}
}
if (running > 0) {
mHandler.sendEmptyMessage(DownloadManagerService.MESSAGE_PROGRESS);
return;
}
if (paused > 0) mHandler.sendEmptyMessage(DownloadManagerService.MESSAGE_PAUSED);
}
void updateMaximumAttempts() {
@ -513,22 +490,6 @@ public class DownloadManager {
}
}
/**
* Fast check for pending downloads. If exists, the user will be notified
* TODO: call this method in somewhere
*
* @param context the application context
*/
public static void notifyUserPendingDownloads(Context context) {
int pending = getPendingDir(context).list().length;
if (pending < 1) return;
Toast.makeText(context, context.getString(
R.string.msg_pending_downloads,
String.valueOf(pending)
), Toast.LENGTH_LONG).show();
}
public MissionState checkForExistingMission(StoredFileHelper storage) {
synchronized (this) {
DownloadMission pending = getPendingMission(storage);

View file

@ -25,14 +25,15 @@ import android.os.IBinder;
import android.os.Message;
import android.os.Parcelable;
import android.preference.PreferenceManager;
import android.util.Log;
import android.util.SparseArray;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationCompat.Builder;
import android.util.Log;
import android.util.SparseArray;
import android.widget.Toast;
import org.schabi.newpipe.R;
import org.schabi.newpipe.download.DownloadActivity;
@ -41,8 +42,6 @@ import org.schabi.newpipe.player.helper.LockManager;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import us.shandian.giga.get.DownloadMission;
import us.shandian.giga.get.MissionRecoveryInfo;
@ -58,11 +57,11 @@ public class DownloadManagerService extends Service {
private static final String TAG = "DownloadManagerService";
public static final int MESSAGE_RUNNING = 0;
public static final int MESSAGE_PAUSED = 1;
public static final int MESSAGE_FINISHED = 2;
public static final int MESSAGE_PROGRESS = 3;
public static final int MESSAGE_ERROR = 4;
public static final int MESSAGE_DELETED = 5;
public static final int MESSAGE_ERROR = 3;
public static final int MESSAGE_DELETED = 4;
private static final int FOREGROUND_NOTIFICATION_ID = 1000;
private static final int DOWNLOADS_NOTIFICATION_ID = 1001;
@ -217,9 +216,11 @@ public class DownloadManagerService extends Service {
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
);
}
return START_NOT_STICKY;
}
}
return START_NOT_STICKY;
return START_STICKY;
}
@Override
@ -250,6 +251,7 @@ public class DownloadManagerService extends Service {
if (icDownloadFailed != null) icDownloadFailed.recycle();
if (icLauncher != null) icLauncher.recycle();
mHandler = null;
mManager.pauseAllMissions(true);
}
@ -274,6 +276,8 @@ public class DownloadManagerService extends Service {
}
private boolean handleMessage(@NonNull Message msg) {
if (mHandler == null) return true;
DownloadMission mission = (DownloadMission) msg.obj;
switch (msg.what) {
@ -284,7 +288,7 @@ public class DownloadManagerService extends Service {
handleConnectivityState(false);
updateForegroundState(mManager.runMissions());
break;
case MESSAGE_PROGRESS:
case MESSAGE_RUNNING:
updateForegroundState(true);
break;
case MESSAGE_ERROR:
@ -300,11 +304,8 @@ public class DownloadManagerService extends Service {
if (msg.what != MESSAGE_ERROR)
mFailedDownloads.delete(mFailedDownloads.indexOfValue(mission));
synchronized (mEchoObservers) {
for (Callback observer : mEchoObservers) {
observer.handleMessage(msg);
}
}
for (Callback observer : mEchoObservers)
observer.handleMessage(msg);
return true;
}
@ -523,16 +524,6 @@ public class DownloadManagerService extends Service {
return PendingIntent.getService(this, intent.hashCode(), intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
private void manageObservers(Callback handler, boolean add) {
synchronized (mEchoObservers) {
if (add) {
mEchoObservers.add(handler);
} else {
mEchoObservers.remove(handler);
}
}
}
private void manageLock(boolean acquire) {
if (acquire == mLockAcquired) return;
@ -605,11 +596,11 @@ public class DownloadManagerService extends Service {
}
public void addMissionEventListener(Callback handler) {
manageObservers(handler, true);
mEchoObservers.add(handler);
}
public void removeMissionEventListener(Callback handler) {
manageObservers(handler, false);
mEchoObservers.remove(handler);
}
public void clearDownloadNotifications() {