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:
parent
1d3a69a29f
commit
a3bbbf03b4
|
@ -60,6 +60,8 @@ import io.reactivex.rxjava3.plugins.RxJavaPlugins;
|
|||
public class App extends Application {
|
||||
public static final String PACKAGE_NAME = BuildConfig.APPLICATION_ID;
|
||||
private static final String TAG = App.class.toString();
|
||||
|
||||
private boolean isFirstRun = false;
|
||||
private static App app;
|
||||
|
||||
@NonNull
|
||||
|
@ -85,7 +87,13 @@ public class App extends Application {
|
|||
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);
|
||||
|
||||
NewPipe.init(getDownloader(),
|
||||
|
@ -255,4 +263,7 @@ public class App extends Application {
|
|||
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.helper.PlayerHolder;
|
||||
import org.schabi.newpipe.player.playqueue.PlayQueue;
|
||||
import org.schabi.newpipe.settings.UpdateSettingsFragment;
|
||||
import org.schabi.newpipe.util.Constants;
|
||||
import org.schabi.newpipe.util.DeviceUtils;
|
||||
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.PeertubeHelper;
|
||||
import org.schabi.newpipe.util.PermissionHelper;
|
||||
import org.schabi.newpipe.util.ReleaseVersionUtil;
|
||||
import org.schabi.newpipe.util.SerializedCache;
|
||||
import org.schabi.newpipe.util.ServiceHelper;
|
||||
import org.schabi.newpipe.util.StateSaver;
|
||||
|
@ -167,6 +169,11 @@ public class MainActivity extends AppCompatActivity {
|
|||
// if this is enabled by the user.
|
||||
NotificationWorker.initialize(this);
|
||||
}
|
||||
if (!UpdateSettingsFragment.wasUserAskedForConsent(this)
|
||||
&& ReleaseVersionUtil.INSTANCE.isReleaseApk()
|
||||
&& !App.getApp().isFirstRun()) {
|
||||
UpdateSettingsFragment.askForConsentToUpdateChecks(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -11,6 +11,7 @@ import androidx.annotation.NonNull;
|
|||
import androidx.annotation.StringRes;
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
import org.schabi.newpipe.App;
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.util.DeviceUtils;
|
||||
|
||||
|
@ -44,14 +45,8 @@ public final class NewPipeSettings {
|
|||
private NewPipeSettings() { }
|
||||
|
||||
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
|
||||
SettingMigrations.runMigrationsIfNeeded(context, isFirstRun);
|
||||
SettingMigrations.runMigrationsIfNeeded(context);
|
||||
|
||||
// readAgain is true so that if new settings are added their default value is set
|
||||
PreferenceManager.setDefaultValues(context, R.xml.main_settings, true);
|
||||
|
@ -68,7 +63,7 @@ public final class NewPipeSettings {
|
|||
saveDefaultVideoDownloadDirectory(context);
|
||||
saveDefaultAudioDownloadDirectory(context);
|
||||
|
||||
disableMediaTunnelingIfNecessary(context, isFirstRun);
|
||||
disableMediaTunnelingIfNecessary(context);
|
||||
}
|
||||
|
||||
static void saveDefaultVideoDownloadDirectory(final Context context) {
|
||||
|
@ -146,8 +141,7 @@ public final class NewPipeSettings {
|
|||
R.string.show_remote_search_suggestions_key);
|
||||
}
|
||||
|
||||
private static void disableMediaTunnelingIfNecessary(@NonNull final Context context,
|
||||
final boolean isFirstRun) {
|
||||
private static void disableMediaTunnelingIfNecessary(@NonNull final Context context) {
|
||||
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
final String disabledTunnelingKey = context.getString(R.string.disable_media_tunneling_key);
|
||||
final String disabledTunnelingAutomaticallyKey =
|
||||
|
@ -162,7 +156,7 @@ public final class NewPipeSettings {
|
|||
prefs.getInt(disabledTunnelingAutomaticallyKey, -1) == 0
|
||||
&& !prefs.getBoolean(disabledTunnelingKey, false);
|
||||
|
||||
if (Boolean.TRUE.equals(isFirstRun)
|
||||
if (App.getApp().isFirstRun()
|
||||
|| (wasDeviceBlacklistUpdated && !wasMediaTunnelingEnabledByUser)) {
|
||||
setMediaTunneling(context);
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import android.util.Log;
|
|||
import androidx.annotation.NonNull;
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
import org.schabi.newpipe.App;
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.error.ErrorInfo;
|
||||
import org.schabi.newpipe.error.ErrorUtil;
|
||||
|
@ -163,15 +164,14 @@ public final class SettingMigrations {
|
|||
private static final int VERSION = 6;
|
||||
|
||||
|
||||
public static void runMigrationsIfNeeded(@NonNull final Context context,
|
||||
final boolean isFirstRun) {
|
||||
public static void runMigrationsIfNeeded(@NonNull final Context context) {
|
||||
// setup migrations and check if there is something to do
|
||||
sp = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
final String lastPrefVersionKey = context.getString(R.string.last_used_preferences_version);
|
||||
final int lastPrefVersion = sp.getInt(lastPrefVersionKey, 0);
|
||||
|
||||
// no migration to run, already up to date
|
||||
if (isFirstRun) {
|
||||
if (App.getApp().isFirstRun()) {
|
||||
sp.edit().putInt(lastPrefVersionKey, VERSION).apply();
|
||||
return;
|
||||
} else if (lastPrefVersion == VERSION) {
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
package org.schabi.newpipe.settings;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
import org.schabi.newpipe.NewVersionWorker;
|
||||
import org.schabi.newpipe.R;
|
||||
|
@ -36,4 +39,38 @@ public class UpdateSettingsFragment extends BasePreferenceFragment {
|
|||
findPreference(getString(R.string.manual_update_key))
|
||||
.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>
|
||||
|
||||
<!-- Updates -->
|
||||
<string name="update_check_consent_key">update_check_consent_key</string>
|
||||
<string name="update_app_key">update_app_key</string>
|
||||
<string name="manual_update_key">manual_update_key</string>
|
||||
<string name="update_pref_screen_key">update_pref_screen_key</string>
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
<string name="install">Install</string>
|
||||
<string name="cancel">Cancel</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="mark_as_watched">Mark as watched</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_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="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_description">Manually check for new versions</string>
|
||||
|
||||
<!-- Minimize to exit action -->
|
||||
<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>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
android:title="@string/settings_category_updates_title">
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="true"
|
||||
android:defaultValue="false"
|
||||
android:key="@string/update_app_key"
|
||||
android:summary="@string/updates_setting_description"
|
||||
android:title="@string/updates_setting_title"
|
||||
|
|
Loading…
Reference in New Issue