mirror of
				https://github.com/TeamNewPipe/NewPipe
				synced 2025-10-31 23:32:59 +00:00 
			
		
		
		
	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
This commit is contained in:
		| @@ -404,11 +404,26 @@ public class DownloadDialog extends DialogFragment implements RadioGroup.OnCheck | ||||
|  | ||||
|     private int getSubtitleIndexBy(List<SubtitlesStream> 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; | ||||
|                     } | ||||
|                 } | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -124,7 +124,7 @@ public class DownloadMission extends Mission { | ||||
|     @SuppressWarnings("UseSparseArrays")// LongSparseArray is not serializable | ||||
|     private final HashMap<Long, Boolean> blockState = new HashMap<>(); | ||||
|     final List<Long> threadBlockPositions = new ArrayList<>(); | ||||
|     final List<Integer> threadBytePositions = new ArrayList<>(); | ||||
|     final List<Long> 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); | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
| @@ -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; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -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); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -183,6 +183,7 @@ public class MissionAdapter extends RecyclerView.Adapter<ViewHolder> { | ||||
|         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<ViewHolder> { | ||||
|                 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<ViewHolder> { | ||||
|  | ||||
|  | ||||
|         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<ViewHolder> { | ||||
|         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<ViewHolder> { | ||||
|             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() { | ||||
|   | ||||
| @@ -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); | ||||
|     } | ||||
| } | ||||
| } | ||||
|   | ||||
| @@ -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; | ||||
|     } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 kapodamy
					kapodamy