Generate a QR bitmap using RxJava instead of AsyncTask.
This commit is contained in:
parent
93a160b40d
commit
e1ca1552f7
@ -34,7 +34,18 @@ import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.SearchView;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
|
||||
import com.google.android.material.appbar.MaterialToolbar;
|
||||
import com.google.android.material.switchmaterial.SwitchMaterial;
|
||||
import com.google.zxing.integration.android.IntentIntegrator;
|
||||
import com.google.zxing.integration.android.IntentResult;
|
||||
|
||||
@ -54,7 +65,6 @@ import org.fdroid.fdroid.net.BluetoothDownloader;
|
||||
import org.fdroid.fdroid.net.Downloader;
|
||||
import org.fdroid.fdroid.net.HttpDownloader;
|
||||
import org.fdroid.fdroid.qr.CameraCharacteristicsChecker;
|
||||
import org.fdroid.fdroid.qr.QrGenAsyncTask;
|
||||
import org.fdroid.fdroid.views.main.MainActivity;
|
||||
|
||||
import java.util.Date;
|
||||
@ -65,17 +75,8 @@ import java.util.Set;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.SearchView;
|
||||
import com.google.android.material.switchmaterial.SwitchMaterial;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
import cc.mvdan.accesspoint.WifiApControl;
|
||||
import io.reactivex.rxjava3.disposables.CompositeDisposable;
|
||||
|
||||
import static org.fdroid.fdroid.views.main.MainActivity.ACTION_REQUEST_SWAP;
|
||||
|
||||
@ -118,6 +119,8 @@ public class SwapWorkflowActivity extends AppCompatActivity {
|
||||
@LayoutRes
|
||||
private int currentSwapViewLayoutRes = STEP_INTRO;
|
||||
|
||||
private final CompositeDisposable compositeDisposable = new CompositeDisposable();
|
||||
|
||||
public static void requestSwap(Context context, String repo) {
|
||||
requestSwap(context, Uri.parse(repo));
|
||||
}
|
||||
@ -235,6 +238,7 @@ public class SwapWorkflowActivity extends AppCompatActivity {
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
compositeDisposable.dispose();
|
||||
localBroadcastManager.unregisterReceiver(downloaderInterruptedReceiver);
|
||||
unbindService(serviceConnection);
|
||||
super.onDestroy();
|
||||
@ -929,11 +933,14 @@ public class SwapWorkflowActivity extends AppCompatActivity {
|
||||
ImageView qrImage = container.findViewById(R.id.wifi_qr_code);
|
||||
if (qrUriString != null && qrImage != null) {
|
||||
Utils.debugLog(TAG, "Encoded swap URI in QR Code: " + qrUriString);
|
||||
new QrGenAsyncTask(SwapWorkflowActivity.this, R.id.wifi_qr_code).execute(qrUriString);
|
||||
|
||||
compositeDisposable.add(Utils.generateQrBitmap(this, qrUriString)
|
||||
.subscribe(qrBitmap -> {
|
||||
qrImage.setImageBitmap(qrBitmap);
|
||||
|
||||
// Replace all blacks with the background blue.
|
||||
qrImage.setColorFilter(new LightingColorFilter(0xffffffff, ContextCompat.getColor(this,
|
||||
R.color.swap_blue)));
|
||||
qrImage.setColorFilter(new LightingColorFilter(0xffffffff,
|
||||
ContextCompat.getColor(this, R.color.swap_blue)));
|
||||
|
||||
final View qrWarningMessage = container.findViewById(R.id.warning_qr_scanner);
|
||||
if (CameraCharacteristicsChecker.getInstance(this).hasAutofocus()) {
|
||||
@ -941,6 +948,8 @@ public class SwapWorkflowActivity extends AppCompatActivity {
|
||||
} else {
|
||||
qrWarningMessage.setVisibility(View.VISIBLE);
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,7 @@ import android.content.pm.Signature;
|
||||
import android.content.res.Resources;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
@ -44,11 +45,21 @@ import android.text.style.TypefaceSpan;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Display;
|
||||
import android.view.View;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
import com.google.zxing.encode.Contents;
|
||||
import com.google.zxing.encode.QRCodeEncoder;
|
||||
import com.nostra13.universalimageloader.core.DisplayImageOptions;
|
||||
import com.nostra13.universalimageloader.core.ImageLoader;
|
||||
import com.nostra13.universalimageloader.core.assist.ImageScaleType;
|
||||
@ -92,10 +103,9 @@ import java.util.TimeZone;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.rxjava3.core.Single;
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers;
|
||||
|
||||
public final class Utils {
|
||||
|
||||
@ -986,6 +996,27 @@ public final class Utils {
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static Single<Bitmap> generateQrBitmap(@NonNull final AppCompatActivity activity,
|
||||
@NonNull final String qrData) {
|
||||
return Single.fromCallable(() -> {
|
||||
Display display = activity.getWindowManager().getDefaultDisplay();
|
||||
Point outSize = new Point();
|
||||
display.getSize(outSize);
|
||||
final int x = outSize.x;
|
||||
final int y = outSize.y;
|
||||
final int qrCodeDimension = Math.min(x, y);
|
||||
debugLog(TAG, "generating QRCode Bitmap of " + qrCodeDimension + "x" + qrCodeDimension);
|
||||
QRCodeEncoder qrCodeEncoder = new QRCodeEncoder(qrData, null,
|
||||
Contents.Type.TEXT, BarcodeFormat.QR_CODE.toString(), qrCodeDimension);
|
||||
|
||||
return qrCodeEncoder.encodeAsBitmap();
|
||||
})
|
||||
.subscribeOn(Schedulers.computation())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.doOnError(throwable -> Log.e(TAG, "Could not encode QR as bitmap", throwable));
|
||||
}
|
||||
|
||||
/**
|
||||
* Keep an instance of this class as an field in an AppCompatActivity for figuring out whether the on
|
||||
* screen keyboard is currently visible or not.
|
||||
|
@ -1,74 +0,0 @@
|
||||
package org.fdroid.fdroid.qr;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Point;
|
||||
import android.os.AsyncTask;
|
||||
import android.util.Log;
|
||||
import android.view.Display;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
import com.google.zxing.WriterException;
|
||||
import com.google.zxing.encode.Contents;
|
||||
import com.google.zxing.encode.QRCodeEncoder;
|
||||
|
||||
import org.fdroid.fdroid.Utils;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
public class QrGenAsyncTask extends AsyncTask<String, Void, Void> {
|
||||
private static final String TAG = "QrGenAsyncTask";
|
||||
|
||||
private final AppCompatActivity activity;
|
||||
private final int viewId;
|
||||
private Bitmap qrBitmap;
|
||||
|
||||
public QrGenAsyncTask(AppCompatActivity activity, int viewId) {
|
||||
this.activity = activity;
|
||||
this.viewId = viewId;
|
||||
}
|
||||
|
||||
/*
|
||||
* The method for getting screen dimens changed, so this uses both the
|
||||
* deprecated one and the 13+ one, and supports all Android versions.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
@TargetApi(13)
|
||||
@Override
|
||||
protected Void doInBackground(String... s) {
|
||||
String qrData = s[0];
|
||||
Display display = activity.getWindowManager().getDefaultDisplay();
|
||||
Point outSize = new Point();
|
||||
int x, y, qrCodeDimension;
|
||||
display.getSize(outSize);
|
||||
x = outSize.x;
|
||||
y = outSize.y;
|
||||
if (x < y) {
|
||||
qrCodeDimension = x;
|
||||
} else {
|
||||
qrCodeDimension = y;
|
||||
}
|
||||
Utils.debugLog(TAG, "generating QRCode Bitmap of " + qrCodeDimension + "x" + qrCodeDimension);
|
||||
QRCodeEncoder qrCodeEncoder = new QRCodeEncoder(qrData, null,
|
||||
Contents.Type.TEXT, BarcodeFormat.QR_CODE.toString(), qrCodeDimension);
|
||||
|
||||
try {
|
||||
qrBitmap = qrCodeEncoder.encodeAsBitmap();
|
||||
} catch (WriterException e) {
|
||||
Log.e(TAG, "Could not encode QR as bitmap", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Void v) {
|
||||
ImageView qrCodeImageView = (ImageView) activity.findViewById(viewId);
|
||||
|
||||
// If the generation takes too long for whatever reason, then this view, and indeed the entire
|
||||
// activity may not be around any more.
|
||||
if (qrCodeImageView != null) {
|
||||
qrCodeImageView.setImageBitmap(qrBitmap);
|
||||
}
|
||||
}
|
||||
}
|
@ -23,9 +23,19 @@ import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.app.NavUtils;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.google.android.material.appbar.MaterialToolbar;
|
||||
import com.google.android.material.textfield.TextInputLayout;
|
||||
|
||||
@ -38,20 +48,12 @@ import org.fdroid.fdroid.Utils;
|
||||
import org.fdroid.fdroid.data.Repo;
|
||||
import org.fdroid.fdroid.data.RepoProvider;
|
||||
import org.fdroid.fdroid.data.Schema.RepoTable;
|
||||
import org.fdroid.fdroid.qr.QrGenAsyncTask;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.app.NavUtils;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import io.reactivex.rxjava3.disposables.Disposable;
|
||||
|
||||
public class RepoDetailsActivity extends AppCompatActivity {
|
||||
private static final String TAG = "RepoDetailsActivity";
|
||||
@ -91,6 +93,8 @@ public class RepoDetailsActivity extends AppCompatActivity {
|
||||
|
||||
private MirrorAdapter adapterToNotify;
|
||||
|
||||
private Disposable disposable;
|
||||
|
||||
/**
|
||||
* Help function to make switching between two view states easier.
|
||||
* Perhaps there is a better way to do this. I recall that using Adobe
|
||||
@ -141,7 +145,19 @@ public class RepoDetailsActivity extends AppCompatActivity {
|
||||
Uri uri = Uri.parse(repo.address);
|
||||
uri = uri.buildUpon().appendQueryParameter("fingerprint", repo.fingerprint).build();
|
||||
String qrUriString = uri.toString();
|
||||
new QrGenAsyncTask(this, R.id.qr_code).execute(qrUriString);
|
||||
disposable = Utils.generateQrBitmap(this, qrUriString)
|
||||
.subscribe(bitmap -> {
|
||||
final ImageView qrCode = findViewById(R.id.qr_code);
|
||||
if (qrCode != null) {
|
||||
qrCode.setImageBitmap(bitmap);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
disposable.dispose();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@TargetApi(14)
|
||||
|
Loading…
x
Reference in New Issue
Block a user