Merge pull request #4499 from Isira-Seneviratne/Replace_AsyncTasks_with_ReactiveX

Use RxJava instead of AsyncTask.
This commit is contained in:
Stypox 2020-11-05 12:39:33 +01:00 committed by GitHub
commit c193b4f07c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 200 additions and 221 deletions

View File

@ -36,6 +36,7 @@ import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import io.reactivex.disposables.Disposable;
import io.reactivex.exceptions.CompositeException; import io.reactivex.exceptions.CompositeException;
import io.reactivex.exceptions.MissingBackpressureException; import io.reactivex.exceptions.MissingBackpressureException;
import io.reactivex.exceptions.OnErrorNotImplementedException; import io.reactivex.exceptions.OnErrorNotImplementedException;
@ -65,6 +66,9 @@ public class App extends MultiDexApplication {
protected static final String TAG = App.class.toString(); protected static final String TAG = App.class.toString();
private static App app; private static App app;
private Disposable disposable = null;
@NonNull
public static App getApp() { public static App getApp() {
return app; return app;
} }
@ -100,7 +104,15 @@ public class App extends MultiDexApplication {
configureRxJavaErrorHandler(); configureRxJavaErrorHandler();
// Check for new version // 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() { protected Downloader getDownloader() {

View File

@ -9,9 +9,9 @@ import android.content.pm.PackageManager;
import android.content.pm.Signature; import android.content.pm.Signature;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.Uri; import android.net.Uri;
import android.os.AsyncTask;
import android.util.Log; import android.util.Log;
import androidx.annotation.NonNull;
import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat; import androidx.core.app.NotificationManagerCompat;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
@ -35,16 +35,18 @@ import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory; import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
/** import io.reactivex.Observable;
* AsyncTask to check if there is a newer version of the NewPipe github apk available or not. import io.reactivex.android.schedulers.AndroidSchedulers;
* If there is a newer version we show a notification, informing the user. On tapping import io.reactivex.disposables.Disposable;
* the notification, the user will be directed to the download link. import io.reactivex.disposables.Disposables;
*/ import io.reactivex.schedulers.Schedulers;
public class CheckForNewAppVersionTask extends AsyncTask<Void, Void, String> {
private static final boolean DEBUG = MainActivity.DEBUG; public final class CheckForNewAppVersion {
private static final String TAG = CheckForNewAppVersionTask.class.getSimpleName(); 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 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"; = "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"; private static final String NEWPIPE_API_URL = "https://newpipe.schabi.org/api/data.json";
@ -52,18 +54,19 @@ public class CheckForNewAppVersionTask extends AsyncTask<Void, Void, String> {
/** /**
* Method to get the apk's SHA1 key. See https://stackoverflow.com/questions/9293019/#22506133. * 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 * @return String with the apk's SHA1 fingeprint in hexadecimal
*/ */
private static String getCertificateSHA1Fingerprint() { private static String getCertificateSHA1Fingerprint(@NonNull final Application application) {
final PackageManager pm = APP.getPackageManager(); final PackageManager pm = application.getPackageManager();
final String packageName = APP.getPackageName(); final String packageName = application.getPackageName();
final int flags = PackageManager.GET_SIGNATURES; final int flags = PackageManager.GET_SIGNATURES;
PackageInfo packageInfo = null; PackageInfo packageInfo = null;
try { try {
packageInfo = pm.getPackageInfo(packageName, flags); packageInfo = pm.getPackageInfo(packageName, flags);
} catch (final PackageManager.NameNotFoundException e) { } catch (final PackageManager.NameNotFoundException e) {
ErrorActivity.reportError(APP, e, null, null, ErrorActivity.reportError(application, e, null, null,
ErrorActivity.ErrorInfo.make(UserAction.SOMETHING_ELSE, "none", ErrorActivity.ErrorInfo.make(UserAction.SOMETHING_ELSE, "none",
"Could not find package info", R.string.app_ui_crash)); "Could not find package info", R.string.app_ui_crash));
} }
@ -78,7 +81,7 @@ public class CheckForNewAppVersionTask extends AsyncTask<Void, Void, String> {
final CertificateFactory cf = CertificateFactory.getInstance("X509"); final CertificateFactory cf = CertificateFactory.getInstance("X509");
c = (X509Certificate) cf.generateCertificate(input); c = (X509Certificate) cf.generateCertificate(input);
} catch (final CertificateException e) { } catch (final CertificateException e) {
ErrorActivity.reportError(APP, e, null, null, ErrorActivity.reportError(application, e, null, null,
ErrorActivity.ErrorInfo.make(UserAction.SOMETHING_ELSE, "none", ErrorActivity.ErrorInfo.make(UserAction.SOMETHING_ELSE, "none",
"Certificate error", R.string.app_ui_crash)); "Certificate error", R.string.app_ui_crash));
} }
@ -90,7 +93,7 @@ public class CheckForNewAppVersionTask extends AsyncTask<Void, Void, String> {
final byte[] publicKey = md.digest(c.getEncoded()); final byte[] publicKey = md.digest(c.getEncoded());
hexString = byte2HexFormatted(publicKey); hexString = byte2HexFormatted(publicKey);
} catch (NoSuchAlgorithmException | CertificateEncodingException e) { } catch (NoSuchAlgorithmException | CertificateEncodingException e) {
ErrorActivity.reportError(APP, e, null, null, ErrorActivity.reportError(application, e, null, null,
ErrorActivity.ErrorInfo.make(UserAction.SOMETHING_ELSE, "none", ErrorActivity.ErrorInfo.make(UserAction.SOMETHING_ELSE, "none",
"Could not retrieve SHA1 key", R.string.app_ui_crash)); "Could not retrieve SHA1 key", R.string.app_ui_crash));
} }
@ -118,24 +121,71 @@ public class CheckForNewAppVersionTask extends AsyncTask<Void, Void, String> {
return str.toString(); 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 private static boolean isConnected(@NonNull final App app) {
protected void onPreExecute() { final ConnectivityManager cm = ContextCompat.getSystemService(app,
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(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 // 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()) { if (!prefs.getBoolean(app.getString(R.string.update_app_key), true)
this.cancel(true); || !isGithubApk(app)) {
} return Disposables.empty();
} }
@Override return Observable.fromCallable(() -> {
protected String doInBackground(final Void... voids) { if (!isConnected(app)) {
if (isCancelled() || !isConnected()) {
return null; return null;
} }
@ -150,13 +200,12 @@ public class CheckForNewAppVersionTask extends AsyncTask<Void, Void, String> {
} }
return null; return null;
} })
.subscribeOn(Schedulers.io())
@Override .observeOn(AndroidSchedulers.mainThread())
protected void onPostExecute(final String response) { .subscribe(response -> {
// Parse the json from the response. // Parse the json from the response.
if (response != null) { if (response != null) {
try { try {
final JsonObject githubStableObject = JsonParser.object().from(response) final JsonObject githubStableObject = JsonParser.object().from(response)
.getObject("flavors").getObject("github").getObject("stable"); .getObject("flavors").getObject("github").getObject("stable");
@ -165,8 +214,8 @@ public class CheckForNewAppVersionTask extends AsyncTask<Void, Void, String> {
final int versionCode = githubStableObject.getInt("version_code"); final int versionCode = githubStableObject.getInt("version_code");
final String apkLocationUrl = githubStableObject.getString("apk"); final String apkLocationUrl = githubStableObject.getString("apk");
compareAppVersionAndShowNotification(versionName, apkLocationUrl, versionCode); compareAppVersionAndShowNotification(app, versionName, apkLocationUrl,
versionCode);
} catch (final JsonParserException e) { } catch (final JsonParserException e) {
// connectivity problems, do not alarm user and fail silently // connectivity problems, do not alarm user and fail silently
if (DEBUG) { if (DEBUG) {
@ -174,48 +223,6 @@ public class CheckForNewAppVersionTask extends AsyncTask<Void, Void, String> {
} }
} }
} }
} });
/**
* 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;
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(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();
} }
} }

View File

@ -1,6 +1,5 @@
package org.schabi.newpipe.about; package org.schabi.newpipe.about;
import android.app.Activity;
import android.os.Bundle; import android.os.Bundle;
import android.view.ContextMenu; import android.view.ContextMenu;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -21,15 +20,19 @@ import java.io.Serializable;
import java.util.Arrays; import java.util.Arrays;
import java.util.Comparator; import java.util.Comparator;
import io.reactivex.disposables.CompositeDisposable;
/** /**
* Fragment containing the software licenses. * Fragment containing the software licenses.
*/ */
public class LicenseFragment extends Fragment { public class LicenseFragment extends Fragment {
private static final String ARG_COMPONENTS = "components"; private static final String ARG_COMPONENTS = "components";
private static final String LICENSE_KEY = "ACTIVE_LICENSE";
private SoftwareComponent[] softwareComponents; private SoftwareComponent[] softwareComponents;
private SoftwareComponent componentForContextMenu; private SoftwareComponent componentForContextMenu;
private License activeLicense; private License activeLicense;
private static final String LICENSE_KEY = "ACTIVE_LICENSE"; private final CompositeDisposable compositeDisposable = new CompositeDisposable();
public static LicenseFragment newInstance(final SoftwareComponent[] softwareComponents) { public static LicenseFragment newInstance(final SoftwareComponent[] softwareComponents) {
if (softwareComponents == null) { if (softwareComponents == null) {
@ -42,16 +45,6 @@ public class LicenseFragment extends Fragment {
return 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 @Override
public void onCreate(@Nullable final Bundle savedInstanceState) { public void onCreate(@Nullable final Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@ -68,6 +61,12 @@ public class LicenseFragment extends Fragment {
Arrays.sort(softwareComponents, Comparator.comparing(SoftwareComponent::getName)); Arrays.sort(softwareComponents, Comparator.comparing(SoftwareComponent::getName));
} }
@Override
public void onDestroy() {
compositeDisposable.dispose();
super.onDestroy();
}
@Nullable @Nullable
@Override @Override
public View onCreateView(final LayoutInflater inflater, @Nullable final ViewGroup container, public View onCreateView(final LayoutInflater inflater, @Nullable final ViewGroup container,
@ -78,7 +77,8 @@ public class LicenseFragment extends Fragment {
final View licenseLink = rootView.findViewById(R.id.app_read_license); final View licenseLink = rootView.findViewById(R.id.app_read_license);
licenseLink.setOnClickListener(v -> { licenseLink.setOnClickListener(v -> {
activeLicense = StandardLicenses.GPL3; activeLicense = StandardLicenses.GPL3;
showLicense(getActivity(), StandardLicenses.GPL3); compositeDisposable.add(LicenseFragmentHelper.showLicense(getActivity(),
StandardLicenses.GPL3));
}); });
for (final SoftwareComponent component : softwareComponents) { for (final SoftwareComponent component : softwareComponents) {
@ -95,13 +95,15 @@ public class LicenseFragment extends Fragment {
componentView.setTag(component); componentView.setTag(component);
componentView.setOnClickListener(v -> { componentView.setOnClickListener(v -> {
activeLicense = component.getLicense(); activeLicense = component.getLicense();
showLicense(getActivity(), component.getLicense()); compositeDisposable.add(LicenseFragmentHelper.showLicense(getActivity(),
component.getLicense()));
}); });
softwareComponentsView.addView(componentView); softwareComponentsView.addView(componentView);
registerForContextMenu(componentView); registerForContextMenu(componentView);
} }
if (activeLicense != null) { if (activeLicense != null) {
showLicense(getActivity(), activeLicense); compositeDisposable.add(LicenseFragmentHelper.showLicense(getActivity(),
activeLicense));
} }
return rootView; return rootView;
} }
@ -129,7 +131,8 @@ public class LicenseFragment extends Fragment {
ShareUtils.openUrlInBrowser(getActivity(), component.getLink()); ShareUtils.openUrlInBrowser(getActivity(), component.getLink());
return true; return true;
case R.id.action_show_license: case R.id.action_show_license:
showLicense(getActivity(), component.getLicense()); compositeDisposable.add(LicenseFragmentHelper.showLicense(getActivity(),
component.getLicense()));
} }
return false; return false;
} }

View File

@ -1,8 +1,6 @@
package org.schabi.newpipe.about; package org.schabi.newpipe.about;
import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.os.AsyncTask;
import android.util.Base64; import android.util.Base64;
import android.webkit.WebView; import android.webkit.WebView;
@ -16,18 +14,18 @@ import org.schabi.newpipe.util.ThemeHelper;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.lang.ref.WeakReference;
import java.nio.charset.StandardCharsets; 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; import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
public class LicenseFragmentHelper extends AsyncTask<Object, Void, Integer> { public final class LicenseFragmentHelper {
private final WeakReference<Activity> weakReference; private LicenseFragmentHelper() { }
private License license;
public LicenseFragmentHelper(@Nullable final Activity activity) {
weakReference = new WeakReference<>(activity);
}
/** /**
* @param context the context to use * @param context the context to use
@ -62,7 +60,7 @@ public class LicenseFragmentHelper extends AsyncTask<Object, Void, Integer> {
* @param context * @param context
* @return String which is a CSS stylesheet according to the context's theme * @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); final boolean isLightTheme = ThemeHelper.isLightThemeSelected(context);
return "body{padding:12px 15px;margin:0;" return "body{padding:12px 15px;margin:0;"
+ "background:#" + getHexRGBColor(context, isLightTheme + "background:#" + getHexRGBColor(context, isLightTheme
@ -84,45 +82,31 @@ public class LicenseFragmentHelper extends AsyncTask<Object, Void, Integer> {
* @param color the color number from R.color * @param color the color number from R.color
* @return a six characters long String with hexadecimal RGB values * @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); return context.getResources().getString(color).substring(3);
} }
@Nullable static Disposable showLicense(@Nullable final Context context, @NonNull final License license) {
private Activity getActivity() { if (context == null) {
final Activity activity = weakReference.get(); return Disposables.empty();
if (activity != null && activity.isFinishing()) {
return null;
} else {
return activity;
}
} }
@Override return Observable.fromCallable(() -> getFormattedLicense(context, license))
protected Integer doInBackground(final Object... objects) { .subscribeOn(Schedulers.io())
license = (License) objects[0]; .observeOn(AndroidSchedulers.mainThread())
return 1; .subscribe(formattedLicense -> {
} final String webViewData = Base64.encodeToString(formattedLicense
@Override
protected void onPostExecute(final Integer result) {
final Activity activity = getActivity();
if (activity == null) {
return;
}
final String webViewData = Base64.encodeToString(getFormattedLicense(activity, license)
.getBytes(StandardCharsets.UTF_8), Base64.NO_PADDING); .getBytes(StandardCharsets.UTF_8), Base64.NO_PADDING);
final WebView webView = new WebView(activity); final WebView webView = new WebView(context);
webView.loadData(webViewData, "text/html; charset=UTF-8", "base64"); webView.loadData(webViewData, "text/html; charset=UTF-8", "base64");
final AlertDialog.Builder alert = new AlertDialog.Builder(activity); final AlertDialog.Builder alert = new AlertDialog.Builder(context);
alert.setTitle(license.getName()); alert.setTitle(license.getName());
alert.setView(webView); alert.setView(webView);
assureCorrectAppLanguage(activity); assureCorrectAppLanguage(context);
alert.setNegativeButton(activity.getString(R.string.finish), alert.setNegativeButton(context.getString(R.string.finish),
(dialog, which) -> dialog.dismiss()); (dialog, which) -> dialog.dismiss());
alert.show(); alert.show();
});
} }
} }

View File

@ -4,7 +4,8 @@ import android.os.Bundle;
import androidx.preference.Preference; 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.MainActivity;
import org.schabi.newpipe.R; import org.schabi.newpipe.R;
@ -15,7 +16,7 @@ public class MainSettingsFragment extends BasePreferenceFragment {
public void onCreatePreferences(final Bundle savedInstanceState, final String rootKey) { public void onCreatePreferences(final Bundle savedInstanceState, final String rootKey) {
addPreferencesFromResource(R.xml.main_settings); addPreferencesFromResource(R.xml.main_settings);
if (!CheckForNewAppVersionTask.isGithubApk()) { if (!CheckForNewAppVersion.isGithubApk(App.getApp())) {
final Preference update = findPreference(getString(R.string.update_pref_screen_key)); final Preference update = findPreference(getString(R.string.update_pref_screen_key));
getPreferenceScreen().removePreference(update); getPreferenceScreen().removePreference(update);

View File

@ -1,13 +1,11 @@
package us.shandian.giga.ui.adapter; package us.shandian.giga.ui.adapter;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.ProgressDialog; import android.app.ProgressDialog;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.graphics.Color; import android.graphics.Color;
import android.net.Uri; import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build; import android.os.Build;
import android.os.Handler; import android.os.Handler;
import android.os.Message; import android.os.Message;
@ -26,7 +24,6 @@ import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes; import androidx.annotation.StringRes;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
import androidx.core.content.FileProvider; import androidx.core.content.FileProvider;
@ -46,12 +43,15 @@ import org.schabi.newpipe.report.UserAction;
import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.NavigationHelper;
import java.io.File; import java.io.File;
import java.lang.ref.WeakReference;
import java.net.URI; import java.net.URI;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Iterator; 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.DownloadMission;
import us.shandian.giga.get.FinishedMission; import us.shandian.giga.get.FinishedMission;
import us.shandian.giga.get.Mission; import us.shandian.giga.get.Mission;
@ -116,6 +116,8 @@ public class MissionAdapter extends Adapter<ViewHolder> implements Handler.Callb
private final Runnable rUpdater = this::updater; private final Runnable rUpdater = this::updater;
private final Runnable rDelete = this::deleteFinishedDownloads; private final Runnable rDelete = this::deleteFinishedDownloads;
private final CompositeDisposable compositeDisposable = new CompositeDisposable();
public MissionAdapter(Context context, @NonNull DownloadManager downloadManager, View emptyMessage, View root) { public MissionAdapter(Context context, @NonNull DownloadManager downloadManager, View emptyMessage, View root) {
mContext = context; mContext = context;
mDownloadManager = downloadManager; mDownloadManager = downloadManager;
@ -675,7 +677,30 @@ public class MissionAdapter extends Adapter<ViewHolder> implements Handler.Callb
return true; return true;
case R.id.md5: case R.id.md5:
case R.id.sha1: 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; return true;
case R.id.source: case R.id.source:
/*Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(h.item.mission.source)); /*Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(h.item.mission.source));
@ -758,8 +783,8 @@ public class MissionAdapter extends Adapter<ViewHolder> implements Handler.Callb
} }
} }
public void onDestroy() { public void onDestroy() {
compositeDisposable.dispose();
mDeleter.dispose(); mDeleter.dispose();
} }
@ -960,60 +985,7 @@ public class MissionAdapter extends Adapter<ViewHolder> implements Handler.Callb
} }
} }
static class ChecksumTask extends AsyncTask<Object, Void, String> {
ProgressDialog progressDialog;
WeakReference<Activity> 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 { public interface RecoverHelper {
void tryRecover(DownloadMission mission); void tryRecover(DownloadMission mission);
} }
} }