From f3d4d4747a162c23da1669514ad2213752705ec1 Mon Sep 17 00:00:00 2001 From: kapodamy Date: Sat, 24 Nov 2018 00:14:37 -0300 Subject: [PATCH] and more fixes * fix content length reading * use float overflow. Expensive, double is used instead * fix invalid cast after click the mission body * use a list for maximum attemps (downloads) * minor clean up (DownloadManager.java) * dont pass SharedPreferences instace to DownloadManager * use a switch instead of checkbox for cross_network_downloads * notify media scanner after deleting a finished download --- .../newpipe/download/DownloadDialog.java | 19 +++++++- .../giga/get/DownloadInitializer.java | 6 ++- .../us/shandian/giga/get/DownloadMission.java | 6 +-- .../shandian/giga/get/DownloadRunnable.java | 2 +- .../giga/get/DownloadRunnableFallback.java | 15 +++++-- .../giga/service/DownloadManager.java | 44 ++++++++----------- .../giga/service/DownloadManagerService.java | 7 ++- .../giga/ui/adapter/MissionAdapter.java | 14 +++--- .../us/shandian/giga/ui/common/Deleter.java | 9 +++- .../java/us/shandian/giga/util/Utility.java | 23 ++++++++-- app/src/main/res/values/settings_keys.xml | 11 +++++ app/src/main/res/xml/download_settings.xml | 7 +-- 12 files changed, 111 insertions(+), 52 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java b/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java index ace143b13..0418eadae 100644 --- a/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java +++ b/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java @@ -404,11 +404,26 @@ public class DownloadDialog extends DialogFragment implements RadioGroup.OnCheck private int getSubtitleIndexBy(List streams) { Localization loc = NewPipe.getPreferredLocalization(); + + for (int i = 0; i < streams.size(); i++) { + Locale streamLocale = streams.get(i).getLocale(); + String tag = streamLocale.getLanguage().concat("-").concat(streamLocale.getCountry()); + if (tag.equalsIgnoreCase(loc.getLanguage())) { + return i; + } + } + + // fallback + // 1st loop match country & language + // 2nd loop match language only + String lang = loc.getLanguage().substring(0, loc.getLanguage().indexOf("-")); + for (int j = 0; j < 2; j++) { for (int i = 0; i < streams.size(); i++) { Locale streamLocale = streams.get(i).getLocale(); - if (streamLocale.getLanguage().equals(loc.getLanguage())) { - if (j > 0 || streamLocale.getCountry().equals(loc.getCountry())) { + + if (streamLocale.getLanguage().equalsIgnoreCase(lang)) { + if (j > 0 || streamLocale.getCountry().equalsIgnoreCase(loc.getCountry())) { return i; } } diff --git a/app/src/main/java/us/shandian/giga/get/DownloadInitializer.java b/app/src/main/java/us/shandian/giga/get/DownloadInitializer.java index 2ea097062..298e7be37 100644 --- a/app/src/main/java/us/shandian/giga/get/DownloadInitializer.java +++ b/app/src/main/java/us/shandian/giga/get/DownloadInitializer.java @@ -35,7 +35,9 @@ public class DownloadInitializer implements Runnable { HttpURLConnection conn = mMission.openConnection(mId, -1, -1); if (!mMission.running || Thread.interrupted()) return; - mMission.length = conn.getContentLength(); + mMission.length = Utility.getContentLength(conn); + + if (mMission.length == 0) { mMission.notifyError(DownloadMission.ERROR_HTTP_NO_CONTENT, null); return; @@ -97,7 +99,7 @@ public class DownloadInitializer implements Runnable { for (long i = 0; i < mMission.currentThreadCount; i++) { mMission.threadBlockPositions.add(i); - mMission.threadBytePositions.add(0); + mMission.threadBytePositions.add(0L); } File file; 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 8e34981cc..851b5cb1b 100644 --- a/app/src/main/java/us/shandian/giga/get/DownloadMission.java +++ b/app/src/main/java/us/shandian/giga/get/DownloadMission.java @@ -124,7 +124,7 @@ public class DownloadMission extends Mission { @SuppressWarnings("UseSparseArrays")// LongSparseArray is not serializable private final HashMap blockState = new HashMap<>(); final List threadBlockPositions = new ArrayList<>(); - final List threadBytePositions = new ArrayList<>(); + final List threadBytePositions = new ArrayList<>(); private transient boolean deleted; int currentThreadCount; @@ -216,7 +216,7 @@ public class DownloadMission extends Mission { * @param threadId the identifier of the thread * @param position the relative position in bytes or zero */ - void setThreadBytePosition(int threadId, int position) { + void setThreadBytePosition(int threadId, long position) { threadBytePositions.set(threadId, position); } @@ -226,7 +226,7 @@ public class DownloadMission extends Mission { * @param threadId the identifier of the thread * @return the relative position in bytes or zero */ - int getBlockBytePosition(int threadId) { + long getBlockBytePosition(int threadId) { return threadBytePositions.get(threadId); } diff --git a/app/src/main/java/us/shandian/giga/get/DownloadRunnable.java b/app/src/main/java/us/shandian/giga/get/DownloadRunnable.java index b6617cfa4..95f4758f9 100644 --- a/app/src/main/java/us/shandian/giga/get/DownloadRunnable.java +++ b/app/src/main/java/us/shandian/giga/get/DownloadRunnable.java @@ -89,7 +89,7 @@ public class DownloadRunnable implements Runnable { end = mMission.length - 1; } - int total = 0; + long total = 0; try { HttpURLConnection conn = mMission.openConnection(mId, start, end); diff --git a/app/src/main/java/us/shandian/giga/get/DownloadRunnableFallback.java b/app/src/main/java/us/shandian/giga/get/DownloadRunnableFallback.java index c484f5158..b648dd812 100644 --- a/app/src/main/java/us/shandian/giga/get/DownloadRunnableFallback.java +++ b/app/src/main/java/us/shandian/giga/get/DownloadRunnableFallback.java @@ -1,5 +1,6 @@ package us.shandian.giga.get; +import android.annotation.SuppressLint; import android.support.annotation.NonNull; import android.util.Log; @@ -10,9 +11,13 @@ import java.net.HttpURLConnection; import java.nio.channels.ClosedByInterruptException; +import us.shandian.giga.util.Utility; + import static org.schabi.newpipe.BuildConfig.DEBUG; -// Single-threaded fallback mode +/** + * Single-threaded fallback mode + */ public class DownloadRunnableFallback implements Runnable { private static final String TAG = "DownloadRunnableFallback"; @@ -43,10 +48,11 @@ public class DownloadRunnableFallback implements Runnable { } @Override + @SuppressLint("LongLogTag") public void run() { boolean done; - int start = 0; + long start = 0; if (!mMission.unknownLength) { start = mMission.getBlockBytePosition(0); @@ -56,11 +62,12 @@ public class DownloadRunnableFallback implements Runnable { } try { - int rangeStart = (mMission.unknownLength || start < 1) ? -1 : start; + long rangeStart = (mMission.unknownLength || start < 1) ? -1 : start; HttpURLConnection conn = mMission.openConnection(1, rangeStart, -1); // secondary check for the file length - if (!mMission.unknownLength) mMission.unknownLength = conn.getContentLength() == -1; + if (!mMission.unknownLength) + mMission.unknownLength = Utility.getContentLength(conn) == -1; f = new RandomAccessFile(mMission.getDownloadedFile(), "rw"); f.seek(mMission.offsets[mMission.current] + start); 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 52b49a0ae..31b5b16a9 100644 --- a/app/src/main/java/us/shandian/giga/service/DownloadManager.java +++ b/app/src/main/java/us/shandian/giga/service/DownloadManager.java @@ -1,9 +1,7 @@ package us.shandian.giga.service; import android.content.Context; -import android.content.SharedPreferences; import android.os.Handler; -import android.preference.PreferenceManager; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v7.util.DiffUtil; @@ -46,9 +44,8 @@ public class DownloadManager { private NetworkState mLastNetworkStatus = NetworkState.Unavailable; - private SharedPreferences mPrefs; - private String mPrefMaxRetry; - private String mPrefCrossNetwork; + int mPrefMaxRetry; + boolean mPrefCrossNetwork; /** * Create a new instance @@ -65,9 +62,6 @@ public class DownloadManager { mHandler = handler; mMissionsFinished = loadFinishedMissions(); mPendingMissionsDir = getPendingDir(context); - mPrefs = PreferenceManager.getDefaultSharedPreferences(context); - mPrefMaxRetry = context.getString(R.string.downloads_max_retry); - mPrefCrossNetwork = context.getString(R.string.cross_network_downloads); if (!Utility.mkdir(mPendingMissionsDir, false)) { throw new RuntimeException("failed to create pending_downloads in data directory"); @@ -196,17 +190,17 @@ public class DownloadManager { /** * Start a new download mission * - * @param urls the list of urls to download - * @param location the location - * @param name the name of the file to create - * @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 postprocessingName the name of the required post-processing algorithm, or {@code null} to ignore. - * @param source source url of the resource - * @param postProcessingArgs the arguments for the post-processing algorithm. + * @param urls the list of urls to download + * @param location the location + * @param name the name of the file to create + * @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 psName the name of the required post-processing algorithm, or {@code null} to ignore. + * @param source source url of the resource + * @param psArgs the arguments for the post-processing algorithm. */ - void startMission(String[] urls, String location, String name, char kind, int threads, String source, - String postprocessingName, String[] postProcessingArgs, long nearLength) { + void startMission(String[] urls, String location, String name, char kind, int threads, + String source, String psName, String[] psArgs, long nearLength) { synchronized (this) { // check for existing pending download DownloadMission pendingMission = getPendingMission(location, name); @@ -225,12 +219,12 @@ public class DownloadManager { if (index >= 0) mDownloadDataSource.deleteMission(mMissionsFinished.remove(index)); } - DownloadMission mission = new DownloadMission(urls, name, location, kind, postprocessingName, postProcessingArgs); + DownloadMission mission = new DownloadMission(urls, name, location, kind, psName, psArgs); mission.timestamp = System.currentTimeMillis(); mission.threadCount = threads; mission.source = source; mission.mHandler = mHandler; - mission.maxRetry = mPrefs.getInt(mPrefMaxRetry, 3); + mission.maxRetry = mPrefMaxRetry; mission.nearLength = nearLength; while (true) { @@ -420,6 +414,7 @@ public class DownloadManager { /** * runs another mission in queue if possible + * * @return true if exits pending missions running or a mission was started, otherwise, false */ boolean runAnotherMission() { @@ -460,18 +455,17 @@ public class DownloadManager { private boolean canDownloadInCurrentNetwork() { if (mLastNetworkStatus == NetworkState.Unavailable) return false; - return !(mPrefs.getBoolean(mPrefCrossNetwork, false) && mLastNetworkStatus == NetworkState.MobileOperating); + return !(mPrefCrossNetwork && mLastNetworkStatus == NetworkState.MobileOperating); } void handleConnectivityChange(NetworkState currentStatus) { if (currentStatus == mLastNetworkStatus) return; mLastNetworkStatus = currentStatus; - boolean pauseOnMobile = mPrefs.getBoolean(mPrefCrossNetwork, false); if (currentStatus == NetworkState.Unavailable) { return; - } else if (currentStatus != NetworkState.MobileOperating || !pauseOnMobile) { + } else if (currentStatus != NetworkState.MobileOperating || !mPrefCrossNetwork) { return; } @@ -488,9 +482,9 @@ public class DownloadManager { if (flag) mHandler.sendEmptyMessage(DownloadManagerService.MESSAGE_PAUSED); } - void updateMaximumAttempts(int maxRetry) { + void updateMaximumAttempts() { synchronized (this) { - for (DownloadMission mission : mMissionsPending) mission.maxRetry = maxRetry; + for (DownloadMission mission : mMissionsPending) mission.maxRetry = mPrefMaxRetry; } } 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 52485e9d8..7b30740d5 100755 --- a/app/src/main/java/us/shandian/giga/service/DownloadManagerService.java +++ b/app/src/main/java/us/shandian/giga/service/DownloadManagerService.java @@ -306,7 +306,12 @@ public class DownloadManagerService extends Service { private void handlePreferenceChange(SharedPreferences prefs, String key) { if (key.equals(getString(R.string.downloads_max_retry))) { - mManager.updateMaximumAttempts(prefs.getInt(key, 3)); + mManager.mPrefMaxRetry = Integer.parseInt( + prefs.getString(key, getString(R.string.default_max_retry)) + ); + mManager.updateMaximumAttempts(); + } else if (key.equals(getString(R.string.cross_network_downloads))) { + mManager.mPrefCrossNetwork = prefs.getBoolean(key, 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 c4eb663f9..4dc40c420 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 @@ -183,6 +183,7 @@ public class MissionAdapter extends RecyclerView.Adapter { return mIterator.getSpecialAtItem(position); } + @SuppressLint("DefaultLocale") private void updateProgress(ViewHolderItem h) { if (h == null || h.item == null || h.item.mission instanceof FinishedMission) return; @@ -216,14 +217,15 @@ public class MissionAdapter extends RecyclerView.Adapter { progress = Float.NaN; h.progress.setProgress(0f); } else { - progress = (float) mission.done / mission.length; + progress = (float) ((double) mission.done / mission.length); if (mission.urls.length > 1 && mission.current < mission.urls.length) { progress = (progress / mission.urls.length) + ((float) mission.current / mission.urls.length); } } if (hasError) { - if (Float.isNaN(progress) || Float.isInfinite(progress)) h.progress.setProgress(1f); + if (Float.isNaN(progress) || Float.isInfinite(progress)) + h.progress.setProgress(1f); h.status.setText(R.string.msg_error); } else if (Float.isNaN(progress) || Float.isInfinite(progress)) { h.status.setText("--.-%"); @@ -275,7 +277,7 @@ public class MissionAdapter extends RecyclerView.Adapter { if (deltaTime > 1000 && deltaDone > 0) { - float speed = (float) deltaDone / deltaTime; + float speed = (float) ((double) deltaDone / deltaTime); String speedStr = Utility.formatSpeed(speed * 1000); String sizeStr = Utility.formatBytes(length); @@ -497,7 +499,7 @@ public class MissionAdapter extends RecyclerView.Adapter { mIterator.start(); mIterator.end(); - for (ViewHolderItem item: mPendingDownloadsItems) { + for (ViewHolderItem item : mPendingDownloadsItems) { item.lastTimeStamp = -1; } @@ -592,11 +594,9 @@ public class MissionAdapter extends RecyclerView.Adapter { checksum = menu.findItem(R.id.checksum); itemView.setOnClickListener((v) -> { - if (((DownloadMission) item.mission).isFinished()) + if (item.mission instanceof FinishedMission) viewWithFileProvider(item.mission.getDownloadedFile()); }); - - //h.itemView.setOnClickListener(v -> showDetail(h)); } private void showPopupMenu() { diff --git a/app/src/main/java/us/shandian/giga/ui/common/Deleter.java b/app/src/main/java/us/shandian/giga/ui/common/Deleter.java index c56e1c703..6407ab019 100644 --- a/app/src/main/java/us/shandian/giga/ui/common/Deleter.java +++ b/app/src/main/java/us/shandian/giga/ui/common/Deleter.java @@ -1,7 +1,9 @@ package us.shandian.giga.ui.common; import android.content.Context; +import android.content.Intent; import android.graphics.Color; +import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.support.design.widget.Snackbar; @@ -11,6 +13,7 @@ import org.schabi.newpipe.R; import java.util.ArrayList; +import us.shandian.giga.get.FinishedMission; import us.shandian.giga.get.Mission; import us.shandian.giga.service.DownloadManager; import us.shandian.giga.service.DownloadManager.MissionIterator; @@ -120,6 +123,10 @@ public class Deleter { mIterator.unHide(mission); mDownloadManager.deleteMission(mission); + + if (mission instanceof FinishedMission) { + mContext.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(mission.getDownloadedFile()))); + } break; } @@ -167,4 +174,4 @@ public class Deleter { bundle.putStringArray(BUNDLE_NAMES, names); bundle.putStringArray(BUNDLE_LOCATIONS, locations); } -} \ No newline at end of file +} diff --git a/app/src/main/java/us/shandian/giga/util/Utility.java b/app/src/main/java/us/shandian/giga/util/Utility.java index 6cd5ef2c5..e5149cf9b 100644 --- a/app/src/main/java/us/shandian/giga/util/Utility.java +++ b/app/src/main/java/us/shandian/giga/util/Utility.java @@ -3,6 +3,7 @@ package us.shandian.giga.util; import android.content.ClipData; import android.content.ClipboardManager; import android.content.Context; +import android.os.Build; import android.support.annotation.ColorInt; import android.support.annotation.DrawableRes; import android.support.annotation.NonNull; @@ -21,6 +22,7 @@ import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; +import java.net.HttpURLConnection; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Locale; @@ -38,11 +40,11 @@ public class Utility { if (bytes < 1024) { return String.format("%d B", bytes); } else if (bytes < 1024 * 1024) { - return String.format("%.2f kB", (float) bytes / 1024); + return String.format("%.2f kB", bytes / 1024d); } else if (bytes < 1024 * 1024 * 1024) { - return String.format("%.2f MB", (float) bytes / 1024 / 1024); + return String.format("%.2f MB", bytes / 1024d / 1024d); } else { - return String.format("%.2f GB", (float) bytes / 1024 / 1024 / 1024); + return String.format("%.2f GB", bytes / 1024d / 1024d / 1024d); } } @@ -255,4 +257,19 @@ public class Utility { return path.exists(); } + + public static long getContentLength(HttpURLConnection connection) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + return connection.getContentLengthLong(); + } + + try { + long length = Long.parseLong(connection.getHeaderField("Content-Length")); + if (length >= 0) return length; + } catch (Exception err) { + // nothing to do + } + + return -1; + } } diff --git a/app/src/main/res/values/settings_keys.xml b/app/src/main/res/values/settings_keys.xml index 7234a6639..2973b69ef 100644 --- a/app/src/main/res/values/settings_keys.xml +++ b/app/src/main/res/values/settings_keys.xml @@ -176,6 +176,17 @@ @string/charset_most_special_characters_value downloads_max_retry + + 1 + 2 + 3 + 4 + 5 + 7 + 10 + 15 + + 3 cross_network_downloads diff --git a/app/src/main/res/xml/download_settings.xml b/app/src/main/res/xml/download_settings.xml index ed38acbb7..7175ae711 100644 --- a/app/src/main/res/xml/download_settings.xml +++ b/app/src/main/res/xml/download_settings.xml @@ -29,14 +29,15 @@ android:summary="@string/settings_file_replacement_character_summary" android:title="@string/settings_file_replacement_character_title"/> - -