mirror of
				https://github.com/TeamNewPipe/NewPipe
				synced 2025-10-30 06:43:00 +00:00 
			
		
		
		
	Ask for consent before starting update checks
NewPipe is contacting its servers without asking for the users' consent. This is categorized as "tracking" by F-Droid (see https://github.com/TeamNewPipe/NewPipe/discussions/10785). This commit disables checking for udpates by default and adds a dialog asking for the user's consent to automatically check for updates if the app version is eligible for them. After upgrading to a version containing this commit the user is asked directly on the first app start. On fresh installs however, showing it on the first app start contributes to a bad onboarding an welcoming experience. Therefore, the dialog is shown at the second app start. Co-authored-by: Stypox <stypox@pm.me>
This commit is contained in:
		| @@ -60,6 +60,8 @@ import io.reactivex.rxjava3.plugins.RxJavaPlugins; | |||||||
| public class App extends Application { | public class App extends Application { | ||||||
|     public static final String PACKAGE_NAME = BuildConfig.APPLICATION_ID; |     public static final String PACKAGE_NAME = BuildConfig.APPLICATION_ID; | ||||||
|     private static final String TAG = App.class.toString(); |     private static final String TAG = App.class.toString(); | ||||||
|  |  | ||||||
|  |     private boolean isFirstRun = false; | ||||||
|     private static App app; |     private static App app; | ||||||
|  |  | ||||||
|     @NonNull |     @NonNull | ||||||
| @@ -85,7 +87,13 @@ public class App extends Application { | |||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         // Initialize settings first because others inits can use its values |         // check if the last used preference version is set | ||||||
|  |         // to determine whether this is the first app run | ||||||
|  |         final int lastUsedPrefVersion = PreferenceManager.getDefaultSharedPreferences(this) | ||||||
|  |                 .getInt(getString(R.string.last_used_preferences_version), -1); | ||||||
|  |         isFirstRun = lastUsedPrefVersion == -1; | ||||||
|  |  | ||||||
|  |         // Initialize settings first because other initializations can use its values | ||||||
|         NewPipeSettings.initSettings(this); |         NewPipeSettings.initSettings(this); | ||||||
|  |  | ||||||
|         NewPipe.init(getDownloader(), |         NewPipe.init(getDownloader(), | ||||||
| @@ -255,4 +263,7 @@ public class App extends Application { | |||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     public boolean isFirstRun() { | ||||||
|  |         return isFirstRun; | ||||||
|  |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -79,6 +79,7 @@ import org.schabi.newpipe.player.Player; | |||||||
| import org.schabi.newpipe.player.event.OnKeyDownListener; | import org.schabi.newpipe.player.event.OnKeyDownListener; | ||||||
| import org.schabi.newpipe.player.helper.PlayerHolder; | import org.schabi.newpipe.player.helper.PlayerHolder; | ||||||
| import org.schabi.newpipe.player.playqueue.PlayQueue; | import org.schabi.newpipe.player.playqueue.PlayQueue; | ||||||
|  | import org.schabi.newpipe.settings.UpdateSettingsFragment; | ||||||
| import org.schabi.newpipe.util.Constants; | import org.schabi.newpipe.util.Constants; | ||||||
| import org.schabi.newpipe.util.DeviceUtils; | import org.schabi.newpipe.util.DeviceUtils; | ||||||
| import org.schabi.newpipe.util.KioskTranslator; | import org.schabi.newpipe.util.KioskTranslator; | ||||||
| @@ -86,6 +87,7 @@ import org.schabi.newpipe.util.Localization; | |||||||
| import org.schabi.newpipe.util.NavigationHelper; | import org.schabi.newpipe.util.NavigationHelper; | ||||||
| import org.schabi.newpipe.util.PeertubeHelper; | import org.schabi.newpipe.util.PeertubeHelper; | ||||||
| import org.schabi.newpipe.util.PermissionHelper; | import org.schabi.newpipe.util.PermissionHelper; | ||||||
|  | import org.schabi.newpipe.util.ReleaseVersionUtil; | ||||||
| import org.schabi.newpipe.util.SerializedCache; | import org.schabi.newpipe.util.SerializedCache; | ||||||
| import org.schabi.newpipe.util.ServiceHelper; | import org.schabi.newpipe.util.ServiceHelper; | ||||||
| import org.schabi.newpipe.util.StateSaver; | import org.schabi.newpipe.util.StateSaver; | ||||||
| @@ -167,6 +169,11 @@ public class MainActivity extends AppCompatActivity { | |||||||
|             // if this is enabled by the user. |             // if this is enabled by the user. | ||||||
|             NotificationWorker.initialize(this); |             NotificationWorker.initialize(this); | ||||||
|         } |         } | ||||||
|  |         if (!UpdateSettingsFragment.wasUserAskedForConsent(this) | ||||||
|  |                 && ReleaseVersionUtil.INSTANCE.isReleaseApk() | ||||||
|  |                 && !App.getApp().isFirstRun()) { | ||||||
|  |             UpdateSettingsFragment.askForConsentToUpdateChecks(this); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|   | |||||||
| @@ -11,6 +11,7 @@ import androidx.annotation.NonNull; | |||||||
| import androidx.annotation.StringRes; | import androidx.annotation.StringRes; | ||||||
| import androidx.preference.PreferenceManager; | import androidx.preference.PreferenceManager; | ||||||
|  |  | ||||||
|  | import org.schabi.newpipe.App; | ||||||
| import org.schabi.newpipe.R; | import org.schabi.newpipe.R; | ||||||
| import org.schabi.newpipe.util.DeviceUtils; | import org.schabi.newpipe.util.DeviceUtils; | ||||||
|  |  | ||||||
| @@ -44,14 +45,8 @@ public final class NewPipeSettings { | |||||||
|     private NewPipeSettings() { } |     private NewPipeSettings() { } | ||||||
|  |  | ||||||
|     public static void initSettings(final Context context) { |     public static void initSettings(final Context context) { | ||||||
|         // check if the last used preference version is set |  | ||||||
|         // to determine whether this is the first app run |  | ||||||
|         final int lastUsedPrefVersion = PreferenceManager.getDefaultSharedPreferences(context) |  | ||||||
|                 .getInt(context.getString(R.string.last_used_preferences_version), -1); |  | ||||||
|         final boolean isFirstRun = lastUsedPrefVersion == -1; |  | ||||||
|  |  | ||||||
|         // first run migrations, then setDefaultValues, since the latter requires the correct types |         // first run migrations, then setDefaultValues, since the latter requires the correct types | ||||||
|         SettingMigrations.runMigrationsIfNeeded(context, isFirstRun); |         SettingMigrations.runMigrationsIfNeeded(context); | ||||||
|  |  | ||||||
|         // readAgain is true so that if new settings are added their default value is set |         // readAgain is true so that if new settings are added their default value is set | ||||||
|         PreferenceManager.setDefaultValues(context, R.xml.main_settings, true); |         PreferenceManager.setDefaultValues(context, R.xml.main_settings, true); | ||||||
| @@ -68,7 +63,7 @@ public final class NewPipeSettings { | |||||||
|         saveDefaultVideoDownloadDirectory(context); |         saveDefaultVideoDownloadDirectory(context); | ||||||
|         saveDefaultAudioDownloadDirectory(context); |         saveDefaultAudioDownloadDirectory(context); | ||||||
|  |  | ||||||
|         disableMediaTunnelingIfNecessary(context, isFirstRun); |         disableMediaTunnelingIfNecessary(context); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     static void saveDefaultVideoDownloadDirectory(final Context context) { |     static void saveDefaultVideoDownloadDirectory(final Context context) { | ||||||
| @@ -146,8 +141,7 @@ public final class NewPipeSettings { | |||||||
|                 R.string.show_remote_search_suggestions_key); |                 R.string.show_remote_search_suggestions_key); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private static void disableMediaTunnelingIfNecessary(@NonNull final Context context, |     private static void disableMediaTunnelingIfNecessary(@NonNull final Context context) { | ||||||
|                                                          final boolean isFirstRun) { |  | ||||||
|         final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); |         final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); | ||||||
|         final String disabledTunnelingKey = context.getString(R.string.disable_media_tunneling_key); |         final String disabledTunnelingKey = context.getString(R.string.disable_media_tunneling_key); | ||||||
|         final String disabledTunnelingAutomaticallyKey = |         final String disabledTunnelingAutomaticallyKey = | ||||||
| @@ -162,7 +156,7 @@ public final class NewPipeSettings { | |||||||
|                 prefs.getInt(disabledTunnelingAutomaticallyKey, -1) == 0 |                 prefs.getInt(disabledTunnelingAutomaticallyKey, -1) == 0 | ||||||
|                         && !prefs.getBoolean(disabledTunnelingKey, false); |                         && !prefs.getBoolean(disabledTunnelingKey, false); | ||||||
|  |  | ||||||
|         if (Boolean.TRUE.equals(isFirstRun) |         if (App.getApp().isFirstRun() | ||||||
|                 || (wasDeviceBlacklistUpdated && !wasMediaTunnelingEnabledByUser)) { |                 || (wasDeviceBlacklistUpdated && !wasMediaTunnelingEnabledByUser)) { | ||||||
|             setMediaTunneling(context); |             setMediaTunneling(context); | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -7,6 +7,7 @@ import android.util.Log; | |||||||
| import androidx.annotation.NonNull; | import androidx.annotation.NonNull; | ||||||
| import androidx.preference.PreferenceManager; | import androidx.preference.PreferenceManager; | ||||||
|  |  | ||||||
|  | import org.schabi.newpipe.App; | ||||||
| import org.schabi.newpipe.R; | import org.schabi.newpipe.R; | ||||||
| import org.schabi.newpipe.error.ErrorInfo; | import org.schabi.newpipe.error.ErrorInfo; | ||||||
| import org.schabi.newpipe.error.ErrorUtil; | import org.schabi.newpipe.error.ErrorUtil; | ||||||
| @@ -163,15 +164,14 @@ public final class SettingMigrations { | |||||||
|     private static final int VERSION = 6; |     private static final int VERSION = 6; | ||||||
|  |  | ||||||
|  |  | ||||||
|     public static void runMigrationsIfNeeded(@NonNull final Context context, |     public static void runMigrationsIfNeeded(@NonNull final Context context) { | ||||||
|                                              final boolean isFirstRun) { |  | ||||||
|         // setup migrations and check if there is something to do |         // setup migrations and check if there is something to do | ||||||
|         sp = PreferenceManager.getDefaultSharedPreferences(context); |         sp = PreferenceManager.getDefaultSharedPreferences(context); | ||||||
|         final String lastPrefVersionKey = context.getString(R.string.last_used_preferences_version); |         final String lastPrefVersionKey = context.getString(R.string.last_used_preferences_version); | ||||||
|         final int lastPrefVersion = sp.getInt(lastPrefVersionKey, 0); |         final int lastPrefVersion = sp.getInt(lastPrefVersionKey, 0); | ||||||
|  |  | ||||||
|         // no migration to run, already up to date |         // no migration to run, already up to date | ||||||
|         if (isFirstRun) { |         if (App.getApp().isFirstRun()) { | ||||||
|             sp.edit().putInt(lastPrefVersionKey, VERSION).apply(); |             sp.edit().putInt(lastPrefVersionKey, VERSION).apply(); | ||||||
|             return; |             return; | ||||||
|         } else if (lastPrefVersion == VERSION) { |         } else if (lastPrefVersion == VERSION) { | ||||||
|   | |||||||
| @@ -1,9 +1,12 @@ | |||||||
| package org.schabi.newpipe.settings; | package org.schabi.newpipe.settings; | ||||||
|  |  | ||||||
|  | import android.app.AlertDialog; | ||||||
|  | import android.content.Context; | ||||||
| import android.os.Bundle; | import android.os.Bundle; | ||||||
| import android.widget.Toast; | import android.widget.Toast; | ||||||
|  |  | ||||||
| import androidx.preference.Preference; | import androidx.preference.Preference; | ||||||
|  | import androidx.preference.PreferenceManager; | ||||||
|  |  | ||||||
| import org.schabi.newpipe.NewVersionWorker; | import org.schabi.newpipe.NewVersionWorker; | ||||||
| import org.schabi.newpipe.R; | import org.schabi.newpipe.R; | ||||||
| @@ -36,4 +39,38 @@ public class UpdateSettingsFragment extends BasePreferenceFragment { | |||||||
|         findPreference(getString(R.string.manual_update_key)) |         findPreference(getString(R.string.manual_update_key)) | ||||||
|                 .setOnPreferenceClickListener(manualUpdateClick); |                 .setOnPreferenceClickListener(manualUpdateClick); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     public static void askForConsentToUpdateChecks(final Context context) { | ||||||
|  |         new AlertDialog.Builder(context) | ||||||
|  |                 .setTitle(context.getString(R.string.check_for_updates)) | ||||||
|  |                 .setMessage(context.getString(R.string.auto_update_check_description)) | ||||||
|  |                 .setPositiveButton(context.getString(R.string.yes), (d, w) -> { | ||||||
|  |                     d.dismiss(); | ||||||
|  |                     setAutoUpdateCheckEnabled(context, true); | ||||||
|  |                 }) | ||||||
|  |                 .setNegativeButton(R.string.no, (d, w) -> { | ||||||
|  |                     d.dismiss(); | ||||||
|  |                     // set explicitly to false, since the default is true on previous versions | ||||||
|  |                     setAutoUpdateCheckEnabled(context, false); | ||||||
|  |                 }) | ||||||
|  |                 .show(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private static void setAutoUpdateCheckEnabled(final Context context, final boolean enabled) { | ||||||
|  |         PreferenceManager.getDefaultSharedPreferences(context) | ||||||
|  |                 .edit() | ||||||
|  |                 .putBoolean(context.getString(R.string.update_app_key), enabled) | ||||||
|  |                 .putBoolean(context.getString(R.string.update_check_consent_key), true) | ||||||
|  |                 .apply(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Whether the user was asked for consent to automatically check for app updates. | ||||||
|  |      * @param context | ||||||
|  |      * @return true if the user was asked for consent, false otherwise | ||||||
|  |      */ | ||||||
|  |     public static boolean wasUserAskedForConsent(final Context context) { | ||||||
|  |         return PreferenceManager.getDefaultSharedPreferences(context) | ||||||
|  |                 .getBoolean(context.getString(R.string.update_check_consent_key), false); | ||||||
|  |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -494,6 +494,7 @@ | |||||||
|     </string-array> |     </string-array> | ||||||
|  |  | ||||||
|     <!-- Updates --> |     <!-- Updates --> | ||||||
|  |     <string name="update_check_consent_key">update_check_consent_key</string> | ||||||
|     <string name="update_app_key">update_app_key</string> |     <string name="update_app_key">update_app_key</string> | ||||||
|     <string name="manual_update_key">manual_update_key</string> |     <string name="manual_update_key">manual_update_key</string> | ||||||
|     <string name="update_pref_screen_key">update_pref_screen_key</string> |     <string name="update_pref_screen_key">update_pref_screen_key</string> | ||||||
|   | |||||||
| @@ -7,6 +7,8 @@ | |||||||
|     <string name="install">Install</string> |     <string name="install">Install</string> | ||||||
|     <string name="cancel">Cancel</string> |     <string name="cancel">Cancel</string> | ||||||
|     <string name="ok">OK</string> |     <string name="ok">OK</string> | ||||||
|  |     <string name="yes">Yes</string> | ||||||
|  |     <string name="no">No</string> | ||||||
|     <string name="open_in_browser">Open in browser</string> |     <string name="open_in_browser">Open in browser</string> | ||||||
|     <string name="mark_as_watched">Mark as watched</string> |     <string name="mark_as_watched">Mark as watched</string> | ||||||
|     <string name="open_in_popup_mode">Open in popup mode</string> |     <string name="open_in_popup_mode">Open in popup mode</string> | ||||||
| @@ -557,8 +559,10 @@ | |||||||
|     <string name="updates_setting_title">Updates</string> |     <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> |     <string name="updates_setting_description">Show a notification to prompt app update when a new version is available</string> | ||||||
|     <string name="check_for_updates">Check for updates</string> |     <string name="check_for_updates">Check for updates</string> | ||||||
|  |     <string name="auto_update_check_description">NewPipe can automatically check for new versions from time to time and notify you once they are available.\nDo you want to enable this?</string> | ||||||
|     <string name="manual_update_title" translatable="false">@string/check_for_updates</string> |     <string name="manual_update_title" translatable="false">@string/check_for_updates</string> | ||||||
|     <string name="manual_update_description">Manually check for new versions</string> |     <string name="manual_update_description">Manually check for new versions</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> | ||||||
|   | |||||||
| @@ -4,7 +4,7 @@ | |||||||
|     android:title="@string/settings_category_updates_title"> |     android:title="@string/settings_category_updates_title"> | ||||||
|  |  | ||||||
|     <SwitchPreferenceCompat |     <SwitchPreferenceCompat | ||||||
|         android:defaultValue="true" |         android:defaultValue="false" | ||||||
|         android:key="@string/update_app_key" |         android:key="@string/update_app_key" | ||||||
|         android:summary="@string/updates_setting_description" |         android:summary="@string/updates_setting_description" | ||||||
|         android:title="@string/updates_setting_title" |         android:title="@string/updates_setting_title" | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Tobi
					Tobi