diff --git a/app/src/main/java/us/shandian/giga/get/DownloadMission.java b/app/src/main/java/us/shandian/giga/get/DownloadMission.java index eb96d53f4..57cd15e8c 100644 --- a/app/src/main/java/us/shandian/giga/get/DownloadMission.java +++ b/app/src/main/java/us/shandian/giga/get/DownloadMission.java @@ -1,7 +1,6 @@ package us.shandian.giga.get; import android.os.Handler; -import android.os.Message; import android.util.Log; import org.schabi.newpipe.Downloader; @@ -264,11 +263,7 @@ public class DownloadMission extends Mission { private void notify(int what) { - Message m = new Message(); - m.what = what; - m.obj = this; - - mHandler.sendMessage(m); + mHandler.obtainMessage(what, this).sendToTarget(); } synchronized void notifyProgress(long deltaLen) { @@ -408,6 +403,7 @@ public class DownloadMission extends Mission { } } + /** * Start downloading with multiple threads. */ @@ -416,14 +412,20 @@ public class DownloadMission extends Mission { // ensure that the previous state is completely paused. joinForThread(init); - if (threads != null) + if (threads != null) { for (Thread thread : threads) joinForThread(thread); + threads = null; + } running = true; errCode = ERROR_NOTHING; + if (hasInvalidStorage()) { + notifyError(ERROR_FILE_CREATION, null); + return; + } + if (current >= urls.length) { - threads = null; runAsync(1, this::notifyFinished); return; } @@ -664,7 +666,7 @@ public class DownloadMission extends Mission { * @return {@code true} is this mission its "healthy", otherwise, {@code false} */ public boolean isCorrupt() { - return (isPsFailed() || errCode == ERROR_POSTPROCESSING_HOLD) || isFinished() || hasInvalidStorage(); + return (isPsFailed() || errCode == ERROR_POSTPROCESSING_HOLD) || isFinished(); } private boolean doPostprocessing() { diff --git a/app/src/main/java/us/shandian/giga/io/StoredFileHelper.java b/app/src/main/java/us/shandian/giga/io/StoredFileHelper.java index f90a756a9..93394fb60 100644 --- a/app/src/main/java/us/shandian/giga/io/StoredFileHelper.java +++ b/app/src/main/java/us/shandian/giga/io/StoredFileHelper.java @@ -251,6 +251,7 @@ public class StoredFileHelper implements Serializable { public boolean existsAsFile() { if (source == null) return false; + // WARNING: DocumentFile.exists() and DocumentFile.isFile() methods are slow boolean exists = docFile == null ? ioFile.exists() : docFile.exists(); boolean isFile = docFile == null ? ioFile.isFile() : docFile.isFile();// ÂżdocFile.isVirtual() means is no-physical? diff --git a/app/src/main/java/us/shandian/giga/service/DownloadManager.java b/app/src/main/java/us/shandian/giga/service/DownloadManager.java index beb5e6dc9..d4f60abcd 100644 --- a/app/src/main/java/us/shandian/giga/service/DownloadManager.java +++ b/app/src/main/java/us/shandian/giga/service/DownloadManager.java @@ -424,10 +424,12 @@ public class DownloadManager { boolean flag = false; for (DownloadMission mission : mMissionsPending) { - if (mission.running || !mission.enqueued || mission.isFinished() || mission.hasInvalidStorage()) + if (mission.running || !mission.enqueued || mission.isFinished()) continue; resumeMission(mission); + if (mission.errCode != DownloadMission.ERROR_NOTHING) continue; + if (mPrefQueueLimit) return true; flag = true; } diff --git a/app/src/main/java/us/shandian/giga/service/DownloadManagerService.java b/app/src/main/java/us/shandian/giga/service/DownloadManagerService.java index 065e21b9d..4463c6825 100755 --- a/app/src/main/java/us/shandian/giga/service/DownloadManagerService.java +++ b/app/src/main/java/us/shandian/giga/service/DownloadManagerService.java @@ -9,6 +9,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; +import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.net.ConnectivityManager; @@ -19,6 +20,7 @@ import android.net.Uri; import android.os.Binder; import android.os.Build; import android.os.Handler; +import android.os.Handler.Callback; import android.os.IBinder; import android.os.Looper; import android.os.Message; @@ -88,14 +90,14 @@ public class DownloadManagerService extends Service { private Builder downloadDoneNotification = null; private StringBuilder downloadDoneList = null; - private final ArrayList mEchoObservers = new ArrayList<>(1); + private final ArrayList mEchoObservers = new ArrayList<>(1); private ConnectivityManager mConnectivityManager; private BroadcastReceiver mNetworkStateListener = null; private ConnectivityManager.NetworkCallback mNetworkStateListenerL = null; private SharedPreferences mPrefs = null; - private final SharedPreferences.OnSharedPreferenceChangeListener mPrefChangeListener = this::handlePreferenceChange; + private final OnSharedPreferenceChangeListener mPrefChangeListener = this::handlePreferenceChange; private boolean mLockAcquired = false; private LockManager mLock = null; @@ -128,12 +130,7 @@ public class DownloadManagerService extends Service { } mBinder = new DownloadManagerBinder(); - mHandler = new Handler(Looper.myLooper()) { - @Override - public void handleMessage(Message msg) { - DownloadManagerService.this.handleMessage(msg); - } - }; + mHandler = new Handler(this::handleMessage); mPrefs = PreferenceManager.getDefaultSharedPreferences(this); @@ -272,7 +269,7 @@ public class DownloadManagerService extends Service { return mBinder; } - public void handleMessage(Message msg) { + private boolean handleMessage(@NonNull Message msg) { DownloadMission mission = (DownloadMission) msg.obj; switch (msg.what) { @@ -300,14 +297,12 @@ public class DownloadManagerService extends Service { mFailedDownloads.delete(mFailedDownloads.indexOfValue(mission)); synchronized (mEchoObservers) { - for (Handler handler : mEchoObservers) { - Message echo = new Message(); - echo.what = msg.what; - echo.obj = msg.obj; - - handler.sendMessage(echo); + for (Callback observer : mEchoObservers) { + observer.handleMessage(msg); } } + + return true; } 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); } - private void manageObservers(Handler handler, boolean add) { + private void manageObservers(Callback handler, boolean add) { synchronized (mEchoObservers) { if (add) { 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); } - public void removeMissionEventListener(Handler handler) { + public void removeMissionEventListener(Callback handler) { manageObservers(handler, false); } diff --git a/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java b/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java index e53ab4f1f..62d209ee1 100644 --- a/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java +++ b/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java @@ -9,7 +9,6 @@ import android.net.Uri; import android.os.AsyncTask; import android.os.Build; import android.os.Handler; -import android.os.Looper; import android.os.Message; import android.support.annotation.NonNull; 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_HOST; -public class MissionAdapter extends Adapter { +public class MissionAdapter extends Adapter implements Handler.Callback { private static final SparseArray ALGORITHMS = new SparseArray<>(); private static final String TAG = "MissionAdapter"; private static final String UNDEFINED_PROGRESS = "--.-%"; @@ -111,21 +110,7 @@ public class MissionAdapter extends Adapter { mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); mLayout = R.layout.mission_item; - mHandler = new Handler(Looper.myLooper()) { - @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(); - } - }; + mHandler = new Handler(context.getMainLooper()); mEmptyMessage = emptyMessage; @@ -403,29 +388,40 @@ public class MissionAdapter extends Adapter { return true; } - public Handler getMessenger() { - return mHandler; - } - - private void onServiceMessage(@NonNull Message msg) { - if (msg.what == DownloadManagerService.MESSAGE_PROGRESS) { - setAutoRefresh(true); - return; + @Override + public boolean handleMessage(@NonNull Message msg) { + if (mStartButton != null && mPauseButton != null) { + checkMasterButtonsVisibility(); } - for (int i = 0; i < mPendingDownloadsItems.size(); i++) { - ViewHolderItem h = mPendingDownloadsItems.get(i); + switch (msg.what) { + 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 (msg.what == DownloadManagerService.MESSAGE_FINISHED) { // DownloadManager should mark the download as finished applyChanges(); - return; + return true; } updateProgress(h); - return; + return true; } + + return false; } private void showError(@NonNull DownloadMission mission) { @@ -563,16 +559,15 @@ public class MissionAdapter extends Adapter { updateProgress(h); return true; case R.id.retry: - if (mission.hasInvalidStorage()) { + if (mission.isPsRunning()) { + mission.psContinue(true); + } else { mDownloadManager.tryRecover(mission); if (mission.storage.isInvalid()) mRecover.tryRecover(mission); else recoverMission(mission); - - return true; } - mission.psContinue(true); return true; case R.id.cancel: mission.psContinue(false); @@ -659,9 +654,13 @@ public class MissionAdapter extends Adapter { public void checkMasterButtonsVisibility() { boolean[] state = mIterator.hasValidPendingMissions(); + setButtonVisible(mPauseButton, state[0]); + setButtonVisible(mStartButton, state[1]); + } - mPauseButton.setVisible(state[0]); - mStartButton.setVisible(state[1]); + private static void setButtonVisible(MenuItem button, boolean visible) { + if (button.isVisible() != visible) + button.setVisible(visible); } public void ensurePausedMissions() { diff --git a/app/src/main/java/us/shandian/giga/ui/fragment/MissionsFragment.java b/app/src/main/java/us/shandian/giga/ui/fragment/MissionsFragment.java index 2b2c09750..0ce245828 100644 --- a/app/src/main/java/us/shandian/giga/ui/fragment/MissionsFragment.java +++ b/app/src/main/java/us/shandian/giga/ui/fragment/MissionsFragment.java @@ -79,7 +79,7 @@ public class MissionsFragment extends Fragment { setAdapterButtons(); - mBinder.addMissionEventListener(mAdapter.getMessenger()); + mBinder.addMissionEventListener(mAdapter); mBinder.enableNotifications(false); updateList(); @@ -159,7 +159,7 @@ public class MissionsFragment extends Fragment { super.onDestroy(); if (mBinder == null || mAdapter == null) return; - mBinder.removeMissionEventListener(mAdapter.getMessenger()); + mBinder.removeMissionEventListener(mAdapter); mBinder.enableNotifications(true); mContext.unbindService(mConnection); mAdapter.deleterDispose(true); @@ -197,12 +197,10 @@ public class MissionsFragment extends Fragment { return true; case R.id.start_downloads: item.setVisible(false); - mPause.setVisible(true); mBinder.getDownloadManager().startAllMissions(); return true; case R.id.pause_downloads: item.setVisible(false); - mStart.setVisible(true); mBinder.getDownloadManager().pauseAllMissions(false); mAdapter.ensurePausedMissions();// update items view default: @@ -280,7 +278,7 @@ public class MissionsFragment extends Fragment { if (mAdapter != null) { mAdapter.deleterDispose(false); mForceUpdate = true; - mBinder.removeMissionEventListener(mAdapter.getMessenger()); + mBinder.removeMissionEventListener(mAdapter); } } @@ -296,7 +294,7 @@ public class MissionsFragment extends Fragment { mAdapter.forceUpdate(); } - mBinder.addMissionEventListener(mAdapter.getMessenger()); + mBinder.addMissionEventListener(mAdapter); mAdapter.checkMasterButtonsVisibility(); } if (mBinder != null) mBinder.enableNotifications(false);