fix merge conflict
|
@ -14,12 +14,14 @@ android {
|
||||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||||
vectorDrawables.useSupportLibrary = true
|
vectorDrawables.useSupportLibrary = true
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
minifyEnabled true
|
minifyEnabled true
|
||||||
shrinkResources true
|
shrinkResources true
|
||||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||||
}
|
}
|
||||||
|
|
||||||
debug {
|
debug {
|
||||||
multiDexEnabled true
|
multiDexEnabled true
|
||||||
debuggable true
|
debuggable true
|
||||||
|
@ -33,6 +35,7 @@ android {
|
||||||
// but continue the build even when errors are found:
|
// but continue the build even when errors are found:
|
||||||
abortOnError false
|
abortOnError false
|
||||||
}
|
}
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
sourceCompatibility JavaVersion.VERSION_1_8
|
sourceCompatibility JavaVersion.VERSION_1_8
|
||||||
targetCompatibility JavaVersion.VERSION_1_8
|
targetCompatibility JavaVersion.VERSION_1_8
|
||||||
|
|
After Width: | Height: | Size: 9.6 KiB |
|
@ -1,5 +1,6 @@
|
||||||
package org.schabi.newpipe;
|
package org.schabi.newpipe;
|
||||||
|
|
||||||
|
import android.annotation.TargetApi;
|
||||||
import android.app.Application;
|
import android.app.Application;
|
||||||
import android.app.NotificationChannel;
|
import android.app.NotificationChannel;
|
||||||
import android.app.NotificationManager;
|
import android.app.NotificationManager;
|
||||||
|
@ -65,6 +66,7 @@ import io.reactivex.plugins.RxJavaPlugins;
|
||||||
public class App extends Application {
|
public class App extends Application {
|
||||||
protected static final String TAG = App.class.toString();
|
protected static final String TAG = App.class.toString();
|
||||||
private RefWatcher refWatcher;
|
private RefWatcher refWatcher;
|
||||||
|
private static App app;
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private static final Class<? extends ReportSenderFactory>[]
|
private static final Class<? extends ReportSenderFactory>[]
|
||||||
|
@ -88,6 +90,8 @@ public class App extends Application {
|
||||||
}
|
}
|
||||||
refWatcher = installLeakCanary();
|
refWatcher = installLeakCanary();
|
||||||
|
|
||||||
|
app = this;
|
||||||
|
|
||||||
// Initialize settings first because others inits can use its values
|
// Initialize settings first because others inits can use its values
|
||||||
SettingsActivity.initSettings(this);
|
SettingsActivity.initSettings(this);
|
||||||
|
|
||||||
|
@ -100,6 +104,9 @@ public class App extends Application {
|
||||||
ImageLoader.getInstance().init(getImageLoaderConfigurations(10, 50));
|
ImageLoader.getInstance().init(getImageLoaderConfigurations(10, 50));
|
||||||
|
|
||||||
configureRxJavaErrorHandler();
|
configureRxJavaErrorHandler();
|
||||||
|
|
||||||
|
// Check for new version
|
||||||
|
new CheckForNewAppVersionTask().execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Downloader getDownloader() {
|
protected Downloader getDownloader() {
|
||||||
|
@ -211,6 +218,31 @@ public class App extends Application {
|
||||||
NotificationManager mNotificationManager =
|
NotificationManager mNotificationManager =
|
||||||
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
mNotificationManager.createNotificationChannel(mChannel);
|
mNotificationManager.createNotificationChannel(mChannel);
|
||||||
|
|
||||||
|
setUpUpdateNotificationChannel(importance);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set up notification channel for app update.
|
||||||
|
* @param importance
|
||||||
|
*/
|
||||||
|
@TargetApi(Build.VERSION_CODES.O)
|
||||||
|
private void setUpUpdateNotificationChannel(int importance) {
|
||||||
|
|
||||||
|
final String appUpdateId
|
||||||
|
= getString(R.string.app_update_notification_channel_id);
|
||||||
|
final CharSequence appUpdateName
|
||||||
|
= getString(R.string.app_update_notification_channel_name);
|
||||||
|
final String appUpdateDescription
|
||||||
|
= getString(R.string.app_update_notification_channel_description);
|
||||||
|
|
||||||
|
NotificationChannel appUpdateChannel
|
||||||
|
= new NotificationChannel(appUpdateId, appUpdateName, importance);
|
||||||
|
appUpdateChannel.setDescription(appUpdateDescription);
|
||||||
|
|
||||||
|
NotificationManager appUpdateNotificationManager
|
||||||
|
= (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
|
appUpdateNotificationManager.createNotificationChannel(appUpdateChannel);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
@ -226,4 +258,8 @@ public class App extends Application {
|
||||||
protected boolean isDisposedRxExceptionsReported() {
|
protected boolean isDisposedRxExceptionsReported() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static App getApp() {
|
||||||
|
return app;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,230 @@
|
||||||
|
package org.schabi.newpipe;
|
||||||
|
|
||||||
|
import android.app.Application;
|
||||||
|
import android.app.PendingIntent;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.content.pm.PackageInfo;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.content.pm.Signature;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
|
import android.support.v4.app.NotificationCompat;
|
||||||
|
import android.support.v4.app.NotificationManagerCompat;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
import org.schabi.newpipe.report.ErrorActivity;
|
||||||
|
import org.schabi.newpipe.report.UserAction;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.cert.CertificateEncodingException;
|
||||||
|
import java.security.cert.CertificateException;
|
||||||
|
import java.security.cert.CertificateFactory;
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import okhttp3.OkHttpClient;
|
||||||
|
import okhttp3.Request;
|
||||||
|
import okhttp3.RequestBody;
|
||||||
|
import okhttp3.Response;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AsyncTask to check if there is a newer version of the NewPipe github apk available or not.
|
||||||
|
* If there is a newer version we show a notification, informing the user. On tapping
|
||||||
|
* the notification, the user will be directed to the download link.
|
||||||
|
*/
|
||||||
|
public class CheckForNewAppVersionTask extends AsyncTask<Void, Void, String> {
|
||||||
|
|
||||||
|
private static final Application app = App.getApp();
|
||||||
|
private static final String GITHUB_APK_SHA1 = "B0:2E:90:7C:1C:D6:FC:57:C3:35:F0:88:D0:8F:50:5F:94:E4:D2:15";
|
||||||
|
private static final String newPipeApiUrl = "https://newpipe.schabi.org/api/data.json";
|
||||||
|
private static final int timeoutPeriod = 30;
|
||||||
|
|
||||||
|
private SharedPreferences mPrefs;
|
||||||
|
private OkHttpClient client;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPreExecute() {
|
||||||
|
|
||||||
|
mPrefs = PreferenceManager.getDefaultSharedPreferences(app);
|
||||||
|
|
||||||
|
// Check if user has enabled/ disabled update checking
|
||||||
|
// and if the current apk is a github one or not.
|
||||||
|
if (!mPrefs.getBoolean(app.getString(R.string.update_app_key), true)
|
||||||
|
|| !isGithubApk()) {
|
||||||
|
this.cancel(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String doInBackground(Void... voids) {
|
||||||
|
|
||||||
|
// Make a network request to get latest NewPipe data.
|
||||||
|
if (client == null) {
|
||||||
|
|
||||||
|
client = new OkHttpClient
|
||||||
|
.Builder()
|
||||||
|
.readTimeout(timeoutPeriod, TimeUnit.SECONDS)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
Request request = new Request.Builder()
|
||||||
|
.url(newPipeApiUrl)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
try {
|
||||||
|
Response response = client.newCall(request).execute();
|
||||||
|
return response.body().string();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
ErrorActivity.reportError(app, ex, null, null,
|
||||||
|
ErrorActivity.ErrorInfo.make(UserAction.SOMETHING_ELSE, "none",
|
||||||
|
"app update API fail", R.string.app_ui_crash));
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(String response) {
|
||||||
|
|
||||||
|
// Parse the json from the response.
|
||||||
|
if (response != null) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
JSONObject mainObject = new JSONObject(response);
|
||||||
|
JSONObject flavoursObject = mainObject.getJSONObject("flavors");
|
||||||
|
JSONObject githubObject = flavoursObject.getJSONObject("github");
|
||||||
|
JSONObject githubStableObject = githubObject.getJSONObject("stable");
|
||||||
|
|
||||||
|
String versionName = githubStableObject.getString("version");
|
||||||
|
String versionCode = githubStableObject.getString("version_code");
|
||||||
|
String apkLocationUrl = githubStableObject.getString("apk");
|
||||||
|
|
||||||
|
compareAppVersionAndShowNotification(versionName, apkLocationUrl, versionCode);
|
||||||
|
|
||||||
|
} catch (JSONException ex) {
|
||||||
|
ErrorActivity.reportError(app, ex, null, null,
|
||||||
|
ErrorActivity.ErrorInfo.make(UserAction.SOMETHING_ELSE, "none",
|
||||||
|
"could not parse app update JSON data", R.string.app_ui_crash));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to compare the current and latest available app version.
|
||||||
|
* If a newer version is available, we show the update notification.
|
||||||
|
* @param versionName
|
||||||
|
* @param apkLocationUrl
|
||||||
|
*/
|
||||||
|
private void compareAppVersionAndShowNotification(String versionName,
|
||||||
|
String apkLocationUrl,
|
||||||
|
String versionCode) {
|
||||||
|
|
||||||
|
int NOTIFICATION_ID = 2000;
|
||||||
|
|
||||||
|
if (BuildConfig.VERSION_CODE < Integer.valueOf(versionCode)) {
|
||||||
|
|
||||||
|
// A pending intent to open the apk location url in the browser.
|
||||||
|
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(apkLocationUrl));
|
||||||
|
PendingIntent pendingIntent
|
||||||
|
= PendingIntent.getActivity(app, 0, intent, 0);
|
||||||
|
|
||||||
|
NotificationCompat.Builder notificationBuilder = new NotificationCompat
|
||||||
|
.Builder(app, app.getString(R.string.app_update_notification_channel_id))
|
||||||
|
.setSmallIcon(R.drawable.ic_newpipe_update)
|
||||||
|
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
||||||
|
.setContentIntent(pendingIntent)
|
||||||
|
.setAutoCancel(true)
|
||||||
|
.setContentTitle(app.getString(R.string.app_update_notification_content_title))
|
||||||
|
.setContentText(app.getString(R.string.app_update_notification_content_text)
|
||||||
|
+ " " + versionName);
|
||||||
|
|
||||||
|
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(app);
|
||||||
|
notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to get the apk's SHA1 key.
|
||||||
|
* https://stackoverflow.com/questions/9293019/get-certificate-fingerprint-from-android-app#22506133
|
||||||
|
*/
|
||||||
|
private static String getCertificateSHA1Fingerprint() {
|
||||||
|
|
||||||
|
PackageManager pm = app.getPackageManager();
|
||||||
|
String packageName = app.getPackageName();
|
||||||
|
int flags = PackageManager.GET_SIGNATURES;
|
||||||
|
PackageInfo packageInfo = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
packageInfo = pm.getPackageInfo(packageName, flags);
|
||||||
|
} catch (PackageManager.NameNotFoundException ex) {
|
||||||
|
ErrorActivity.reportError(app, ex, null, null,
|
||||||
|
ErrorActivity.ErrorInfo.make(UserAction.SOMETHING_ELSE, "none",
|
||||||
|
"Could not find package info", R.string.app_ui_crash));
|
||||||
|
}
|
||||||
|
|
||||||
|
Signature[] signatures = packageInfo.signatures;
|
||||||
|
byte[] cert = signatures[0].toByteArray();
|
||||||
|
InputStream input = new ByteArrayInputStream(cert);
|
||||||
|
|
||||||
|
CertificateFactory cf = null;
|
||||||
|
X509Certificate c = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
cf = CertificateFactory.getInstance("X509");
|
||||||
|
c = (X509Certificate) cf.generateCertificate(input);
|
||||||
|
} catch (CertificateException ex) {
|
||||||
|
ErrorActivity.reportError(app, ex, null, null,
|
||||||
|
ErrorActivity.ErrorInfo.make(UserAction.SOMETHING_ELSE, "none",
|
||||||
|
"Certificate error", R.string.app_ui_crash));
|
||||||
|
}
|
||||||
|
|
||||||
|
String hexString = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
MessageDigest md = MessageDigest.getInstance("SHA1");
|
||||||
|
byte[] publicKey = md.digest(c.getEncoded());
|
||||||
|
hexString = byte2HexFormatted(publicKey);
|
||||||
|
} catch (NoSuchAlgorithmException ex1) {
|
||||||
|
ErrorActivity.reportError(app, ex1, null, null,
|
||||||
|
ErrorActivity.ErrorInfo.make(UserAction.SOMETHING_ELSE, "none",
|
||||||
|
"Could not retrieve SHA1 key", R.string.app_ui_crash));
|
||||||
|
} catch (CertificateEncodingException ex2) {
|
||||||
|
ErrorActivity.reportError(app, ex2, null, null,
|
||||||
|
ErrorActivity.ErrorInfo.make(UserAction.SOMETHING_ELSE, "none",
|
||||||
|
"Could not retrieve SHA1 key", R.string.app_ui_crash));
|
||||||
|
}
|
||||||
|
|
||||||
|
return hexString;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String byte2HexFormatted(byte[] arr) {
|
||||||
|
|
||||||
|
StringBuilder str = new StringBuilder(arr.length * 2);
|
||||||
|
|
||||||
|
for (int i = 0; i < arr.length; i++) {
|
||||||
|
String h = Integer.toHexString(arr[i]);
|
||||||
|
int l = h.length();
|
||||||
|
if (l == 1) h = "0" + h;
|
||||||
|
if (l > 2) h = h.substring(l - 2, l);
|
||||||
|
str.append(h.toUpperCase());
|
||||||
|
if (i < (arr.length - 1)) str.append(':');
|
||||||
|
}
|
||||||
|
return str.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isGithubApk() {
|
||||||
|
|
||||||
|
return getCertificateSHA1Fingerprint().equals(GITHUB_APK_SHA1);
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ import android.os.Bundle;
|
||||||
import android.support.v7.preference.Preference;
|
import android.support.v7.preference.Preference;
|
||||||
|
|
||||||
import org.schabi.newpipe.BuildConfig;
|
import org.schabi.newpipe.BuildConfig;
|
||||||
|
import org.schabi.newpipe.CheckForNewAppVersionTask;
|
||||||
import org.schabi.newpipe.R;
|
import org.schabi.newpipe.R;
|
||||||
|
|
||||||
public class MainSettingsFragment extends BasePreferenceFragment {
|
public class MainSettingsFragment extends BasePreferenceFragment {
|
||||||
|
@ -13,6 +14,13 @@ public class MainSettingsFragment extends BasePreferenceFragment {
|
||||||
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
||||||
addPreferencesFromResource(R.xml.main_settings);
|
addPreferencesFromResource(R.xml.main_settings);
|
||||||
|
|
||||||
|
if (!CheckForNewAppVersionTask.isGithubApk()) {
|
||||||
|
final Preference update = findPreference(getString(R.string.update_pref_screen_key));
|
||||||
|
getPreferenceScreen().removePreference(update);
|
||||||
|
|
||||||
|
defaultPreferences.edit().putBoolean(getString(R.string.update_app_key), false).apply();
|
||||||
|
}
|
||||||
|
|
||||||
if (!DEBUG) {
|
if (!DEBUG) {
|
||||||
final Preference debug = findPreference(getString(R.string.debug_pref_screen_key));
|
final Preference debug = findPreference(getString(R.string.debug_pref_screen_key));
|
||||||
getPreferenceScreen().removePreference(debug);
|
getPreferenceScreen().removePreference(debug);
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
package org.schabi.newpipe.settings;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
import android.support.v7.preference.Preference;
|
||||||
|
|
||||||
|
import org.schabi.newpipe.CheckForNewAppVersionTask;
|
||||||
|
import org.schabi.newpipe.R;
|
||||||
|
|
||||||
|
public class UpdateSettingsFragment extends BasePreferenceFragment {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
String updateToggleKey = getString(R.string.update_app_key);
|
||||||
|
findPreference(updateToggleKey).setOnPreferenceChangeListener(updatePreferenceChange);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
||||||
|
addPreferencesFromResource(R.xml.update_settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Preference.OnPreferenceChangeListener updatePreferenceChange
|
||||||
|
= (preference, newValue) -> {
|
||||||
|
|
||||||
|
defaultPreferences.edit().putBoolean(getString(R.string.update_app_key),
|
||||||
|
(boolean) newValue).apply();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
}
|
After Width: | Height: | Size: 680 B |
After Width: | Height: | Size: 720 B |
After Width: | Height: | Size: 720 B |
After Width: | Height: | Size: 512 B |
After Width: | Height: | Size: 401 B |
After Width: | Height: | Size: 379 B |
After Width: | Height: | Size: 562 B |
After Width: | Height: | Size: 734 B |
After Width: | Height: | Size: 954 B |
After Width: | Height: | Size: 1010 B |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 431 B |
After Width: | Height: | Size: 379 B |
After Width: | Height: | Size: 710 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 431 B |
After Width: | Height: | Size: 379 B |
After Width: | Height: | Size: 710 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 2.0 KiB |
|
@ -41,6 +41,7 @@
|
||||||
<attr name="ic_list" format="reference"/>
|
<attr name="ic_list" format="reference"/>
|
||||||
<attr name="ic_grid" format="reference"/>
|
<attr name="ic_grid" format="reference"/>
|
||||||
<attr name="ic_delete" format="reference"/>
|
<attr name="ic_delete" format="reference"/>
|
||||||
|
<attr name="ic_settings_update" format="reference"/>
|
||||||
|
|
||||||
<!-- Can't refer to colors directly in drawable's xml-->
|
<!-- Can't refer to colors directly in drawable's xml-->
|
||||||
<attr name="toolbar_shadow_drawable" format="reference"/>
|
<attr name="toolbar_shadow_drawable" format="reference"/>
|
||||||
|
|
|
@ -222,6 +222,10 @@
|
||||||
<item>@string/always_ask_open_action_key</item>
|
<item>@string/always_ask_open_action_key</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
<!-- Updates -->
|
||||||
|
<string name="update_app_key" translatable="false">update_app_key</string>
|
||||||
|
<string name="update_pref_screen_key" translatable="false">update_pref_screen_key</string>
|
||||||
|
|
||||||
<!-- alternatively, load these from some local android data store -->
|
<!-- alternatively, load these from some local android data store -->
|
||||||
<string-array name="language_codes" translatable="false">
|
<string-array name="language_codes" translatable="false">
|
||||||
<item>af</item>
|
<item>af</item>
|
||||||
|
|
|
@ -112,6 +112,7 @@
|
||||||
<string name="settings_category_appearance_title">Appearance</string>
|
<string name="settings_category_appearance_title">Appearance</string>
|
||||||
<string name="settings_category_other_title">Other</string>
|
<string name="settings_category_other_title">Other</string>
|
||||||
<string name="settings_category_debug_title">Debug</string>
|
<string name="settings_category_debug_title">Debug</string>
|
||||||
|
<string name="settings_category_updates_title">Updates</string>
|
||||||
<string name="background_player_playing_toast">Playing in background</string>
|
<string name="background_player_playing_toast">Playing in background</string>
|
||||||
<string name="popup_playing_toast">Playing in popup mode</string>
|
<string name="popup_playing_toast">Playing in popup mode</string>
|
||||||
<string name="background_player_append">Queued on background player</string>
|
<string name="background_player_append">Queued on background player</string>
|
||||||
|
@ -153,6 +154,10 @@
|
||||||
<string name="notification_channel_name">NewPipe Notification</string>
|
<string name="notification_channel_name">NewPipe Notification</string>
|
||||||
<string name="notification_channel_description">Notifications for NewPipe background and popup players</string>
|
<string name="notification_channel_description">Notifications for NewPipe background and popup players</string>
|
||||||
|
|
||||||
|
<string name="app_update_notification_channel_id" translatable="false">newpipeAppUpdate</string>
|
||||||
|
<string name="app_update_notification_channel_name">App Update Notification</string>
|
||||||
|
<string name="app_update_notification_channel_description">Notifications for new NewPipe version</string>
|
||||||
|
|
||||||
<string name="unknown_content">[Unknown]</string>
|
<string name="unknown_content">[Unknown]</string>
|
||||||
|
|
||||||
<string name="toggle_orientation">Toggle Orientation</string>
|
<string name="toggle_orientation">Toggle Orientation</string>
|
||||||
|
@ -513,6 +518,10 @@
|
||||||
<item>144p</item>
|
<item>144p</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
<!-- Updates Settings -->
|
||||||
|
<string name="updates_setting_title">Updates</string>
|
||||||
|
<string name="updates_setting_description">Show a notification to prompt app update when a new version is available</string>
|
||||||
|
|
||||||
<!-- Minimize to exit action -->
|
<!-- Minimize to exit action -->
|
||||||
<string name="minimize_on_exit_title">Minimize on app switch</string>
|
<string name="minimize_on_exit_title">Minimize on app switch</string>
|
||||||
<string name="minimize_on_exit_summary">Action when switching to other app from main video player — %s</string>
|
<string name="minimize_on_exit_summary">Action when switching to other app from main video player — %s</string>
|
||||||
|
@ -525,16 +534,21 @@
|
||||||
<string name="auto">Auto</string>
|
<string name="auto">Auto</string>
|
||||||
<string name="switch_view">Switch View</string>
|
<string name="switch_view">Switch View</string>
|
||||||
|
|
||||||
|
<!-- App update notification -->
|
||||||
|
<string name="app_update_notification_content_title">NewPipe Update Available!</string>
|
||||||
|
<string name="app_update_notification_content_text">Tap to download</string>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<string name="missions_header_finished">Finished</string>
|
<string name="missions_header_finished">Finished</string>
|
||||||
<string name="missions_header_pending">In queue</string>
|
<string name="missions_header_pending">In queue</string>
|
||||||
|
|
||||||
<string name="paused">paused</string>
|
<string name="paused">paused</string>
|
||||||
<string name="queued">queued</string>
|
<string name="queued">queued</string>
|
||||||
<string name="post_processing">post-processing</string>
|
<string name="post_processing">post-processing</string>
|
||||||
|
|
||||||
<string name="enqueue">Queue</string>
|
<string name="enqueue">Queue</string>
|
||||||
|
|
||||||
<string name="permission_denied">Action denied by the system</string>
|
<string name="permission_denied">Action denied by the system</string>
|
||||||
|
|
||||||
<!-- download notifications -->
|
<!-- download notifications -->
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
<item name="ic_list">@drawable/ic_list_black_24dp</item>
|
<item name="ic_list">@drawable/ic_list_black_24dp</item>
|
||||||
<item name="ic_grid">@drawable/ic_grid_black_24dp</item>
|
<item name="ic_grid">@drawable/ic_grid_black_24dp</item>
|
||||||
<item name="ic_delete">@drawable/ic_delete_black_24dp</item>
|
<item name="ic_delete">@drawable/ic_delete_black_24dp</item>
|
||||||
|
<item name="ic_settings_update">@drawable/ic_settings_update_black</item>
|
||||||
|
|
||||||
<item name="separator_color">@color/light_separator_color</item>
|
<item name="separator_color">@color/light_separator_color</item>
|
||||||
<item name="contrast_background_color">@color/light_contrast_background_color</item>
|
<item name="contrast_background_color">@color/light_contrast_background_color</item>
|
||||||
|
@ -118,6 +119,7 @@
|
||||||
<item name="ic_list">@drawable/ic_list_white_24dp</item>
|
<item name="ic_list">@drawable/ic_list_white_24dp</item>
|
||||||
<item name="ic_grid">@drawable/ic_grid_white_24dp</item>
|
<item name="ic_grid">@drawable/ic_grid_white_24dp</item>
|
||||||
<item name="ic_delete">@drawable/ic_delete_white_24dp</item>
|
<item name="ic_delete">@drawable/ic_delete_white_24dp</item>
|
||||||
|
<item name="ic_settings_update">@drawable/ic_settings_update_white</item>
|
||||||
|
|
||||||
<item name="separator_color">@color/dark_separator_color</item>
|
<item name="separator_color">@color/dark_separator_color</item>
|
||||||
<item name="contrast_background_color">@color/dark_contrast_background_color</item>
|
<item name="contrast_background_color">@color/dark_contrast_background_color</item>
|
||||||
|
|
|
@ -29,6 +29,12 @@
|
||||||
android:icon="?attr/language"
|
android:icon="?attr/language"
|
||||||
android:title="@string/content"/>
|
android:title="@string/content"/>
|
||||||
|
|
||||||
|
<PreferenceScreen
|
||||||
|
android:fragment="org.schabi.newpipe.settings.UpdateSettingsFragment"
|
||||||
|
android:icon="?attr/ic_settings_update"
|
||||||
|
android:title="@string/settings_category_updates_title"
|
||||||
|
android:key="update_pref_screen_key"/>
|
||||||
|
|
||||||
<PreferenceScreen
|
<PreferenceScreen
|
||||||
android:fragment="org.schabi.newpipe.settings.DebugSettingsFragment"
|
android:fragment="org.schabi.newpipe.settings.DebugSettingsFragment"
|
||||||
android:icon="?attr/bug"
|
android:icon="?attr/bug"
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<PreferenceScreen
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:key="general_preferences"
|
||||||
|
android:title="@string/settings_category_updates_title">
|
||||||
|
|
||||||
|
<SwitchPreference
|
||||||
|
android:defaultValue="true"
|
||||||
|
android:key="@string/update_app_key"
|
||||||
|
android:title="@string/updates_setting_title"
|
||||||
|
android:summary="@string/updates_setting_description"/>
|
||||||
|
|
||||||
|
</PreferenceScreen>
|