From ef5084036cf2a21dfdfdb2f18b655900292ba51c Mon Sep 17 00:00:00 2001 From: Isira Seneviratne Date: Mon, 12 Oct 2020 06:25:35 +0530 Subject: [PATCH 1/3] Use RxJava instead of AsyncTask to check for new app versions. --- app/src/main/java/org/schabi/newpipe/App.java | 14 +- ...onTask.java => CheckForNewAppVersion.java} | 201 +++++++++--------- .../settings/MainSettingsFragment.java | 5 +- 3 files changed, 120 insertions(+), 100 deletions(-) rename app/src/main/java/org/schabi/newpipe/{CheckForNewAppVersionTask.java => CheckForNewAppVersion.java} (58%) diff --git a/app/src/main/java/org/schabi/newpipe/App.java b/app/src/main/java/org/schabi/newpipe/App.java index a94acda8e..5fdc1058a 100644 --- a/app/src/main/java/org/schabi/newpipe/App.java +++ b/app/src/main/java/org/schabi/newpipe/App.java @@ -36,6 +36,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import io.reactivex.disposables.Disposable; import io.reactivex.exceptions.CompositeException; import io.reactivex.exceptions.MissingBackpressureException; import io.reactivex.exceptions.OnErrorNotImplementedException; @@ -65,6 +66,9 @@ public class App extends MultiDexApplication { protected static final String TAG = App.class.toString(); private static App app; + private Disposable disposable = null; + + @NonNull public static App getApp() { return app; } @@ -100,7 +104,15 @@ public class App extends MultiDexApplication { configureRxJavaErrorHandler(); // Check for new version - new CheckForNewAppVersionTask().execute(); + disposable = CheckForNewAppVersion.checkNewVersion(this); + } + + @Override + public void onTerminate() { + if (disposable != null) { + disposable.dispose(); + } + super.onTerminate(); } protected Downloader getDownloader() { diff --git a/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersionTask.java b/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersion.java similarity index 58% rename from app/src/main/java/org/schabi/newpipe/CheckForNewAppVersionTask.java rename to app/src/main/java/org/schabi/newpipe/CheckForNewAppVersion.java index 10a6a73d7..a193149e2 100644 --- a/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersionTask.java +++ b/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersion.java @@ -9,9 +9,9 @@ import android.content.pm.PackageManager; import android.content.pm.Signature; import android.net.ConnectivityManager; import android.net.Uri; -import android.os.AsyncTask; import android.util.Log; +import androidx.annotation.NonNull; import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationManagerCompat; import androidx.core.content.ContextCompat; @@ -35,16 +35,18 @@ import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; -/** - * AsyncTask to check if there is a newer version of the NewPipe github apk available or not. - * If there is a newer version we show a notification, informing the user. On tapping - * the notification, the user will be directed to the download link. - */ -public class CheckForNewAppVersionTask extends AsyncTask { - private static final boolean DEBUG = MainActivity.DEBUG; - private static final String TAG = CheckForNewAppVersionTask.class.getSimpleName(); +import io.reactivex.Observable; +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 { + private CheckForNewAppVersion() { } + + private static final boolean DEBUG = MainActivity.DEBUG; + private static final String TAG = CheckForNewAppVersion.class.getSimpleName(); - private static final Application APP = App.getApp(); private static final String GITHUB_APK_SHA1 = "B0:2E:90:7C:1C:D6:FC:57:C3:35:F0:88:D0:8F:50:5F:94:E4:D2:15"; private static final String NEWPIPE_API_URL = "https://newpipe.schabi.org/api/data.json"; @@ -52,18 +54,19 @@ public class CheckForNewAppVersionTask extends AsyncTask { /** * Method to get the apk's SHA1 key. See https://stackoverflow.com/questions/9293019/#22506133. * + * @param application The application * @return String with the apk's SHA1 fingeprint in hexadecimal */ - private static String getCertificateSHA1Fingerprint() { - final PackageManager pm = APP.getPackageManager(); - final String packageName = APP.getPackageName(); + 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; try { packageInfo = pm.getPackageInfo(packageName, flags); } catch (final PackageManager.NameNotFoundException e) { - ErrorActivity.reportError(APP, e, null, null, + ErrorActivity.reportError(application, e, null, null, ErrorActivity.ErrorInfo.make(UserAction.SOMETHING_ELSE, "none", "Could not find package info", R.string.app_ui_crash)); } @@ -78,7 +81,7 @@ public class CheckForNewAppVersionTask extends AsyncTask { final CertificateFactory cf = CertificateFactory.getInstance("X509"); c = (X509Certificate) cf.generateCertificate(input); } catch (final CertificateException e) { - ErrorActivity.reportError(APP, e, null, null, + ErrorActivity.reportError(application, e, null, null, ErrorActivity.ErrorInfo.make(UserAction.SOMETHING_ELSE, "none", "Certificate error", R.string.app_ui_crash)); } @@ -90,7 +93,7 @@ public class CheckForNewAppVersionTask extends AsyncTask { final byte[] publicKey = md.digest(c.getEncoded()); hexString = byte2HexFormatted(publicKey); } catch (NoSuchAlgorithmException | CertificateEncodingException e) { - ErrorActivity.reportError(APP, e, null, null, + ErrorActivity.reportError(application, e, null, null, ErrorActivity.ErrorInfo.make(UserAction.SOMETHING_ELSE, "none", "Could not retrieve SHA1 key", R.string.app_ui_crash)); } @@ -118,104 +121,108 @@ public class CheckForNewAppVersionTask extends AsyncTask { return str.toString(); } - public static boolean isGithubApk() { - return getCertificateSHA1Fingerprint().equals(GITHUB_APK_SHA1); + /** + * Method to compare the current and latest available app version. + * If a newer version is available, we show the update notification. + * + * @param application The application + * @param versionName Name of new version + * @param apkLocationUrl Url with the new apk + * @param versionCode Code of new version + */ + private static void compareAppVersionAndShowNotification(@NonNull final Application application, + final String versionName, + final String apkLocationUrl, + final int versionCode) { + final int notificationId = 2000; + + if (BuildConfig.VERSION_CODE < versionCode) { + // A pending intent to open the apk location url in the browser. + final Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(apkLocationUrl)); + final PendingIntent pendingIntent + = PendingIntent.getActivity(application, 0, intent, 0); + + final String channelId = application + .getString(R.string.app_update_notification_channel_id); + final NotificationCompat.Builder notificationBuilder + = new NotificationCompat.Builder(application, channelId) + .setSmallIcon(R.drawable.ic_newpipe_update) + .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) + .setContentIntent(pendingIntent) + .setAutoCancel(true) + .setContentTitle(application + .getString(R.string.app_update_notification_content_title)) + .setContentText(application + .getString(R.string.app_update_notification_content_text) + + " " + versionName); + + final NotificationManagerCompat notificationManager + = NotificationManagerCompat.from(application); + notificationManager.notify(notificationId, notificationBuilder.build()); + } } - @Override - protected void onPreExecute() { - final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(APP); + private static boolean isConnected(@NonNull final App app) { + final ConnectivityManager cm = ContextCompat.getSystemService(app, + ConnectivityManager.class); + return cm.getActiveNetworkInfo() != null + && cm.getActiveNetworkInfo().isConnected(); + } + + public static boolean isGithubApk(@NonNull final App app) { + return getCertificateSHA1Fingerprint(app).equals(GITHUB_APK_SHA1); + } + + @NonNull + 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()) { - this.cancel(true); - } - } - - @Override - protected String doInBackground(final Void... voids) { - if (isCancelled() || !isConnected()) { - return null; + if (!prefs.getBoolean(app.getString(R.string.update_app_key), true) + || !isGithubApk(app)) { + return Disposables.empty(); } - // 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 Observable.fromCallable(() -> { + if (!isConnected(app)) { + return null; } - } - - return null; - } - - @Override - protected void onPostExecute(final String response) { - // Parse the json from the response. - if (response != null) { + // Make a network request to get latest NewPipe data. 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"); - - compareAppVersionAndShowNotification(versionName, apkLocationUrl, versionCode); - - } catch (final JsonParserException e) { + 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)); } } - } - } - /** - * Method to compare the current and latest available app version. - * If a newer version is available, we show the update notification. - * - * @param versionName Name of new version - * @param apkLocationUrl Url with the new apk - * @param versionCode Code of new version - */ - private void compareAppVersionAndShowNotification(final String versionName, - final String apkLocationUrl, - final int versionCode) { - final int notificationId = 2000; + return null; + }) + .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"); - if (BuildConfig.VERSION_CODE < versionCode) { + final String versionName = githubStableObject.getString("version"); + final int versionCode = githubStableObject.getInt("version_code"); + final String apkLocationUrl = githubStableObject.getString("apk"); - // A pending intent to open the apk location url in the browser. - final Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(apkLocationUrl)); - final PendingIntent pendingIntent - = PendingIntent.getActivity(APP, 0, intent, 0); - - final NotificationCompat.Builder notificationBuilder = new NotificationCompat - .Builder(APP, APP.getString(R.string.app_update_notification_channel_id)) - .setSmallIcon(R.drawable.ic_newpipe_update) - .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) - .setContentIntent(pendingIntent) - .setAutoCancel(true) - .setContentTitle(APP.getString(R.string.app_update_notification_content_title)) - .setContentText(APP.getString(R.string.app_update_notification_content_text) - + " " + versionName); - - final NotificationManagerCompat notificationManager - = NotificationManagerCompat.from(APP); - notificationManager.notify(notificationId, notificationBuilder.build()); - } - } - - private boolean isConnected() { - final ConnectivityManager cm = ContextCompat.getSystemService(APP, - ConnectivityManager.class); - return cm.getActiveNetworkInfo() != null - && cm.getActiveNetworkInfo().isConnected(); + compareAppVersionAndShowNotification(app, versionName, apkLocationUrl, + versionCode); + } catch (final JsonParserException e) { + // connectivity problems, do not alarm user and fail silently + if (DEBUG) { + Log.w(TAG, Log.getStackTraceString(e)); + } + } + } + }); } } diff --git a/app/src/main/java/org/schabi/newpipe/settings/MainSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/MainSettingsFragment.java index 6d6f0fa75..2f65af4d6 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/MainSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/MainSettingsFragment.java @@ -4,7 +4,8 @@ import android.os.Bundle; import androidx.preference.Preference; -import org.schabi.newpipe.CheckForNewAppVersionTask; +import org.schabi.newpipe.App; +import org.schabi.newpipe.CheckForNewAppVersion; import org.schabi.newpipe.MainActivity; import org.schabi.newpipe.R; @@ -15,7 +16,7 @@ public class MainSettingsFragment extends BasePreferenceFragment { public void onCreatePreferences(final Bundle savedInstanceState, final String rootKey) { addPreferencesFromResource(R.xml.main_settings); - if (!CheckForNewAppVersionTask.isGithubApk()) { + if (!CheckForNewAppVersion.isGithubApk(App.getApp())) { final Preference update = findPreference(getString(R.string.update_pref_screen_key)); getPreferenceScreen().removePreference(update); From 8ec55ef39450ee214e3bd1eb21d3663aa72a0d57 Mon Sep 17 00:00:00 2001 From: Isira Seneviratne Date: Mon, 12 Oct 2020 12:42:59 +0530 Subject: [PATCH 2/3] Use RxJava instead of AsyncTask in LicenseFragmentHelper. --- .../schabi/newpipe/about/LicenseFragment.java | 37 +++++----- .../newpipe/about/LicenseFragmentHelper.java | 74 ++++++++----------- 2 files changed, 49 insertions(+), 62 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/about/LicenseFragment.java b/app/src/main/java/org/schabi/newpipe/about/LicenseFragment.java index a6e64616d..bac789dbd 100644 --- a/app/src/main/java/org/schabi/newpipe/about/LicenseFragment.java +++ b/app/src/main/java/org/schabi/newpipe/about/LicenseFragment.java @@ -1,6 +1,5 @@ package org.schabi.newpipe.about; -import android.app.Activity; import android.os.Bundle; import android.view.ContextMenu; import android.view.LayoutInflater; @@ -21,15 +20,19 @@ import java.io.Serializable; import java.util.Arrays; import java.util.Comparator; +import io.reactivex.disposables.CompositeDisposable; + /** * Fragment containing the software licenses. */ public class LicenseFragment extends Fragment { private static final String ARG_COMPONENTS = "components"; + private static final String LICENSE_KEY = "ACTIVE_LICENSE"; + private SoftwareComponent[] softwareComponents; private SoftwareComponent componentForContextMenu; private License activeLicense; - private static final String LICENSE_KEY = "ACTIVE_LICENSE"; + private final CompositeDisposable compositeDisposable = new CompositeDisposable(); public static LicenseFragment newInstance(final SoftwareComponent[] softwareComponents) { if (softwareComponents == null) { @@ -42,16 +45,6 @@ public class LicenseFragment extends Fragment { return fragment; } - /** - * Shows a popup containing the license. - * - * @param context the context to use - * @param license the license to show - */ - private static void showLicense(final Activity context, final License license) { - new LicenseFragmentHelper(context).execute(license); - } - @Override public void onCreate(@Nullable final Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -68,6 +61,12 @@ public class LicenseFragment extends Fragment { Arrays.sort(softwareComponents, Comparator.comparing(SoftwareComponent::getName)); } + @Override + public void onDestroy() { + compositeDisposable.dispose(); + super.onDestroy(); + } + @Nullable @Override public View onCreateView(final LayoutInflater inflater, @Nullable final ViewGroup container, @@ -77,8 +76,9 @@ public class LicenseFragment extends Fragment { final View licenseLink = rootView.findViewById(R.id.app_read_license); licenseLink.setOnClickListener(v -> { - activeLicense = StandardLicenses.GPL3; - showLicense(getActivity(), StandardLicenses.GPL3); + activeLicense = StandardLicenses.GPL3; + compositeDisposable.add(LicenseFragmentHelper.showLicense(getActivity(), + StandardLicenses.GPL3)); }); for (final SoftwareComponent component : softwareComponents) { @@ -95,13 +95,15 @@ public class LicenseFragment extends Fragment { componentView.setTag(component); componentView.setOnClickListener(v -> { activeLicense = component.getLicense(); - showLicense(getActivity(), component.getLicense()); + compositeDisposable.add(LicenseFragmentHelper.showLicense(getActivity(), + component.getLicense())); }); softwareComponentsView.addView(componentView); registerForContextMenu(componentView); } if (activeLicense != null) { - showLicense(getActivity(), activeLicense); + compositeDisposable.add(LicenseFragmentHelper.showLicense(getActivity(), + activeLicense)); } return rootView; } @@ -129,7 +131,8 @@ public class LicenseFragment extends Fragment { ShareUtils.openUrlInBrowser(getActivity(), component.getLink()); return true; case R.id.action_show_license: - showLicense(getActivity(), component.getLicense()); + compositeDisposable.add(LicenseFragmentHelper.showLicense(getActivity(), + component.getLicense())); } return false; } diff --git a/app/src/main/java/org/schabi/newpipe/about/LicenseFragmentHelper.java b/app/src/main/java/org/schabi/newpipe/about/LicenseFragmentHelper.java index 01a01bc88..8a2ab6fa9 100644 --- a/app/src/main/java/org/schabi/newpipe/about/LicenseFragmentHelper.java +++ b/app/src/main/java/org/schabi/newpipe/about/LicenseFragmentHelper.java @@ -1,8 +1,6 @@ package org.schabi.newpipe.about; -import android.app.Activity; import android.content.Context; -import android.os.AsyncTask; import android.util.Base64; import android.webkit.WebView; @@ -16,18 +14,18 @@ import org.schabi.newpipe.util.ThemeHelper; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; -import java.lang.ref.WeakReference; import java.nio.charset.StandardCharsets; +import io.reactivex.Observable; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.disposables.Disposables; +import io.reactivex.schedulers.Schedulers; + import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage; -public class LicenseFragmentHelper extends AsyncTask { - private final WeakReference weakReference; - private License license; - - public LicenseFragmentHelper(@Nullable final Activity activity) { - weakReference = new WeakReference<>(activity); - } +public final class LicenseFragmentHelper { + private LicenseFragmentHelper() { } /** * @param context the context to use @@ -62,7 +60,7 @@ public class LicenseFragmentHelper extends AsyncTask { * @param context * @return String which is a CSS stylesheet according to the context's theme */ - private static String getLicenseStylesheet(final Context context) { + private static String getLicenseStylesheet(@NonNull final Context context) { final boolean isLightTheme = ThemeHelper.isLightThemeSelected(context); return "body{padding:12px 15px;margin:0;" + "background:#" + getHexRGBColor(context, isLightTheme @@ -84,45 +82,31 @@ public class LicenseFragmentHelper extends AsyncTask { * @param color the color number from R.color * @return a six characters long String with hexadecimal RGB values */ - private static String getHexRGBColor(final Context context, final int color) { + private static String getHexRGBColor(@NonNull final Context context, final int color) { return context.getResources().getString(color).substring(3); } - @Nullable - private Activity getActivity() { - final Activity activity = weakReference.get(); - - if (activity != null && activity.isFinishing()) { - return null; - } else { - return activity; - } - } - - @Override - protected Integer doInBackground(final Object... objects) { - license = (License) objects[0]; - return 1; - } - - @Override - protected void onPostExecute(final Integer result) { - final Activity activity = getActivity(); - if (activity == null) { - return; + static Disposable showLicense(@Nullable final Context context, @NonNull final License license) { + if (context == null) { + return Disposables.empty(); } - final String webViewData = Base64.encodeToString(getFormattedLicense(activity, license) - .getBytes(StandardCharsets.UTF_8), Base64.NO_PADDING); - final WebView webView = new WebView(activity); - webView.loadData(webViewData, "text/html; charset=UTF-8", "base64"); + return Observable.fromCallable(() -> getFormattedLicense(context, license)) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(formattedLicense -> { + final String webViewData = Base64.encodeToString(formattedLicense + .getBytes(StandardCharsets.UTF_8), Base64.NO_PADDING); + final WebView webView = new WebView(context); + webView.loadData(webViewData, "text/html; charset=UTF-8", "base64"); - final AlertDialog.Builder alert = new AlertDialog.Builder(activity); - alert.setTitle(license.getName()); - alert.setView(webView); - assureCorrectAppLanguage(activity); - alert.setNegativeButton(activity.getString(R.string.finish), - (dialog, which) -> dialog.dismiss()); - alert.show(); + final AlertDialog.Builder alert = new AlertDialog.Builder(context); + alert.setTitle(license.getName()); + alert.setView(webView); + assureCorrectAppLanguage(context); + alert.setNegativeButton(context.getString(R.string.finish), + (dialog, which) -> dialog.dismiss()); + alert.show(); + }); } } From 3b69e0dd2551a1760fd0d6cfb9cdf89e857f23c4 Mon Sep 17 00:00:00 2001 From: Isira Seneviratne Date: Mon, 12 Oct 2020 12:56:16 +0530 Subject: [PATCH 3/3] Use RxJava instead of AsyncTask in MissionAdapter. --- .../giga/ui/adapter/MissionAdapter.java | 90 +++++++------------ 1 file changed, 31 insertions(+), 59 deletions(-) diff --git a/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java b/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java index eb0fec596..80c238d91 100644 --- a/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java +++ b/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java @@ -1,13 +1,11 @@ package us.shandian.giga.ui.adapter; import android.annotation.SuppressLint; -import android.app.Activity; import android.app.ProgressDialog; import android.content.Context; import android.content.Intent; import android.graphics.Color; import android.net.Uri; -import android.os.AsyncTask; import android.os.Build; import android.os.Handler; import android.os.Message; @@ -26,7 +24,6 @@ import android.widget.TextView; import android.widget.Toast; import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import androidx.annotation.StringRes; import androidx.appcompat.app.AlertDialog; import androidx.core.content.FileProvider; @@ -46,12 +43,15 @@ import org.schabi.newpipe.report.UserAction; import org.schabi.newpipe.util.NavigationHelper; import java.io.File; -import java.lang.ref.WeakReference; import java.net.URI; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; +import io.reactivex.Observable; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.CompositeDisposable; +import io.reactivex.schedulers.Schedulers; import us.shandian.giga.get.DownloadMission; import us.shandian.giga.get.FinishedMission; import us.shandian.giga.get.Mission; @@ -116,6 +116,8 @@ public class MissionAdapter extends Adapter implements Handler.Callb private final Runnable rUpdater = this::updater; private final Runnable rDelete = this::deleteFinishedDownloads; + private final CompositeDisposable compositeDisposable = new CompositeDisposable(); + public MissionAdapter(Context context, @NonNull DownloadManager downloadManager, View emptyMessage, View root) { mContext = context; mDownloadManager = downloadManager; @@ -675,7 +677,30 @@ public class MissionAdapter extends Adapter implements Handler.Callb return true; case R.id.md5: case R.id.sha1: - new ChecksumTask(mContext).execute(h.item.mission.storage, ALGORITHMS.get(id)); + ProgressDialog progressDialog = null; + if (mContext != null) { + // Create dialog + progressDialog = new ProgressDialog(mContext); + progressDialog.setCancelable(false); + progressDialog.setMessage(mContext.getString(R.string.msg_wait)); + progressDialog.show(); + } + final ProgressDialog finalProgressDialog = progressDialog; + final StoredFileHelper storage = h.item.mission.storage; + compositeDisposable.add( + Observable.fromCallable(() -> Utility.checksum(storage, ALGORITHMS.get(id))) + .subscribeOn(Schedulers.computation()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(result -> { + if (finalProgressDialog != null) { + Utility.copyToClipboard(finalProgressDialog.getContext(), + result); + if (mContext != null) { + finalProgressDialog.dismiss(); + } + } + }) + ); return true; case R.id.source: /*Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(h.item.mission.source)); @@ -758,8 +783,8 @@ public class MissionAdapter extends Adapter implements Handler.Callb } } - public void onDestroy() { + compositeDisposable.dispose(); mDeleter.dispose(); } @@ -960,60 +985,7 @@ public class MissionAdapter extends Adapter implements Handler.Callb } } - - static class ChecksumTask extends AsyncTask { - ProgressDialog progressDialog; - WeakReference weakReference; - - ChecksumTask(@NonNull Context context) { - weakReference = new WeakReference<>((Activity) context); - } - - @Override - protected void onPreExecute() { - super.onPreExecute(); - - Activity activity = getActivity(); - if (activity != null) { - // Create dialog - progressDialog = new ProgressDialog(activity); - progressDialog.setCancelable(false); - progressDialog.setMessage(activity.getString(R.string.msg_wait)); - progressDialog.show(); - } - } - - @Override - protected String doInBackground(Object... params) { - return Utility.checksum((StoredFileHelper) params[0], (String) params[1]); - } - - @Override - protected void onPostExecute(String result) { - super.onPostExecute(result); - - if (progressDialog != null) { - Utility.copyToClipboard(progressDialog.getContext(), result); - if (getActivity() != null) { - progressDialog.dismiss(); - } - } - } - - @Nullable - private Activity getActivity() { - Activity activity = weakReference.get(); - - if (activity != null && activity.isFinishing()) { - return null; - } else { - return activity; - } - } - } - public interface RecoverHelper { void tryRecover(DownloadMission mission); } - }