From 40f00af1964b60ffa72e680078e84524a35c014c Mon Sep 17 00:00:00 2001 From: chschtsch Date: Tue, 29 Dec 2015 17:35:51 +0300 Subject: [PATCH 01/36] refactor localization --- .../java/org/schabi/newpipe/Localization.java | 79 +++++++++++++++++++ .../newpipe/VideoInfoItemViewCreator.java | 6 +- .../newpipe/VideoItemDetailFragment.java | 63 +++------------ .../org/schabi/newpipe/VideoListAdapter.java | 2 +- 4 files changed, 93 insertions(+), 57 deletions(-) create mode 100644 app/src/main/java/org/schabi/newpipe/Localization.java diff --git a/app/src/main/java/org/schabi/newpipe/Localization.java b/app/src/main/java/org/schabi/newpipe/Localization.java new file mode 100644 index 000000000..8b9689585 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/Localization.java @@ -0,0 +1,79 @@ +package org.schabi.newpipe; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.SharedPreferences; +import android.content.res.Resources; +import android.preference.PreferenceManager; + +import java.text.DateFormat; +import java.text.NumberFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +/** + * Created by chschtsch on 12/29/15. + */ + +public class Localization { + + public static Context contextOfApplication = null; + + public static Locale getPreferredLocale(Context context) { + SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context); + + String languageCode = sp.getString(String.valueOf(R.string.searchLanguage), "en"); + + if(languageCode.length() == 2) { + return new Locale(languageCode); + } + else if(languageCode.contains("_")) { + String country = languageCode + .substring(languageCode.indexOf("_"), languageCode.length()); + return new Locale(languageCode.substring(0, 2), country); + } + return Locale.getDefault(); + } + + public static String localizeViewCount(long viewCount, Context context) { + Locale locale = getPreferredLocale(context); + + Resources res = context.getResources(); + String viewsString = res.getString(R.string.viewCountText); + + NumberFormat nf = NumberFormat.getInstance(locale); + String formattedViewCount = nf.format(viewCount); + return String.format(viewsString, formattedViewCount); + } + + public static String localizeNumber(long number, Context context) { + Locale locale = getPreferredLocale(context); + NumberFormat nf = NumberFormat.getInstance(locale); + return nf.format(number); + } + + private static String formatDate(String date, Context context) { + Locale locale = getPreferredLocale(context); + SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd"); + Date datum = null; + try { + datum = formatter.parse(date); + } catch (ParseException e) { + e.printStackTrace(); + } + + DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM, locale); + + return df.format(datum); + } + + public static String localizeDate(String date, Context context) { + Resources res = context.getResources(); + String dateString = res.getString(R.string.uploadDateText); + + String formattedDate = formatDate(date, context); + return String.format(dateString, formattedDate); + } +} diff --git a/app/src/main/java/org/schabi/newpipe/VideoInfoItemViewCreator.java b/app/src/main/java/org/schabi/newpipe/VideoInfoItemViewCreator.java index b7eaa4285..c2bbb069e 100644 --- a/app/src/main/java/org/schabi/newpipe/VideoInfoItemViewCreator.java +++ b/app/src/main/java/org/schabi/newpipe/VideoInfoItemViewCreator.java @@ -1,5 +1,6 @@ package org.schabi.newpipe; +import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -33,7 +34,7 @@ class VideoInfoItemViewCreator { this.inflater = inflater; } - public View getViewFromVideoInfoItem(View convertView, ViewGroup parent, VideoPreviewInfo info) { + public View getViewFromVideoInfoItem(View convertView, ViewGroup parent, VideoPreviewInfo info, Context context) { ViewHolder holder; if(convertView == null) { convertView = inflater.inflate(R.layout.video_item, parent, false); @@ -59,8 +60,7 @@ class VideoInfoItemViewCreator { if(!info.upload_date.isEmpty()) { holder.itemUploadDateView.setText(info.upload_date); } else { - //tweak if necessary: This is a hack to prevent having white space in the layout :P - holder.itemUploadDateView.setText(String.format("%d", info.view_count)); + holder.itemUploadDateView.setText(Localization.localizeViewCount(info.view_count, context)); } return convertView; diff --git a/app/src/main/java/org/schabi/newpipe/VideoItemDetailFragment.java b/app/src/main/java/org/schabi/newpipe/VideoItemDetailFragment.java index 0173c07de..92c25e2aa 100644 --- a/app/src/main/java/org/schabi/newpipe/VideoItemDetailFragment.java +++ b/app/src/main/java/org/schabi/newpipe/VideoItemDetailFragment.java @@ -1,9 +1,7 @@ package org.schabi.newpipe; -import android.annotation.SuppressLint; import android.app.Activity; import android.content.Intent; -import android.content.SharedPreferences; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; @@ -35,13 +33,7 @@ import android.view.MenuItem; import android.widget.Toast; import java.net.URL; -import java.text.DateFormat; -import java.text.NumberFormat; -import java.text.ParseException; -import java.text.SimpleDateFormat; import java.util.ArrayList; -import java.util.Date; -import java.util.Locale; import java.util.Vector; import org.schabi.newpipe.services.VideoExtractor; @@ -235,7 +227,7 @@ public class VideoItemDetailFragment extends Fragment { switch (info.errorCode) { case VideoInfo.NO_ERROR: { View nextVideoView = videoItemViewCreator - .getViewFromVideoInfoItem(null, nextVideoFrame, info.nextVideo); + .getViewFromVideoInfoItem(null, nextVideoFrame, info.nextVideo, getContext()); nextVideoFrame.addView(nextVideoView); @@ -253,31 +245,20 @@ public class VideoItemDetailFragment extends Fragment { uploaderView.setText(info.uploader); actionBarHandler.setChannelName(info.uploader); - Locale locale = getPreferredLocale(); - NumberFormat nf = NumberFormat.getInstance(locale); - String localisedViewCount = nf.format(info.view_count); - viewCountView.setText( - String.format( - res.getString(R.string.viewCountText), localisedViewCount)); + String localizedViewCount = Localization.localizeViewCount(info.view_count, getContext()); + viewCountView.setText(localizedViewCount); - thumbsUpView.setText(nf.format(info.like_count)); - thumbsDownView.setText(nf.format(info.dislike_count)); + String localizedLikeCount = Localization.localizeNumber(info.like_count, getContext()); + thumbsUpView.setText(localizedLikeCount); - @SuppressLint("SimpleDateFormat") - SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd"); - Date datum = null; - try { - datum = formatter.parse(info.upload_date); - } catch (ParseException e) { - e.printStackTrace(); - } + String localizedDislikeCount = Localization.localizeNumber(info.dislike_count, getContext()); + thumbsDownView.setText(localizedDislikeCount); - DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM, locale); + String localizedDate = Localization.localizeDate(info.upload_date, getContext()); + uploadDateView.setText(localizedDate); - String localisedDate = df.format(datum); - uploadDateView.setText( - String.format(res.getString(R.string.uploadDateText), localisedDate)); descriptionView.setText(Html.fromHtml(info.description)); + descriptionView.setMovementMethod(LinkMovementMethod.getInstance()); actionBarHandler.setServiceId(streamingServiceId); @@ -458,30 +439,6 @@ public class VideoItemDetailFragment extends Fragment { } } - - - /**Returns the java.util.Locale object which corresponds to the locale set in NewPipe's preferences. - * Currently not affected by the device's locale.*/ - private Locale getPreferredLocale() { - SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext()); - String languageKey = getContext().getString(R.string.searchLanguage); - //i know the following line defaults languageCode to "en", but java is picky about uninitialised values - // Schabi: well lint tels me the value is redundant. I'll suppress it for now. - @SuppressWarnings("UnusedAssignment") - String languageCode = "en"; - languageCode = sp.getString(languageKey, "en"); - - if(languageCode.length() == 2) { - return new Locale(languageCode); - } - else if(languageCode.contains("_")) { - String country = languageCode - .substring(languageCode.indexOf("_"), languageCode.length()); - return new Locale(languageCode.substring(0, 2), country); - } - return Locale.getDefault(); - } - private boolean checkIfLandscape() { DisplayMetrics displayMetrics = new DisplayMetrics(); getActivity().getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); diff --git a/app/src/main/java/org/schabi/newpipe/VideoListAdapter.java b/app/src/main/java/org/schabi/newpipe/VideoListAdapter.java index e85e74e22..70672d040 100644 --- a/app/src/main/java/org/schabi/newpipe/VideoListAdapter.java +++ b/app/src/main/java/org/schabi/newpipe/VideoListAdapter.java @@ -96,7 +96,7 @@ class VideoListAdapter extends BaseAdapter { @Override public View getView(int position, View convertView, ViewGroup parent) { - convertView = viewCreator.getViewFromVideoInfoItem(convertView, parent, videoList.get(position)); + convertView = viewCreator.getViewFromVideoInfoItem(convertView, parent, videoList.get(position), context); if(listView.isItemChecked(position)) { convertView.setBackgroundColor(ContextCompat.getColor(context,R.color.primaryColorYoutube)); From 48e299b2ac2586a07808fff8f4b28f645f34fd0c Mon Sep 17 00:00:00 2001 From: chschtsch Date: Tue, 29 Dec 2015 17:53:24 +0300 Subject: [PATCH 02/36] code cleanup --- app/src/main/java/org/schabi/newpipe/Localization.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/Localization.java b/app/src/main/java/org/schabi/newpipe/Localization.java index 8b9689585..b38c52a90 100644 --- a/app/src/main/java/org/schabi/newpipe/Localization.java +++ b/app/src/main/java/org/schabi/newpipe/Localization.java @@ -19,8 +19,6 @@ import java.util.Locale; public class Localization { - public static Context contextOfApplication = null; - public static Locale getPreferredLocale(Context context) { SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context); From f61b915894ee0c701a1407e27fe07e2c4a47d6e5 Mon Sep 17 00:00:00 2001 From: Greg Date: Tue, 29 Dec 2015 21:44:06 +0100 Subject: [PATCH 03/36] Translated using Weblate (Russian) Currently translated at 100.0% (48 of 48 strings) --- app/src/main/res/values-ru/strings.xml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index a2dbdd50f..36368fe09 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -51,4 +51,7 @@ Миниатюра аватара пользователся Дислайки Лайки - +Использовать внешний проигрыватель для видео + Использовать внешний проигрыватель для аудио + Проигрывание в фоновом режиме + From 78df57970330a2537faa77365ffc2685e47406cc Mon Sep 17 00:00:00 2001 From: Greg Date: Tue, 29 Dec 2015 21:45:44 +0100 Subject: [PATCH 04/36] Translated using Weblate (Hebrew) Currently translated at 100% (0 of 0 strings) Created new translation. --- app/src/main/res/values-he/strings.xml | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 app/src/main/res/values-he/strings.xml diff --git a/app/src/main/res/values-he/strings.xml b/app/src/main/res/values-he/strings.xml new file mode 100644 index 000000000..a6b3daec9 --- /dev/null +++ b/app/src/main/res/values-he/strings.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file From 43149fd832093a215842a06386d9b89f8dce2386 Mon Sep 17 00:00:00 2001 From: M2ck Date: Mon, 21 Dec 2015 14:20:08 +0100 Subject: [PATCH 05/36] Translated using Weblate (French) Currently translated at 100.0% (48 of 48 strings) --- app/src/main/res/values-fr/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 4800a7493..e1cfeeff0 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -49,4 +49,5 @@ Avatar de l\'utilisateur Utiliser un lecteur vidéo externe Utiliser un lecteur audio externe + Lecture en arrière-plan From e91fc225e1c9757aa4c78fd753ed6ae7c7df76ae Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Thu, 31 Dec 2015 21:53:14 +0100 Subject: [PATCH 06/36] after receiving panic trigger, quit remove from history This makes the app fully exit, and removes it from the Recent Apps listing with the goal of hiding whatever the user was currently watching, and/or searching for. PanicKit provides a common framework for creating "panic button" apps that can trigger actions in "panic responder" apps. In this case, the response is to lock the app, if it has been configured to do so https://dev.guardianproject.info/projects/panic/wiki --- app/src/main/AndroidManifest.xml | 13 +++++++ .../java/org/schabi/newpipe/ExitActivity.java | 36 +++++++++++++++++++ .../newpipe/PanicResponderActivity.java | 32 +++++++++++++++++ 3 files changed, 81 insertions(+) create mode 100644 app/src/main/java/org/schabi/newpipe/ExitActivity.java create mode 100644 app/src/main/java/org/schabi/newpipe/PanicResponderActivity.java diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 05eda83c5..ae3f5f056 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -84,5 +84,18 @@ android:name=".SettingsActivity" android:label="@string/title_activity_settings" > + + + + + + + diff --git a/app/src/main/java/org/schabi/newpipe/ExitActivity.java b/app/src/main/java/org/schabi/newpipe/ExitActivity.java new file mode 100644 index 000000000..c193ffbde --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/ExitActivity.java @@ -0,0 +1,36 @@ + +package org.schabi.newpipe; + +import android.annotation.SuppressLint; +import android.app.Activity; +import android.content.Intent; +import android.os.Build; +import android.os.Bundle; + +public class ExitActivity extends Activity { + + @SuppressLint("NewApi") + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + if (Build.VERSION.SDK_INT >= 21) { + finishAndRemoveTask(); + } else { + finish(); + } + + System.exit(0); + } + + public static void exitAndRemoveFromRecentApps(Activity activity) { + Intent intent = new Intent(activity, ExitActivity.class); + + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK + | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS + | Intent.FLAG_ACTIVITY_CLEAR_TASK + | Intent.FLAG_ACTIVITY_NO_ANIMATION); + + activity.startActivity(intent); + } +} diff --git a/app/src/main/java/org/schabi/newpipe/PanicResponderActivity.java b/app/src/main/java/org/schabi/newpipe/PanicResponderActivity.java new file mode 100644 index 000000000..e9bf0e985 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/PanicResponderActivity.java @@ -0,0 +1,32 @@ + +package org.schabi.newpipe; + +import android.annotation.SuppressLint; +import android.app.Activity; +import android.content.Intent; +import android.os.Build; +import android.os.Bundle; + +public class PanicResponderActivity extends Activity { + + public static final String PANIC_TRIGGER_ACTION = "info.guardianproject.panic.action.TRIGGER"; + + @SuppressLint("NewApi") + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + Intent intent = getIntent(); + if (intent != null && PANIC_TRIGGER_ACTION.equals(intent.getAction())) { + // TODO explicitly clear the search results once they are restored when the app restarts + // or if the app reloads the current video after being killed, that should be cleared also + ExitActivity.exitAndRemoveFromRecentApps(this); + } + + if (Build.VERSION.SDK_INT >= 21) { + finishAndRemoveTask(); + } else { + finish(); + } + } +} From 6deb67437798738e0d27a8a353e027023b6c775f Mon Sep 17 00:00:00 2001 From: Greg Date: Tue, 29 Dec 2015 22:23:26 +0100 Subject: [PATCH 07/36] Translated using Weblate (Hebrew) Currently translated at 16.6% (8 of 48 strings) --- app/src/main/res/values-he/strings.xml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/values-he/strings.xml b/app/src/main/res/values-he/strings.xml index a6b3daec9..a11e14119 100644 --- a/app/src/main/res/values-he/strings.xml +++ b/app/src/main/res/values-he/strings.xml @@ -1,2 +1,10 @@ - - \ No newline at end of file + +%1$s צפיות + הועלה בתאריך %1$s + שתף + חפש + הבא + הורדה + הגדרות + הגדרות + From 5533f6ba86a4c8b51b20469e03cece12aef48e63 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Fri, 1 Jan 2016 22:09:36 +0100 Subject: [PATCH 08/36] use the standard "Movies" folder for downloads On all of the devices that I've checked, there is a folder called "Movies" on the SD Card by default. NewPipe should use that standard location since it is always downloading movies :). People can always change that via the preferences. Also, this makes the defaults the same when creating the dir and when setting the destination URL. --- .../java/org/schabi/newpipe/DownloadDialog.java | 14 ++++++-------- .../org/schabi/newpipe/SettingsActivity.java | 17 ----------------- .../schabi/newpipe/VideoItemListActivity.java | 3 ++- app/src/main/res/xml/settings_screen.xml | 5 ++--- 4 files changed, 10 insertions(+), 29 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/DownloadDialog.java b/app/src/main/java/org/schabi/newpipe/DownloadDialog.java index 903251e58..a943ad423 100644 --- a/app/src/main/java/org/schabi/newpipe/DownloadDialog.java +++ b/app/src/main/java/org/schabi/newpipe/DownloadDialog.java @@ -57,7 +57,7 @@ public class DownloadDialog extends DialogFragment { @Override public void onClick(DialogInterface dialog, int which) { Context context = getActivity(); - SharedPreferences defaultPreferences = PreferenceManager.getDefaultSharedPreferences(context); + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); String suffix = ""; String title = arguments.getString(TITLE); String url = ""; @@ -73,10 +73,10 @@ public class DownloadDialog extends DialogFragment { default: Log.d(TAG, "lolz"); } - //to avoid hard-coded string like "/storage/emulated/0/NewPipe" - final File dir = new File(defaultPreferences.getString( - "download_path_preference", - Environment.getExternalStorageDirectory().getAbsolutePath() + "/NewPipe")); + //to avoid hard-coded string like "/storage/emulated/0/Movies" + String downloadPath = prefs.getString(getString(R.string.downloadPathPreference), + Environment.getExternalStorageDirectory().getAbsolutePath() + "/Movies"); + final File dir = new File(downloadPath); if(!dir.exists()) { boolean mkdir = dir.mkdir(); //attempt to create directory if(!mkdir && !dir.isDirectory()) { @@ -87,9 +87,7 @@ public class DownloadDialog extends DialogFragment { DownloadManager dm = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); DownloadManager.Request request = new DownloadManager.Request( Uri.parse(url)); - request.setDestinationUri(Uri.fromFile(new File( - defaultPreferences.getString("download_path_preference", "/storage/emulated/0/NewPipe") - + "/" + title + suffix))); + request.setDestinationUri(Uri.fromFile(new File(dir + "/" + title + suffix))); request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); try { dm.enqueue(request); diff --git a/app/src/main/java/org/schabi/newpipe/SettingsActivity.java b/app/src/main/java/org/schabi/newpipe/SettingsActivity.java index b434b53d8..c8a548ab6 100644 --- a/app/src/main/java/org/schabi/newpipe/SettingsActivity.java +++ b/app/src/main/java/org/schabi/newpipe/SettingsActivity.java @@ -1,13 +1,9 @@ package org.schabi.newpipe; -import android.content.Context; -import android.content.SharedPreferences; import android.content.res.Configuration; import android.os.Bundle; -import android.os.Environment; import android.preference.PreferenceActivity; import android.preference.PreferenceFragment; -import android.preference.PreferenceManager; import android.support.annotation.LayoutRes; import android.support.annotation.NonNull; import android.support.v7.app.ActionBar; @@ -148,17 +144,4 @@ public class SettingsActivity extends PreferenceActivity { } return true; } - - public static void initSettings(Context context) { - PreferenceManager.setDefaultValues(context, R.xml.settings_screen, false); - SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context); - if(sp.getString(context.getString(R.string.downloadPathPreference), "").isEmpty()){ - SharedPreferences.Editor spEditor = sp.edit(); - String newPipeDownloadStorage = - Environment.getExternalStorageDirectory().getAbsolutePath() + "/NewPipe"; - spEditor.putString(context.getString(R.string.downloadPathPreference) - , newPipeDownloadStorage); - spEditor.apply(); - } - } } diff --git a/app/src/main/java/org/schabi/newpipe/VideoItemListActivity.java b/app/src/main/java/org/schabi/newpipe/VideoItemListActivity.java index 6aaf10d41..d15709b23 100644 --- a/app/src/main/java/org/schabi/newpipe/VideoItemListActivity.java +++ b/app/src/main/java/org/schabi/newpipe/VideoItemListActivity.java @@ -3,6 +3,7 @@ package org.schabi.newpipe; import android.content.Context; import android.content.Intent; import android.os.Bundle; +import android.preference.PreferenceManager; import android.support.v4.app.NavUtils; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.SearchView; @@ -171,7 +172,7 @@ public class VideoItemListActivity extends AppCompatActivity } } - SettingsActivity.initSettings(this); + PreferenceManager.setDefaultValues(this, R.xml.settings_screen, false); } /** diff --git a/app/src/main/res/xml/settings_screen.xml b/app/src/main/res/xml/settings_screen.xml index 98399f778..d4b21426f 100644 --- a/app/src/main/res/xml/settings_screen.xml +++ b/app/src/main/res/xml/settings_screen.xml @@ -64,8 +64,7 @@ android:key="@string/downloadPathPreference" android:title="@string/downloadLocation" android:summary="@string/downloadLocationSummary" - android:dialogTitle="@string/downloadLocationDialogTitle" - android:defaultValue=""/> + android:dialogTitle="@string/downloadLocationDialogTitle" /> - \ No newline at end of file + From b31490c4e34e7256bf270cb255ec2ffc51f5701a Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Fri, 1 Jan 2016 22:23:00 +0100 Subject: [PATCH 09/36] make all strings translatable --- app/src/main/AndroidManifest.xml | 6 ++---- app/src/main/res/layout/paginate_footer.xml | 2 +- app/src/main/res/values/strings.xml | 2 ++ 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ae3f5f056..8f562698d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -74,12 +74,10 @@ android:parentActivityName=".VideoItemDetailActivity" tools:ignore="UnusedAttribute"> - - + android:label="@string/background_player_name" + android:exported="false" /> diff --git a/app/src/main/res/layout/paginate_footer.xml b/app/src/main/res/layout/paginate_footer.xml index 8e5d7571d..b3757c1af 100644 --- a/app/src/main/res/layout/paginate_footer.xml +++ b/app/src/main/res/layout/paginate_footer.xml @@ -8,7 +8,7 @@ NewPipe + NewPipe Background Player NewPipe %1$s views Uploaded on %1$s @@ -10,6 +11,7 @@ https://f-droid.org/repository/browse/?fdfilter=vlc&fdid=org.videolan.vlc Open in browser Share + Loading Download Search Settings From 4fe3cb2bca146aa35848a7530641b4273b73c107 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Fri, 1 Jan 2016 22:26:25 +0100 Subject: [PATCH 10/36] use symlinks to provide alternate folders for Hebrew and Indonesian These two languages must be included twice (iw/he and id/in) For a full discussion of why, see: https://gitlab.com/fdroid/fdroidclient/issues/139 https://stackoverflow.com/questions/5074769/cyanogenmod-translate-a-project/8470980#8470980 https://stackoverflow.com/questions/8393771/android-not-using-finding-my-hebrew-localization I included a blank placeholder file for Indonesian, it can be simply replaced by the real one, whenever that comes along. --- app/src/main/res/values-id | 1 + app/src/main/res/values-in/strings.xml | 3 +++ app/src/main/res/values-iw | 1 + 3 files changed, 5 insertions(+) create mode 120000 app/src/main/res/values-id create mode 100644 app/src/main/res/values-in/strings.xml create mode 120000 app/src/main/res/values-iw diff --git a/app/src/main/res/values-id b/app/src/main/res/values-id new file mode 120000 index 000000000..9ea8dda4b --- /dev/null +++ b/app/src/main/res/values-id @@ -0,0 +1 @@ +values-in \ No newline at end of file diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml new file mode 100644 index 000000000..9c5ad89af --- /dev/null +++ b/app/src/main/res/values-in/strings.xml @@ -0,0 +1,3 @@ + + + diff --git a/app/src/main/res/values-iw b/app/src/main/res/values-iw new file mode 120000 index 000000000..57bf91954 --- /dev/null +++ b/app/src/main/res/values-iw @@ -0,0 +1 @@ +values-he \ No newline at end of file From 3c1e64d8dc35e22b5327fbd1e2664c7826067c8c Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Fri, 1 Jan 2016 23:17:39 +0100 Subject: [PATCH 11/36] simplify youtube URL IntentFilters Each elements applies to the whole IntentFilter, so there is no need to declare the host, scheme, etc. multiple times within a single IntentFilter. Also, pathPrefix="/" will match all paths, so it is unnecessary. --- app/src/main/AndroidManifest.xml | 53 ++++++++++++-------------------- 1 file changed, 20 insertions(+), 33 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 8f562698d..ab3ceaf9b 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -29,43 +29,30 @@ + - + + - - - - - - - - + + + + + + + + + + + + + + + + + Date: Fri, 1 Jan 2016 23:29:50 +0100 Subject: [PATCH 12/36] support another youtube URL format: https://www.youtube.com/v/mS1gstS6YS8 https://developer.apple.com/library/ios/featuredarticles/iPhoneURLScheme_Reference/YouTubeLinks/YouTubeLinks.html --- app/src/main/AndroidManifest.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ab3ceaf9b..3cd85adec 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -41,6 +41,7 @@ + From 2a93e9bd2e15ca33ef11ea89e414c99604e676fc Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Fri, 1 Jan 2016 23:32:09 +0100 Subject: [PATCH 13/36] precisely target these URLs https://www.youtube.com/watch?v=mS1gstS6YS8 These URLs have a Path that always starts with "/watch" so no need for a pattern. Also, everything after the "?" is considered the "Query String", not the Path. Anything after a "#" is the "Feature String". The path matching in IntentFilters only see the Path, and nothing from the "Query String" or "Feature String". these are the available kinds of URLs: https://developer.apple.com/library/ios/featuredarticles/iPhoneURLScheme_Reference/YouTubeLinks/YouTubeLinks.html --- app/src/main/AndroidManifest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3cd85adec..861f773ff 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -42,7 +42,7 @@ - + From efe5de4c7526bbc50c79f09c5522f10bd8dc7502 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Fri, 1 Jan 2016 23:51:34 +0100 Subject: [PATCH 14/36] support youtube's custom URL schemes (vnd.youtube: and vnd.youtube.launch:) --- app/src/main/AndroidManifest.xml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 861f773ff..54894f679 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -55,6 +55,15 @@ + + + + + + + + + Date: Fri, 1 Jan 2016 23:52:22 +0100 Subject: [PATCH 15/36] youtube URLs can also come from media searches and NFC sends --- app/src/main/AndroidManifest.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 54894f679..d028886b1 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -32,6 +32,8 @@ + + @@ -46,6 +48,8 @@ + + @@ -57,6 +61,8 @@ + + From d715eae0d1fc2893aed4a7c057a01d3a6409b08a Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Sat, 2 Jan 2016 01:33:08 +0100 Subject: [PATCH 16/36] route video downloads to "Movies" and audio to "Music" use the standard Android folders when downloading files. --- app/src/main/java/org/schabi/newpipe/DownloadDialog.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/schabi/newpipe/DownloadDialog.java b/app/src/main/java/org/schabi/newpipe/DownloadDialog.java index a943ad423..3001455f9 100644 --- a/app/src/main/java/org/schabi/newpipe/DownloadDialog.java +++ b/app/src/main/java/org/schabi/newpipe/DownloadDialog.java @@ -61,21 +61,24 @@ public class DownloadDialog extends DialogFragment { String suffix = ""; String title = arguments.getString(TITLE); String url = ""; + String downloadFolder = "Download"; switch(which) { case 0: // Video suffix = arguments.getString(FILE_SUFFIX_VIDEO); url = arguments.getString(VIDEO_URL); + downloadFolder = "Movies"; break; case 1: suffix = arguments.getString(FILE_SUFFIX_AUDIO); url = arguments.getString(AUDIO_URL); + downloadFolder = "Music"; break; default: Log.d(TAG, "lolz"); } //to avoid hard-coded string like "/storage/emulated/0/Movies" String downloadPath = prefs.getString(getString(R.string.downloadPathPreference), - Environment.getExternalStorageDirectory().getAbsolutePath() + "/Movies"); + Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + downloadFolder); final File dir = new File(downloadPath); if(!dir.exists()) { boolean mkdir = dir.mkdir(); //attempt to create directory From 966ac0673c07c3fa6ef178f9f63f085890d8ac01 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Sat, 2 Jan 2016 01:29:31 +0100 Subject: [PATCH 17/36] gradle.properties is only commented out defaults, so remove from git For anyone who tweaks this file for local settings, it becomes painful to have it committed in git because those changes which are only relevant to the local setup will show up in git as changed. --- .gitignore | 1 + gradle.properties | 18 ------------------ 2 files changed, 1 insertion(+), 18 deletions(-) delete mode 100644 gradle.properties diff --git a/.gitignore b/.gitignore index 42caadb93..2b3c40d66 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ /app/app.iml /.idea /*.iml +gradle.properties diff --git a/gradle.properties b/gradle.properties deleted file mode 100644 index 1d3591c8a..000000000 --- a/gradle.properties +++ /dev/null @@ -1,18 +0,0 @@ -# Project-wide Gradle settings. - -# IDE (e.g. Android Studio) users: -# Gradle settings configured through the IDE *will override* -# any settings specified in this file. - -# For more details on how to configure your build environment visit -# http://www.gradle.org/docs/current/userguide/build_environment.html - -# Specifies the JVM arguments used for the daemon process. -# The setting is particularly useful for tweaking memory settings. -# Default value: -Xmx10248m -XX:MaxPermSize=256m -# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 - -# When configured, Gradle will run in incubating parallel mode. -# This option should only be used with decoupled projects. More details, visit -# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects -# org.gradle.parallel=true \ No newline at end of file From 7cbb135f286727adf02e77b0114cdf541c1eda87 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Sat, 2 Jan 2016 11:59:28 +0100 Subject: [PATCH 18/36] include Tibetan as a language option The Tibetan alphabet was only recently included on Android, so the language name needs to also have the English there. Otherwise it'll appear blank on devices without Tibetan. --- app/src/main/res/values/settings_keys.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/res/values/settings_keys.xml b/app/src/main/res/values/settings_keys.xml index 8d33b8cbe..0ff359a46 100644 --- a/app/src/main/res/values/settings_keys.xml +++ b/app/src/main/res/values/settings_keys.xml @@ -71,6 +71,7 @@ sl fi sv + bo vi tr bg @@ -149,6 +150,7 @@ Slovenščina Suomi Svenska + Tibetan བོད་སྐད། Tiếng Việt Türkçe Български From 7dadb2b26c7b3409527da3d1a0dc5fca58e9c99a Mon Sep 17 00:00:00 2001 From: Christian Schabesberger Date: Sat, 2 Jan 2016 16:08:18 +0100 Subject: [PATCH 19/36] fixed close notification problem --- .../org/schabi/newpipe/BackgroundPlayer.java | 144 +++++++++++------- .../res/drawable-hdpi/ic_close_white_24dp.png | Bin 0 -> 221 bytes .../res/drawable-mdpi/ic_close_white_24dp.png | Bin 0 -> 175 bytes .../drawable-xhdpi/ic_close_white_24dp.png | Bin 0 -> 257 bytes .../drawable-xxhdpi/ic_close_white_24dp.png | Bin 0 -> 347 bytes .../drawable-xxxhdpi/ic_close_white_24dp.png | Bin 0 -> 436 bytes .../main/res/layout/player_notification.xml | 66 ++++++++ .../layout/player_notification_expanded.xml | 80 ++++++++++ app/src/main/res/values/colors.xml | 1 + app/src/main/res/values/strings.xml | 1 + 10 files changed, 240 insertions(+), 52 deletions(-) create mode 100644 app/src/main/res/drawable-hdpi/ic_close_white_24dp.png create mode 100644 app/src/main/res/drawable-mdpi/ic_close_white_24dp.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_close_white_24dp.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_close_white_24dp.png create mode 100644 app/src/main/res/drawable-xxxhdpi/ic_close_white_24dp.png create mode 100644 app/src/main/res/layout/player_notification.xml create mode 100644 app/src/main/res/layout/player_notification_expanded.xml diff --git a/app/src/main/java/org/schabi/newpipe/BackgroundPlayer.java b/app/src/main/java/org/schabi/newpipe/BackgroundPlayer.java index 5573e2771..f9caef26a 100644 --- a/app/src/main/java/org/schabi/newpipe/BackgroundPlayer.java +++ b/app/src/main/java/org/schabi/newpipe/BackgroundPlayer.java @@ -17,6 +17,7 @@ import android.os.IBinder; import android.os.PowerManager; import android.support.v7.app.NotificationCompat; import android.util.Log; +import android.widget.RemoteViews; import android.widget.Toast; import java.io.IOException; @@ -113,9 +114,9 @@ public class BackgroundPlayer extends Service /*implements MediaPlayer.OnPrepare private int noteID = TAG.hashCode(); private BackgroundPlayer owner; private NotificationManager noteMgr; - private NotificationCompat.Builder noteBuilder; private WifiManager.WifiLock wifiLock; private Bitmap videoThumbnail = null; + private NotificationCompat.Builder noteBuilder; public PlayerThread(String src, String title, BackgroundPlayer owner) { this.source = src; @@ -124,10 +125,9 @@ public class BackgroundPlayer extends Service /*implements MediaPlayer.OnPrepare mediaPlayer = new MediaPlayer(); mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); } + @Override public void run() { - Resources res = getApplicationContext().getResources(); - mediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);//cpu lock try { mediaPlayer.setDataSource(source); @@ -177,54 +177,7 @@ public class BackgroundPlayer extends Service /*implements MediaPlayer.OnPrepare filter.addAction(ACTION_STOP); registerReceiver(broadcastReceiver, filter); - PendingIntent playPI = PendingIntent.getBroadcast(owner, noteID, - new Intent(ACTION_PLAYPAUSE), PendingIntent.FLAG_UPDATE_CURRENT); - - NotificationCompat.Action playButton = new NotificationCompat.Action.Builder - (R.drawable.ic_play_arrow_white_48dp, "Play", playPI).build(); - - /* - NotificationCompat.Action pauseButton = new NotificationCompat.Action.Builder - (R.drawable.ic_pause_white_24dp, "Pause", playPI).build(); - */ - - PendingIntent stopPI = PendingIntent.getBroadcast(owner, noteID, - new Intent(ACTION_STOP), PendingIntent.FLAG_UPDATE_CURRENT); - - noteBuilder = new NotificationCompat.Builder(owner); - noteBuilder - .setContentTitle(title) - //really? Id like to put something more helpful here. - //.setContentText("NewPipe is playing in the background") - .setContentText(channelName) - //.setAutoCancel(!mediaPlayer.isPlaying()) - .setOngoing(true) - .setDeleteIntent(stopPI) - //doesn't fit with Notification.MediaStyle - //.setProgress(vidLength, 0, false) - .setSmallIcon(R.drawable.ic_play_circle_filled_white_24dp) - .setLargeIcon(videoThumbnail) - .setTicker( - String.format(res.getString( - R.string.backgroundPlayerTickerText), title)) - .addAction(playButton); - //.setVisibility(NotificationCompat.VISIBILITY_PUBLIC) - //.setLargeIcon(cover) - if(android.os.Build.VERSION.SDK_INT >= 16) - noteBuilder.setPriority(Notification.PRIORITY_LOW); - if(android.os.Build.VERSION.SDK_INT >= 21) - noteBuilder.setCategory(Notification.CATEGORY_TRANSPORT); - - noteBuilder.setStyle(new NotificationCompat.MediaStyle() - //.setMediaSession(mMediaSession.getSessionToken()) - .setShowActionsInCompactView(new int[]{0}) - .setShowCancelButton(true) - .setCancelButtonIntent(stopPI)); - if(videoThumbnail != null) { - noteBuilder.setLargeIcon(videoThumbnail); - } - - Notification note = noteBuilder.build(); + Notification note = buildNotification(); Intent openDetailView = new Intent(getApplicationContext(), VideoItemDetailActivity.class); @@ -252,7 +205,6 @@ public class BackgroundPlayer extends Service /*implements MediaPlayer.OnPrepare Log.d(TAG, "sleep failure"); } }*/ - } private final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { @@ -306,5 +258,93 @@ public class BackgroundPlayer extends Service /*implements MediaPlayer.OnPrepare afterPlayCleanup(); } } + + private Notification buildNotification() { + Notification note; + Resources res = getApplicationContext().getResources(); + noteBuilder = new NotificationCompat.Builder(owner); + + PendingIntent playPI = PendingIntent.getBroadcast(owner, noteID, + new Intent(ACTION_PLAYPAUSE), PendingIntent.FLAG_UPDATE_CURRENT); + PendingIntent stopPI = PendingIntent.getBroadcast(owner, noteID, + new Intent(ACTION_STOP), PendingIntent.FLAG_UPDATE_CURRENT); + /* + NotificationCompat.Action pauseButton = new NotificationCompat.Action.Builder + (R.drawable.ic_pause_white_24dp, "Pause", playPI).build(); + */ + + noteBuilder + .setOngoing(true) + .setDeleteIntent(stopPI) + //doesn't fit with Notification.MediaStyle + //.setProgress(vidLength, 0, false) + .setSmallIcon(R.drawable.ic_play_circle_filled_white_24dp) + .setTicker( + String.format(res.getString( + R.string.backgroundPlayerTickerText), title)); + + if (android.os.Build.VERSION.SDK_INT < 21) { + + NotificationCompat.Action playButton = new NotificationCompat.Action.Builder + (R.drawable.ic_play_arrow_white_48dp, + res.getString(R.string.play), playPI).build(); + + noteBuilder + .setContentTitle(title) + //really? Id like to put something more helpful here. + //.setContentText("NewPipe is playing in the background") + .setContentText(channelName) + //.setAutoCancel(!mediaPlayer.isPlaying()) + .setDeleteIntent(stopPI) + //doesn't fit with Notification.MediaStyle + //.setProgress(vidLength, 0, false) + .setLargeIcon(videoThumbnail) + .addAction(playButton); + //.setVisibility(NotificationCompat.VISIBILITY_PUBLIC) + //.setLargeIcon(cover) + + if (android.os.Build.VERSION.SDK_INT >= 16) + noteBuilder.setPriority(Notification.PRIORITY_LOW); + + noteBuilder.setStyle(new NotificationCompat.MediaStyle() + //.setMediaSession(mMediaSession.getSessionToken()) + .setShowActionsInCompactView(new int[]{0}) + .setShowCancelButton(true) + .setCancelButtonIntent(stopPI)); + if (videoThumbnail != null) { + noteBuilder.setLargeIcon(videoThumbnail); + } + note = noteBuilder.build(); + } else { + RemoteViews view = + new RemoteViews(BuildConfig.APPLICATION_ID, R.layout.player_notification); + view.setImageViewBitmap(R.id.backgroundCover, videoThumbnail); + view.setTextViewText(R.id.backgroundSongName, title); + view.setTextViewText(R.id.backgroundArtist, channelName); + view.setOnClickPendingIntent(R.id.backgroundStop, stopPI); + view.setOnClickPendingIntent(R.id.backgroundPlayPause, playPI); + + RemoteViews expandedView = + new RemoteViews(BuildConfig.APPLICATION_ID, R.layout.player_notification); + expandedView.setImageViewBitmap(R.id.backgroundCover, videoThumbnail); + expandedView.setTextViewText(R.id.backgroundSongName, title); + expandedView.setTextViewText(R.id.backgroundArtist, channelName); + expandedView.setOnClickPendingIntent(R.id.backgroundStop, stopPI); + expandedView.setOnClickPendingIntent(R.id.backgroundPlayPause, playPI); + + noteBuilder.setCategory(Notification.CATEGORY_TRANSPORT); + + //Make notification appear on lockscreen + noteBuilder.setVisibility(Notification.VISIBILITY_PUBLIC); + + note = noteBuilder.build(); + note.contentView = view; + + //todo: This never shows up. I was not able to figure out why: + note.bigContentView = expandedView; + } + + return note; + } } } diff --git a/app/src/main/res/drawable-hdpi/ic_close_white_24dp.png b/app/src/main/res/drawable-hdpi/ic_close_white_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..ceb1a1eebf2b2cc9a008f42010e144f4dab968de GIT binary patch literal 221 zcmV<303!d1P)og+*{ z>6z1@lfD*AYSPav72B5kK^|J))MUC zlz7ydwCsb8xn}W?^r?}5wtsjdmvX{3=JbT!J9sKPrYmk={m|7^>A|Z*7j^D$`>}ry Zqi^Z9GQN4ct^!@a;OXk;vd$@?2>?I&LQeny literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xhdpi/ic_close_white_24dp.png b/app/src/main/res/drawable-xhdpi/ic_close_white_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..b7c7ffd0e795ba76ed3a062566c9016448795f7a GIT binary patch literal 257 zcmV+c0sj7pP) zOA5m<3jYBNi%A&<@ZO?$P9};P4Y5CjG5$M&YXI45J{s}~# zf|&?x1_gn4B7+hS@X!l}&!voFhmZP^sujifL@~PKMMM~{6xH}^g$q7WOzwCQ5vHTU z6`v~H@rlA8e;CUh_(b84zg=+ih`wG<)HiJjzSlQx5#CnjMR;A)R^jtaTa9;7rSy)7O%~`cm?ZjXImW?6TYRT<;U^@VKiSj`soFk00000NkvXX Hu0mjfhD&W| literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxhdpi/ic_close_white_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_close_white_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..6b717e0dda8649aa3b5f1d6851ba0dd20cc4ea66 GIT binary patch literal 347 zcmV-h0i^zkP)vMkH8EXyh{JTRaptiwcq@D(P;=ehLbl?EMKm*m7(@7_siS}}k zNFtnck{HL4mc!ypcyUoqJV~4rM^fS3C#iAnkyJU3biCmDy`VZLOv=LXld^HVq32ETvhYyB39D^lU%DgQgv&#U%8l^-CA%qY@2qA=!B5=cm zUgehujQG*l{{`@rPr!f|fEk^>KI9WteE@ilV6HEl&_rJ@p_zU*;T}RirIc{5NocNLm*7JGdV(AM zYYDFOvk5~8{Z*t_>U=!XvoehUSEh=adIga45oe)B9kGgT}7UT3Cirmr(oHPv^YQ1-p=Hlh5u;xggf zX{&yw+El-OrrKQJRl@b7x{HLmNkj95`a#LLnW{Veb2C+!`ppt#r)=g4@?c8RY{yJj~W@W|h^mU4q`i)2y~Rw@J`jIh$1%|In!~{Tb{nMqaxlgb+dq eA%qY@zJ@mriVM?qfwL0;0000 + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/player_notification_expanded.xml b/app/src/main/res/layout/player_notification_expanded.xml new file mode 100644 index 000000000..3fd379a6b --- /dev/null +++ b/app/src/main/res/layout/player_notification_expanded.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index e14ee9606..7e0d71406 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -7,4 +7,5 @@ #efff #6000 #EEEEEE + #323232 \ 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 177280277..ffa004d91 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -53,6 +53,7 @@ %1$s - NewPipe Playing in background https://www.c3s.cc/ + Play Video preview thumbnail From adcb8c64699f78c99444af035605753077b92d12 Mon Sep 17 00:00:00 2001 From: Christian Schabesberger Date: Sat, 2 Jan 2016 17:40:58 +0100 Subject: [PATCH 20/36] add c3s thumbnail and moved on to 0.7.1 --- README.md | 1 + app/build.gradle | 4 +- .../newpipe/VideoItemDetailFragment.java | 4 +- .../res/drawable-nodpi/gruese_die_gema.png | Bin 0 -> 91384 bytes .../gruese_die_gema_unangebracht.png | Bin 15826 -> 0 bytes assets/gruese_die_gema.svg | 288 ++++++++++-------- 6 files changed, 163 insertions(+), 134 deletions(-) create mode 100644 app/src/main/res/drawable-nodpi/gruese_die_gema.png delete mode 100644 app/src/main/res/drawable-nodpi/gruese_die_gema_unangebracht.png diff --git a/README.md b/README.md index e6d1d9498..e7ce4f965 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,7 @@ NewPipe does not use any Google framework libraries, or the YouTube API. It only * Open a video in Kodi * Show Next/Related videos * Search YouTube in a specific language +* Orbot support (no streaming yet) ### Coming Features diff --git a/app/build.gradle b/app/build.gradle index 871a98a9d..fb4598597 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -8,8 +8,8 @@ android { applicationId "org.schabi.newpipe" minSdkVersion 15 targetSdkVersion 23 - versionCode 9 - versionName "0.7.0" + versionCode 10 + versionName "0.7.1" } buildTypes { release { diff --git a/app/src/main/java/org/schabi/newpipe/VideoItemDetailFragment.java b/app/src/main/java/org/schabi/newpipe/VideoItemDetailFragment.java index 92c25e2aa..ddec1e36e 100644 --- a/app/src/main/java/org/schabi/newpipe/VideoItemDetailFragment.java +++ b/app/src/main/java/org/schabi/newpipe/VideoItemDetailFragment.java @@ -287,7 +287,7 @@ public class VideoItemDetailFragment extends Fragment { VideoItemDetailFragment.ARG_ITEM_ID, currentVideoInfo.nextVideo.id); */ detailIntent.putExtra( VideoItemDetailFragment.VIDEO_URL, currentVideoInfo.nextVideo.webpage_url); - //todo: make id dynamic the following line is crap + detailIntent.putExtra(VideoItemDetailFragment.STREAMING_SERVICE, streamingServiceId); startActivity(detailIntent); } @@ -296,7 +296,7 @@ public class VideoItemDetailFragment extends Fragment { break; case VideoInfo.ERROR_BLOCKED_BY_GEMA: thumbnailView.setImageBitmap(BitmapFactory.decodeResource( - getResources(), R.drawable.gruese_die_gema_unangebracht)); + getResources(), R.drawable.gruese_die_gema)); backgroundButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { diff --git a/app/src/main/res/drawable-nodpi/gruese_die_gema.png b/app/src/main/res/drawable-nodpi/gruese_die_gema.png new file mode 100644 index 0000000000000000000000000000000000000000..d6e2af3d5a2e1db00249e6e07d2a5894ed4e3723 GIT binary patch literal 91384 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

pv{t=0v@uYO2e~9jcj>>re z*Kg4)wC->k%Pp))Pgq7lDA1$jSNC3z6NHTM-Us(J=8-ez1{uAsYNa$ZE+_RYg(r3V zId%-Qhq?+aQIrt7>51)j-N8W5nQJcHtM1r#%Rc(JJ&nJlfwaa?ziH5lwsFrQ5#FX8 zy~u~wN)RXxQgJY`*aOk0*3@$lgcmZk#bXt&eVy=^YAN9xR;?NHSk>lDri64mgDHB)gGjDi*EX2}w zpC<3$+N4!zSQtNhqU!v0X2xb^Vx{X4ExgSR zH41!UCro=lEwiVs4GlHeLbuDyw_jL&7M}c0>;1vK(12p(Oa)dF&pH~Y+zxD`-A|E3D+2~T`d zdqwQTElt+w3E2!>AIu0|CPlDCr4qhC4&5&t4?^*qUv4!muqdN`GCS!j0-pqhv7YGtFsDKMSfRQEC$a)g7lkI_%G!-q9X-4W?Mm!wisbLDrfx2+j%%j*aE^XcrBt z1A`%V)KigiMzh6{JF->31iUXJw)=R#E7*q~JbZY+wOy<89^qV}$k=(V|J$k=&m*~z zcNo6<184IYtVXkU5ueee9jab^7UWmbkq({(X1fOnZct7W3(zi5OfxjR(Ap7}cm*#N z?QkyJzS&PWkU~(CGACFILOhwOY({e<@=zLC`N^BG%=VIrzGdI%Mf6z8pYZ+c*xsq) z_~R+D7&&nbGaG=p|5DGgm`?4#z7Vyu+P>$2F;ZoM1{FsRMm`38i~)sAmpfSj zkVVSZWR$f)o|2_R^xzb*hHho0VR%9d2RvGmce`+cvJbCh)=@Nv3H!r9!VjF-o~uD3 z5X*MymmrU+13yXYomxT&lF4mdclA%d|aucQgUULjn7 zfuK(aq^mcJh}ON6qX0qWK5)B$=oNE1h6e{J$aanP-vQUW>+AYG?k!}>@WG?!q3b?r zFoJ{Z2x{&S3&?wSEY$SzxSKck z3oe7smgjSybptJU_89=+=qY@wz&9Zc9`!#+^4;M7i9APhsu8D5Y!zvHL@X@K&qo7l zXX)G_E*=6|SPbk4qS22maY6#7*DWC}O^uR8Z`gHk4?_iEf`|443xN>ICK8?Osj!`kauSWigP)6gM=^)Rs^ zTXL!ep~7j(Oz*Fb|3yhz*+$?o8^DbYSO7&$9I5KvffbZJ7=*j3rv&3s3fpV&jw#>2 z{`g_)-A~yAyPz=G4{VfERlN=Bn&Bw9`OWr<2N%LwUVpQ7a-u@e+G24KQ8=2KN%ey| z7?>Ik=?Ee%aKQA0Sd0ZKNIVh@zFi3n!ioKe9V}%lZvngrP{k;pfO7^+Sm}3{JkhQ( zJXMQz+I5LoQ>d$7?u2-uAhY}cjN>ziXBLk=*ujM8C6f5#+Qjj-oU=c?(pr#s7ufWo zk7e8o;*Ngrb`g=weWu_|l$@QNoehKSQfqN7;HQ)V7gP|&N{D(JP_m`ickqG77vPMv zzut{SL=3$*JR_;*pFe*}pi5>Vc^*OtG_BIVSEGU6w5*OmiS>SnzQqrG;(45p;piPC zZ9A19sqCJan(B|3cgH&tOq~%t$4}Zc9|~PXCWwS z1`4^4$eY<^3F11BK6VTEDY{lxx2YAd2>5Gt1jbFo4#UyEbI#%N9Q;fym~t zv9PKt1yYk};0ICAeUx6=bo4??_z(r|7bA$%c8f2O4mCeIJFE-uWEn5q2Qe&yO-ITj zFqf_T$|hfO8M;_b#sk0OpP`=8p8N^8E8-8vJ13Fx5+gXoM^F(Eei{R~*z~jIWK;zqT+;;F@pr1;VcA5J8ISlA*fL;N+KVT9VTxoX~5>^WmAF

    KlgYg1=QQ_k^ENpU8)$FF)5tSZlC2W-yYjGko> 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 E14e80X8-^I literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-nodpi/gruese_die_gema_unangebracht.png b/app/src/main/res/drawable-nodpi/gruese_die_gema_unangebracht.png deleted file mode 100644 index e19491b7be43d2334b20dd16f96d3350de96a6dd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15826 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

    vb?iYs?kC&; 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 HFMR$7*qOZg diff --git a/assets/gruese_die_gema.svg b/assets/gruese_die_gema.svg index 48ebc8db0..eace7bf44 100644 --- a/assets/gruese_die_gema.svg +++ b/assets/gruese_die_gema.svg @@ -7,7 +7,6 @@ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" - xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" width="426" @@ -16,7 +15,10 @@ id="svg2" version="1.1" inkscape:version="0.91 r13725" - sodipodi:docname="gruese_die_gema_unangebracht.svg"> + sodipodi:docname="gruese_die_gema.svg" + inkscape:export-filename="/home/the-scrabi/Projects/NewPipe/assets/gruese_die_gema.png" + inkscape:export-xdpi="216.33803" + inkscape:export-ydpi="216.33803"> + inkscape:window-width="1015" + inkscape:window-height="417" + inkscape:window-x="287" + inkscape:window-y="491" + inkscape:window-maximized="0" /> @@ -46,7 +48,7 @@ image/svg+xml - + @@ -56,129 +58,155 @@ id="layer1" transform="translate(0,-812.36212)"> - - - - - - - - - - - - - - - - - - - - - + id="g4230" + transform="matrix(0.67525011,0,0,0.67525011,-14.086916,282.00859)"> + + + + + + + + + + + + + + + + + + + + + + + + + - + Genervt? Gib der Alternative c3s + + eine Chance. From d3500e90360b284d789e01b3ec95ada0a735345f Mon Sep 17 00:00:00 2001 From: Christian Schabesberger Date: Sat, 2 Jan 2016 17:41:33 +0100 Subject: [PATCH 21/36] removed onion routing from readme --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index e7ce4f965..e6d1d9498 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,6 @@ NewPipe does not use any Google framework libraries, or the YouTube API. It only * Open a video in Kodi * Show Next/Related videos * Search YouTube in a specific language -* Orbot support (no streaming yet) ### Coming Features From dfcb4edb8127ea3b3c40243d48890261ce0de79b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mladen=20Pejakovi=C4=87?= Date: Sat, 2 Jan 2016 18:03:57 +0100 Subject: [PATCH 22/36] Translated using Weblate (Serbian) Currently translated at 100.0% (51 of 51 strings) --- app/src/main/res/values-sr/strings.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/src/main/res/values-sr/strings.xml b/app/src/main/res/values-sr/strings.xml index 7ab3d8eaa..107434167 100644 --- a/app/src/main/res/values-sr/strings.xml +++ b/app/src/main/res/values-sr/strings.xml @@ -54,4 +54,8 @@ Користи спољашњи аудио плејер Пуштам у позадини + Позадински плејер за Јутјуб цев + Учитавам + Пусти + From eeb612f9a2014418b2211c012ee81cc849624c45 Mon Sep 17 00:00:00 2001 From: Matej U Date: Sat, 2 Jan 2016 19:48:46 +0100 Subject: [PATCH 23/36] Translated using Weblate (Slovenian) Currently translated at 100.0% (51 of 51 strings) --- app/src/main/res/values-sl/strings.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/src/main/res/values-sl/strings.xml b/app/src/main/res/values-sl/strings.xml index 91f54dc11..412d9a56c 100644 --- a/app/src/main/res/values-sl/strings.xml +++ b/app/src/main/res/values-sl/strings.xml @@ -47,4 +47,9 @@ Všeč mi je Ni mi všeč + Ozadnji predvajalnik NewPipe + Nalaganje ... + Predvajanje v ozadju + Predvajaj + From ef255d12ae3704b94441d7ac4bcacc4e2ad40f6f Mon Sep 17 00:00:00 2001 From: GDR! Date: Thu, 24 Dec 2015 14:55:33 +0100 Subject: [PATCH 24/36] Test tor code --- app/build.gradle | 3 +- .../java/org/schabi/newpipe/Downloader.java | 8 +++-- .../org/schabi/newpipe/PlayVideoActivity.java | 30 ++++++++++++++++++- app/src/main/res/values/strings.xml | 2 ++ app/src/main/res/xml/settings_screen.xml | 5 ++++ 5 files changed, 44 insertions(+), 4 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index fb4598597..9eb3ccef7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -17,7 +17,7 @@ android { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } - + lintOptions { checkReleaseBuilds false // Or, if you prefer, you can continue to check for errors in release builds, @@ -35,4 +35,5 @@ dependencies { compile 'com.android.support:recyclerview-v7:23.1.1' compile 'org.jsoup:jsoup:1.8.3' compile 'org.mozilla:rhino:1.7.7' + compile 'info.guardianproject.netcipher:netcipher:1.2' } diff --git a/app/src/main/java/org/schabi/newpipe/Downloader.java b/app/src/main/java/org/schabi/newpipe/Downloader.java index f0a19cfc5..c15c2ddc3 100644 --- a/app/src/main/java/org/schabi/newpipe/Downloader.java +++ b/app/src/main/java/org/schabi/newpipe/Downloader.java @@ -7,6 +7,8 @@ import java.net.HttpURLConnection; import java.net.URL; import java.net.UnknownHostException; +import info.guardianproject.netcipher.NetCipher; + /** * Created by Christian Schabesberger on 14.08.15. * @@ -37,10 +39,11 @@ public class Downloader { * @param language the language (usually a 2-character code) to set as the preferred language * @return the contents of the specified text file*/ public static String download(String siteUrl, String language) { + NetCipher.useTor(); String ret = ""; try { URL url = new URL(siteUrl); - HttpURLConnection con = (HttpURLConnection) url.openConnection(); + HttpURLConnection con = (HttpURLConnection) NetCipher.getHttpURLConnection(url); con.setRequestProperty("Accept-Language", language); ret = dl(con); } @@ -81,10 +84,11 @@ public class Downloader { * @return the contents of the specified text file*/ public static String download(String siteUrl) { String ret = ""; + NetCipher.useTor(); try { URL url = new URL(siteUrl); - HttpURLConnection con = (HttpURLConnection) url.openConnection(); + HttpURLConnection con = (HttpURLConnection) NetCipher.getHttpURLConnection(url); ret = dl(con); } catch(Exception e) { diff --git a/app/src/main/java/org/schabi/newpipe/PlayVideoActivity.java b/app/src/main/java/org/schabi/newpipe/PlayVideoActivity.java index d5fea8c3e..a7aeda10f 100644 --- a/app/src/main/java/org/schabi/newpipe/PlayVideoActivity.java +++ b/app/src/main/java/org/schabi/newpipe/PlayVideoActivity.java @@ -3,6 +3,7 @@ package org.schabi.newpipe; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; +import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.content.pm.ActivityInfo; import android.content.res.Configuration; import android.media.MediaPlayer; @@ -25,6 +26,7 @@ import android.widget.Button; import android.widget.MediaController; import android.widget.ProgressBar; import android.widget.VideoView; +import info.guardianproject.netcipher.NetCipher; /** * Copyright (C) Christian Schabesberger 2015 @@ -44,7 +46,7 @@ import android.widget.VideoView; * along with NewPipe. If not, see . */ -public class PlayVideoActivity extends AppCompatActivity { +public class PlayVideoActivity extends AppCompatActivity implements OnSharedPreferenceChangeListener { //// TODO: 11.09.15 add "choose stream" menu @@ -170,6 +172,9 @@ public class PlayVideoActivity extends AppCompatActivity { if(prefs.getBoolean(PREF_IS_LANDSCAPE, false) && !isLandscape) { toggleOrientation(); } + + setTorPreference(prefs); + prefs.registerOnSharedPreferenceChangeListener(this); } @Override @@ -187,6 +192,13 @@ public class PlayVideoActivity extends AppCompatActivity { videoView.pause(); } + @Override + protected void onDestroy() { + super.onDestroy(); + prefs = getPreferences(Context.MODE_PRIVATE); + prefs.unregisterOnSharedPreferenceChangeListener(this); + } + @Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); @@ -348,4 +360,20 @@ public class PlayVideoActivity extends AppCompatActivity { editor.putBoolean(PREF_IS_LANDSCAPE, isLandscape); editor.apply(); } + + private void setTorPreference(SharedPreferences prefs) { + if(prefs.getBoolean(getString(R.string.useTor), false)) { + NetCipher.useTor(); + } else { + NetCipher.setProxy(null); + } + } + + @Override + public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { + if(key.equals(getString(R.string.useTor))) { + setTorPreference(prefs); + } + } + } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 12fb9275d..c2d1becdd 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -63,4 +63,6 @@ Uploader thumbnail Dislikes Likes + Use Tor + Proxy connections via The Onion Router diff --git a/app/src/main/res/xml/settings_screen.xml b/app/src/main/res/xml/settings_screen.xml index d4b21426f..953ded807 100644 --- a/app/src/main/res/xml/settings_screen.xml +++ b/app/src/main/res/xml/settings_screen.xml @@ -72,5 +72,10 @@ android:summary="@string/autoPlayThroughIntentSummary" android:defaultValue="false" /> + + From 0265da4ae61286b8137185108bdd10a1cde51931 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Thu, 24 Dec 2015 14:55:33 +0100 Subject: [PATCH 25/36] use HttpsURLConnections since youtube.com always uses HTTPS This helps enforce that the connection is encrypted. If for whatever reason an unencrypted connection is created, an Exception will be thrown. --- app/src/main/java/org/schabi/newpipe/Downloader.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/Downloader.java b/app/src/main/java/org/schabi/newpipe/Downloader.java index c15c2ddc3..9e33ce322 100644 --- a/app/src/main/java/org/schabi/newpipe/Downloader.java +++ b/app/src/main/java/org/schabi/newpipe/Downloader.java @@ -7,6 +7,8 @@ import java.net.HttpURLConnection; import java.net.URL; import java.net.UnknownHostException; +import javax.net.ssl.HttpsURLConnection; + import info.guardianproject.netcipher.NetCipher; /** @@ -43,7 +45,7 @@ public class Downloader { String ret = ""; try { URL url = new URL(siteUrl); - HttpURLConnection con = (HttpURLConnection) NetCipher.getHttpURLConnection(url); + HttpsURLConnection con = NetCipher.getHttpsURLConnection(url); con.setRequestProperty("Accept-Language", language); ret = dl(con); } @@ -88,7 +90,7 @@ public class Downloader { try { URL url = new URL(siteUrl); - HttpURLConnection con = (HttpURLConnection) NetCipher.getHttpURLConnection(url); + HttpsURLConnection con = NetCipher.getHttpsURLConnection(url); ret = dl(con); } catch(Exception e) { From e63d43151b711bdc032ae851c5eb053939026b77 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Fri, 1 Jan 2016 19:45:41 +0100 Subject: [PATCH 26/36] add a title plus summary to "Use Tor" preference --- app/src/main/res/values/strings.xml | 2 +- app/src/main/res/xml/settings_screen.xml | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c2d1becdd..c7058759e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -64,5 +64,5 @@ Dislikes Likes Use Tor - Proxy connections via The Onion Router + Force download traffic through Tor for increased privacy (streaming videos not yet supported) diff --git a/app/src/main/res/xml/settings_screen.xml b/app/src/main/res/xml/settings_screen.xml index 953ded807..f7ab99a53 100644 --- a/app/src/main/res/xml/settings_screen.xml +++ b/app/src/main/res/xml/settings_screen.xml @@ -74,7 +74,8 @@ From 6bd2468d44b09df89d95c999a98f7045c246303e Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Fri, 1 Jan 2016 20:29:21 +0100 Subject: [PATCH 27/36] if Orbot is installed, then default to using Tor If the user has not changed the "Use Tor" preference, then the default should be to use Tor if Orbot is installed. The user can still override it by going an unchecking "Use Tor". --- app/src/main/java/org/schabi/newpipe/PlayVideoActivity.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/schabi/newpipe/PlayVideoActivity.java b/app/src/main/java/org/schabi/newpipe/PlayVideoActivity.java index a7aeda10f..f5e595624 100644 --- a/app/src/main/java/org/schabi/newpipe/PlayVideoActivity.java +++ b/app/src/main/java/org/schabi/newpipe/PlayVideoActivity.java @@ -27,6 +27,7 @@ import android.widget.MediaController; import android.widget.ProgressBar; import android.widget.VideoView; import info.guardianproject.netcipher.NetCipher; +import info.guardianproject.netcipher.proxy.OrbotHelper; /** * Copyright (C) Christian Schabesberger 2015 @@ -362,7 +363,8 @@ public class PlayVideoActivity extends AppCompatActivity implements OnSharedPref } private void setTorPreference(SharedPreferences prefs) { - if(prefs.getBoolean(getString(R.string.useTor), false)) { + // if Orbot is installed, then default to using Tor, the user can still override + if(prefs.getBoolean(getString(R.string.useTor), OrbotHelper.isOrbotInstalled(this))) { NetCipher.useTor(); } else { NetCipher.setProxy(null); From d3879a03982f3e8da4831704fb0ef280b884405f Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Fri, 1 Jan 2016 22:16:41 +0100 Subject: [PATCH 28/36] setup Tor at app start, and config immediately when pref is changed This adds an Application subclass to get the onCreate() method, which is called once at the first start up of the app, before any Activity starts. Tor is configured there to ensure it is setup before anything happens. This also moves the "Use Tor" pref listener to a more appropriate place. --- app/src/main/AndroidManifest.xml | 1 + app/src/main/java/org/schabi/newpipe/App.java | 32 +++++++++++++++++++ .../java/org/schabi/newpipe/Downloader.java | 2 -- .../org/schabi/newpipe/PlayVideoActivity.java | 26 +-------------- .../org/schabi/newpipe/SettingsActivity.java | 19 +++++++++++ app/src/main/res/xml/settings_screen.xml | 3 +- 6 files changed, 54 insertions(+), 29 deletions(-) create mode 100644 app/src/main/java/org/schabi/newpipe/App.java diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d028886b1..ef84c57b3 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -7,6 +7,7 @@ @@ -47,7 +44,7 @@ import info.guardianproject.netcipher.proxy.OrbotHelper; * along with NewPipe. If not, see . */ -public class PlayVideoActivity extends AppCompatActivity implements OnSharedPreferenceChangeListener { +public class PlayVideoActivity extends AppCompatActivity { //// TODO: 11.09.15 add "choose stream" menu @@ -173,9 +170,6 @@ public class PlayVideoActivity extends AppCompatActivity implements OnSharedPref if(prefs.getBoolean(PREF_IS_LANDSCAPE, false) && !isLandscape) { toggleOrientation(); } - - setTorPreference(prefs); - prefs.registerOnSharedPreferenceChangeListener(this); } @Override @@ -197,7 +191,6 @@ public class PlayVideoActivity extends AppCompatActivity implements OnSharedPref protected void onDestroy() { super.onDestroy(); prefs = getPreferences(Context.MODE_PRIVATE); - prefs.unregisterOnSharedPreferenceChangeListener(this); } @Override @@ -361,21 +354,4 @@ public class PlayVideoActivity extends AppCompatActivity implements OnSharedPref editor.putBoolean(PREF_IS_LANDSCAPE, isLandscape); editor.apply(); } - - private void setTorPreference(SharedPreferences prefs) { - // if Orbot is installed, then default to using Tor, the user can still override - if(prefs.getBoolean(getString(R.string.useTor), OrbotHelper.isOrbotInstalled(this))) { - NetCipher.useTor(); - } else { - NetCipher.setProxy(null); - } - } - - @Override - public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { - if(key.equals(getString(R.string.useTor))) { - setTorPreference(prefs); - } - } - } diff --git a/app/src/main/java/org/schabi/newpipe/SettingsActivity.java b/app/src/main/java/org/schabi/newpipe/SettingsActivity.java index c8a548ab6..c8c089a98 100644 --- a/app/src/main/java/org/schabi/newpipe/SettingsActivity.java +++ b/app/src/main/java/org/schabi/newpipe/SettingsActivity.java @@ -2,6 +2,8 @@ package org.schabi.newpipe; import android.content.res.Configuration; import android.os.Bundle; +import android.preference.CheckBoxPreference; +import android.preference.Preference; import android.preference.PreferenceActivity; import android.preference.PreferenceFragment; import android.support.annotation.LayoutRes; @@ -13,6 +15,8 @@ import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; +import info.guardianproject.netcipher.proxy.OrbotHelper; + /** * Created by Christian Schabesberger on 31.08.15. * @@ -52,10 +56,25 @@ public class SettingsActivity extends PreferenceActivity { } public static class SettingsFragment extends PreferenceFragment { + private CheckBoxPreference useTorCheckBox; + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.settings_screen); + + // if Orbot is installed, then default to using Tor, the user can still override + useTorCheckBox = (CheckBoxPreference) findPreference(getString(R.string.useTor)); + boolean useTor = OrbotHelper.isOrbotInstalled(getActivity()); + useTorCheckBox.setDefaultValue(useTor); + useTorCheckBox.setChecked(useTor); + useTorCheckBox.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(Preference preference, Object useTor) { + App.configureTor((Boolean) useTor); + return true; + } + }); } } diff --git a/app/src/main/res/xml/settings_screen.xml b/app/src/main/res/xml/settings_screen.xml index f7ab99a53..4d21b457b 100644 --- a/app/src/main/res/xml/settings_screen.xml +++ b/app/src/main/res/xml/settings_screen.xml @@ -75,8 +75,7 @@ + android:summary="@string/useTorSummary" /> From 5663e543a47eb90af320e5ebb09fcd2b8243c36d Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Fri, 1 Jan 2016 23:04:29 +0100 Subject: [PATCH 29/36] whenever an Activity resumes and tor is enabled, request it start This makes sure that Orbot is running when the user expects it to be. If NewPipe is configured to use Tor, then going to a NewPipe screen should ensure Tor is running. --- app/src/main/java/org/schabi/newpipe/App.java | 12 +++++++++++- .../java/org/schabi/newpipe/PlayVideoActivity.java | 6 ++++++ .../org/schabi/newpipe/VideoItemDetailActivity.java | 6 ++++++ .../org/schabi/newpipe/VideoItemListActivity.java | 6 ++++++ 4 files changed, 29 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/schabi/newpipe/App.java b/app/src/main/java/org/schabi/newpipe/App.java index a8afccd4a..95127d7fe 100644 --- a/app/src/main/java/org/schabi/newpipe/App.java +++ b/app/src/main/java/org/schabi/newpipe/App.java @@ -1,6 +1,7 @@ package org.schabi.newpipe; import android.app.Application; +import android.content.Context; import android.content.SharedPreferences; import android.preference.PreferenceManager; @@ -9,6 +10,8 @@ import info.guardianproject.netcipher.proxy.OrbotHelper; public class App extends Application { + private static boolean useTor; + @Override public void onCreate() { super.onCreate(); @@ -22,11 +25,18 @@ public class App extends Application { /** * Set the proxy settings based on whether Tor should be enabled or not. */ - static void configureTor(boolean useTor) { + static void configureTor(boolean enabled) { + useTor = enabled; if (useTor) { NetCipher.useTor(); } else { NetCipher.setProxy(null); } } + + static void checkStartTor(Context context) { + if (useTor) { + OrbotHelper.requestStartTor(context); + } + } } diff --git a/app/src/main/java/org/schabi/newpipe/PlayVideoActivity.java b/app/src/main/java/org/schabi/newpipe/PlayVideoActivity.java index 2500c7dfe..13a1cefed 100644 --- a/app/src/main/java/org/schabi/newpipe/PlayVideoActivity.java +++ b/app/src/main/java/org/schabi/newpipe/PlayVideoActivity.java @@ -187,6 +187,12 @@ public class PlayVideoActivity extends AppCompatActivity { videoView.pause(); } + @Override + public void onResume() { + super.onResume(); + App.checkStartTor(this); + } + @Override protected void onDestroy() { super.onDestroy(); diff --git a/app/src/main/java/org/schabi/newpipe/VideoItemDetailActivity.java b/app/src/main/java/org/schabi/newpipe/VideoItemDetailActivity.java index 4a553241f..f93ca4b9e 100644 --- a/app/src/main/java/org/schabi/newpipe/VideoItemDetailActivity.java +++ b/app/src/main/java/org/schabi/newpipe/VideoItemDetailActivity.java @@ -113,6 +113,12 @@ public class VideoItemDetailActivity extends AppCompatActivity { .commit(); } + @Override + public void onResume() { + super.onResume(); + App.checkStartTor(this); + } + @Override public void onSaveInstanceState(Bundle outState) { outState.putString(VideoItemDetailFragment.VIDEO_URL, videoUrl); diff --git a/app/src/main/java/org/schabi/newpipe/VideoItemListActivity.java b/app/src/main/java/org/schabi/newpipe/VideoItemListActivity.java index d15709b23..8c4f5c57e 100644 --- a/app/src/main/java/org/schabi/newpipe/VideoItemListActivity.java +++ b/app/src/main/java/org/schabi/newpipe/VideoItemListActivity.java @@ -175,6 +175,12 @@ public class VideoItemListActivity extends AppCompatActivity PreferenceManager.setDefaultValues(this, R.xml.settings_screen, false); } + @Override + public void onResume() { + super.onResume(); + App.checkStartTor(this); + } + /** * Callback method from {@link VideoItemListFragment.Callbacks} * indicating that the item with the given ID was selected. From 984dd1cc25d6add07d136a6a602e836fb99f8462 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Fri, 1 Jan 2016 23:06:16 +0100 Subject: [PATCH 30/36] checking on "Use Tor" when Orbot is not installed starts install If the user turns on "Use Tor" and they are missing Orbot, bring them to the screen to install Tor. --- .../org/schabi/newpipe/SettingsActivity.java | 30 +++++++++++++++++-- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/SettingsActivity.java b/app/src/main/java/org/schabi/newpipe/SettingsActivity.java index c8c089a98..f599ebd8b 100644 --- a/app/src/main/java/org/schabi/newpipe/SettingsActivity.java +++ b/app/src/main/java/org/schabi/newpipe/SettingsActivity.java @@ -1,5 +1,8 @@ package org.schabi.newpipe; +import android.app.Activity; +import android.content.Context; +import android.content.Intent; import android.content.res.Configuration; import android.os.Bundle; import android.preference.CheckBoxPreference; @@ -39,6 +42,7 @@ import info.guardianproject.netcipher.proxy.OrbotHelper; public class SettingsActivity extends PreferenceActivity { + private static final int REQUEST_INSTALL_ORBOT = 0x1234; private AppCompatDelegate mDelegate = null; @Override @@ -65,19 +69,39 @@ public class SettingsActivity extends PreferenceActivity { // if Orbot is installed, then default to using Tor, the user can still override useTorCheckBox = (CheckBoxPreference) findPreference(getString(R.string.useTor)); - boolean useTor = OrbotHelper.isOrbotInstalled(getActivity()); + final Activity activity = getActivity(); + final boolean useTor = OrbotHelper.isOrbotInstalled(activity); useTorCheckBox.setDefaultValue(useTor); useTorCheckBox.setChecked(useTor); useTorCheckBox.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { @Override - public boolean onPreferenceChange(Preference preference, Object useTor) { - App.configureTor((Boolean) useTor); + public boolean onPreferenceChange(Preference preference, Object o) { + boolean useTor = (Boolean) o; + if (useTor) { + if (OrbotHelper.isOrbotInstalled(activity)) { + App.configureTor(true); + } else { + Intent intent = OrbotHelper.getOrbotInstallIntent(activity); + activity.startActivityForResult(intent, REQUEST_INSTALL_ORBOT); + } + } else { + App.configureTor(false); + } return true; } }); } } + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + // try to start tor regardless of resultCode since clicking back after + // installing the app does not necessarily return RESULT_OK + App.configureTor(requestCode == REQUEST_INSTALL_ORBOT + && OrbotHelper.requestStartTor(this)); + } + @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); From b3a1a5dcc23ebc9de26137bdc31a3700ca22d43d Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Sat, 2 Jan 2016 21:53:48 +0100 Subject: [PATCH 31/36] Android provides global vars for the actual download directories --- app/src/main/java/org/schabi/newpipe/DownloadDialog.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/DownloadDialog.java b/app/src/main/java/org/schabi/newpipe/DownloadDialog.java index 3001455f9..dd2f2c9d6 100644 --- a/app/src/main/java/org/schabi/newpipe/DownloadDialog.java +++ b/app/src/main/java/org/schabi/newpipe/DownloadDialog.java @@ -61,17 +61,17 @@ public class DownloadDialog extends DialogFragment { String suffix = ""; String title = arguments.getString(TITLE); String url = ""; - String downloadFolder = "Download"; + String downloadFolder = Environment.DIRECTORY_DOWNLOADS; switch(which) { case 0: // Video suffix = arguments.getString(FILE_SUFFIX_VIDEO); url = arguments.getString(VIDEO_URL); - downloadFolder = "Movies"; + downloadFolder = Environment.DIRECTORY_MOVIES; break; case 1: suffix = arguments.getString(FILE_SUFFIX_AUDIO); url = arguments.getString(AUDIO_URL); - downloadFolder = "Music"; + downloadFolder = Environment.DIRECTORY_MUSIC; break; default: Log.d(TAG, "lolz"); From 0bb0226bc2d0d8e90ccc91ce9252d3db6410bf85 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Sat, 2 Jan 2016 22:47:21 +0100 Subject: [PATCH 32/36] download files via Tor when Tor is enabled DownloadManager does not let you set its proxy or change how it connects to the internet. So we have to make a custom one, unfortunately. This is a very basic downloader with none of the special sauce that makes the built-in DownloadManager handy. --- app/src/main/java/org/schabi/newpipe/App.java | 4 ++ .../org/schabi/newpipe/DownloadDialog.java | 24 +++++--- .../java/org/schabi/newpipe/Downloader.java | 56 +++++++++++++++++++ 3 files changed, 75 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/App.java b/app/src/main/java/org/schabi/newpipe/App.java index 95127d7fe..877000e61 100644 --- a/app/src/main/java/org/schabi/newpipe/App.java +++ b/app/src/main/java/org/schabi/newpipe/App.java @@ -39,4 +39,8 @@ public class App extends Application { OrbotHelper.requestStartTor(context); } } + + static boolean isUsingTor() { + return useTor; + } } diff --git a/app/src/main/java/org/schabi/newpipe/DownloadDialog.java b/app/src/main/java/org/schabi/newpipe/DownloadDialog.java index dd2f2c9d6..c53ab8512 100644 --- a/app/src/main/java/org/schabi/newpipe/DownloadDialog.java +++ b/app/src/main/java/org/schabi/newpipe/DownloadDialog.java @@ -87,15 +87,21 @@ public class DownloadDialog extends DialogFragment { //TODO notify user "download directory should be changed" ? } } - DownloadManager dm = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); - DownloadManager.Request request = new DownloadManager.Request( - Uri.parse(url)); - request.setDestinationUri(Uri.fromFile(new File(dir + "/" + title + suffix))); - request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); - try { - dm.enqueue(request); - } catch (Exception e) { - e.printStackTrace(); + String saveFilePath = dir + "/" + title + suffix; + if (App.isUsingTor()) { + // if using Tor, do not use DownloadManager because the proxy cannot be set + Downloader.downloadFile(url, saveFilePath); + } else { + DownloadManager dm = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); + DownloadManager.Request request = new DownloadManager.Request( + Uri.parse(url)); + request.setDestinationUri(Uri.fromFile(new File(saveFilePath))); + request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); + try { + dm.enqueue(request); + } catch (Exception e) { + e.printStackTrace(); + } } } }); diff --git a/app/src/main/java/org/schabi/newpipe/Downloader.java b/app/src/main/java/org/schabi/newpipe/Downloader.java index f0fe75582..b1ada078c 100644 --- a/app/src/main/java/org/schabi/newpipe/Downloader.java +++ b/app/src/main/java/org/schabi/newpipe/Downloader.java @@ -1,9 +1,17 @@ package org.schabi.newpipe; +import android.os.AsyncTask; +import android.util.Log; + +import java.io.BufferedInputStream; import java.io.BufferedReader; +import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; +import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; +import java.net.MalformedURLException; import java.net.URL; import java.net.UnknownHostException; @@ -32,6 +40,7 @@ import info.guardianproject.netcipher.NetCipher; */ public class Downloader { + public static final String TAG = "Downloader"; private static final String USER_AGENT = "Mozilla/5.0"; @@ -97,4 +106,51 @@ public class Downloader { return ret; } + + /** + * Downloads a file from a URL in the background using an {@link AsyncTask}. + * + * @param fileURL HTTP URL of the file to be downloaded + * @param saveFilePath path of the directory to save the file + * @throws IOException + */ + public static void downloadFile(final String fileURL, final String saveFilePath) { + new AsyncTask() { + @Override + protected Void doInBackground(Void... voids) { + HttpsURLConnection con = null; + try { + con = NetCipher.getHttpsURLConnection(fileURL); + int responseCode = con.getResponseCode(); + + // always check HTTP response code first + if (responseCode == HttpURLConnection.HTTP_OK) { + InputStream inputStream = new BufferedInputStream(con.getInputStream()); + FileOutputStream outputStream = new FileOutputStream(saveFilePath); + + int bytesRead = -1; + byte[] buffer = new byte[8192]; + while ((bytesRead = inputStream.read(buffer)) != -1) { + outputStream.write(buffer, 0, bytesRead); + } + + outputStream.close(); + inputStream.close(); + + } else { + Log.i(TAG, "No file to download. Server replied HTTP code: " + responseCode); + } + } catch (IOException e) { + e.printStackTrace(); + } finally { + if (con != null) { + con.disconnect(); + con = null; + } + } + return null; + } + }.execute(); + } + } From 9127f7f0c22591353a4ba3da8737872a2502eb4e Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Sun, 3 Jan 2016 00:04:55 +0100 Subject: [PATCH 33/36] make progress notification for Tor downloader (closes #39) --- .../org/schabi/newpipe/DownloadDialog.java | 2 +- .../java/org/schabi/newpipe/Downloader.java | 53 +++++++++++++++++-- 2 files changed, 51 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/DownloadDialog.java b/app/src/main/java/org/schabi/newpipe/DownloadDialog.java index c53ab8512..1f018618a 100644 --- a/app/src/main/java/org/schabi/newpipe/DownloadDialog.java +++ b/app/src/main/java/org/schabi/newpipe/DownloadDialog.java @@ -90,7 +90,7 @@ public class DownloadDialog extends DialogFragment { String saveFilePath = dir + "/" + title + suffix; if (App.isUsingTor()) { // if using Tor, do not use DownloadManager because the proxy cannot be set - Downloader.downloadFile(url, saveFilePath); + Downloader.downloadFile(getContext(), url, saveFilePath); } else { DownloadManager dm = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); DownloadManager.Request request = new DownloadManager.Request( diff --git a/app/src/main/java/org/schabi/newpipe/Downloader.java b/app/src/main/java/org/schabi/newpipe/Downloader.java index b1ada078c..8a296c61e 100644 --- a/app/src/main/java/org/schabi/newpipe/Downloader.java +++ b/app/src/main/java/org/schabi/newpipe/Downloader.java @@ -1,6 +1,12 @@ package org.schabi.newpipe; +import android.app.Notification; +import android.app.NotificationManager; +import android.content.Context; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; import android.os.AsyncTask; +import android.support.v4.app.NotificationCompat; import android.util.Log; import java.io.BufferedInputStream; @@ -114,8 +120,28 @@ public class Downloader { * @param saveFilePath path of the directory to save the file * @throws IOException */ - public static void downloadFile(final String fileURL, final String saveFilePath) { - new AsyncTask() { + public static void downloadFile(final Context context, final String fileURL, final String saveFilePath) { + new AsyncTask() { + + private NotificationManager nm; + private NotificationCompat.Builder builder; + private int notifyId = 0x1234; + private int fileSize = 0xffffffff; + + @Override + protected void onPreExecute() { + super.onPreExecute(); + nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + Drawable icon = context.getResources().getDrawable(R.mipmap.ic_launcher); + builder = new NotificationCompat.Builder(context) + .setSmallIcon(android.R.drawable.stat_sys_download) + .setLargeIcon(((BitmapDrawable) icon).getBitmap()) + .setContentTitle(saveFilePath.substring(saveFilePath.lastIndexOf('/') + 1)) + .setContentText(saveFilePath) + .setProgress(fileSize, 0, false); + nm.notify(notifyId, builder.build()); + } + @Override protected Void doInBackground(Void... voids) { HttpsURLConnection con = null; @@ -125,17 +151,26 @@ public class Downloader { // always check HTTP response code first if (responseCode == HttpURLConnection.HTTP_OK) { + fileSize = con.getContentLength(); InputStream inputStream = new BufferedInputStream(con.getInputStream()); FileOutputStream outputStream = new FileOutputStream(saveFilePath); + int bufferSize = 8192; + int downloaded = 0; + int bytesRead = -1; - byte[] buffer = new byte[8192]; + byte[] buffer = new byte[bufferSize]; while ((bytesRead = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, bytesRead); + downloaded += bytesRead; + if (downloaded % 50000 < bufferSize) { + publishProgress(downloaded); + } } outputStream.close(); inputStream.close(); + publishProgress(bufferSize); } else { Log.i(TAG, "No file to download. Server replied HTTP code: " + responseCode); @@ -150,6 +185,18 @@ public class Downloader { } return null; } + + @Override + protected void onProgressUpdate(Integer... progress) { + builder.setProgress(fileSize, progress[0], false); + nm.notify(notifyId, builder.build()); + } + + @Override + protected void onPostExecute(Void aVoid) { + super.onPostExecute(aVoid); + nm.cancel(notifyId); + } }.execute(); } From 94d2f03e9bb34c298779ef8e0e9ad712443536fb Mon Sep 17 00:00:00 2001 From: naofum Date: Sun, 3 Jan 2016 10:31:33 +0100 Subject: [PATCH 34/36] Translated using Weblate (Japanese) Currently translated at 100.0% (51 of 51 strings) --- app/src/main/res/values-ja/strings.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 558918270..c09605941 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -50,4 +50,8 @@ 外部オーディオ プレイヤーを使用する バックグラウンドで再生しています + NewPipe バックグラウンド プレーヤー + 読み込み中 + 再生 + From 0a334804a31c8df5ef14cdec2df15e55a8ccdbfb Mon Sep 17 00:00:00 2001 From: M2ck Date: Sun, 3 Jan 2016 16:56:41 +0100 Subject: [PATCH 35/36] Translated using Weblate (French) Currently translated at 100.0% (51 of 51 strings) --- app/src/main/res/values-fr/strings.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index e1cfeeff0..227877c52 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -50,4 +50,8 @@ Utiliser un lecteur vidéo externe Utiliser un lecteur audio externe Lecture en arrière-plan + Lecteur en arrière-plan NewPipe + Chargement + Lecture + From 9804bb95cc36891fc80b76f0ffeae2465885d800 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mladen=20Pejakovi=C4=87?= Date: Sun, 3 Jan 2016 19:11:18 +0100 Subject: [PATCH 36/36] Translated using Weblate (Serbian) Currently translated at 100.0% (53 of 53 strings) --- app/src/main/res/values-sr/strings.xml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/values-sr/strings.xml b/app/src/main/res/values-sr/strings.xml index 107434167..e0c092d25 100644 --- a/app/src/main/res/values-sr/strings.xml +++ b/app/src/main/res/values-sr/strings.xml @@ -58,4 +58,6 @@ Учитавам Пусти - + Користи Тор + Принудно преусмерење саобраћаја кроз Тор за доданту приватност (токови још нису подржани) +