Skip to content

Commit a3bbbf0

Browse files
TobiGrStypox
andcommitted
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 #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>
1 parent 1d3a69a commit a3bbbf0

8 files changed

Lines changed: 70 additions & 16 deletions

File tree

app/src/main/java/org/schabi/newpipe/App.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@
6060
public class App extends Application {
6161
public static final String PACKAGE_NAME = BuildConfig.APPLICATION_ID;
6262
private static final String TAG = App.class.toString();
63+
64+
private boolean isFirstRun = false;
6365
private static App app;
6466

6567
@NonNull
@@ -85,7 +87,13 @@ public void onCreate() {
8587
return;
8688
}
8789

88-
// Initialize settings first because others inits can use its values
90+
// check if the last used preference version is set
91+
// to determine whether this is the first app run
92+
final int lastUsedPrefVersion = PreferenceManager.getDefaultSharedPreferences(this)
93+
.getInt(getString(R.string.last_used_preferences_version), -1);
94+
isFirstRun = lastUsedPrefVersion == -1;
95+
96+
// Initialize settings first because other initializations can use its values
8997
NewPipeSettings.initSettings(this);
9098

9199
NewPipe.init(getDownloader(),
@@ -255,4 +263,7 @@ protected boolean isDisposedRxExceptionsReported() {
255263
return false;
256264
}
257265

266+
public boolean isFirstRun() {
267+
return isFirstRun;
268+
}
258269
}

app/src/main/java/org/schabi/newpipe/MainActivity.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,13 +79,15 @@
7979
import org.schabi.newpipe.player.event.OnKeyDownListener;
8080
import org.schabi.newpipe.player.helper.PlayerHolder;
8181
import org.schabi.newpipe.player.playqueue.PlayQueue;
82+
import org.schabi.newpipe.settings.UpdateSettingsFragment;
8283
import org.schabi.newpipe.util.Constants;
8384
import org.schabi.newpipe.util.DeviceUtils;
8485
import org.schabi.newpipe.util.KioskTranslator;
8586
import org.schabi.newpipe.util.Localization;
8687
import org.schabi.newpipe.util.NavigationHelper;
8788
import org.schabi.newpipe.util.PeertubeHelper;
8889
import org.schabi.newpipe.util.PermissionHelper;
90+
import org.schabi.newpipe.util.ReleaseVersionUtil;
8991
import org.schabi.newpipe.util.SerializedCache;
9092
import org.schabi.newpipe.util.ServiceHelper;
9193
import org.schabi.newpipe.util.StateSaver;
@@ -167,6 +169,11 @@ protected void onCreate(final Bundle savedInstanceState) {
167169
// if this is enabled by the user.
168170
NotificationWorker.initialize(this);
169171
}
172+
if (!UpdateSettingsFragment.wasUserAskedForConsent(this)
173+
&& ReleaseVersionUtil.INSTANCE.isReleaseApk()
174+
&& !App.getApp().isFirstRun()) {
175+
UpdateSettingsFragment.askForConsentToUpdateChecks(this);
176+
}
170177
}
171178

172179
@Override

app/src/main/java/org/schabi/newpipe/settings/NewPipeSettings.java

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import androidx.annotation.StringRes;
1212
import androidx.preference.PreferenceManager;
1313

14+
import org.schabi.newpipe.App;
1415
import org.schabi.newpipe.R;
1516
import org.schabi.newpipe.util.DeviceUtils;
1617

@@ -44,14 +45,8 @@ public final class NewPipeSettings {
4445
private NewPipeSettings() { }
4546

4647
public static void initSettings(final Context context) {
47-
// check if the last used preference version is set
48-
// to determine whether this is the first app run
49-
final int lastUsedPrefVersion = PreferenceManager.getDefaultSharedPreferences(context)
50-
.getInt(context.getString(R.string.last_used_preferences_version), -1);
51-
final boolean isFirstRun = lastUsedPrefVersion == -1;
52-
5348
// first run migrations, then setDefaultValues, since the latter requires the correct types
54-
SettingMigrations.runMigrationsIfNeeded(context, isFirstRun);
49+
SettingMigrations.runMigrationsIfNeeded(context);
5550

5651
// readAgain is true so that if new settings are added their default value is set
5752
PreferenceManager.setDefaultValues(context, R.xml.main_settings, true);
@@ -68,7 +63,7 @@ public static void initSettings(final Context context) {
6863
saveDefaultVideoDownloadDirectory(context);
6964
saveDefaultAudioDownloadDirectory(context);
7065

71-
disableMediaTunnelingIfNecessary(context, isFirstRun);
66+
disableMediaTunnelingIfNecessary(context);
7267
}
7368

7469
static void saveDefaultVideoDownloadDirectory(final Context context) {
@@ -146,8 +141,7 @@ public static boolean showRemoteSearchSuggestions(final Context context,
146141
R.string.show_remote_search_suggestions_key);
147142
}
148143

149-
private static void disableMediaTunnelingIfNecessary(@NonNull final Context context,
150-
final boolean isFirstRun) {
144+
private static void disableMediaTunnelingIfNecessary(@NonNull final Context context) {
151145
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
152146
final String disabledTunnelingKey = context.getString(R.string.disable_media_tunneling_key);
153147
final String disabledTunnelingAutomaticallyKey =
@@ -162,7 +156,7 @@ private static void disableMediaTunnelingIfNecessary(@NonNull final Context cont
162156
prefs.getInt(disabledTunnelingAutomaticallyKey, -1) == 0
163157
&& !prefs.getBoolean(disabledTunnelingKey, false);
164158

165-
if (Boolean.TRUE.equals(isFirstRun)
159+
if (App.getApp().isFirstRun()
166160
|| (wasDeviceBlacklistUpdated && !wasMediaTunnelingEnabledByUser)) {
167161
setMediaTunneling(context);
168162
}

app/src/main/java/org/schabi/newpipe/settings/SettingMigrations.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import androidx.annotation.NonNull;
88
import androidx.preference.PreferenceManager;
99

10+
import org.schabi.newpipe.App;
1011
import org.schabi.newpipe.R;
1112
import org.schabi.newpipe.error.ErrorInfo;
1213
import org.schabi.newpipe.error.ErrorUtil;
@@ -163,15 +164,14 @@ protected void migrate(@NonNull final Context context) {
163164
private static final int VERSION = 6;
164165

165166

166-
public static void runMigrationsIfNeeded(@NonNull final Context context,
167-
final boolean isFirstRun) {
167+
public static void runMigrationsIfNeeded(@NonNull final Context context) {
168168
// setup migrations and check if there is something to do
169169
sp = PreferenceManager.getDefaultSharedPreferences(context);
170170
final String lastPrefVersionKey = context.getString(R.string.last_used_preferences_version);
171171
final int lastPrefVersion = sp.getInt(lastPrefVersionKey, 0);
172172

173173
// no migration to run, already up to date
174-
if (isFirstRun) {
174+
if (App.getApp().isFirstRun()) {
175175
sp.edit().putInt(lastPrefVersionKey, VERSION).apply();
176176
return;
177177
} else if (lastPrefVersion == VERSION) {

app/src/main/java/org/schabi/newpipe/settings/UpdateSettingsFragment.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
package org.schabi.newpipe.settings;
22

3+
import android.app.AlertDialog;
4+
import android.content.Context;
35
import android.os.Bundle;
46
import android.widget.Toast;
57

68
import androidx.preference.Preference;
9+
import androidx.preference.PreferenceManager;
710

811
import org.schabi.newpipe.NewVersionWorker;
912
import org.schabi.newpipe.R;
@@ -36,4 +39,38 @@ public void onCreatePreferences(final Bundle savedInstanceState, final String ro
3639
findPreference(getString(R.string.manual_update_key))
3740
.setOnPreferenceClickListener(manualUpdateClick);
3841
}
42+
43+
public static void askForConsentToUpdateChecks(final Context context) {
44+
new AlertDialog.Builder(context)
45+
.setTitle(context.getString(R.string.check_for_updates))
46+
.setMessage(context.getString(R.string.auto_update_check_description))
47+
.setPositiveButton(context.getString(R.string.yes), (d, w) -> {
48+
d.dismiss();
49+
setAutoUpdateCheckEnabled(context, true);
50+
})
51+
.setNegativeButton(R.string.no, (d, w) -> {
52+
d.dismiss();
53+
// set explicitly to false, since the default is true on previous versions
54+
setAutoUpdateCheckEnabled(context, false);
55+
})
56+
.show();
57+
}
58+
59+
private static void setAutoUpdateCheckEnabled(final Context context, final boolean enabled) {
60+
PreferenceManager.getDefaultSharedPreferences(context)
61+
.edit()
62+
.putBoolean(context.getString(R.string.update_app_key), enabled)
63+
.putBoolean(context.getString(R.string.update_check_consent_key), true)
64+
.apply();
65+
}
66+
67+
/**
68+
* Whether the user was asked for consent to automatically check for app updates.
69+
* @param context
70+
* @return true if the user was asked for consent, false otherwise
71+
*/
72+
public static boolean wasUserAskedForConsent(final Context context) {
73+
return PreferenceManager.getDefaultSharedPreferences(context)
74+
.getBoolean(context.getString(R.string.update_check_consent_key), false);
75+
}
3976
}

app/src/main/res/values/settings_keys.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,7 @@
494494
</string-array>
495495

496496
<!-- Updates -->
497+
<string name="update_check_consent_key">update_check_consent_key</string>
497498
<string name="update_app_key">update_app_key</string>
498499
<string name="manual_update_key">manual_update_key</string>
499500
<string name="update_pref_screen_key">update_pref_screen_key</string>

app/src/main/res/values/strings.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
<string name="install">Install</string>
88
<string name="cancel">Cancel</string>
99
<string name="ok">OK</string>
10+
<string name="yes">Yes</string>
11+
<string name="no">No</string>
1012
<string name="open_in_browser">Open in browser</string>
1113
<string name="mark_as_watched">Mark as watched</string>
1214
<string name="open_in_popup_mode">Open in popup mode</string>
@@ -557,8 +559,10 @@
557559
<string name="updates_setting_title">Updates</string>
558560
<string name="updates_setting_description">Show a notification to prompt app update when a new version is available</string>
559561
<string name="check_for_updates">Check for updates</string>
562+
<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>
560563
<string name="manual_update_title" translatable="false">@string/check_for_updates</string>
561564
<string name="manual_update_description">Manually check for new versions</string>
565+
562566
<!-- Minimize to exit action -->
563567
<string name="minimize_on_exit_title">Minimize on app switch</string>
564568
<string name="minimize_on_exit_summary">Action when switching to other app from main video player — %s</string>

app/src/main/res/xml/update_settings.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
android:title="@string/settings_category_updates_title">
55

66
<SwitchPreferenceCompat
7-
android:defaultValue="true"
7+
android:defaultValue="false"
88
android:key="@string/update_app_key"
99
android:summary="@string/updates_setting_description"
1010
android:title="@string/updates_setting_title"

0 commit comments

Comments
 (0)