Changes for Android 9 (Pie)
* validate the stored file before start the mission * add warning on StoredFileHelper.java * simplify the communication between MissionAdapter and DownloadManagerService.java since shares the same looper * simplify setVisible() "start/pause all downloads" buttons logic
This commit is contained in:
parent
85d1888ba7
commit
1a643126de
|
@ -1,7 +1,6 @@
|
||||||
package us.shandian.giga.get;
|
package us.shandian.giga.get;
|
||||||
|
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Message;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import org.schabi.newpipe.Downloader;
|
import org.schabi.newpipe.Downloader;
|
||||||
|
@ -264,11 +263,7 @@ public class DownloadMission extends Mission {
|
||||||
|
|
||||||
|
|
||||||
private void notify(int what) {
|
private void notify(int what) {
|
||||||
Message m = new Message();
|
mHandler.obtainMessage(what, this).sendToTarget();
|
||||||
m.what = what;
|
|
||||||
m.obj = this;
|
|
||||||
|
|
||||||
mHandler.sendMessage(m);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized void notifyProgress(long deltaLen) {
|
synchronized void notifyProgress(long deltaLen) {
|
||||||
|
@ -408,6 +403,7 @@ public class DownloadMission extends Mission {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start downloading with multiple threads.
|
* Start downloading with multiple threads.
|
||||||
*/
|
*/
|
||||||
|
@ -416,14 +412,20 @@ public class DownloadMission extends Mission {
|
||||||
|
|
||||||
// ensure that the previous state is completely paused.
|
// ensure that the previous state is completely paused.
|
||||||
joinForThread(init);
|
joinForThread(init);
|
||||||
if (threads != null)
|
if (threads != null) {
|
||||||
for (Thread thread : threads) joinForThread(thread);
|
for (Thread thread : threads) joinForThread(thread);
|
||||||
|
threads = null;
|
||||||
|
}
|
||||||
|
|
||||||
running = true;
|
running = true;
|
||||||
errCode = ERROR_NOTHING;
|
errCode = ERROR_NOTHING;
|
||||||
|
|
||||||
|
if (hasInvalidStorage()) {
|
||||||
|
notifyError(ERROR_FILE_CREATION, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (current >= urls.length) {
|
if (current >= urls.length) {
|
||||||
threads = null;
|
|
||||||
runAsync(1, this::notifyFinished);
|
runAsync(1, this::notifyFinished);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -664,7 +666,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() {
|
||||||
return (isPsFailed() || errCode == ERROR_POSTPROCESSING_HOLD) || isFinished() || hasInvalidStorage();
|
return (isPsFailed() || errCode == ERROR_POSTPROCESSING_HOLD) || isFinished();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean doPostprocessing() {
|
private boolean doPostprocessing() {
|
||||||
|
|
|
@ -251,6 +251,7 @@ public class StoredFileHelper implements Serializable {
|
||||||
public boolean existsAsFile() {
|
public boolean existsAsFile() {
|
||||||
if (source == null) return false;
|
if (source == null) return false;
|
||||||
|
|
||||||
|
// WARNING: DocumentFile.exists() and DocumentFile.isFile() methods are slow
|
||||||
boolean exists = docFile == null ? ioFile.exists() : docFile.exists();
|
boolean exists = docFile == null ? ioFile.exists() : docFile.exists();
|
||||||
boolean isFile = docFile == null ? ioFile.isFile() : docFile.isFile();// ¿docFile.isVirtual() means is no-physical?
|
boolean isFile = docFile == null ? ioFile.isFile() : docFile.isFile();// ¿docFile.isVirtual() means is no-physical?
|
||||||
|
|
||||||
|
|
|
@ -424,10 +424,12 @@ public class DownloadManager {
|
||||||
|
|
||||||
boolean flag = false;
|
boolean flag = false;
|
||||||
for (DownloadMission mission : mMissionsPending) {
|
for (DownloadMission mission : mMissionsPending) {
|
||||||
if (mission.running || !mission.enqueued || mission.isFinished() || mission.hasInvalidStorage())
|
if (mission.running || !mission.enqueued || mission.isFinished())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
resumeMission(mission);
|
resumeMission(mission);
|
||||||
|
if (mission.errCode != DownloadMission.ERROR_NOTHING) continue;
|
||||||
|
|
||||||
if (mPrefQueueLimit) return true;
|
if (mPrefQueueLimit) return true;
|
||||||
flag = true;
|
flag = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
|
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.BitmapFactory;
|
import android.graphics.BitmapFactory;
|
||||||
import android.net.ConnectivityManager;
|
import android.net.ConnectivityManager;
|
||||||
|
@ -19,6 +20,7 @@ import android.net.Uri;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
import android.os.Handler.Callback;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
|
@ -88,14 +90,14 @@ public class DownloadManagerService extends Service {
|
||||||
private Builder downloadDoneNotification = null;
|
private Builder downloadDoneNotification = null;
|
||||||
private StringBuilder downloadDoneList = null;
|
private StringBuilder downloadDoneList = null;
|
||||||
|
|
||||||
private final ArrayList<Handler> mEchoObservers = new ArrayList<>(1);
|
private final ArrayList<Callback> mEchoObservers = new ArrayList<>(1);
|
||||||
|
|
||||||
private ConnectivityManager mConnectivityManager;
|
private ConnectivityManager mConnectivityManager;
|
||||||
private BroadcastReceiver mNetworkStateListener = null;
|
private BroadcastReceiver mNetworkStateListener = null;
|
||||||
private ConnectivityManager.NetworkCallback mNetworkStateListenerL = null;
|
private ConnectivityManager.NetworkCallback mNetworkStateListenerL = null;
|
||||||
|
|
||||||
private SharedPreferences mPrefs = null;
|
private SharedPreferences mPrefs = null;
|
||||||
private final SharedPreferences.OnSharedPreferenceChangeListener mPrefChangeListener = this::handlePreferenceChange;
|
private final OnSharedPreferenceChangeListener mPrefChangeListener = this::handlePreferenceChange;
|
||||||
|
|
||||||
private boolean mLockAcquired = false;
|
private boolean mLockAcquired = false;
|
||||||
private LockManager mLock = null;
|
private LockManager mLock = null;
|
||||||
|
@ -128,12 +130,7 @@ public class DownloadManagerService extends Service {
|
||||||
}
|
}
|
||||||
|
|
||||||
mBinder = new DownloadManagerBinder();
|
mBinder = new DownloadManagerBinder();
|
||||||
mHandler = new Handler(Looper.myLooper()) {
|
mHandler = new Handler(this::handleMessage);
|
||||||
@Override
|
|
||||||
public void handleMessage(Message msg) {
|
|
||||||
DownloadManagerService.this.handleMessage(msg);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
|
mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||||
|
|
||||||
|
@ -272,7 +269,7 @@ public class DownloadManagerService extends Service {
|
||||||
return mBinder;
|
return mBinder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handleMessage(Message msg) {
|
private boolean handleMessage(@NonNull Message msg) {
|
||||||
DownloadMission mission = (DownloadMission) msg.obj;
|
DownloadMission mission = (DownloadMission) msg.obj;
|
||||||
|
|
||||||
switch (msg.what) {
|
switch (msg.what) {
|
||||||
|
@ -300,14 +297,12 @@ public class DownloadManagerService extends Service {
|
||||||
mFailedDownloads.delete(mFailedDownloads.indexOfValue(mission));
|
mFailedDownloads.delete(mFailedDownloads.indexOfValue(mission));
|
||||||
|
|
||||||
synchronized (mEchoObservers) {
|
synchronized (mEchoObservers) {
|
||||||
for (Handler handler : mEchoObservers) {
|
for (Callback observer : mEchoObservers) {
|
||||||
Message echo = new Message();
|
observer.handleMessage(msg);
|
||||||
echo.what = msg.what;
|
|
||||||
echo.obj = msg.obj;
|
|
||||||
|
|
||||||
handler.sendMessage(echo);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleConnectivityState(boolean updateOnly) {
|
private void handleConnectivityState(boolean updateOnly) {
|
||||||
|
@ -515,7 +510,7 @@ public class DownloadManagerService extends Service {
|
||||||
return PendingIntent.getService(this, intent.hashCode(), intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
return PendingIntent.getService(this, intent.hashCode(), intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void manageObservers(Handler handler, boolean add) {
|
private void manageObservers(Callback handler, boolean add) {
|
||||||
synchronized (mEchoObservers) {
|
synchronized (mEchoObservers) {
|
||||||
if (add) {
|
if (add) {
|
||||||
mEchoObservers.add(handler);
|
mEchoObservers.add(handler);
|
||||||
|
@ -596,11 +591,11 @@ public class DownloadManagerService extends Service {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addMissionEventListener(Handler handler) {
|
public void addMissionEventListener(Callback handler) {
|
||||||
manageObservers(handler, true);
|
manageObservers(handler, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeMissionEventListener(Handler handler) {
|
public void removeMissionEventListener(Callback handler) {
|
||||||
manageObservers(handler, false);
|
manageObservers(handler, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,6 @@ import android.net.Uri;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Looper;
|
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
|
@ -77,7 +76,7 @@ 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;
|
||||||
import static us.shandian.giga.get.DownloadMission.ERROR_UNKNOWN_HOST;
|
import static us.shandian.giga.get.DownloadMission.ERROR_UNKNOWN_HOST;
|
||||||
|
|
||||||
public class MissionAdapter extends Adapter<ViewHolder> {
|
public class MissionAdapter extends Adapter<ViewHolder> implements Handler.Callback {
|
||||||
private static final SparseArray<String> ALGORITHMS = new SparseArray<>();
|
private static final SparseArray<String> ALGORITHMS = new SparseArray<>();
|
||||||
private static final String TAG = "MissionAdapter";
|
private static final String TAG = "MissionAdapter";
|
||||||
private static final String UNDEFINED_PROGRESS = "--.-%";
|
private static final String UNDEFINED_PROGRESS = "--.-%";
|
||||||
|
@ -111,21 +110,7 @@ public class MissionAdapter extends Adapter<ViewHolder> {
|
||||||
mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||||
mLayout = R.layout.mission_item;
|
mLayout = R.layout.mission_item;
|
||||||
|
|
||||||
mHandler = new Handler(Looper.myLooper()) {
|
mHandler = new Handler(context.getMainLooper());
|
||||||
@Override
|
|
||||||
public void handleMessage(Message msg) {
|
|
||||||
switch (msg.what) {
|
|
||||||
case DownloadManagerService.MESSAGE_PROGRESS:
|
|
||||||
case DownloadManagerService.MESSAGE_ERROR:
|
|
||||||
case DownloadManagerService.MESSAGE_FINISHED:
|
|
||||||
onServiceMessage(msg);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mStartButton != null && mPauseButton != null)
|
|
||||||
checkMasterButtonsVisibility();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
mEmptyMessage = emptyMessage;
|
mEmptyMessage = emptyMessage;
|
||||||
|
|
||||||
|
@ -403,29 +388,40 @@ public class MissionAdapter extends Adapter<ViewHolder> {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Handler getMessenger() {
|
@Override
|
||||||
return mHandler;
|
public boolean handleMessage(@NonNull Message msg) {
|
||||||
}
|
if (mStartButton != null && mPauseButton != null) {
|
||||||
|
checkMasterButtonsVisibility();
|
||||||
private void onServiceMessage(@NonNull Message msg) {
|
|
||||||
if (msg.what == DownloadManagerService.MESSAGE_PROGRESS) {
|
|
||||||
setAutoRefresh(true);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < mPendingDownloadsItems.size(); i++) {
|
switch (msg.what) {
|
||||||
ViewHolderItem h = mPendingDownloadsItems.get(i);
|
case DownloadManagerService.MESSAGE_PROGRESS:
|
||||||
|
case DownloadManagerService.MESSAGE_ERROR:
|
||||||
|
case DownloadManagerService.MESSAGE_FINISHED:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msg.what == DownloadManagerService.MESSAGE_PROGRESS) {
|
||||||
|
setAutoRefresh(true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ViewHolderItem h : mPendingDownloadsItems) {
|
||||||
if (h.item.mission != msg.obj) continue;
|
if (h.item.mission != msg.obj) continue;
|
||||||
|
|
||||||
if (msg.what == DownloadManagerService.MESSAGE_FINISHED) {
|
if (msg.what == DownloadManagerService.MESSAGE_FINISHED) {
|
||||||
// DownloadManager should mark the download as finished
|
// DownloadManager should mark the download as finished
|
||||||
applyChanges();
|
applyChanges();
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateProgress(h);
|
updateProgress(h);
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showError(@NonNull DownloadMission mission) {
|
private void showError(@NonNull DownloadMission mission) {
|
||||||
|
@ -563,16 +559,15 @@ public class MissionAdapter extends Adapter<ViewHolder> {
|
||||||
updateProgress(h);
|
updateProgress(h);
|
||||||
return true;
|
return true;
|
||||||
case R.id.retry:
|
case R.id.retry:
|
||||||
if (mission.hasInvalidStorage()) {
|
if (mission.isPsRunning()) {
|
||||||
|
mission.psContinue(true);
|
||||||
|
} else {
|
||||||
mDownloadManager.tryRecover(mission);
|
mDownloadManager.tryRecover(mission);
|
||||||
if (mission.storage.isInvalid())
|
if (mission.storage.isInvalid())
|
||||||
mRecover.tryRecover(mission);
|
mRecover.tryRecover(mission);
|
||||||
else
|
else
|
||||||
recoverMission(mission);
|
recoverMission(mission);
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
mission.psContinue(true);
|
|
||||||
return true;
|
return true;
|
||||||
case R.id.cancel:
|
case R.id.cancel:
|
||||||
mission.psContinue(false);
|
mission.psContinue(false);
|
||||||
|
@ -659,9 +654,13 @@ public class MissionAdapter extends Adapter<ViewHolder> {
|
||||||
|
|
||||||
public void checkMasterButtonsVisibility() {
|
public void checkMasterButtonsVisibility() {
|
||||||
boolean[] state = mIterator.hasValidPendingMissions();
|
boolean[] state = mIterator.hasValidPendingMissions();
|
||||||
|
setButtonVisible(mPauseButton, state[0]);
|
||||||
|
setButtonVisible(mStartButton, state[1]);
|
||||||
|
}
|
||||||
|
|
||||||
mPauseButton.setVisible(state[0]);
|
private static void setButtonVisible(MenuItem button, boolean visible) {
|
||||||
mStartButton.setVisible(state[1]);
|
if (button.isVisible() != visible)
|
||||||
|
button.setVisible(visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ensurePausedMissions() {
|
public void ensurePausedMissions() {
|
||||||
|
|
|
@ -79,7 +79,7 @@ public class MissionsFragment extends Fragment {
|
||||||
|
|
||||||
setAdapterButtons();
|
setAdapterButtons();
|
||||||
|
|
||||||
mBinder.addMissionEventListener(mAdapter.getMessenger());
|
mBinder.addMissionEventListener(mAdapter);
|
||||||
mBinder.enableNotifications(false);
|
mBinder.enableNotifications(false);
|
||||||
|
|
||||||
updateList();
|
updateList();
|
||||||
|
@ -159,7 +159,7 @@ public class MissionsFragment extends Fragment {
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
if (mBinder == null || mAdapter == null) return;
|
if (mBinder == null || mAdapter == null) return;
|
||||||
|
|
||||||
mBinder.removeMissionEventListener(mAdapter.getMessenger());
|
mBinder.removeMissionEventListener(mAdapter);
|
||||||
mBinder.enableNotifications(true);
|
mBinder.enableNotifications(true);
|
||||||
mContext.unbindService(mConnection);
|
mContext.unbindService(mConnection);
|
||||||
mAdapter.deleterDispose(true);
|
mAdapter.deleterDispose(true);
|
||||||
|
@ -197,12 +197,10 @@ public class MissionsFragment extends Fragment {
|
||||||
return true;
|
return true;
|
||||||
case R.id.start_downloads:
|
case R.id.start_downloads:
|
||||||
item.setVisible(false);
|
item.setVisible(false);
|
||||||
mPause.setVisible(true);
|
|
||||||
mBinder.getDownloadManager().startAllMissions();
|
mBinder.getDownloadManager().startAllMissions();
|
||||||
return true;
|
return true;
|
||||||
case R.id.pause_downloads:
|
case R.id.pause_downloads:
|
||||||
item.setVisible(false);
|
item.setVisible(false);
|
||||||
mStart.setVisible(true);
|
|
||||||
mBinder.getDownloadManager().pauseAllMissions(false);
|
mBinder.getDownloadManager().pauseAllMissions(false);
|
||||||
mAdapter.ensurePausedMissions();// update items view
|
mAdapter.ensurePausedMissions();// update items view
|
||||||
default:
|
default:
|
||||||
|
@ -280,7 +278,7 @@ public class MissionsFragment extends Fragment {
|
||||||
if (mAdapter != null) {
|
if (mAdapter != null) {
|
||||||
mAdapter.deleterDispose(false);
|
mAdapter.deleterDispose(false);
|
||||||
mForceUpdate = true;
|
mForceUpdate = true;
|
||||||
mBinder.removeMissionEventListener(mAdapter.getMessenger());
|
mBinder.removeMissionEventListener(mAdapter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -296,7 +294,7 @@ public class MissionsFragment extends Fragment {
|
||||||
mAdapter.forceUpdate();
|
mAdapter.forceUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
mBinder.addMissionEventListener(mAdapter.getMessenger());
|
mBinder.addMissionEventListener(mAdapter);
|
||||||
mAdapter.checkMasterButtonsVisibility();
|
mAdapter.checkMasterButtonsVisibility();
|
||||||
}
|
}
|
||||||
if (mBinder != null) mBinder.enableNotifications(false);
|
if (mBinder != null) mBinder.enableNotifications(false);
|
||||||
|
|
Loading…
Reference in New Issue