diff --git a/app/src/main/java/org/schabi/newpipe/App.java b/app/src/main/java/org/schabi/newpipe/App.java index 51d0f1016..5348db115 100644 --- a/app/src/main/java/org/schabi/newpipe/App.java +++ b/app/src/main/java/org/schabi/newpipe/App.java @@ -8,6 +8,7 @@ import android.os.Build; import android.util.Log; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.multidex.MultiDexApplication; import androidx.preference.PreferenceManager; @@ -67,7 +68,7 @@ public class App extends MultiDexApplication { protected static final String TAG = App.class.toString(); private static App app; - private Disposable disposable = null; + @Nullable private Disposable disposable = null; @NonNull public static App getApp() { diff --git a/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersion.java b/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersion.java index 1bec52dcd..661337b28 100644 --- a/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersion.java +++ b/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersion.java @@ -12,6 +12,7 @@ import android.net.Uri; import android.util.Log; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationManagerCompat; import androidx.core.content.ContextCompat; @@ -21,13 +22,11 @@ import com.grack.nanojson.JsonObject; import com.grack.nanojson.JsonParser; import com.grack.nanojson.JsonParserException; -import org.schabi.newpipe.extractor.exceptions.ReCaptchaException; import org.schabi.newpipe.report.ErrorActivity; import org.schabi.newpipe.report.ErrorInfo; import org.schabi.newpipe.report.UserAction; import java.io.ByteArrayInputStream; -import java.io.IOException; import java.io.InputStream; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; @@ -36,10 +35,9 @@ import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; -import io.reactivex.Observable; +import io.reactivex.Maybe; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.Disposable; -import io.reactivex.disposables.Disposables; import io.reactivex.schedulers.Schedulers; public final class CheckForNewAppVersion { @@ -58,48 +56,43 @@ public final class CheckForNewAppVersion { * @param application The application * @return String with the apk's SHA1 fingeprint in hexadecimal */ + @NonNull private static String getCertificateSHA1Fingerprint(@NonNull final Application application) { - final PackageManager pm = application.getPackageManager(); - final String packageName = application.getPackageName(); - final int flags = PackageManager.GET_SIGNATURES; - PackageInfo packageInfo = null; - + final PackageInfo packageInfo; try { - packageInfo = pm.getPackageInfo(packageName, flags); + packageInfo = application.getPackageManager().getPackageInfo( + application.getPackageName(), PackageManager.GET_SIGNATURES); } catch (final PackageManager.NameNotFoundException e) { ErrorActivity.reportError(application, e, null, null, ErrorInfo.make(UserAction.SOMETHING_ELSE, "none", "Could not find package info", R.string.app_ui_crash)); + return ""; } - final Signature[] signatures = packageInfo.signatures; - final byte[] cert = signatures[0].toByteArray(); - final InputStream input = new ByteArrayInputStream(cert); - - X509Certificate c = null; - + final X509Certificate c; try { + final Signature[] signatures = packageInfo.signatures; + final byte[] cert = signatures[0].toByteArray(); + final InputStream input = new ByteArrayInputStream(cert); final CertificateFactory cf = CertificateFactory.getInstance("X509"); c = (X509Certificate) cf.generateCertificate(input); } catch (final CertificateException e) { ErrorActivity.reportError(application, e, null, null, ErrorInfo.make(UserAction.SOMETHING_ELSE, "none", "Certificate error", R.string.app_ui_crash)); + return ""; } - String hexString = null; - try { final MessageDigest md = MessageDigest.getInstance("SHA1"); final byte[] publicKey = md.digest(c.getEncoded()); - hexString = byte2HexFormatted(publicKey); + return byte2HexFormatted(publicKey); } catch (NoSuchAlgorithmException | CertificateEncodingException e) { ErrorActivity.reportError(application, e, null, null, ErrorInfo.make(UserAction.SOMETHING_ELSE, "none", "Could not retrieve SHA1 key", R.string.app_ui_crash)); + return ""; } - - return hexString; } private static String byte2HexFormatted(final byte[] arr) { @@ -164,66 +157,66 @@ public final class CheckForNewAppVersion { } private static boolean isConnected(@NonNull final App app) { - final ConnectivityManager cm = ContextCompat.getSystemService(app, - ConnectivityManager.class); - return cm.getActiveNetworkInfo() != null - && cm.getActiveNetworkInfo().isConnected(); + final ConnectivityManager connectivityManager = + ContextCompat.getSystemService(app, ConnectivityManager.class); + return connectivityManager != null && connectivityManager.getActiveNetworkInfo() != null + && connectivityManager.getActiveNetworkInfo().isConnected(); } public static boolean isGithubApk(@NonNull final App app) { return getCertificateSHA1Fingerprint(app).equals(GITHUB_APK_SHA1); } - @NonNull + @Nullable public static Disposable checkNewVersion(@NonNull final App app) { final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(app); // Check if user has enabled/disabled update checking // and if the current apk is a github one or not. - if (!prefs.getBoolean(app.getString(R.string.update_app_key), true) - || !isGithubApk(app)) { - return Disposables.empty(); + if (!prefs.getBoolean(app.getString(R.string.update_app_key), true) || !isGithubApk(app)) { + return null; } - return Observable.fromCallable(() -> { - if (!isConnected(app)) { - return null; - } + return Maybe + .fromCallable(() -> { + if (!isConnected(app)) { + return null; + } - // Make a network request to get latest NewPipe data. - try { - return DownloaderImpl.getInstance().get(NEWPIPE_API_URL).responseBody(); - } catch (IOException | ReCaptchaException e) { - // connectivity problems, do not alarm user and fail silently - if (DEBUG) { - Log.w(TAG, Log.getStackTraceString(e)); - } - } - - return null; - }) + // Make a network request to get latest NewPipe data. + return DownloaderImpl.getInstance().get(NEWPIPE_API_URL).responseBody(); + }) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(response -> { - // Parse the json from the response. - if (response != null) { - try { - final JsonObject githubStableObject = JsonParser.object().from(response) - .getObject("flavors").getObject("github").getObject("stable"); + .subscribe( + response -> { + // Parse the json from the response. + try { + final JsonObject githubStableObject = JsonParser.object() + .from(response).getObject("flavors").getObject("github") + .getObject("stable"); - final String versionName = githubStableObject.getString("version"); - final int versionCode = githubStableObject.getInt("version_code"); - final String apkLocationUrl = githubStableObject.getString("apk"); + final String versionName = githubStableObject + .getString("version"); + final int versionCode = githubStableObject + .getInt("version_code"); + final String apkLocationUrl = githubStableObject + .getString("apk"); - compareAppVersionAndShowNotification(app, versionName, apkLocationUrl, - versionCode); - } catch (final JsonParserException 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, Log.getStackTraceString(e)); + Log.w(TAG, "Could not get NewPipe API: network problem", e); } - } - } - }); + }); } }