Merge pull request #6980 from bravenewpipe/check-for-update-after-toggle-and-restart

resets the expire date for checking for updates
This commit is contained in:
Tobi 2021-10-02 09:07:05 +02:00 committed by GitHub
commit ce592f4baf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 90 additions and 73 deletions

View File

@ -359,6 +359,9 @@
<service <service
android:name=".RouterActivity$FetcherService" android:name=".RouterActivity$FetcherService"
android:exported="false" /> android:exported="false" />
<service
android:name=".CheckForNewAppVersion"
android:exported="false" />
<!-- opting out of sending metrics to Google in Android System WebView --> <!-- opting out of sending metrics to Google in Android System WebView -->
<meta-data android:name="android.webkit.WebView.MetricsOptOut" android:value="true" /> <meta-data android:name="android.webkit.WebView.MetricsOptOut" android:value="true" />

View File

@ -5,7 +5,6 @@ import android.content.SharedPreferences;
import android.util.Log; import android.util.Log;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.NotificationChannelCompat; import androidx.core.app.NotificationChannelCompat;
import androidx.core.app.NotificationManagerCompat; import androidx.core.app.NotificationManagerCompat;
import androidx.multidex.MultiDexApplication; import androidx.multidex.MultiDexApplication;
@ -37,7 +36,6 @@ import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import io.reactivex.rxjava3.disposables.Disposable;
import io.reactivex.rxjava3.exceptions.CompositeException; import io.reactivex.rxjava3.exceptions.CompositeException;
import io.reactivex.rxjava3.exceptions.MissingBackpressureException; import io.reactivex.rxjava3.exceptions.MissingBackpressureException;
import io.reactivex.rxjava3.exceptions.OnErrorNotImplementedException; import io.reactivex.rxjava3.exceptions.OnErrorNotImplementedException;
@ -45,6 +43,8 @@ import io.reactivex.rxjava3.exceptions.UndeliverableException;
import io.reactivex.rxjava3.functions.Consumer; import io.reactivex.rxjava3.functions.Consumer;
import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.plugins.RxJavaPlugins;
import static org.schabi.newpipe.CheckForNewAppVersion.startNewVersionCheckService;
/* /*
* Copyright (C) Hans-Christoph Steiner 2016 <hans@eds.org> * Copyright (C) Hans-Christoph Steiner 2016 <hans@eds.org>
* App.java is part of NewPipe. * App.java is part of NewPipe.
@ -68,9 +68,6 @@ public class App extends MultiDexApplication {
private static final String TAG = App.class.toString(); private static final String TAG = App.class.toString();
private static App app; private static App app;
@Nullable
private Disposable disposable = null;
@NonNull @NonNull
public static App getApp() { public static App getApp() {
return app; return app;
@ -118,14 +115,11 @@ public class App extends MultiDexApplication {
configureRxJavaErrorHandler(); configureRxJavaErrorHandler();
// Check for new version // Check for new version
disposable = CheckForNewAppVersion.checkNewVersion(this); startNewVersionCheckService();
} }
@Override @Override
public void onTerminate() { public void onTerminate() {
if (disposable != null) {
disposable.dispose();
}
super.onTerminate(); super.onTerminate();
PicassoHelper.terminate(); PicassoHelper.terminate();
} }

View File

@ -1,6 +1,7 @@
package org.schabi.newpipe; package org.schabi.newpipe;
import android.app.Application; import android.app.Application;
import android.app.IntentService;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
@ -25,8 +26,11 @@ import com.grack.nanojson.JsonParserException;
import org.schabi.newpipe.error.ErrorActivity; import org.schabi.newpipe.error.ErrorActivity;
import org.schabi.newpipe.error.ErrorInfo; import org.schabi.newpipe.error.ErrorInfo;
import org.schabi.newpipe.error.UserAction; import org.schabi.newpipe.error.UserAction;
import org.schabi.newpipe.extractor.downloader.Response;
import org.schabi.newpipe.extractor.exceptions.ReCaptchaException;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
@ -36,13 +40,10 @@ import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
import java.util.List; import java.util.List;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; public final class CheckForNewAppVersion extends IntentService {
import io.reactivex.rxjava3.core.Maybe; public CheckForNewAppVersion() {
import io.reactivex.rxjava3.disposables.Disposable; super("CheckForNewAppVersion");
import io.reactivex.rxjava3.schedulers.Schedulers; }
public final class CheckForNewAppVersion {
private CheckForNewAppVersion() { }
private static final boolean DEBUG = MainActivity.DEBUG; private static final boolean DEBUG = MainActivity.DEBUG;
private static final String TAG = CheckForNewAppVersion.class.getSimpleName(); private static final String TAG = CheckForNewAppVersion.class.getSimpleName();
@ -168,78 +169,87 @@ public final class CheckForNewAppVersion {
return getCertificateSHA1Fingerprint(app).equals(GITHUB_APK_SHA1); return getCertificateSHA1Fingerprint(app).equals(GITHUB_APK_SHA1);
} }
@Nullable private void checkNewVersion() throws IOException, ReCaptchaException {
public static Disposable checkNewVersion(@NonNull final App app) { final App app = App.getApp();
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(app); final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(app);
final NewVersionManager manager = new NewVersionManager(); final NewVersionManager manager = new NewVersionManager();
// Check if user has enabled/disabled update checking // Check if user has enabled/disabled update checking
// and if the current apk is a github one or not. // and if the current apk is a github one or not.
if (!prefs.getBoolean(app.getString(R.string.update_app_key), true) || !isGithubApk(app)) { if (!prefs.getBoolean(app.getString(R.string.update_app_key), true) || !isGithubApk(app)) {
return null; return;
} }
// Check if the last request has happened a certain time ago // Check if the last request has happened a certain time ago
// to reduce the number of API requests. // to reduce the number of API requests.
final long expiry = prefs.getLong(app.getString(R.string.update_expiry_key), 0); final long expiry = prefs.getLong(app.getString(R.string.update_expiry_key), 0);
if (!manager.isExpired(expiry)) { if (!manager.isExpired(expiry)) {
return null; return;
} }
return Maybe // Make a network request to get latest NewPipe data.
.fromCallable(() -> { final Response response = DownloaderImpl.getInstance().get(NEWPIPE_API_URL);
if (!isConnected(app)) { handleResponse(response, manager, prefs, app);
return null; }
}
// Make a network request to get latest NewPipe data. private void handleResponse(@NonNull final Response response,
return DownloaderImpl.getInstance().get(NEWPIPE_API_URL); @NonNull final NewVersionManager manager,
}) @NonNull final SharedPreferences prefs,
.subscribeOn(Schedulers.io()) @NonNull final App app) {
.observeOn(AndroidSchedulers.mainThread()) try {
.subscribe( // Store a timestamp which needs to be exceeded,
response -> { // before a new request to the API is made.
try { final long newExpiry = manager
// Store a timestamp which needs to be exceeded, .coerceExpiry(response.getHeader("expires"));
// before a new request to the API is made. prefs.edit()
final long newExpiry = manager .putLong(app.getString(R.string.update_expiry_key), newExpiry)
.coerceExpiry(response.getHeader("expires")); .apply();
prefs.edit() } catch (final Exception e) {
.putLong(app.getString(R.string.update_expiry_key), newExpiry) if (DEBUG) {
.apply(); Log.w(TAG, "Could not extract and save new expiry date", e);
} catch (final Exception e) { }
if (DEBUG) { }
Log.w(TAG, "Could not extract and save new expiry date", e);
}
}
// Parse the json from the response. // Parse the json from the response.
try { try {
final JsonObject githubStableObject = JsonParser.object() final JsonObject githubStableObject = JsonParser.object()
.from(response.responseBody()).getObject("flavors") .from(response.responseBody()).getObject("flavors")
.getObject("github").getObject("stable"); .getObject("github").getObject("stable");
final String versionName = githubStableObject final String versionName = githubStableObject
.getString("version"); .getString("version");
final int versionCode = githubStableObject final int versionCode = githubStableObject
.getInt("version_code"); .getInt("version_code");
final String apkLocationUrl = githubStableObject final String apkLocationUrl = githubStableObject
.getString("apk"); .getString("apk");
compareAppVersionAndShowNotification(app, versionName,
apkLocationUrl, versionCode);
} catch (final JsonParserException e) {
// Most likely something is wrong in data received from NEWPIPE_API_URL.
// Do not alarm user and fail silently.
if (DEBUG) {
Log.w(TAG, "Could not get NewPipe API: invalid json", e);
}
}
}
public static void startNewVersionCheckService() {
final Intent intent = new Intent(App.getApp().getApplicationContext(),
CheckForNewAppVersion.class);
App.getApp().startService(intent);
}
@Override
protected void onHandleIntent(@Nullable final Intent intent) {
try {
checkNewVersion();
} catch (final IOException e) {
Log.w(TAG, "Could not fetch NewPipe API: probably network problem", e);
} catch (final ReCaptchaException e) {
Log.e(TAG, "ReCaptchaException should never happen here.", e);
}
compareAppVersionAndShowNotification(app, versionName,
apkLocationUrl, versionCode);
} catch (final JsonParserException e) {
// connectivity problems, do not alarm user and fail silently
if (DEBUG) {
Log.w(TAG, "Could not get NewPipe API: invalid json", e);
}
}
},
e -> {
// connectivity problems, do not alarm user and fail silently
if (DEBUG) {
Log.w(TAG, "Could not get NewPipe API: network problem", e);
}
});
} }
} }

View File

@ -6,11 +6,21 @@ import androidx.preference.Preference;
import org.schabi.newpipe.R; import org.schabi.newpipe.R;
import static org.schabi.newpipe.CheckForNewAppVersion.startNewVersionCheckService;
public class UpdateSettingsFragment extends BasePreferenceFragment { public class UpdateSettingsFragment extends BasePreferenceFragment {
private final Preference.OnPreferenceChangeListener updatePreferenceChange private final Preference.OnPreferenceChangeListener updatePreferenceChange
= (preference, newValue) -> { = (preference, checkForUpdates) -> {
defaultPreferences.edit() defaultPreferences.edit()
.putBoolean(getString(R.string.update_app_key), (boolean) newValue).apply(); .putBoolean(getString(R.string.update_app_key), (boolean) checkForUpdates).apply();
if ((boolean) checkForUpdates) {
// Search for updates immediately when update checks are enabled.
// Reset the expire time. This is necessary to check for an update immediately.
defaultPreferences.edit()
.putLong(getString(R.string.update_expiry_key), 0).apply();
startNewVersionCheckService();
}
return true; return true;
}; };