From d1b0cd74be873acc2a23b93836c41bbe10cd6a9f Mon Sep 17 00:00:00 2001 From: James Straub Date: Sat, 21 Apr 2018 12:35:04 -0400 Subject: [PATCH 01/80] Added the ability to limit video quality if using mobile data. * Added a dropdown to video & audio settings * Changes to ListHelper: ** Limits resolution when code requests the default video resolution ** Limits audio bitrate when code requests the default audio bitrate ** Removed some dead code and did some cleanup ** Make methods private/protected to help understand what was in use ** The code now chooses one format over an other using a simple raking system defined in array constants. I realized I needed to do this in order to choose the most efficient video stream. I did my best to evaluate the video and audio formats based on quality and efficiency. It's not an exact science. ** Made changes to the tests to support my changes --- .../newpipe/player/MainVideoPlayer.java | 2 +- .../newpipe/player/PopupVideoPlayer.java | 2 +- .../org/schabi/newpipe/util/ListHelper.java | 383 +++++++++++++----- app/src/main/res/values/settings_keys.xml | 28 ++ app/src/main/res/values/strings.xml | 2 + app/src/main/res/xml/video_audio_settings.xml | 10 +- .../schabi/newpipe/util/ListHelperTest.java | 124 +++++- 7 files changed, 432 insertions(+), 119 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/MainVideoPlayer.java b/app/src/main/java/org/schabi/newpipe/player/MainVideoPlayer.java index aedcdb791..33832b7a2 100644 --- a/app/src/main/java/org/schabi/newpipe/player/MainVideoPlayer.java +++ b/app/src/main/java/org/schabi/newpipe/player/MainVideoPlayer.java @@ -645,7 +645,7 @@ public final class MainVideoPlayer extends AppCompatActivity @Override protected int getOverrideResolutionIndex(final List sortedVideos, final String playbackQuality) { - return ListHelper.getDefaultResolutionIndex(context, sortedVideos, playbackQuality); + return ListHelper.getResolutionIndex(context, sortedVideos, playbackQuality); } /*////////////////////////////////////////////////////////////////////////// diff --git a/app/src/main/java/org/schabi/newpipe/player/PopupVideoPlayer.java b/app/src/main/java/org/schabi/newpipe/player/PopupVideoPlayer.java index 9528bf2bc..d7eee46d1 100644 --- a/app/src/main/java/org/schabi/newpipe/player/PopupVideoPlayer.java +++ b/app/src/main/java/org/schabi/newpipe/player/PopupVideoPlayer.java @@ -509,7 +509,7 @@ public final class PopupVideoPlayer extends Service { @Override protected int getOverrideResolutionIndex(final List sortedVideos, final String playbackQuality) { - return ListHelper.getPopupDefaultResolutionIndex(context, sortedVideos, playbackQuality); + return ListHelper.getPopupResolutionIndex(context, sortedVideos, playbackQuality); } /*////////////////////////////////////////////////////////////////////////// diff --git a/app/src/main/java/org/schabi/newpipe/util/ListHelper.java b/app/src/main/java/org/schabi/newpipe/util/ListHelper.java index 79fd1e496..93d20e22e 100644 --- a/app/src/main/java/org/schabi/newpipe/util/ListHelper.java +++ b/app/src/main/java/org/schabi/newpipe/util/ListHelper.java @@ -2,6 +2,7 @@ package org.schabi.newpipe.util; import android.content.Context; import android.content.SharedPreferences; +import android.net.ConnectivityManager; import android.preference.PreferenceManager; import android.support.annotation.StringRes; @@ -13,56 +14,38 @@ import org.schabi.newpipe.extractor.stream.VideoStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; -import java.util.Comparator; import java.util.HashMap; import java.util.List; @SuppressWarnings("WeakerAccess") public final class ListHelper { + // Video format in order of quality. 0=lowest quality, n=highest quality + private static final List VIDEO_FORMAT_QUALITY_RANKING = + Arrays.asList(MediaFormat.v3GPP, MediaFormat.WEBM, MediaFormat.MPEG_4); + + // Audio format in order of quality. 0=lowest quality, n=highest quality + private static final List AUDIO_FORMAT_QUALITY_RANKING = + Arrays.asList(MediaFormat.MP3, MediaFormat.WEBMA, MediaFormat.M4A); + // Audio format in order of efficiency. 0=most efficient, n=least efficient + private static final List AUDIO_FORMAT_EFFICIENCY_RANKING = + Arrays.asList(MediaFormat.WEBMA, MediaFormat.M4A, MediaFormat.MP3); + private static final List HIGH_RESOLUTION_LIST = Arrays.asList("1440p", "2160p", "1440p60", "2160p60"); - /** - * Return the index of the default stream in the list, based on the parameters - * defaultResolution and defaultFormat - * - * @return index of the default resolution&format - */ - public static int getDefaultResolutionIndex(String defaultResolution, String bestResolutionKey, MediaFormat defaultFormat, List videoStreams) { - if (videoStreams == null || videoStreams.isEmpty()) return -1; - - sortStreamList(videoStreams, false); - if (defaultResolution.equals(bestResolutionKey)) { - return 0; - } - - int defaultStreamIndex = getDefaultStreamIndex(defaultResolution, defaultFormat, videoStreams); - if (defaultStreamIndex == -1 && defaultResolution.contains("p60")) { - defaultStreamIndex = getDefaultStreamIndex(defaultResolution.replace("p60", "p"), defaultFormat, videoStreams); - } - - // this is actually an error, - // but maybe there is really no stream fitting to the default value. - if (defaultStreamIndex == -1) return 0; - - return defaultStreamIndex; - } - /** * @see #getDefaultResolutionIndex(String, String, MediaFormat, List) */ public static int getDefaultResolutionIndex(Context context, List videoStreams) { - SharedPreferences defaultPreferences = PreferenceManager.getDefaultSharedPreferences(context); - if (defaultPreferences == null) return 0; - - String defaultResolution = defaultPreferences.getString(context.getString(R.string.default_resolution_key), context.getString(R.string.default_resolution_value)); - return getDefaultResolutionIndex(context, videoStreams, defaultResolution); + String defaultResolution = computeDefaultResolution(context, + R.string.default_resolution_key, R.string.default_resolution_value); + return getDefaultResolutionWithDefaultFormat(context, defaultResolution, videoStreams); } /** * @see #getDefaultResolutionIndex(String, String, MediaFormat, List) */ - public static int getDefaultResolutionIndex(Context context, List videoStreams, String defaultResolution) { + public static int getResolutionIndex(Context context, List videoStreams, String defaultResolution) { return getDefaultResolutionWithDefaultFormat(context, defaultResolution, videoStreams); } @@ -70,69 +53,33 @@ public final class ListHelper { * @see #getDefaultResolutionIndex(String, String, MediaFormat, List) */ public static int getPopupDefaultResolutionIndex(Context context, List videoStreams) { - SharedPreferences defaultPreferences = PreferenceManager.getDefaultSharedPreferences(context); - if (defaultPreferences == null) return 0; - - String defaultResolution = defaultPreferences.getString(context.getString(R.string.default_popup_resolution_key), context.getString(R.string.default_popup_resolution_value)); - return getPopupDefaultResolutionIndex(context, videoStreams, defaultResolution); + String defaultResolution = computeDefaultResolution(context, + R.string.default_popup_resolution_key, R.string.default_popup_resolution_value); + return getDefaultResolutionWithDefaultFormat(context, defaultResolution, videoStreams); } /** * @see #getDefaultResolutionIndex(String, String, MediaFormat, List) */ - public static int getPopupDefaultResolutionIndex(Context context, List videoStreams, String defaultResolution) { + public static int getPopupResolutionIndex(Context context, List videoStreams, String defaultResolution) { return getDefaultResolutionWithDefaultFormat(context, defaultResolution, videoStreams); } public static int getDefaultAudioFormat(Context context, List audioStreams) { - MediaFormat defaultFormat = getDefaultFormat(context, R.string.default_audio_format_key, R.string.default_audio_format_value); - return getHighestQualityAudioIndex(defaultFormat, audioStreams); - } + MediaFormat defaultFormat = getDefaultFormat(context, R.string.default_audio_format_key, + R.string.default_audio_format_value); - public static int getHighestQualityAudioIndex(List audioStreams) { - if (audioStreams == null || audioStreams.isEmpty()) return -1; - - int highestQualityIndex = 0; - if (audioStreams.size() > 1) for (int i = 1; i < audioStreams.size(); i++) { - AudioStream audioStream = audioStreams.get(i); - if (audioStream.getAverageBitrate() >= audioStreams.get(highestQualityIndex).getAverageBitrate()) highestQualityIndex = i; + // If the user has chosen to limit resolution to conserve mobile data + // usage then we should also limit our audio usage. + int result; + if (isLimitingDataUsage(context)) { + result = getMostCompactAudioIndex(defaultFormat, audioStreams); } - return highestQualityIndex; - } - - /** - * Get the audio from the list with the highest bitrate - * - * @param audioStreams list the audio streams - * @return audio with highest average bitrate - */ - public static AudioStream getHighestQualityAudio(List audioStreams) { - if (audioStreams == null || audioStreams.isEmpty()) return null; - - return audioStreams.get(getHighestQualityAudioIndex(audioStreams)); - } - - /** - * Get the audio from the list with the highest bitrate - * - * @param audioStreams list the audio streams - * @return index of the audio with the highest average bitrate of the default format - */ - public static int getHighestQualityAudioIndex(MediaFormat defaultFormat, List audioStreams) { - if (audioStreams == null || audioStreams.isEmpty() || defaultFormat == null) return -1; - - int highestQualityIndex = -1; - for (int i = 0; i < audioStreams.size(); i++) { - AudioStream audioStream = audioStreams.get(i); - if (highestQualityIndex == -1 && audioStream.getFormat() == defaultFormat) highestQualityIndex = i; - - if (highestQualityIndex != -1 && audioStream.getFormat() == defaultFormat - && audioStream.getAverageBitrate() > audioStreams.get(highestQualityIndex).getAverageBitrate()) { - highestQualityIndex = i; - } + else { + result = getHighestQualityAudioIndex(defaultFormat, audioStreams); } - if (highestQualityIndex == -1) highestQualityIndex = getHighestQualityAudioIndex(audioStreams); - return highestQualityIndex; + + return result; } /** @@ -154,6 +101,49 @@ public final class ListHelper { return getSortedStreamVideosList(defaultFormat, showHigherResolutions, videoStreams, videoOnlyStreams, ascendingOrder); } + /*////////////////////////////////////////////////////////////////////////// + // Utils + //////////////////////////////////////////////////////////////////////////*/ + + private static String computeDefaultResolution(Context context, int key, int value) { + SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); + + // Load the prefered resolution otherwise the best available + String resolution = preferences != null ? preferences.getString(context.getString(key), + context.getString(value)) : context.getString(R.string.best_resolution_key); + + String maxResolution = getResolutionLimit(context); + if (maxResolution != null && compareVideoStreamResolution(maxResolution, resolution) < 1){ + resolution = maxResolution; + } + return resolution; + } + + /** + * Return the index of the default stream in the list, based on the parameters + * defaultResolution and defaultFormat + * + * @return index of the default resolution&format + */ + static int getDefaultResolutionIndex(String defaultResolution, String bestResolutionKey, + MediaFormat defaultFormat, List videoStreams) { + if (videoStreams == null || videoStreams.isEmpty()) return -1; + + sortStreamList(videoStreams, false); + if (defaultResolution.equals(bestResolutionKey)) { + return 0; + } + + int defaultStreamIndex = getVideoStreamIndex(defaultResolution, defaultFormat, videoStreams); + + // this is actually an error, + // but maybe there is really no stream fitting to the default value. + if (defaultStreamIndex == -1) { + return 0; + } + return defaultStreamIndex; + } + /** * Join the two lists of video streams (video_only and normal videos), and sort them according with default format * chosen by the user @@ -165,7 +155,7 @@ public final class ListHelper { * @param ascendingOrder true -> smallest to greatest | false -> greatest to smallest @return the sorted list * @return the sorted list */ - public static List getSortedStreamVideosList(MediaFormat defaultFormat, boolean showHigherResolutions, List videoStreams, List videoOnlyStreams, boolean ascendingOrder) { + static List getSortedStreamVideosList(MediaFormat defaultFormat, boolean showHigherResolutions, List videoStreams, List videoOnlyStreams, boolean ascendingOrder) { ArrayList retList = new ArrayList<>(); HashMap hashMap = new HashMap<>(); @@ -215,36 +205,138 @@ public final class ListHelper { * @param videoStreams list that the sorting will be applied * @param ascendingOrder true -> smallest to greatest | false -> greatest to smallest */ - public static void sortStreamList(List videoStreams, final boolean ascendingOrder) { - Collections.sort(videoStreams, new Comparator() { - @Override - public int compare(VideoStream o1, VideoStream o2) { - int res1 = Integer.parseInt(o1.getResolution().replace("0p60", "1").replaceAll("[^\\d.]", "")); - int res2 = Integer.parseInt(o2.getResolution().replace("0p60", "1").replaceAll("[^\\d.]", "")); - - return ascendingOrder ? res1 - res2 : res2 - res1; - } + private static void sortStreamList(List videoStreams, final boolean ascendingOrder) { + Collections.sort(videoStreams, (o1, o2) -> { + int result = compareVideoStreamResolution(o1, o2, VIDEO_FORMAT_QUALITY_RANKING); + return result == 0 ? 0 : (ascendingOrder ? result : -result); }); } - /*////////////////////////////////////////////////////////////////////////// - // Utils - //////////////////////////////////////////////////////////////////////////*/ + /** + * Get the audio from the list with the highest quality. Format will be ignored if it yields + * no results. + * + * @param audioStreams list the audio streams + * @return index of the audio with the highest average bitrate of the default format + */ + static int getHighestQualityAudioIndex(MediaFormat format, List audioStreams) { + int result = -1; + if (audioStreams != null) { + while(result == -1) { + AudioStream prevStream = null; + for (int idx = 0; idx < audioStreams.size(); idx++) { + AudioStream stream = audioStreams.get(idx); + if ((format == null || stream.getFormat() == format) && + (prevStream == null || compareAudioStreamBitrate(prevStream, stream, + AUDIO_FORMAT_QUALITY_RANKING) < 0)) { + prevStream = stream; + result = idx; + } + } + if (result == -1 && format == null) { + break; + } + format = null; + } + } + return result; + } - private static int getDefaultStreamIndex(String defaultResolution, MediaFormat defaultFormat, List videoStreams) { - int defaultStreamIndex = -1; - for (int i = 0; i < videoStreams.size(); i++) { - VideoStream stream = videoStreams.get(i); - if (defaultStreamIndex == -1 && stream.getResolution().equals(defaultResolution)) defaultStreamIndex = i; + /** + * Get the audio from the list with the lowest bitrate and efficient format. Format will be + * ignored if it yields no results. + * + * @param format The target format type or null if it doesn't matter + * @param audioStreams list the audio streams + * @return index of the audio stream that can produce the most compact results or -1 if not found. + */ + static int getMostCompactAudioIndex(MediaFormat format, List audioStreams) { + int result = -1; + if (audioStreams != null) { + while(result == -1) { + AudioStream prevStream = null; + for (int idx = 0; idx < audioStreams.size(); idx++) { + AudioStream stream = audioStreams.get(idx); + if ((format == null || stream.getFormat() == format) && + (prevStream == null || compareAudioStreamBitrate(prevStream, stream, + AUDIO_FORMAT_EFFICIENCY_RANKING) > 0)) { + prevStream = stream; + result = idx; + } + } + if (result == -1 && format == null) { + break; + } + format = null; + } + } + return result; + } - if (stream.getFormat() == defaultFormat && stream.getResolution().equals(defaultResolution)) { - return i; + /** + * Locates a possible match for the given resolution and format in the provided list. + * In this order: + * 1. Find a format and resolution match + * 2. Find a format and resolution match and ignore the refresh + * 3. Find a resolution match + * 4. Find a resolution match and ignore the refresh + * 5. Find a resolution just below the requested resolution and ignore the refresh + * 6. Give up + */ + static int getVideoStreamIndex(String targetResolution, MediaFormat targetFormat, + List videoStreams) { + int fullMatchIndex = -1; + int fullMatchNoRefreshIndex = -1; + int resMatchOnlyIndex = -1; + int resMatchOnlyNoRefreshIndex = -1; + int lowerResMatchNoRefreshIndex = -1; + String targetResolutionNoRefresh = targetResolution.replaceAll("p\\d+$", "p"); + + for (int idx = 0; idx < videoStreams.size(); idx++) { + MediaFormat format = targetFormat == null ? null : videoStreams.get(idx).getFormat(); + String resolution = videoStreams.get(idx).getResolution(); + String resolutionNoRefresh = resolution.replaceAll("p\\d+$", "p"); + + if (format == targetFormat && resolution.equals(targetResolution)) { + fullMatchIndex = idx; + } + + if (format == targetFormat && resolutionNoRefresh.equals(targetResolutionNoRefresh)) { + fullMatchNoRefreshIndex = idx; + } + + if (resMatchOnlyIndex == -1 && resolution.equals(targetResolution)) { + resMatchOnlyIndex = idx; + } + + if (resMatchOnlyNoRefreshIndex == -1 && resolutionNoRefresh.equals(targetResolutionNoRefresh)) { + resMatchOnlyNoRefreshIndex = idx; + } + + if (lowerResMatchNoRefreshIndex == -1 && compareVideoStreamResolution(resolutionNoRefresh, targetResolutionNoRefresh) < 0) { + lowerResMatchNoRefreshIndex = idx; } } - return defaultStreamIndex; + if (fullMatchIndex != -1) { + return fullMatchIndex; + } + if (fullMatchNoRefreshIndex != -1) { + return fullMatchNoRefreshIndex; + } + if (resMatchOnlyIndex != -1) { + return resMatchOnlyIndex; + } + if (resMatchOnlyNoRefreshIndex != -1) { + return resMatchOnlyNoRefreshIndex; + } + return lowerResMatchNoRefreshIndex; } + /** + * Fetches the desired resolution or returns the default if it is not found. The resolution + * will be reduced if video chocking is active. + */ private static int getDefaultResolutionWithDefaultFormat(Context context, String defaultResolution, List videoStreams) { MediaFormat defaultFormat = getDefaultFormat(context, R.string.default_video_format_key, R.string.default_video_format_value); return getDefaultResolutionIndex(defaultResolution, context.getString(R.string.best_resolution_key), defaultFormat, videoStreams); @@ -280,4 +372,85 @@ public final class ListHelper { } return format; } + + // Compares the quality of two audio streams + private static int compareAudioStreamBitrate(AudioStream streamA, AudioStream streamB, + List formatRanking) { + if (streamA == null) { + return -1; + } + if (streamB == null) { + return 1; + } + if (streamA.getAverageBitrate() < streamB.getAverageBitrate()) { + return -1; + } + if (streamA.getAverageBitrate() > streamB.getAverageBitrate()) { + return 1; + } + + // Same bitrate and format + return formatRanking.indexOf(streamA.getFormat()) - formatRanking.indexOf(streamB.getFormat()); + } + + private static int compareVideoStreamResolution(String r1, String r2) { + int res1 = Integer.parseInt(r1.replaceAll("0p\\d+$", "1") + .replaceAll("[^\\d.]", "")); + int res2 = Integer.parseInt(r2.replaceAll("0p\\d+$", "1") + .replaceAll("[^\\d.]", "")); + return res1 - res2; + } + + // Compares the quality of two video streams. + private static int compareVideoStreamResolution(VideoStream streamA, VideoStream streamB, + List formatRanking) { + if (streamA == null) { + return -1; + } + if (streamB == null) { + return 1; + } + + int resComp = compareVideoStreamResolution(streamA.getResolution(), streamB.getResolution()); + if (resComp != 0) { + return resComp; + } + + // Same bitrate and format + return formatRanking.indexOf(streamA.getFormat()) - formatRanking.indexOf(streamB.getFormat()); + } + + + + private static boolean isLimitingDataUsage(Context context) { + return getResolutionLimit(context) != null; + } + + /** + * The maximum resolution allowed + * @param context App context + * @return maximum resolution allowed or null if there is no maximum + */ + private static String getResolutionLimit(Context context) { + String resolutionLimit = null; + if (!isWifiActive(context)) { + SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); + String defValue = context.getString(R.string.limit_data_usage_none_key); + String value = preferences.getString( + context.getString(R.string.limit_mobile_data_usage_key), defValue); + resolutionLimit = value.equals(defValue) ? null : value; + } + return resolutionLimit; + } + + /** + * Are we connected to wifi? + * @param context App context + * @return True if connected to wifi + */ + private static boolean isWifiActive(Context context) + { + ConnectivityManager manager = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE); + return manager.getActiveNetworkInfo().getType() == ConnectivityManager.TYPE_WIFI; + } } diff --git a/app/src/main/res/values/settings_keys.xml b/app/src/main/res/values/settings_keys.xml index befe17958..03be62431 100644 --- a/app/src/main/res/values/settings_keys.xml +++ b/app/src/main/res/values/settings_keys.xml @@ -851,4 +851,32 @@ ZM ZW + + + limit_mobile_data_usage + @string/limit_data_usage_none_key + + @string/limit_data_usage_none_description + 1080p60 + 1080p + 720p60 + 720p + 480p + 360p + 240p + 144p + + + @string/limit_data_usage_none_key + 1080p60 + 1080p + 720p60 + 720p + 480p + 360p + 240p + 144p + + limit_data_usage_none + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 6f3dc7d0a..9fa5c7eda 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -66,6 +66,8 @@ Default video format WebM — free format M4A — better quality + No limit + Limit resolution when using mobile data Theme Light Dark diff --git a/app/src/main/res/xml/video_audio_settings.xml b/app/src/main/res/xml/video_audio_settings.xml index 6a3b7a0b3..6ec0da215 100644 --- a/app/src/main/res/xml/video_audio_settings.xml +++ b/app/src/main/res/xml/video_audio_settings.xml @@ -19,6 +19,14 @@ android:summary="%s" android:title="@string/default_popup_resolution_title"/> + + + android:title="@string/default_audio_format_title" /> ())); } + @Test + public void getLowestQualityAudioFormatTest() throws Exception { + AudioStream stream = audioStreamsTestList.get(ListHelper.getMostCompactAudioIndex(MediaFormat.M4A, audioStreamsTestList)); + assertEquals(128, stream.average_bitrate); + assertEquals(MediaFormat.M4A, stream.getFormat()); + stream = audioStreamsTestList.get(ListHelper.getMostCompactAudioIndex(MediaFormat.WEBMA, audioStreamsTestList)); + assertEquals(64, stream.average_bitrate); + assertEquals(MediaFormat.WEBMA, stream.getFormat()); + + stream = audioStreamsTestList.get(ListHelper.getMostCompactAudioIndex(MediaFormat.MP3, audioStreamsTestList)); + assertEquals(64, stream.average_bitrate); + assertEquals(MediaFormat.MP3, stream.getFormat()); + } + + @Test + public void getLowestQualityAudioFormatPreferredAbsent() throws Exception { + + ////////////////////////////////////////// + // Doesn't contain the preferred format // + //////////////////////////////////////// + + List testList = new ArrayList<>(Arrays.asList( + new AudioStream("", MediaFormat.M4A, /**/ 128), + new AudioStream("", MediaFormat.WEBMA, /**/ 192))); + // List doesn't contains this format, it should fallback to the most compact audio no matter what format it is. + AudioStream stream = testList.get(ListHelper.getMostCompactAudioIndex(MediaFormat.MP3, testList)); + assertEquals(128, stream.average_bitrate); + assertEquals(MediaFormat.M4A, stream.getFormat()); + + // WEBMA is more compact than M4A + testList.add(new AudioStream("", MediaFormat.WEBMA, /**/ 128)); + stream = testList.get(ListHelper.getMostCompactAudioIndex(MediaFormat.MP3, testList)); + assertEquals(128, stream.average_bitrate); + assertEquals(MediaFormat.WEBMA, stream.getFormat()); + + //////////////////////////////////////////////////////// + // Multiple not-preferred-formats and equal bitrates // + ////////////////////////////////////////////////////// + + testList = new ArrayList<>(Arrays.asList( + new AudioStream("", MediaFormat.WEBMA, /**/ 192), + new AudioStream("", MediaFormat.M4A, /**/ 192), + new AudioStream("", MediaFormat.WEBMA, /**/ 256), + new AudioStream("", MediaFormat.M4A, /**/ 192), + new AudioStream("", MediaFormat.WEBMA, /**/ 192), + new AudioStream("", MediaFormat.M4A, /**/ 192))); + // List doesn't contains this format, it should fallback to the most compact audio no matter what format it is. + stream = testList.get(ListHelper.getMostCompactAudioIndex(MediaFormat.MP3, testList)); + assertEquals(192, stream.average_bitrate); + assertEquals(MediaFormat.WEBMA, stream.getFormat()); + + // Should be same as above + stream = testList.get(ListHelper.getMostCompactAudioIndex(null, testList)); + assertEquals(192, stream.average_bitrate); + assertEquals(MediaFormat.WEBMA, stream.getFormat()); + } + + @Test + public void getLowestQualityAudioNull() throws Exception { + assertEquals(-1, ListHelper.getMostCompactAudioIndex(null, null)); + assertEquals(-1, ListHelper.getMostCompactAudioIndex(null, new ArrayList())); + } + + @Test + public void getVideoDefaultStreamIndexCombinations() throws Exception { + List testList = Arrays.asList( + new VideoStream("", MediaFormat.MPEG_4, /**/ "1080p"), + new VideoStream("", MediaFormat.MPEG_4, /**/ "720p60"), + new VideoStream("", MediaFormat.MPEG_4, /**/ "720p"), + new VideoStream("", MediaFormat.WEBM, /**/ "480p"), + new VideoStream("", MediaFormat.MPEG_4, /**/ "360p"), + new VideoStream("", MediaFormat.WEBM, /**/ "360p"), + new VideoStream("", MediaFormat.v3GPP, /**/ "240p60"), + new VideoStream("", MediaFormat.WEBM, /**/ "144p")); + + // exact matches + assertEquals(1, ListHelper.getVideoStreamIndex("720p60", MediaFormat.MPEG_4, testList)); + assertEquals(2, ListHelper.getVideoStreamIndex("720p", MediaFormat.MPEG_4, testList)); + + // match but not refresh + assertEquals(0, ListHelper.getVideoStreamIndex("1080p60", MediaFormat.MPEG_4, testList)); + assertEquals(6, ListHelper.getVideoStreamIndex("240p", MediaFormat.v3GPP, testList)); + + // match but not format + assertEquals(1, ListHelper.getVideoStreamIndex("720p60", MediaFormat.WEBM, testList)); + assertEquals(2, ListHelper.getVideoStreamIndex("720p", MediaFormat.WEBM, testList)); + assertEquals(1, ListHelper.getVideoStreamIndex("720p60", null, testList)); + assertEquals(2, ListHelper.getVideoStreamIndex("720p", null, testList)); + + // match but not format and not refresh + assertEquals(0, ListHelper.getVideoStreamIndex("1080p60", MediaFormat.WEBM, testList)); + assertEquals(6, ListHelper.getVideoStreamIndex("240p", MediaFormat.WEBM, testList)); + assertEquals(0, ListHelper.getVideoStreamIndex("1080p60", null, testList)); + assertEquals(6, ListHelper.getVideoStreamIndex("240p", null, testList)); + + // match closest lower resolution + assertEquals(7, ListHelper.getVideoStreamIndex("200p", MediaFormat.WEBM, testList)); + assertEquals(7, ListHelper.getVideoStreamIndex("200p60", MediaFormat.WEBM, testList)); + assertEquals(7, ListHelper.getVideoStreamIndex("200p", MediaFormat.MPEG_4, testList)); + assertEquals(7, ListHelper.getVideoStreamIndex("200p60", MediaFormat.MPEG_4, testList)); + assertEquals(7, ListHelper.getVideoStreamIndex("200p", null, testList)); + assertEquals(7, ListHelper.getVideoStreamIndex("200p60", null, testList)); + + // Can't find a match + assertEquals(-1, ListHelper.getVideoStreamIndex("100p", null, testList)); + } } \ No newline at end of file From 646fa877ba61dda1be57d11e166cde1d51ee0ab6 Mon Sep 17 00:00:00 2001 From: James Straub Date: Sun, 22 Apr 2018 10:20:19 -0400 Subject: [PATCH 02/80] Update to mobile data limiting - Moved non-key strings from string_keys.xml to strings.xml - Code style changes - Replaced a hard coded key string with resource constant --- .../org/schabi/newpipe/util/ListHelper.java | 15 ++++------ app/src/main/res/values/settings_keys.xml | 23 -------------- app/src/main/res/values/strings.xml | 30 +++++++++++++++++-- 3 files changed, 34 insertions(+), 34 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/util/ListHelper.java b/app/src/main/java/org/schabi/newpipe/util/ListHelper.java index 93d20e22e..4f607b581 100644 --- a/app/src/main/java/org/schabi/newpipe/util/ListHelper.java +++ b/app/src/main/java/org/schabi/newpipe/util/ListHelper.java @@ -71,15 +71,11 @@ public final class ListHelper { // If the user has chosen to limit resolution to conserve mobile data // usage then we should also limit our audio usage. - int result; if (isLimitingDataUsage(context)) { - result = getMostCompactAudioIndex(defaultFormat, audioStreams); + return getMostCompactAudioIndex(defaultFormat, audioStreams); + } else { + return getHighestQualityAudioIndex(defaultFormat, audioStreams); } - else { - result = getHighestQualityAudioIndex(defaultFormat, audioStreams); - } - - return result; } /** @@ -109,8 +105,9 @@ public final class ListHelper { SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); // Load the prefered resolution otherwise the best available - String resolution = preferences != null ? preferences.getString(context.getString(key), - context.getString(value)) : context.getString(R.string.best_resolution_key); + String resolution = preferences != null + ? preferences.getString(context.getString(key), context.getString(value)) + : context.getString(R.string.best_resolution_key); String maxResolution = getResolutionLimit(context); if (maxResolution != null && compareVideoStreamResolution(maxResolution, resolution) < 1){ diff --git a/app/src/main/res/values/settings_keys.xml b/app/src/main/res/values/settings_keys.xml index 03be62431..2fadeb756 100644 --- a/app/src/main/res/values/settings_keys.xml +++ b/app/src/main/res/values/settings_keys.xml @@ -854,29 +854,6 @@ limit_mobile_data_usage - @string/limit_data_usage_none_key - - @string/limit_data_usage_none_description - 1080p60 - 1080p - 720p60 - 720p - 480p - 360p - 240p - 144p - - - @string/limit_data_usage_none_key - 1080p60 - 1080p - 720p60 - 720p - 480p - 360p - 240p - 144p - limit_data_usage_none \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9fa5c7eda..ab9718a0c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -66,8 +66,6 @@ Default video format WebM — free format M4A — better quality - No limit - Limit resolution when using mobile data Theme Light Dark @@ -468,4 +466,32 @@ Unhook (may cause distortion) Nightcore Default + + + No limit + Limit resolution when using mobile data + @string/limit_data_usage_none_key + + @string/limit_data_usage_none_description + 1080p60 + 1080p + 720p60 + 720p + 480p + 360p + 240p + 144p + + + @string/limit_data_usage_none_key + 1080p60 + 1080p + 720p60 + 720p + 480p + 360p + 240p + 144p + + From 78123ff6f59da0b52201a1a3a716264879e53b3c Mon Sep 17 00:00:00 2001 From: Ali Demirtas Date: Mon, 14 May 2018 19:09:51 +0000 Subject: [PATCH 03/80] Translated using Weblate (Turkish) Currently translated at 100.0% (365 of 365 strings) --- app/src/main/res/values-tr/strings.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 7d5fbfd4f..00b5bf237 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -469,4 +469,6 @@ 1 öge silindi. NewPipe, telif müsaadeli özgür yazılımdır: İstediğiniz gibi kullanabilir, öğrenebilir, paylaşabilir, iyileştirebilirsiniz. Özellikle; Özgür Yazılım Vakfı tarafından yayımlanan GNU Genel Kamu Lisansı\'nın, lisansın 3. sürümüyle veya (isterseniz) daha sonraki sürümünün koşulları altında yeniden dağıtabilir ve/veya düzenleyebilirsiniz. + Ayrıca ayarları içe aktarmak istiyor musunuz? + From deeb667d6f3d574f605b12f098fda0b11a6bf712 Mon Sep 17 00:00:00 2001 From: ditokp Date: Mon, 14 May 2018 14:09:17 +0000 Subject: [PATCH 04/80] Translated using Weblate (Indonesian) Currently translated at 100.0% (365 of 365 strings) --- app/src/main/res/values-id/strings.xml | 56 +++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/values-id/strings.xml b/app/src/main/res/values-id/strings.xml index 006b50e34..024bbf0b0 100644 --- a/app/src/main/res/values-id/strings.xml +++ b/app/src/main/res/values-id/strings.xml @@ -381,7 +381,7 @@ membuka di mode popup Fon lebih besar Aktifkan LeakCanary - + Nightcore Bawaan Tidak ada aplikasi pemutar stream (Anda bisa memasang VLC untuk memutarnya) Unduh berkas stream. @@ -408,4 +408,58 @@ membuka di mode popup Markah Antre otomatis stream berikutnya + Berhenti langganan channel ini + Tidak dapat memperbarui langganan + Langganan + Gunakan pencarian dengan cepat dengan tidak tepat + Pencarian tidak beraturan memungkinkan pengguna untuk mencari posisi lebih cepat dengan ketepatan yang berkurang + NewPipe adalah perangkat lunak libre copyleft: Anda dapat menggunakannya, mempelajarinya, berbagi, dan meningkatkannya sesuai keinginan Anda. Secara khusus Anda dapat mendistribusikan ulang dan/atau memodifikasinya di bawah syarat-syarat Lisensi GNU General Public License yang diterbitkan oleh Free Software Foundation, baik versi 3 dari Lisensi, atau (sesuai pilihan Anda) versi yang lebih baru. + Apa Anda ingin juga mengimpor pengaturan? + + Lebih disukai tindakan \'terbuka\' + Aksi bawaan ketika membuka konten — %s + + Keterangan + Mengubah skala keterangan teks pemutar dan gaya latar belakang. Perlu memulai ulang aplikasi agar berdampak. + + Pemantauan kebocoran memori dapat menyebabkan aplikasi menjadi tidak responsif saat terjadi dumping + + Laporkan Kesalahan di Luar-Siklus + Memaksa pelaporan pengecualian Rx yang tidak dapat dikirim di luar kepingan atau siklus hidup aktivitas setelah dibuang + + Impor/Ekspor + Impor + Impor dari + Ekspor ke + + Mengimpor… + Mengekspor… + + Impor file + Ekspor sebelumnya + + Tidak dapat mengimpor langganan + Tidak dapat mengekspor langganan + + Impor langganan YouTube dengan mengunduh file ekspor: +\n +\n1. Pergi ke URL ini: %1$s +\n2. Masuk ketika disuruh +\n3. Unduhan akan dimulai (Itulah file ekspornya) + Untuk mengimpor profil SoundCloud dengan mengetik URL atau ID Anda: +\n +\n1. Nyalakan \"mode desktop\" di web-browser (situsnya tidak tersedia untuk perangkat mobile) +\n2. Pergi ke URL ini: %1$s +\n3. Masuk ketika disuruh +\n4. Salin URL profil Anda ketika dialihkan. + IDanda, soundcloud.com/idanda + + Perlu diingat operasi ini bisa menyedot jaringan yang mahal. +\n +\nApakah Anda ingin melanjutkan? + + Kontrol Kecepatan Pemutaran + Tempo + Nada + Lepas kaitan (dapat menyebabkan distorsi) From 160560f1fdb805fb493dc2f1e0c6fc663a2b2d68 Mon Sep 17 00:00:00 2001 From: HashikDonthineni Date: Mon, 14 May 2018 15:03:45 +0000 Subject: [PATCH 05/80] Translated using Weblate (Telugu) Currently translated at 35.3% (129 of 365 strings) --- app/src/main/res/values-te/strings.xml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/values-te/strings.xml b/app/src/main/res/values-te/strings.xml index 95810d19a..d2231ce43 100644 --- a/app/src/main/res/values-te/strings.xml +++ b/app/src/main/res/values-te/strings.xml @@ -196,4 +196,6 @@ వివరాలు ఆడియో సెట్టింగ్లు ఎన్క్యూలో పట్టుకోండి - +"మీదగార వీడియో కి కావాల్సిన ప్లేయర్ లేదు. VLC ప్లేయర్ ఇన్స్టాల్ చేసుకుంటారా?" + "మీదగార వీడియో కి కావాల్సిన ప్లేయర్ లేదు (మీరు VLC ఇసన్తాల్ చేసుకోవచ్చు)" + From 105ac2f6ff5e2fe6e45097f264ee2956f50f5e39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Freddy=20Mor=C3=A1n=20Jr?= Date: Mon, 14 May 2018 18:25:03 +0000 Subject: [PATCH 06/80] Translated using Weblate (Spanish) Currently translated at 99.4% (363 of 365 strings) --- app/src/main/res/values-es/strings.xml | 34 +++++++++++++------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index b0980b13b..d12544d40 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -398,7 +398,7 @@ abrir en modo popup La monitorización de fugas de memoria puede causar que la app no responda cuando hay Heap Dump Reportar errores fuera del ciclo de duración - Forzar la notificación de excepciones no entregables de RX que ocurren fuera del fragmento o del ciclo de actividad después de disponer + Forzar reporte de excepciones no entregables de RX fuera del fragmento o del ciclo de actividad después del descarte Usar búsqueda rápida inexacta La búsqueda inexacta permite al reproductor buscar posiciones más rápido con menor precisión @@ -425,22 +425,20 @@ abrir en modo popup Importar archivo Exportación anterior - Importación de suscripciones fallida - Exportación de suscripciones fallida + No se pudo importar suscripciones + No se pudo exportar suscripciones - Para importar sus suscripciones de YouTube, necesitará el archivo de exportación, el cual puede ser descargado siguiendo estas instrucciones: -\n -\n1. Vaya a esta URL: %1$s -\n2. Ingrese a su cuenta cuando se le pida -\n3. Una descarga debería comenzar (ese es el archivo de exportación) - Para importar sus seguimientos de SoundCloud, debe conocer la URL o el ID de su perfil. Si es así, simplemente escriba cualquiera de ellos en la entrada de abajo y ya está listo para comenzar. -\n -\nSi no es así, puede seguir estos pasos: -\n -\n1. Active el \"modo escritorio\" en algún navegador (el sitio no está disponible para dispositivos móviles) -\n2. Vaya a esta URL: %1$s -\n3. Ingrese a su cuenta cuando se le pida -\n4. Copie la URL a la que fue redireccionado (esa es la URL de su perfil) + Importe suscripciones de YouTube descargando el archivo de exportación: +\n +\n1. Vaya a esta URL: %1$s +\n2. Inicie sesión cuando se le pida +\n3. Una descarga debería empezar (ese es el archivo de exportación) + Importe un perfil de SoundCloud escribiendo la URL o su ID: +\n +\n1. Active el \"modo escritorio\" en un navegador web (el sitio no está disponible para dispositivos móviles) +\n2. Vaya a esta URL: %1$s +\n3. Inicie sesión cuando se le pida +\n4. Copie la URL del perfil a la que fue redireccionado. suID, soundcloud.com/suID Tenga en cuenta que esta operación puede ser costosa para la red. @@ -452,7 +450,7 @@ abrir en modo popup Metadatos eliminados del caché Eliminar todos los datos de la página web en caché Metadatos del caché limpiados - Control de velocidad de la reproducción + Controles de velocidad de reproducción Tiempo Tono Desenganchar (puede casusar distorsión) @@ -479,4 +477,6 @@ abrir en modo popup 1 elemento eliminado. NewPipe es un software copyleft libre: puedes usarlo, estudiarlo, compartirlo y mejorarlo a tu antojo. Específicamente, puedes redistribuirlo y/o modificarlo bajo los términos de la Licencia Pública General GNU publicada por la Free Software Foundation, ya sea la versión 3 de la Licencia, o (a tu elección) cualquier versión posterior. + ¿Desea importar también los ajustes? + From 14f5d54b504b67ad38c0d32f8d78e7e56befed28 Mon Sep 17 00:00:00 2001 From: Ale-Ma Date: Tue, 15 May 2018 22:13:39 +0000 Subject: [PATCH 07/80] Translated using Weblate (Italian) Currently translated at 100.0% (365 of 365 strings) --- app/src/main/res/values-it/strings.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 2ff6c21ea..decf6b133 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -478,4 +478,6 @@ 1 elemento eliminato. NewPipe è un software libero con licenza copyleft: puoi usarlo, studiarlo, condividerlo e migliorarlo a tuo piacimento. In particolare, è possibile ridistribuirlo e/o modificarlo secondo i termini della GNU General Public License pubblicata dalla Free Software Foundation, sia nella versione 3 della Licenza, sia (a propria discrezione) in qualsiasi versione successiva. + Vuoi anche importare le impostazioni? + From 0bda964ecec1cc716fd082c6a15a303616fdc6bf Mon Sep 17 00:00:00 2001 From: Robson Cassiano Date: Wed, 16 May 2018 13:42:25 +0000 Subject: [PATCH 08/80] Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (365 of 365 strings) --- app/src/main/res/values-pt-rBR/strings.xml | 77 ++++++++++++---------- 1 file changed, 44 insertions(+), 33 deletions(-) diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index ee67a8901..d69f4ddad 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -10,7 +10,7 @@ Reproduzir Vídeo com restrição de idade. Permissão para vídeos com essa restrição podem ser feitas no menu configurações. Vídeo - Reproduzir o vídeo automaticamente quando o NewPipe for aberto a partir de outro app + Reproduz o vídeo quando o NewPipe for aberto a partir de outro aplicativo Reproduzir automaticamente Preto Bloqueado pelo GEMA @@ -66,7 +66,7 @@ Compartilhar Compartilhar com Exibir conteúdo com restrição de idade - Exibir próximo vídeo e relacionados + Exibir \'próximo\' vídeo e \'relacionados\' Desculpe, isto não deveria ter acontecido. Iniciar Permissão para acessar armazenamento negada @@ -168,7 +168,7 @@ abrir em modo popup Sobre Contribuintes Licenças - Um leve, simples e grátis aplicativo de YouTube para Android. + Streaming leve e gratuito no Android. Ver no GitHub Licença do NewPipe Sempre que tiver ideias, traduções, mudanças do design, limpeza de código ou grandes alterações de código, a ajuda é bem vinda. Quanto mais for feito, melhor o aplicativo fica! @@ -200,7 +200,7 @@ abrir em modo popup Histórico de pesquisas Armazenar histórico de pesquisa localmente - Histórico + Histórico & Cache Armazenar histórico de vídeos assistidos Histórico Pesquisado @@ -256,13 +256,13 @@ abrir em modo popup Em Alta Top 50 Novos e tendências -Mostrar dica para mantenha pressionado para pendurar +"Mostrar dica \"mantenha pressionado\" para enfileirar" Mostrar dica quando o botão de plano de fundo ou de popup for pressionado na página de detalhes do vídeo Adicionado a fila do reprodutor em plano de fundo Adicionado a fila no reprodutor popup Reproduzir tudo - Falha ao reproduzir esta stream + Não foi possível reproduzir esta stream Ocorreu um erro no reprodutor Recuperando erro do reprodutor @@ -280,10 +280,10 @@ abrir em modo popup Iniciar aqui em plano de fundo Iniciar aqui em popup Doar - NewPipe é desenvolvido por voluntários que gastam seu tempo livre para trazer a melhor experiência para você. Agora é a hora de retribuir o favor e ter certeza que os desenvolvedores podem fazer com que o NewPipe fique ainda melhor enquanto desfrutam uma xícara de café! + NewPipe é desenvolvido por voluntários que usam seu tempo para trazer a melhor experiência para você. Retribua para ajudar os desenvolvedores a tornarem o NewPipe ainda melhor enquanto desfrutam uma xícara de café. Retribuir Site oficial - Para obter mais informações e as últimas notícias sobre o NewPipe visite nosso Site. + Visite o site do NewPipe para mais informações e novidades. Nenhum reprodutor de stream encontrado (você pode instalar o VLC para reproduzir isto) País do conteúdo padrão Serviço @@ -306,7 +306,7 @@ abrir em modo popup Sempre perguntar Obtendo informações… - O conteúdo solicitado está carregando + Carregando o conteúdo requisitado Importar base de dados Exportar base de dados Isso irá sobrescrever seu histórico e inscrições @@ -350,14 +350,14 @@ abrir em modo popup Remover Favorito Deseja remover esta lista de reprodução? - Lista de Reprodução Criada + Lista de Reprodução criada Adicionado a lista de reprodução Miniatura para a lista de reprodução alterada Falha ao apagar lista de reprodução Sem Legenda - FIT + Ajustar Preencher Zoom @@ -371,15 +371,15 @@ abrir em modo popup Gerado automaticamente Habilitar LeakCanary - Monitoramento de vazamento de memória pode fazer com que o app fique sem responder quando estiver despejando a pilha + "Monitoramento de vazamento de memória pode fazer com que o app fique sem responder quando estiver despejando a pilha " - Reportar Erros fora do ciclo de vida + Reportar Erros de Fora do Ciclo de Vida Forçar o report de exceções Rx não entregáveis ocorrendo fora do fragmento ou ciclo de vida da atividade após o dispose Usar índice de indexação rápido porém não preciso Usar índice de indexação inexato Adicionar a próxima stream à fila automaticamente - Anexar automaticamente uma stream relacionada quando a reprodução iniciar na última stream em uma fila não repetitiva. + Auto anexar uma stream relacionada quando a reprodução iniciar na última stream em uma fila não repetitiva. Sincronizar Arquivo @@ -404,20 +404,18 @@ abrir em modo popup Importação de inscrições falhou Exportação de inscrições falhou - "Para importar inscrições do YouTube você vai precisar exportar o arquivo, o que pode ser baixado seguindo estas informações: -\n -\n1. Vá para este link: %1$s -\n2. Faça login na sua conta quando solicitado -\n3. O download deverá começar (isto é exportar arquivo)" - Para importar as contas que você segue no SoundCloud, você terá que saber o link ou id do seu perfil. Se você souber, basta escrever um deles no campo abaixo e estará tudo pronto. -\n -\nSe você não souber, você pode seguir estas etapas: -\n -\n1. Habilite \"modo desktop\" em algum navegador da internet ( o site não está disponível para dispositivos móveis) -\n2. Vá para esta url: %1$s -\n3. Faça login na sua conta quando solicitado -\n4. Copie o link no qual que você foi redirecionado (este é o link do seu perfil) - seuid, soundcloud.com/seuid + "Importe as inscrições da sua conta no YouTube através do arquivo exportado por ela em: +\n +\n1. Vá para este link: %1$s +\n2. Faça login quando solicitado +\n3. O download deverá começar (isto é o arquivo exportado)" + Importe uma conta do SoundCloud escrevendo o ID ou a URL no campo abaixo: +\n +\n1. Habilite o \"modo desktop\" em algum navegador da internet (pois essa opção não está disponível para páginas mobile) +\n2. Vá para esta URL: %1$s +\n3. Faça login quando solicitado +\n4. Copie o link no qual você foi redirecionado (este é o link do seu perfil). + seuID, soundcloud.com/seuid Tenha em mente que esta operação poderá usar bastante a conexão com a internet. \n @@ -427,23 +425,36 @@ abrir em modo popup Limpar o cache de metadados Remover todos os dados de páginas em cache Cache de metadados foi limpo - Controle de Velocidade de reprodução - Tempo + Controles de Velocidade de Reprodução + "Tempo " Desabilite para para de carregar todas as miniaturas e economizar dados e uso de memória. Alterar esta configuração irá limpar o cache de imagens na memória e em disco. Passo Desenganchar Padrão -Ação de abrir preferida +Ação de \'abrir\' preferida Ação padrão quando abrir conteúdo — %s Sem fontes disponíveis para download Abrir gaveta Fechar gaveta - Legenda + Legendas Modifique o tamanho da legenda e o estilo da tela de fundo. Necessário reiniciar o aplicativo para ter efeito. Night-core - Nenhum player foi encontrado para este arquivo + Nenhum player instalado para reproduzir este arquivo + + "Limpar histórico de já assistidos " + Deleta o histórico de videos já reproduzidos. + Deleta todo o histórico de já reproduzidos. + Histórico de já assistidos deletado. + Limpar histórico de pesquisa + Deleta histórico de palavras chave pesquisadas. + Deletar todo o histórico de pesquisa. + Histórico de pesquisa deletado. + 1 item deletado. + + NewPipe is copyleft libre software: Você pode usar, estudar, compartilhar e melhorar ele a vontade. Mais especificamente você pode redistribuir e/ou modificar ele sob os termos da GNU General Public License como publicada pela Free Software Foundation, tanto a versão 3 dessa Licença, ou (a sua escolha) qualquer outra versão posterior. + Você também quer importar as configurações? From f48aeb91f4c91689bacf7c9f1eb3df51fdbd8033 Mon Sep 17 00:00:00 2001 From: Osoitz Date: Wed, 16 May 2018 09:05:00 +0000 Subject: [PATCH 09/80] Translated using Weblate (Basque) Currently translated at 98.9% (361 of 365 strings) --- app/src/main/res/values-eu/strings.xml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/values-eu/strings.xml b/app/src/main/res/values-eu/strings.xml index b2301d49b..a25817695 100644 --- a/app/src/main/res/values-eu/strings.xml +++ b/app/src/main/res/values-eu/strings.xml @@ -450,4 +450,6 @@ Deslotu (distortsioa sor lezake) Nightcore Lehenetsia - +Ezarpenak ere inportatu nahi dituzu? + + From 73eea5608a342a55fd31cec2a9cc02d23c511536 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Adri=C3=A3o?= Date: Wed, 16 May 2018 11:12:16 +0000 Subject: [PATCH 10/80] Translated using Weblate (Portuguese) Currently translated at 86.3% (315 of 365 strings) --- app/src/main/res/values-pt/strings.xml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index 773bd4ff2..dec2c6f77 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -30,7 +30,7 @@ M4A — melhor qualidade Descarregar Vídeo seguinte - Mostrar vídeos seguintes e semelhantes + Mostrar vídeos \'seguintes\' e \'semelhantes\' URL não suportado Idioma padrão do conteúdo Vídeo e áudio @@ -89,7 +89,7 @@ Permissão para aceder ao armazenamento foi negada Toque para iniciar a pesquisa Reprodução automática - Reproduzir vídeo automaticamente se o NewPipe for invocado por outra aplicação + Reproduzir vídeo se o NewPipe for invocado por outra aplicação direto Reportar um erro @@ -205,7 +205,7 @@ Histórico de pesquisa Guardar termos de pesquisa localmente - Histórico + Histórico e Cache Guardar histórico de vídeos assistidos Retomar ao ganhar foco Continuar reprodução após interrupções (ex. chamadas) @@ -419,4 +419,5 @@ Tempo Nightcore Predefinido - +Limpar histórico de exibição + From 9c5ca9f09d061e6d1ffd2469c7529e1dd5344edc Mon Sep 17 00:00:00 2001 From: Robson Cassiano Date: Wed, 16 May 2018 14:24:20 +0000 Subject: [PATCH 11/80] Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (365 of 365 strings) --- app/src/main/res/values-pt-rBR/strings.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index d69f4ddad..5570f5f1a 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -266,7 +266,7 @@ abrir em modo popup Ocorreu um erro no reprodutor Recuperando erro do reprodutor - Reprodutor de plano de fundo + Reprodutor de Plano de Fundo Reprodutor Popup Remover Detalhes @@ -274,10 +274,10 @@ abrir em modo popup Mantenha pressionado para colocar na fila [Desconhecido] - Adicionar a fila em plano de fundo + Adicionar a fila em Plano de Fundo Adicionar a fila em Popup Iniciar a reproduzir à partir daqui - Iniciar aqui em plano de fundo + Iniciar aqui em Plano de Fundo Iniciar aqui em popup Doar NewPipe é desenvolvido por voluntários que usam seu tempo para trazer a melhor experiência para você. Retribua para ajudar os desenvolvedores a tornarem o NewPipe ainda melhor enquanto desfrutam uma xícara de café. @@ -291,7 +291,7 @@ abrir em modo popup Apenas esta vez Alterar a orientação - Alterar para plano de fundo + Alterar para Plano de Fundo Alterar para Popup Aletar para principal @@ -355,7 +355,7 @@ abrir em modo popup Miniatura para a lista de reprodução alterada Falha ao apagar lista de reprodução - Sem Legenda + Sem Legendas Ajustar Preencher From 3403a127c12f859e57ffcf0f18916636a88a647c Mon Sep 17 00:00:00 2001 From: Osoitz Date: Fri, 18 May 2018 08:16:27 +0000 Subject: [PATCH 12/80] Translated using Weblate (Basque) Currently translated at 100.0% (365 of 365 strings) --- app/src/main/res/values-eu/strings.xml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/values-eu/strings.xml b/app/src/main/res/values-eu/strings.xml index a25817695..2e82edf74 100644 --- a/app/src/main/res/values-eu/strings.xml +++ b/app/src/main/res/values-eu/strings.xml @@ -321,7 +321,7 @@ Gehitu hona - Erabili gutxi gora beherako bilaketa azkarra + Erabili bilaketa azkar ez zehatza Kargatu iruditxoak Irudien cache-a ezabatuta Ezabatu cache-ko metadatuak @@ -452,4 +452,9 @@ Lehenetsia Ezarpenak ere inportatu nahi dituzu? + Bilaketa ez zehatzak posizioak azkarrago baina prezisio gutxiagoz bilatzea ahalbidetzen du + "Desgaitu iruditxoak kargatzea gelditzeko eta datuak eta memoria aurrezteko. Hau aldatzean memoria eta diskoko irudien cache-ak garbituko dira." + NewPipe Software Librea eta Copyleft da: Nahi eran erabili, ikertu, partekatu eta hobetu dezakezu. Zehazki, elkarbanatzea eta aldatzea Free Software Foundation-ek argitaratutako GNU General Public License-ren 3. bertsioa edo berriagoren baten terminoen arabera egiteko baimena duzu. + Behartu aktibitatearen bizitza ziklotik kanpo baztertu eta gero entregatu ezin diren Rx salbuespenen inguruko txostena. + From 0a1743251e07b262366eee53808f80a21b6128e9 Mon Sep 17 00:00:00 2001 From: Dual Natan Date: Fri, 18 May 2018 09:26:47 +0000 Subject: [PATCH 13/80] Translated using Weblate (Macedonian) Currently translated at 100.0% (365 of 365 strings) --- app/src/main/res/values-mk/strings.xml | 73 +++++++++++++++++--------- 1 file changed, 47 insertions(+), 26 deletions(-) diff --git a/app/src/main/res/values-mk/strings.xml b/app/src/main/res/values-mk/strings.xml index 8acba20ca..859023418 100644 --- a/app/src/main/res/values-mk/strings.xml +++ b/app/src/main/res/values-mk/strings.xml @@ -47,7 +47,7 @@ Внеси локација за зачувување аудио Автоматско пуштање - Автоматски пушта видео кога NewPipe е повикана од друга апликација + Пушта видео кога NewPipe е повикана од друга апликација Стандардна резолуција Стандардна резолуција на подпрозорчето Покажи повисоки резолуции @@ -83,13 +83,13 @@ Покажи предлози при пребарување Историја на пребарувањата Зачувај ги пребарувањата локално - Историја + Историја и зачувано Зачувај ја листата на гледани видеа Продолжи видео при враќање на фокусот Продолжи го видеото по прекини (пр. телефонски повик) Превземи Следно видео - Покажи следни и слични видеа + Покажи „следни“ и „слични“ видеа Покажи совет „задржи за прикачување“ Прикажи совет кога позадината или копче од подпрозорчето се притиснати, на страната за видео детаљи Неподдржана URL врска @@ -257,7 +257,7 @@ Оваа привилегија е потребна за \nотворање во подпрозорче - reCAPTCHA + „reCAPTCHA“ reCAPTCHA Предизвик Потребен е reCAPTCHA предизвик @@ -284,10 +284,10 @@ Ако имаш идеи за; превод, дизајн, чистење или големи промени во кодот - помошта е секогаш добредојдена. Што повеќе се работи, подобра е апликацијата! Види на GitHub Донирај - NewPipe се гради од волонтери кои го вложуваат слободното време за важето задоволство. Време е да им возвратиме за тие да можат да ја подобрат апликацијата, уживајќи во топло кафе! + NewPipe се гради од волонтери кои го вложуваат слободното време за важето задоволство. Време е да им возвратиме за тие да можат да ја подобрат апликацијата, уживајќи во топло кафе. Возврати Вебсајт - За повеќе информации и најновите новости за NewPipe посети ја вебстраната. + За повеќе информации и новости за NewPipe посети ја вебстраната. "Лиценцата на NewPipe " Прочитај лиценца @@ -361,16 +361,16 @@ Избриши ја белешката Сакаш да ја избришеш плејлистата? - Успешно создадена плејлиста + Листата е создадена Додадено во плејлиста Се смени иконата на плејлистата - Неуспешно бришење на плејлистата + Неуспешно бришење на листата Без превод - ВКЛОПИ - ИСПОЛНИ - ЗУМИРАЈ + Вклопи + Исполни + Зумирај Автоматски создадено Големина на преводот @@ -398,29 +398,50 @@ Неуспешно внесување членства Неуспешно изнесување членства - За да ги внесеш твоите YouTube членства, ти треба фајл кој можеш да го добиеш на следниот начин: -\n -\n1. Оди на оваа врска: %1$s -\n2. Пријави се на твојот профил + Внеси YouTube членства, преку симнување на извозен фајл: +\n +\n1. Оди на оваа врска: %1$s +\n2. Пријави се на твојот профил \n3. Ќе започне превземање (тој фајл ти треба) - За да ги внесете вашите SoundCloud членства, ви треба URL или ID на профилот. Ако ги знаете, само внесете едно од нив во полето, и готови сте. -\n -\nАко не ги знаете, одете по следните чекори: -\n -\n1. Вклучете „десктоп режим“ во вашиот пребарувач (страната не е достапна за мобилни уреди) -\n2. Одете на оваа врска: %1$s -\n3. Пријавете се на вашиот профил -\n4. Копирајте го URL-то на кое бевте пренасочени (тоа е URL-то на вашиот профил) + Внеси SoundCloud членства, преку внесување URL или ID на профилот: +\n +\n1. Вклучете „десктоп режим“ во вашиот пребарувач (страната не е достапна за мобилни уреди) +\n2. Одете на оваа врска: %1$s +\n3. Пријавете се на вашиот профил +\n4. Копирајте го URL-то на кое бевте пренасочени (тоа е URL-то на вашиот профил). korisnickoime, soundcloud.com/korisnickoime Треба да знаеш дека оваа операција троши многу интернет. \n \nСакаш да продолжиш? - Контрола на брзина на траката + Контрола на брзината на траката Темпо Тон Откачи (може да создаде мутации) - Nightcore + „Nightcore“ Стандардно - +Избриши историја на гледаност + Ја брише историјата на пуштени видеа. + Избриши ја целата историја на гледаност. + Избришана е историјата на гледаност. + Избриши историја на пребарувања + Ја брише историјата на пребарувања. + Избриши ја целата историја на пребарувања. + Избришана е историјата на пребарувања. + Нема стримови за симнување + + 1 ставка избришана. + + Нема апликација за пуштање на овој фајл + + NewPipe е „copyleft“ слободен софтвер: Можеш да ја користиш, истражуваш и подобруваш по твоја желба. Можеш да ја редистрибуираш и/или да ја промениш под условите на GNU GPL лиценцата, публикувана од фондацијата FSF - или верзија 3 од лиценцата, или (по можност) понова верзија. + Дали сакаш да се внесат и подесувањата? + + Преферирана акција за „отворање“ + Стандардна акција при отворање видеа — %s + + Преводи + Смени ја големината и стилот на преводот. Потребен е рестарт за промена. + + From 882fbf927567c617d70510a888c0ebee6ddbc189 Mon Sep 17 00:00:00 2001 From: DafabHoid Date: Fri, 18 May 2018 18:18:37 +0200 Subject: [PATCH 14/80] Fix crash on loading not yet finished downloads from .giga files --- .../main/java/us/shandian/giga/get/DownloadMission.java | 8 ++++++++ 1 file changed, 8 insertions(+) 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 c48e5ffbc..f02eaae28 100644 --- a/app/src/main/java/us/shandian/giga/get/DownloadMission.java +++ b/app/src/main/java/us/shandian/giga/get/DownloadMission.java @@ -5,6 +5,7 @@ import android.os.Looper; import android.util.Log; import java.io.File; +import java.io.ObjectInputStream; import java.io.Serializable; import java.lang.ref.WeakReference; import java.util.ArrayList; @@ -312,6 +313,13 @@ public class DownloadMission implements Serializable { } } + private void readObject(ObjectInputStream inputStream) + throws java.io.IOException, ClassNotFoundException + { + inputStream.defaultReadObject(); + mListeners = new ArrayList<>(); + } + private void deleteThisFromFile() { new File(getMetaFilename()).delete(); } From ae8121b680a3c11f1a21f3091278510804f0f8f3 Mon Sep 17 00:00:00 2001 From: DafabHoid Date: Fri, 18 May 2018 18:23:32 +0200 Subject: [PATCH 15/80] Utility: Buffer the output to files when serializing --- .../java/us/shandian/giga/util/Utility.java | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) 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 2d44e8c15..de9a16a1b 100644 --- a/app/src/main/java/us/shandian/giga/util/Utility.java +++ b/app/src/main/java/us/shandian/giga/util/Utility.java @@ -12,6 +12,7 @@ import android.widget.Toast; import org.schabi.newpipe.R; import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; @@ -59,17 +60,17 @@ public class Utility { ObjectOutputStream objectOutputStream = null; try { - objectOutputStream = new ObjectOutputStream(new FileOutputStream(fileName)); + objectOutputStream = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(fileName))); objectOutputStream.writeObject(serializable); } catch (Exception e) { //nothing to do - } - - if(objectOutputStream != null) { - try { - objectOutputStream.close(); - } catch (Exception e) { - //nothing to do + } finally { + if(objectOutputStream != null) { + try { + objectOutputStream.close(); + } catch (Exception e) { + //nothing to do + } } } } From f84aff63e34adb7fbd011df1d3c5fc38cf97c03d Mon Sep 17 00:00:00 2001 From: AB Date: Fri, 18 May 2018 17:06:33 +0000 Subject: [PATCH 16/80] Translated using Weblate (Ukrainian) Currently translated at 100.0% (365 of 365 strings) --- app/src/main/res/values-uk/strings.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 4a06e9a1e..914b294ea 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -461,4 +461,6 @@ Видалено один фраґмент. "NewPipe є вільною копілефт програмою: Ви можете використовувати її, поширювати та вдосконавлювати за власним розсудом. Зокрема ви можете перерозподіляти та/або змінювати її за умов використання GNU General Public License, опублікованою Free Software Foundation, під 3-ю версією ліцензії, або (на ваш вибір) будь-якою пізнішою версією." + Чи ви також бажаєте імпортувати налаштування? + From 1c752b0e185903c62ae593f769e1f1a510ff6fda Mon Sep 17 00:00:00 2001 From: Nishargo Nigar Date: Fri, 18 May 2018 06:05:44 +0000 Subject: [PATCH 17/80] Translated using Weblate (Bengali (Bangladesh)) Currently translated at 34.2% (125 of 365 strings) --- app/src/main/res/values-bn-rBD/strings.xml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/app/src/main/res/values-bn-rBD/strings.xml b/app/src/main/res/values-bn-rBD/strings.xml index 1034e361c..466f71a55 100644 --- a/app/src/main/res/values-bn-rBD/strings.xml +++ b/app/src/main/res/values-bn-rBD/strings.xml @@ -5,15 +5,15 @@ প্রকাশকাল %1$s কোন স্ট্রিম প্লেয়ার পাওয়া যায়নি। তুমি কি VLC ইনস্টল করতে চাও? ইনস্টল - বাদ দাও + "বাদ দিন " - ব্রাউজারে খোলো - পপআপ মোডে খোলো + "ব্রাউজারে ওপেন করো " + "popup মোডে Open করো " শেয়ার ডাউনলোড খোঁজ - সেটিং - তুমি কি বলতে চাচ্ছ %1$s ? + "সেটিংস " + আপনি কি বুঝিয়েছেনঃ %1$s ? শেয়ার কর ব্রাউজার পছন্দ কর রোটেশন @@ -200,4 +200,5 @@ সেটিংস ওয়েব সাইট খুলুন ওয়েব সাইট + "কোন স্ট্রিম প্লেয়ার পাওয়া যায়নি (প্লে করতে VLC ইন্সটল করতে পারেন) " From 006c4ecb029a0ffa695876909931256dbd01b2f1 Mon Sep 17 00:00:00 2001 From: Osoitz Date: Fri, 18 May 2018 08:24:23 +0000 Subject: [PATCH 18/80] Translated using Weblate (Basque) Currently translated at 100.0% (365 of 365 strings) --- app/src/main/res/values-eu/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values-eu/strings.xml b/app/src/main/res/values-eu/strings.xml index 2e82edf74..570a9a064 100644 --- a/app/src/main/res/values-eu/strings.xml +++ b/app/src/main/res/values-eu/strings.xml @@ -455,6 +455,6 @@ Bilaketa ez zehatzak posizioak azkarrago baina prezisio gutxiagoz bilatzea ahalbidetzen du "Desgaitu iruditxoak kargatzea gelditzeko eta datuak eta memoria aurrezteko. Hau aldatzean memoria eta diskoko irudien cache-ak garbituko dira." NewPipe Software Librea eta Copyleft da: Nahi eran erabili, ikertu, partekatu eta hobetu dezakezu. Zehazki, elkarbanatzea eta aldatzea Free Software Foundation-ek argitaratutako GNU General Public License-ren 3. bertsioa edo berriagoren baten terminoen arabera egiteko baimena duzu. - Behartu aktibitatearen bizitza ziklotik kanpo baztertu eta gero entregatu ezin diren Rx salbuespenen inguruko txostena. + Behartu aktibitatearen bizitza ziklotik kanpo baztertu eta gero entregatu ezin diren Rx salbuespenen inguruko txostena From 9b3f19c19bd07db57bf7abd176429331e2d343e8 Mon Sep 17 00:00:00 2001 From: lartial Date: Sun, 20 May 2018 01:56:29 +0000 Subject: [PATCH 19/80] Translated using Weblate (Indonesian) Currently translated at 100.0% (365 of 365 strings) --- app/src/main/res/values-id/strings.xml | 86 +++++++++++++------------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/app/src/main/res/values-id/strings.xml b/app/src/main/res/values-id/strings.xml index 024bbf0b0..44973426f 100644 --- a/app/src/main/res/values-id/strings.xml +++ b/app/src/main/res/values-id/strings.xml @@ -50,7 +50,7 @@ Putar Konten Tampilkan konten batasan usia - Video Dibatasi Usia. Aktifkan video batasan usia bisa lewat Pengaturan. + "Video Dibatasi Usia. Memperbolehkan ditonton dapat diatur lewat Pengaturan." Galat jaringan Tidak bisa memuat semua Thumbnail Maksud Anda: %1$s ? @@ -66,12 +66,12 @@ Konten tidak tersedia Diblokir oleh GEMA Tidak bisa menyiapkan menu unduhan - Ini adalah SIARAN LANGSUNG, yang mana ini belum didukung. + Ini adalah SIARAN LANGSUNG, yang sekarang ini belum didukung. Tidak bisa memuat gambar Maaf, hal tersebut seharusnya tidak terjadi. Lapor galat via surat elektronik Maaf, telah terjadi galat. - LAPOR + LAPORKAN Info: Yang terjadi: Komentar Anda (dalam bahasa Inggris): @@ -154,7 +154,7 @@ membuka di mode popup Format video baku - Resolusi popup bawaan + Resolusi popup baku Tampilkan resolusi yang lebih tinggi Hanya perangkat tertentu yang mendukung pemutaran video 2K/4K Latar Belakang @@ -199,11 +199,11 @@ membuka di mode popup Aplikasi streaming gratis dan ringan untuk Android. Lihat di Github Lisensi NewPipe - Terlepas apakah Anda memiliki ide, terjemahan, perubahan desain, pembersihan kode, atau perubahan kode yang signifikan, segala bantuan akan selalu diterima. Semakin banyak akan semakin baik jadinya! + Terlepas apakah Anda memiliki ide untuk; terjemahan, perubahan desain, pembersihan kode, atau perubahan kode yang signifikan, segala bantuan akan selalu diterima. Semakin banyak akan semakin baik jadinya! Baca lisensi Kontribusi Berlangganan - Langganan + Masih Berlangganan Apa Yang Baru Lanjutkan saat fokus @@ -227,37 +227,37 @@ membuka di mode popup Otomatis tambahkan stream yang terkait ketika memutar stream terakhir dalam antrean tanpa perulangan. Simpan daftar video yang telah ditonton Tampilkan tip \"tahan untuk menambahkan\" - Tampilkan tip ketika belakang layar atau tombol popup ditekan pada laman detail video + Tampilkan tip ketika tombol latar belakang atau popup ditekan pada halaman detail video Negara konten baku Layanan Pemutar Perilaku Riwayat & Tembolok Debug - Mengantri di belakang pemutar - Mengantri di pemutar sembulan - Daftar putar + Mengantre di belakang pemutar + Mengantre di popup pemutar + Daftar Putar Tidak jadi Putar Semua Selalu Hanya Sekali Berkas - Notifikasi untuk Layar Belakang NewPipe dan Pemutar Sembulan + "Notifikasi untuk Latar Belakang NewPipe dan Popup Pemutar " [Tidak diketahui] Ubah Orientasi Kembali ke Layar Belakang - Kembali ke Sembulan + Kembali ke Popup Kembali ke Utama - Impor basis data - Ekspor basis data + Impor database + Ekspor database Akan menimpa riwayat dan langganan kamu saat ini - Ekspor riwayat, langganan dan daftar putar. + Ekspor riwayat, daftat langganan dan daftar putar. Tidak bisa memutar stream ini - Galat yg tidak bisa dibetulkan terjadi di pemutar + Galat yg tidak bisa dipulihkan terjadi di pemutar Memulihkan dari galat pemutar Playar eksternal tidak mendukung tipe tautan ini URL tidak valid @@ -265,7 +265,7 @@ membuka di mode popup Stream audio tidak ditemukan Direktori tidak valid Berkas/konten sumber tidak valid - Berkas tidak ada atau tidak memiliki izin untuk membaca atau menulisnya + Berkas tid tersedia atau tidak memiliki izin untuk membaca atau menulisnya Nama berkas tidak boleh kosong Sebuah galat terjadi: %1$s @@ -296,7 +296,7 @@ membuka di mode popup Donasi NewPipe dikembangkan oleh relawan yang menyisihkan waktu untuk memberi Anda pengalaman terbaik. Berikan dukungan kepada pengembang membuat NewPipe menjadi lebih baik lagi sembari menikmati secangkir kopi. - Beri balik + Beri dukungan Situs Kunjungi situs web NewPipe untuk info dan berita. Sudah dicari @@ -305,48 +305,48 @@ membuka di mode popup Kamu ingin menghapus item ini dari riwayat pencarian? Kamu ingin menghapus item ini dari riwayat tontonan? Kamu yakin ingin menghapus semua item dari riwayat? - Diputar Terakhir + Terakhir Diputar Paling sering Diputar Konten laman utama Laman Kosong - Laman Kiosk + Laman Kios Laman Langganan Laman Umpan Laman Kanal Pilih sebuah kanal Tidak ada kanal yg dilanggani - Pilih sebuah kiosk + Pilih sebuah kios Ekspor berhasil Impor berhasil Berkas ZIP tidak valid Perhatian: Tidak dapat mengimpor semua berkas. Ini akan menimpa pengaturan kamu saat ini. - Kiosk + Kios Tren Top 50 Baru & Panas - Pemutar Layar Belakang - Pemutar Sembulan + Pemutar Latar Belakang + Popup Pemutar Hapus Rincian Pengaturan Audio - Tahan Untuk Mengantri - Antri di Layar Belakang - Antri di Sembulan - Mulai Putar Disini - Mulai Disini di Layar Belakang - Mulai Disini di Sembulan + Tahan Untuk Mengantre + Antre di Latar Belakang + Antre di Popup + Mulai Putar di Sini + Mulai Disini di Latar Belakang + Mulai Disini dengan Popup - Bukan Menu + Buka Menu Tutup Menu Sesuatu akan muncul di sini segera ;D Pemutar video - Pemutar Layar Belakang - Pemutar sembulan + Pemutar Latar Belakang + Popup pemutar Selalu tanya Mendapatkan info… @@ -368,7 +368,7 @@ membuka di mode popup Thumbnail daftar putar diubah Tidak bisa menghapus daftar putar - Tidak ada Caption + Tidak Ada Takarir Pas Isi @@ -385,7 +385,7 @@ membuka di mode popup Bawaan Tidak ada aplikasi pemutar stream (Anda bisa memasang VLC untuk memutarnya) Unduh berkas stream. - Tidak bisa merubah langganan + Tidak bisa mengubah langganan Tampilkan info Tambahkan Ke @@ -411,20 +411,20 @@ membuka di mode popup Berhenti langganan channel ini Tidak dapat memperbarui langganan Langganan - Gunakan pencarian dengan cepat dengan tidak tepat + Gunakan pencarian cepat yang tidak beraturan Pencarian tidak beraturan memungkinkan pengguna untuk mencari posisi lebih cepat dengan ketepatan yang berkurang NewPipe adalah perangkat lunak libre copyleft: Anda dapat menggunakannya, mempelajarinya, berbagi, dan meningkatkannya sesuai keinginan Anda. Secara khusus Anda dapat mendistribusikan ulang dan/atau memodifikasinya di bawah syarat-syarat Lisensi GNU General Public License yang diterbitkan oleh Free Software Foundation, baik versi 3 dari Lisensi, atau (sesuai pilihan Anda) versi yang lebih baru. Apa Anda ingin juga mengimpor pengaturan? - Lebih disukai tindakan \'terbuka\' + Tindakan \'buka\' yang disukai Aksi bawaan ketika membuka konten — %s - Keterangan - Mengubah skala keterangan teks pemutar dan gaya latar belakang. Perlu memulai ulang aplikasi agar berdampak. + Takarir + Mengubah skala keterangan teks pemutar dan gaya latar belakang. Perlu memulai ulang aplikasi untuk melihat hasilnya. Pemantauan kebocoran memori dapat menyebabkan aplikasi menjadi tidak responsif saat terjadi dumping - Laporkan Kesalahan di Luar-Siklus + Laporkan Kesalahan di-Luar-Siklus Memaksa pelaporan pengecualian Rx yang tidak dapat dikirim di luar kepingan atau siklus hidup aktivitas setelah dibuang Impor/Ekspor @@ -441,16 +441,16 @@ membuka di mode popup Tidak dapat mengimpor langganan Tidak dapat mengekspor langganan - Impor langganan YouTube dengan mengunduh file ekspor: + Impor daftar langganan YouTube dengan mengunduh file ekspor: \n \n1. Pergi ke URL ini: %1$s -\n2. Masuk ketika disuruh +\n2. Masuk ketika ditanya \n3. Unduhan akan dimulai (Itulah file ekspornya) Untuk mengimpor profil SoundCloud dengan mengetik URL atau ID Anda: \n \n1. Nyalakan \"mode desktop\" di web-browser (situsnya tidak tersedia untuk perangkat mobile) \n2. Pergi ke URL ini: %1$s -\n3. Masuk ketika disuruh +\n3. Log in ketika ditanya \n4. Salin URL profil Anda ketika dialihkan. IDanda, soundcloud.com/idanda From 1fa541776b7e0498e9665d6b0c130c64ccc2745b Mon Sep 17 00:00:00 2001 From: SN Date: Mon, 21 May 2018 06:13:00 +0000 Subject: [PATCH 20/80] Translated using Weblate (Hindi) Currently translated at 80.0% (292 of 365 strings) --- app/src/main/res/values-hi/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/res/values-hi/strings.xml b/app/src/main/res/values-hi/strings.xml index 783390be8..64656d801 100644 --- a/app/src/main/res/values-hi/strings.xml +++ b/app/src/main/res/values-hi/strings.xml @@ -376,4 +376,5 @@ हीप डंप करने के दौरान मेमोरी लीक मॉनिटरिंग app को अनुत्तरदायी बना सकता है Out-of-Lifecycle त्रुटियों की रिपोर्ट करें + छायाप्रारुप लोड करें From dd467b4d63bdec441e8c7308055b2dcad36f8c2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Allan=20Nordh=C3=B8y?= Date: Mon, 21 May 2018 08:34:14 +0000 Subject: [PATCH 21/80] =?UTF-8?q?Translated=20using=20Weblate=20(Norwegian?= =?UTF-8?q?=20Bokm=C3=A5l)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently translated at 96.1% (351 of 365 strings) --- app/src/main/res/values-nb-rNO/strings.xml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/app/src/main/res/values-nb-rNO/strings.xml b/app/src/main/res/values-nb-rNO/strings.xml index 3a1eb60d1..3a5ca33a2 100644 --- a/app/src/main/res/values-nb-rNO/strings.xml +++ b/app/src/main/res/values-nb-rNO/strings.xml @@ -457,4 +457,14 @@ \n1. Skru på \"skrivebordsmodus\" i en nettleser ( siden er ikke tilgjengelig for mobile enheter) \n2. Logg inn når forespurt \n4. Kopier profil-nettadressen du ble videresendt til. + Unøyaktig blafring tillater spilleren å blafre til posisjoner raskere med redusert nøyaktighet + Skru av for å stoppe alle miniatyrbilder fra innlasting og spare data og minnebruke. Endring av dette vil tømme både disk- og minne-hurtiglager. + Legg til en relatert strøm ved avspilling av forrige strøm i ikke-repeterende kø. + Minnelekkasjeoppsyn kan forårsake programmet å opptre uresponsivt under haugdumping + + Rapporter feil som opptrer utenfor sin levetid + Tving rapportering av uleverbare Rx-unntak utenom fragment eller aktivitetslevetid etter forkastelse + + Avhekt (kan forårsake forvrenging) + Nightcore From 2834e5d78f60b253f7ec367be28fe47c09b904a8 Mon Sep 17 00:00:00 2001 From: Daria Szatan Date: Wed, 23 May 2018 16:59:47 +0000 Subject: [PATCH 22/80] Translated using Weblate (Polish) Currently translated at 100.0% (365 of 365 strings) --- app/src/main/res/values-pl/strings.xml | 63 ++++++++++++++++---------- 1 file changed, 39 insertions(+), 24 deletions(-) diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 77944149e..ca31bab9e 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -27,7 +27,7 @@ Podaj ścieżkę zapisu audio Autoodtwarzanie - Automatycznie odtwórz wideo, kiedy NewPipe zostanie wywołany z innej aplikacji + Odtwórz wideo, kiedy NewPipe zostanie wywołany z innej aplikacji Domyślna rozdzielczość Odtwórz w Kodi Aplikacja Kore nie została znaleziona. Zainstalować ją? @@ -43,7 +43,7 @@ Pobrane Następny film - Pokaż następne i podobne filmy + Pokaż \'następne\' i \'podobne\' filmy URL nieobsługiwany Domyślny język zawartości Wideo i audio @@ -180,7 +180,7 @@ Otwórz stronę O programie Licencje - Darmowa, lekka alternatywa YouTube dla Androida. + Wolne, lekkie przesyłanie strumieniowania na Androidzie. Zobacz na GitHubie Licencja NewPipe Jeżeli masz pomysł na tłumaczenie, zmiany w wyglądzie aplikacji, oczyszczenie kodu źródłowego, pomoc jest zawsze mile widziana. Im więcej jest zrobione, tym lepiej! @@ -203,7 +203,7 @@ Historia wyszukiwania Zapisuj lokalnie historię wyszukiwania - Historia + Historia i pamięć podręczna Zapisuj historię oglądania Wznów gdy na pierwszym planie Kontynuuj odtwarzanie po przerwaniu (np. po rozmowie telefonicznej) @@ -237,7 +237,7 @@ [Nieznany] - Nie udało się odtworzyć strumienia + Nie można odtworzyć strumienia Wystąpił nieodwracalny błąd odtwarzacza Odzyskiwanie po błędzie odtwarzacza @@ -266,7 +266,7 @@ Większość znaków specjalnych Dotacja - NewPipe rozwijane jest przez wolontariuszy, którzy poświęcają swój wolny czas, by zapewnić ci jak najlepsze wrażenia podczas korzystania z aplikacji. To dobry moment aby wesprzeć programistów i sprawić, aby program był jeszcze lepszy, nie przerywając przy tym popijania kawy! + NewPipe rozwijane jest przez wolontariuszy, którzy poświęcają swój wolny czas, by zapewnić ci jak najlepsze wrażenia podczas korzystania z aplikacji. To dobry moment, aby wesprzeć programistów i sprawić, by program był jeszcze lepszy, nie przerywając przy tym popijania kawy! Daj od siebie Witryna By otrzymać więcej informacji oraz najnowsze wiadomości o NewPipe, odwiedź naszą stronę. @@ -298,7 +298,7 @@ Odtwórz teraz Odtwórz w tle Odtwórz w okienku -Nie znaleziono odtwarzacza strumieniowego (żeby odtworzyć możesz zainstalować VLC) +Nie znaleziono odtwarzacza strumieniowego (żeby odtworzyć, możesz zainstalować VLC) Domyślny kraj zawartości Usługa Zawsze @@ -316,7 +316,7 @@ Pytaj za każdym razem Informacje… - Ładuję żądaną zawartość + Ładowanie żądanej zawartości Pobierz plik strumienia. Pokaż informacje @@ -370,16 +370,16 @@ Usuń z zakładek Czy chcesz usunąć playlistę? - Playlista utworzona pomyślnie + Playlista utworzona Dodano do playlisty Miniaturka playlisty zmieniona - Błąd podczas usuwania playlisty + Nie można usunąć playlisty Bez napisów - DOPASUJ - WYPEŁNIJ - POWIĘKSZ + Dopasuj + Wypełnij + Powiększ Wygenerowane automatycznie Rozmiar czcionki etykiet @@ -438,24 +438,39 @@ Tempo Wysokość dźwięku Domyślna -twojeid, soundcloud.com/twojeid +twojeID, soundcloud.com/twojeid Odczep (może powodować zniekształcenia) Nightcore - "Aby zaimportować obserwowane z SoundCloud, musisz znać identyfikator lub link do swojego profilu. Jeśli znasz którykolwiek z nich, po prostu wpisz go w polu poniżej. -\n -\nW przeciwnym wypadku spróbuj poniższych kroków: -\n -\n1. Włącz \"tryb stacjonarny\" w przeglądarce (strona z której zaraz skorzystasz nie jest dostępna w trybie mobilnym) -\n2. Odwiedź stronę: %1$s -\n3. Zaloguj się na swoje konto -\n4. Skopiuj adres, na który przeglądarka przekieruje cię po zalogowaniu (to jest adres twojego profilu)" + Aby zaimportować obserwowane z SoundCloud, musisz znać identyfikator lub link do swojego profilu. Jeśli znasz którykolwiek z nich, po prostu wpisz go w polu poniżej. +\n +\nW przeciwnym wypadku spróbuj poniższych kroków: +\n +\n1. Włącz \"tryb stacjonarny\" w przeglądarce (strona, z której zaraz skorzystasz, nie jest dostępna w trybie mobilnym) +\n2. Odwiedź stronę: %1$s +\n3. Zaloguj się na swoje konto +\n4. Skopiuj adres, na który przeglądarka przekieruje cię po zalogowaniu (to jest adres twojego profilu). Brak źródeł do pobrania - Preferowana akcja podczas otwierania + Preferowana akcja podczas \'otwierania\' Domyślna akcja podczas otwierania materiału - %s Napisy - Zmień kolor tekstu i tła napisów. Wymaga restartu odtwarzacza. + Zmień kolor tekstu i tła napisów. Wymaga restartu aplikacji. + + Wyczyść historię oglądania + Usuwa historię odtworzonych strumieni. + Usuń całą historię oglądania. + Usunięto historię oglądania. + Wyczyść historię wyszukiwania + Usuwa historię wyszukiwania słów kluczowych. + Usuń całą historię wyszukiwania. + Usunięto historię wyszukiwania. + Usunięto jedną pozycję. + + Nie zainstalowano aplikacji do odtworzenia tego pliku + + NewPipe jest wolnym i bezpłatnym oprogramowaniem: Możesz używać, brać udział oraz udoskonalać je według własnego uznania. W szczególności możesz redystrybuować lub/i modyfikować pod zasadami GNU General Public License opublikowanej przez Free Software Fundation w wersji 3 lub (w zależności od ciebie) dowolnej późniejszej wersji. + Czy chcesz zaimportować również ustawienia? From 93605774f02d4b8df097e67687abcc51e03cc340 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?SINUS=20=28=E0=A6=B8=E0=A6=BE=E0=A6=87=E0=A6=A8=E0=A6=BE?= =?UTF-8?q?=E0=A6=B8=29?= Date: Wed, 23 May 2018 15:30:38 +0000 Subject: [PATCH 23/80] Translated using Weblate (Bengali (Bangladesh)) Currently translated at 40.0% (146 of 365 strings) --- app/src/main/res/values-bn-rBD/strings.xml | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/app/src/main/res/values-bn-rBD/strings.xml b/app/src/main/res/values-bn-rBD/strings.xml index 466f71a55..859e16aa9 100644 --- a/app/src/main/res/values-bn-rBD/strings.xml +++ b/app/src/main/res/values-bn-rBD/strings.xml @@ -25,12 +25,12 @@ পপআপ ভিডিও ডাউনলোড করার পাথ - ডাউনলোড করা ভিডিও সঞ্চয় করার পাথ। + ডাউনলোড করা ভিডিওগুলো রাখার ফোল্ডার ভিডিওগুলির জন্য ডাউনলোডের পাথ প্রবেশ করাও অডিও ডাউনলোড পাথ ডাউনলোড করা অডিও সঞ্চয় করার পাথ - অডিও ফাইলগুলির জন্য ডাউনলোডের পাথ প্রবেশ করাও। + অডিও ফাইলগুলির জন্য ডাউনলোডের পাথ প্রবেশ করাও স্বয়ংক্রিয়ভাবে প্লে করো যখন অন্য অ্যাপ্লিকেশন থেকে চালু করা হয় স্বয়ংক্রিয়ভাবে একটি ভিডিও প্লে করো যখন NewPipe অন্য অ্যাপ্লিকেশন থেকে চালু করা হয়। @@ -42,7 +42,7 @@ Kore অ্যাপ্লিকেশন খুঁজে পাওয়া যায়নি। Kore ইনস্টল করবে? দেখাও \"Kodi এর মাধ্যমে চালাও \" বিকল্প - Kodi মিডিয়া সেন্টারে এর মাধ্যমে ভিডিও প্লে করার জন্য একটি বিকল্প প্রদর্শন কর। + Kodi মিডিয়া সেন্টারে এর মাধ্যমে ভিডিও প্লে করার জন্য একটি বিকল্প প্রদর্শন কর অডিও ডিফল্ট অডিও ফরম্যাট পছন্দসই ভিডিও ফরম্যাট @@ -201,4 +201,15 @@ ওয়েব সাইট খুলুন ওয়েব সাইট "কোন স্ট্রিম প্লেয়ার পাওয়া যায়নি (প্লে করতে VLC ইন্সটল করতে পারেন) " + যদি এই অপশন অন থাকে তবে কিছু ভিডিওর অডিও কাজ নাও করতে পারে + সাবস্ক্রাইব + সাবস্ক্রাইব করা আছে + চ্যানেল সাবস্ক্রাইব করা হয়েছে + সাবস্ক্রিপশন পরিবর্তন করা হয়নি + সাবস্ক্রিপশন আপডেট করতে ব্যার্থ হয়েছে + প্রধান + সাবস্ক্রিপশন + বুকমার্কস + + দ্রুত টানা ব্যাবহার করুন From 73a71e0f5cbe1ed7230b5db88e7428af6748ca10 Mon Sep 17 00:00:00 2001 From: Bogdan Khomutsky Date: Fri, 25 May 2018 06:22:43 +0000 Subject: [PATCH 24/80] Translated using Weblate (Russian) Currently translated at 100.0% (365 of 365 strings) --- app/src/main/res/values-ru/strings.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index ff52dd10c..8cf32c61f 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -472,4 +472,6 @@ NewPipe - программное обеспечение copyleft libre: вы можете использовать, изучать и улучшать его по своему усмотрению. В частности, вы можете распространять и/или изменять его в соответствии с GNU General Public License, опубликованным Free Software Foundation, либо версией 3 License, либо (по вашему выбору) любой более поздней версии. Предпочтительное действие \'открытие\' + Желаете ли вы также импортировать настройки? + From c78cc6f2fdd7e8c8cd25337a06d33560954d5e3b Mon Sep 17 00:00:00 2001 From: TobiGr Date: Thu, 24 May 2018 17:10:28 +0200 Subject: [PATCH 25/80] Add dialog to accept privacy policy before sending crash report Add link to privacy policy in about fragment Replace some onClickListeners with Lamdas --- .../java/org/schabi/newpipe/MainActivity.java | 3 ++ .../schabi/newpipe/about/AboutActivity.java | 38 ++++++------------- .../newpipe/about/LicenseFragmentHelper.java | 2 +- .../schabi/newpipe/report/ErrorActivity.java | 35 +++++++++++++---- app/src/main/res/layout/fragment_about.xml | 21 ++++++++++ app/src/main/res/values/strings.xml | 9 +++++ 6 files changed, 72 insertions(+), 36 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/MainActivity.java b/app/src/main/java/org/schabi/newpipe/MainActivity.java index 0ce6772bb..22fa661d3 100644 --- a/app/src/main/java/org/schabi/newpipe/MainActivity.java +++ b/app/src/main/java/org/schabi/newpipe/MainActivity.java @@ -20,6 +20,9 @@ package org.schabi.newpipe; +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; diff --git a/app/src/main/java/org/schabi/newpipe/about/AboutActivity.java b/app/src/main/java/org/schabi/newpipe/about/AboutActivity.java index 962ec8a36..0450290d2 100644 --- a/app/src/main/java/org/schabi/newpipe/about/AboutActivity.java +++ b/app/src/main/java/org/schabi/newpipe/about/AboutActivity.java @@ -128,47 +128,31 @@ public class AboutActivity extends AppCompatActivity { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_about, container, false); + Context context = this.getContext(); + TextView version = rootView.findViewById(R.id.app_version); version.setText(BuildConfig.VERSION_NAME); View githubLink = rootView.findViewById(R.id.github_link); - githubLink.setOnClickListener(new OnGithubLinkClickListener()); + githubLink.setOnClickListener(nv -> openWebsite(context.getString(R.string.github_url), context)); View donationLink = rootView.findViewById(R.id.donation_link); - donationLink.setOnClickListener(new OnDonationLinkClickListener()); + donationLink.setOnClickListener(v -> openWebsite(context.getString(R.string.donation_url), context)); View websiteLink = rootView.findViewById(R.id.website_link); - websiteLink.setOnClickListener(new OnWebsiteLinkClickListener()); + websiteLink.setOnClickListener(nv -> openWebsite(context.getString(R.string.website_url), context)); + + View privacyPolicyLink = rootView.findViewById(R.id.privacy_policy_link); + privacyPolicyLink.setOnClickListener(v -> openWebsite(context.getString(R.string.privacy_policy_url), context)); return rootView; } - private static class OnGithubLinkClickListener implements View.OnClickListener { - @Override - public void onClick(final View view) { - final Context context = view.getContext(); - Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(context.getString(R.string.github_url))); - context.startActivity(intent); - } + private void openWebsite(String url, Context context) { + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); + context.startActivity(intent); } - private static class OnDonationLinkClickListener implements View.OnClickListener { - @Override - public void onClick(final View view) { - final Context context = view.getContext(); - Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(context.getString(R.string.donation_url))); - context.startActivity(intent); - } - } - - private static class OnWebsiteLinkClickListener implements View.OnClickListener { - @Override - public void onClick(final View view) { - final Context context = view.getContext(); - Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(context.getString(R.string.website_url))); - context.startActivity(intent); - } - } } diff --git a/app/src/main/java/org/schabi/newpipe/about/LicenseFragmentHelper.java b/app/src/main/java/org/schabi/newpipe/about/LicenseFragmentHelper.java index e4436322a..701e18cbf 100644 --- a/app/src/main/java/org/schabi/newpipe/about/LicenseFragmentHelper.java +++ b/app/src/main/java/org/schabi/newpipe/about/LicenseFragmentHelper.java @@ -42,7 +42,7 @@ public class LicenseFragmentHelper extends AsyncTask { } @Override - protected void onPostExecute(Integer result){ + protected void onPostExecute(Integer result) { Activity activity = getActivity(); if (activity == null) { return; diff --git a/app/src/main/java/org/schabi/newpipe/report/ErrorActivity.java b/app/src/main/java/org/schabi/newpipe/report/ErrorActivity.java index 1b60c596f..3ad08c3ec 100644 --- a/app/src/main/java/org/schabi/newpipe/report/ErrorActivity.java +++ b/app/src/main/java/org/schabi/newpipe/report/ErrorActivity.java @@ -1,7 +1,9 @@ package org.schabi.newpipe.report; import android.app.Activity; +import android.app.AlertDialog; import android.content.Context; +import android.content.DialogInterface; import android.content.Intent; import android.graphics.Color; import android.net.Uri; @@ -33,10 +35,8 @@ import org.json.JSONArray; import org.json.JSONObject; import org.schabi.newpipe.ActivityCommunicator; import org.schabi.newpipe.BuildConfig; -import org.schabi.newpipe.Downloader; import org.schabi.newpipe.MainActivity; import org.schabi.newpipe.R; -import org.schabi.newpipe.extractor.utils.Parser; import org.schabi.newpipe.util.ThemeHelper; import java.io.PrintWriter; @@ -44,9 +44,9 @@ import java.io.StringWriter; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; -import java.util.Locale; import java.util.TimeZone; import java.util.Vector; +import java.util.concurrent.atomic.AtomicBoolean; /* * Created by Christian Schabesberger on 24.10.15. @@ -210,12 +210,31 @@ public class ErrorActivity extends AppCompatActivity { currentTimeStamp = getCurrentTimeStamp(); reportButton.setOnClickListener((View v) -> { - Intent i = new Intent(Intent.ACTION_SENDTO); - i.setData(Uri.parse("mailto:" + ERROR_EMAIL_ADDRESS)) - .putExtra(Intent.EXTRA_SUBJECT, ERROR_EMAIL_SUBJECT) - .putExtra(Intent.EXTRA_TEXT, buildJson()); + Context context = this; + new AlertDialog.Builder(context) + .setIcon(android.R.drawable.ic_dialog_alert) + .setTitle(R.string.privacy_policy_title) + .setMessage(R.string.start_accept_privacy_policy) + .setCancelable(false) + .setNeutralButton(R.string.read_privacy_policy, (dialog, which) -> { + Intent webIntent = new Intent(Intent.ACTION_VIEW, + Uri.parse(context.getString(R.string.privacy_policy_url)) + ); + context.startActivity(webIntent); + }) + .setPositiveButton(R.string.accept, (dialog, which) -> { + Intent i = new Intent(Intent.ACTION_SENDTO); + i.setData(Uri.parse("mailto:" + ERROR_EMAIL_ADDRESS)) + .putExtra(Intent.EXTRA_SUBJECT, ERROR_EMAIL_SUBJECT) + .putExtra(Intent.EXTRA_TEXT, buildJson()); + + startActivity(Intent.createChooser(i, "Send Email")); + }) + .setNegativeButton(R.string.decline, (dialog, which) -> { + // do nothing + }) + .show(); - startActivity(Intent.createChooser(i, "Send Email")); }); // normal bugreport diff --git a/app/src/main/res/layout/fragment_about.xml b/app/src/main/res/layout/fragment_about.xml index 6e1db563a..320f72ab9 100644 --- a/app/src/main/res/layout/fragment_about.xml +++ b/app/src/main/res/layout/fragment_about.xml @@ -111,5 +111,26 @@ android:layout_gravity="end" android:text="@string/open_in_browser" /> + + + + +