mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-02-26 12:44:38 +00:00
Fix device linking issues on newer devices.
This commit is contained in:
committed by
Alex Hart
parent
cc31417c97
commit
d260c48393
@@ -25,11 +25,11 @@ import org.signal.libsignal.protocol.InvalidKeyException;
|
||||
import org.signal.libsignal.protocol.ecc.Curve;
|
||||
import org.signal.libsignal.protocol.ecc.ECPublicKey;
|
||||
import org.signal.libsignal.zkgroup.profiles.ProfileKey;
|
||||
import org.signal.qr.kitkat.ScanListener;
|
||||
import org.thoughtcrime.securesms.crypto.ProfileKeyUtil;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.permissions.Permissions;
|
||||
import org.thoughtcrime.securesms.qr.ScanListener;
|
||||
import org.thoughtcrime.securesms.util.Base64;
|
||||
import org.thoughtcrime.securesms.util.DynamicLanguage;
|
||||
import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme;
|
||||
|
||||
@@ -15,26 +15,25 @@ import android.widget.LinearLayout;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.thoughtcrime.securesms.components.camera.CameraView;
|
||||
import org.thoughtcrime.securesms.qr.ScanListener;
|
||||
import org.thoughtcrime.securesms.qr.ScanningThread;
|
||||
import org.signal.qr.QrScannerView;
|
||||
import org.signal.qr.kitkat.ScanListener;
|
||||
import org.thoughtcrime.securesms.util.LifecycleDisposable;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
|
||||
public class DeviceAddFragment extends LoggingFragment {
|
||||
|
||||
private ViewGroup container;
|
||||
private LinearLayout overlay;
|
||||
private ImageView devicesImage;
|
||||
private CameraView scannerView;
|
||||
private ScanningThread scanningThread;
|
||||
private ScanListener scanListener;
|
||||
private final LifecycleDisposable lifecycleDisposable = new LifecycleDisposable();
|
||||
|
||||
private LinearLayout overlay;
|
||||
private ImageView devicesImage;
|
||||
private ScanListener scanListener;
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup viewGroup, Bundle bundle) {
|
||||
this.container = ViewUtil.inflate(inflater, viewGroup, R.layout.device_add_fragment);
|
||||
this.overlay = this.container.findViewById(R.id.overlay);
|
||||
this.scannerView = this.container.findViewById(R.id.scanner);
|
||||
this.devicesImage = this.container.findViewById(R.id.devices);
|
||||
ViewGroup container = ViewUtil.inflate(inflater, viewGroup, R.layout.device_add_fragment);
|
||||
this.overlay = container.findViewById(R.id.overlay);
|
||||
QrScannerView scannerView = container.findViewById(R.id.scanner);
|
||||
this.devicesImage = container.findViewById(R.id.devices);
|
||||
|
||||
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
|
||||
this.overlay.setOrientation(LinearLayout.HORIZONTAL);
|
||||
@@ -43,7 +42,7 @@ public class DeviceAddFragment extends LoggingFragment {
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
this.container.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
|
||||
container.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
|
||||
@TargetApi(21)
|
||||
@Override
|
||||
public void onLayoutChange(View v, int left, int top, int right, int bottom,
|
||||
@@ -59,52 +58,34 @@ public class DeviceAddFragment extends LoggingFragment {
|
||||
});
|
||||
}
|
||||
|
||||
return this.container;
|
||||
}
|
||||
scannerView.start(getViewLifecycleOwner());
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
this.scanningThread = new ScanningThread();
|
||||
this.scanningThread.setScanListener(scanListener);
|
||||
this.scannerView.onResume();
|
||||
this.scannerView.setPreviewCallback(scanningThread);
|
||||
this.scanningThread.start();
|
||||
}
|
||||
lifecycleDisposable.bindTo(getViewLifecycleOwner());
|
||||
lifecycleDisposable.add(scannerView.getQrData().subscribe(qrData -> {
|
||||
if (scanListener != null) {
|
||||
scanListener.onQrDataFound(qrData);
|
||||
}
|
||||
}));
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
this.scannerView.onPause();
|
||||
this.scanningThread.stopScanning();
|
||||
return container;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(@NonNull Configuration newConfiguration) {
|
||||
super.onConfigurationChanged(newConfiguration);
|
||||
|
||||
this.scannerView.onPause();
|
||||
|
||||
if (newConfiguration.orientation == Configuration.ORIENTATION_LANDSCAPE) {
|
||||
overlay.setOrientation(LinearLayout.HORIZONTAL);
|
||||
} else {
|
||||
overlay.setOrientation(LinearLayout.VERTICAL);
|
||||
}
|
||||
|
||||
this.scannerView.onResume();
|
||||
this.scannerView.setPreviewCallback(scanningThread);
|
||||
}
|
||||
|
||||
|
||||
public ImageView getDevicesImage() {
|
||||
return devicesImage;
|
||||
}
|
||||
|
||||
public void setScanListener(ScanListener scanListener) {
|
||||
this.scanListener = scanListener;
|
||||
|
||||
if (this.scanningThread != null) {
|
||||
this.scanningThread.setScanListener(scanListener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ import androidx.annotation.Nullable;
|
||||
|
||||
import org.signal.core.util.ThreadUtil;
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.signal.qr.kitkat.QrCameraView;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.util.BitmapUtil;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
@@ -228,7 +229,7 @@ public class CameraView extends ViewGroup {
|
||||
listeners.add(listener);
|
||||
}
|
||||
|
||||
public void setPreviewCallback(final @NonNull PreviewCallback previewCallback) {
|
||||
public void setPreviewCallback(final @NonNull QrCameraView.PreviewCallback previewCallback) {
|
||||
enqueueTask(new PostInitializationTask<Void>() {
|
||||
@Override
|
||||
protected void onPostMain(Void avoid) {
|
||||
@@ -243,7 +244,7 @@ public class CameraView extends ViewGroup {
|
||||
final int rotation = getCameraPictureOrientation();
|
||||
final Size previewSize = camera.getParameters().getPreviewSize();
|
||||
if (data != null) {
|
||||
previewCallback.onPreviewFrame(new PreviewFrame(data, previewSize.width, previewSize.height, rotation));
|
||||
previewCallback.onPreviewFrame(new QrCameraView.PreviewFrame(data, previewSize.width, previewSize.height, rotation));
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -568,40 +569,6 @@ public class CameraView extends ViewGroup {
|
||||
void onCameraStop();
|
||||
}
|
||||
|
||||
public interface PreviewCallback {
|
||||
void onPreviewFrame(@NonNull PreviewFrame frame);
|
||||
}
|
||||
|
||||
public static class PreviewFrame {
|
||||
private final @NonNull byte[] data;
|
||||
private final int width;
|
||||
private final int height;
|
||||
private final int orientation;
|
||||
|
||||
private PreviewFrame(@NonNull byte[] data, int width, int height, int orientation) {
|
||||
this.data = data;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.orientation = orientation;
|
||||
}
|
||||
|
||||
public @NonNull byte[] getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
public int getOrientation() {
|
||||
return orientation;
|
||||
}
|
||||
}
|
||||
|
||||
private enum State {
|
||||
PAUSED, RESUMED, ACTIVE
|
||||
}
|
||||
|
||||
@@ -13,11 +13,11 @@ import androidx.navigation.Navigation;
|
||||
|
||||
import org.signal.core.util.ThreadUtil;
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.signal.qr.kitkat.ScanningThread;
|
||||
import org.thoughtcrime.securesms.LoggingFragment;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.components.camera.CameraView;
|
||||
import org.thoughtcrime.securesms.payments.MobileCoinPublicAddress;
|
||||
import org.thoughtcrime.securesms.qr.ScanningThread;
|
||||
import org.thoughtcrime.securesms.util.navigation.SafeNavigation;
|
||||
|
||||
public final class PaymentsTransferQrScanFragment extends LoggingFragment {
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
package org.thoughtcrime.securesms.qr;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
public interface ScanListener {
|
||||
void onQrDataFound(@NonNull String data);
|
||||
}
|
||||
@@ -1,126 +0,0 @@
|
||||
package org.thoughtcrime.securesms.qr;
|
||||
|
||||
import android.content.res.Configuration;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.google.zxing.BinaryBitmap;
|
||||
import com.google.zxing.ChecksumException;
|
||||
import com.google.zxing.DecodeHintType;
|
||||
import com.google.zxing.FormatException;
|
||||
import com.google.zxing.NotFoundException;
|
||||
import com.google.zxing.PlanarYUVLuminanceSource;
|
||||
import com.google.zxing.Result;
|
||||
import com.google.zxing.common.HybridBinarizer;
|
||||
import com.google.zxing.qrcode.QRCodeReader;
|
||||
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.components.camera.CameraView;
|
||||
import org.thoughtcrime.securesms.components.camera.CameraView.PreviewFrame;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
public class ScanningThread extends Thread implements CameraView.PreviewCallback {
|
||||
|
||||
private static final String TAG = Log.tag(ScanningThread.class);
|
||||
|
||||
private final QRCodeReader reader = new QRCodeReader();
|
||||
private final AtomicReference<ScanListener> scanListener = new AtomicReference<>();
|
||||
private final Map<DecodeHintType, String> hints = new HashMap<>();
|
||||
|
||||
private boolean scanning = true;
|
||||
private PreviewFrame previewFrame;
|
||||
|
||||
public void setCharacterSet(String characterSet) {
|
||||
hints.put(DecodeHintType.CHARACTER_SET, characterSet);
|
||||
}
|
||||
|
||||
public void setScanListener(ScanListener scanListener) {
|
||||
this.scanListener.set(scanListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPreviewFrame(@NonNull PreviewFrame previewFrame) {
|
||||
try {
|
||||
synchronized (this) {
|
||||
this.previewFrame = previewFrame;
|
||||
this.notify();
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
Log.w(TAG, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
while (true) {
|
||||
PreviewFrame ourFrame;
|
||||
|
||||
synchronized (this) {
|
||||
while (scanning && previewFrame == null) {
|
||||
Util.wait(this, 0);
|
||||
}
|
||||
|
||||
if (!scanning) return;
|
||||
else ourFrame = previewFrame;
|
||||
|
||||
previewFrame = null;
|
||||
}
|
||||
|
||||
String data = getScannedData(ourFrame.getData(), ourFrame.getWidth(), ourFrame.getHeight(), ourFrame.getOrientation());
|
||||
ScanListener scanListener = this.scanListener.get();
|
||||
|
||||
if (data != null && scanListener != null) {
|
||||
scanListener.onQrDataFound(data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void stopScanning() {
|
||||
synchronized (this) {
|
||||
scanning = false;
|
||||
notify();
|
||||
}
|
||||
}
|
||||
|
||||
private @Nullable String getScannedData(byte[] data, int width, int height, int orientation) {
|
||||
try {
|
||||
if (orientation == Configuration.ORIENTATION_PORTRAIT) {
|
||||
byte[] rotatedData = new byte[data.length];
|
||||
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
rotatedData[x * height + height - y - 1] = data[x + y * width];
|
||||
}
|
||||
}
|
||||
|
||||
int tmp = width;
|
||||
width = height;
|
||||
height = tmp;
|
||||
data = rotatedData;
|
||||
}
|
||||
|
||||
PlanarYUVLuminanceSource source = new PlanarYUVLuminanceSource(data, width, height,
|
||||
0, 0, width, height,
|
||||
false);
|
||||
|
||||
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
|
||||
Result result = reader.decode(bitmap, hints);
|
||||
|
||||
if (result != null) return result.getText();
|
||||
|
||||
} catch (NullPointerException | ChecksumException | FormatException e) {
|
||||
Log.w(TAG, e);
|
||||
} catch (NotFoundException e) {
|
||||
// Thanks ZXing...
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -6,11 +6,11 @@ import android.view.View
|
||||
import android.widget.Toast
|
||||
import androidx.fragment.app.Fragment
|
||||
import org.signal.core.util.ThreadUtil
|
||||
import org.signal.qr.kitkat.ScanListener
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.crypto.IdentityKeyParcelable
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.permissions.Permissions
|
||||
import org.thoughtcrime.securesms.qr.ScanListener
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.util.ServiceUtil
|
||||
|
||||
@@ -9,11 +9,11 @@ import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import androidx.core.view.OneShotPreDrawListener
|
||||
import androidx.fragment.app.Fragment
|
||||
import org.signal.qr.kitkat.ScanListener
|
||||
import org.signal.qr.kitkat.ScanningThread
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.ShapeScrim
|
||||
import org.thoughtcrime.securesms.components.camera.CameraView
|
||||
import org.thoughtcrime.securesms.qr.ScanListener
|
||||
import org.thoughtcrime.securesms.qr.ScanningThread
|
||||
import org.thoughtcrime.securesms.util.ViewUtil
|
||||
import org.thoughtcrime.securesms.util.fragments.requireListener
|
||||
|
||||
|
||||
Reference in New Issue
Block a user