mirror of
https://github.com/Team4388/RidgeScout.git
synced 2026-06-09 00:37:59 -06:00
Work on speedier qr code scanning.
This commit is contained in:
+22
-1
@@ -51,8 +51,29 @@ dependencies {
|
|||||||
androidTestImplementation(libs.ext.junit)
|
androidTestImplementation(libs.ext.junit)
|
||||||
androidTestImplementation(libs.espresso.core)
|
androidTestImplementation(libs.espresso.core)
|
||||||
|
|
||||||
|
// CameraX\
|
||||||
|
// implementation(libs.camera.core)
|
||||||
|
// implementation(libs.androidx.camera.camera2)
|
||||||
|
// implementation(libs.camera.lifecycle)
|
||||||
|
|
||||||
|
// CameraX View class
|
||||||
|
|
||||||
|
var camerax_version = "1.3.2"
|
||||||
|
// implementation(libs.camera.core)
|
||||||
|
// implementation(libs.androidx.camera.camera2)
|
||||||
|
// implementation(libs.camera.lifecycle)
|
||||||
|
implementation("androidx.camera:camera-core:1.3.2")
|
||||||
|
implementation("androidx.camera:camera-camera2:1.3.2")
|
||||||
|
implementation("androidx.camera:camera-lifecycle:1.3.2")
|
||||||
|
implementation("androidx.camera:camera-view:${camerax_version}")
|
||||||
|
// implementation("com.quickbirdstudios:yuvtomat:1.1.0")
|
||||||
|
|
||||||
|
|
||||||
// implementation("com.github.yuriy-budiyev:code-scanner:2.3.0")
|
// implementation("com.github.yuriy-budiyev:code-scanner:2.3.0")
|
||||||
// implementation("com.github.kenglxn.QRGen:android:3.0.1")
|
// implementation("com.github.kenglxn.QRGen:android:3.0.1")
|
||||||
// implementation("com.journeyapps:zxing-android-embedded:2.3.0")
|
// implementation("com.github.nisrulz:qreader:2.1.1")
|
||||||
|
// implementation("com.journeyapps:zxing-android-embedded:4.3.0")
|
||||||
|
// implementation("androidx.camera:1.0.0-alpha09")
|
||||||
|
// api("com.otaliastudios:cameraview:2.7.2")
|
||||||
implementation("com.dlazaro66.qrcodereaderview:qrcodereaderview:2.0.3")
|
implementation("com.dlazaro66.qrcodereaderview:qrcodereaderview:2.0.3")
|
||||||
}
|
}
|
||||||
@@ -14,6 +14,7 @@
|
|||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/Theme.ScoutingApp2025"
|
android:theme="@style/Theme.ScoutingApp2025"
|
||||||
|
android:hardwareAccelerated="true"
|
||||||
tools:targetApi="31">
|
tools:targetApi="31">
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
|
|||||||
@@ -0,0 +1,165 @@
|
|||||||
|
package com.astatin3.scoutingapp2025;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.ImageFormat;
|
||||||
|
import android.graphics.YuvImage;
|
||||||
|
import android.media.Image;
|
||||||
|
import android.renderscript.Allocation;
|
||||||
|
import android.renderscript.Element;
|
||||||
|
import android.renderscript.RenderScript;
|
||||||
|
import android.renderscript.ScriptIntrinsicYuvToRGB;
|
||||||
|
import android.renderscript.Type;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public class YuvConvertor {
|
||||||
|
private final Allocation in, out;
|
||||||
|
private final ScriptIntrinsicYuvToRGB script;
|
||||||
|
|
||||||
|
public YuvConvertor(Context context, int width, int height) {
|
||||||
|
RenderScript rs = RenderScript.create(context);
|
||||||
|
this.script = ScriptIntrinsicYuvToRGB.create(
|
||||||
|
rs, Element.U8_4(rs));
|
||||||
|
|
||||||
|
// NV21 YUV image of dimension 4 X 4 has following packing:
|
||||||
|
// YYYYYYYYYYYYYYYYVUVUVUVU
|
||||||
|
// With each pixel (of any channel) taking 8 bits.
|
||||||
|
int yuvByteArrayLength = (int) (width * height * 1.5f);
|
||||||
|
Type.Builder yuvType = new Type.Builder(rs, Element.U8(rs))
|
||||||
|
.setX(yuvByteArrayLength);
|
||||||
|
this.in = Allocation.createTyped(
|
||||||
|
rs, yuvType.create(), Allocation.USAGE_SCRIPT);
|
||||||
|
|
||||||
|
Type.Builder rgbaType = new Type.Builder(rs, Element.RGBA_8888(rs))
|
||||||
|
.setX(width)
|
||||||
|
.setY(height);
|
||||||
|
this.out = Allocation.createTyped(
|
||||||
|
rs, rgbaType.create(), Allocation.USAGE_SCRIPT);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Bitmap toBitmap(Image image) {
|
||||||
|
if (image.getFormat() != ImageFormat.YUV_420_888) {
|
||||||
|
throw new IllegalArgumentException("Only supports YUV_420_888.");
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] yuvByteArray = toNv21(image);
|
||||||
|
in.copyFrom(yuvByteArray);
|
||||||
|
script.setInput(in);
|
||||||
|
script.forEach(out);
|
||||||
|
|
||||||
|
// Allocate memory for the bitmap to return. If you have a reusable Bitmap
|
||||||
|
// I recommending using that.
|
||||||
|
Bitmap bitmap = Bitmap.createBitmap(
|
||||||
|
image.getWidth(), image.getHeight(), Bitmap.Config.ARGB_8888);
|
||||||
|
out.copyTo(bitmap);
|
||||||
|
|
||||||
|
return bitmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] toNv21(Image image) {
|
||||||
|
int width = image.getWidth();
|
||||||
|
int height = image.getHeight();
|
||||||
|
|
||||||
|
// Order of U/V channel guaranteed, read more:
|
||||||
|
// https://developer.android.com/reference/android/graphics/ImageFormat#YUV_420_888
|
||||||
|
Image.Plane yPlane = image.getPlanes()[0];
|
||||||
|
Image.Plane uPlane = image.getPlanes()[1];
|
||||||
|
Image.Plane vPlane = image.getPlanes()[2];
|
||||||
|
|
||||||
|
ByteBuffer yBuffer = yPlane.getBuffer();
|
||||||
|
ByteBuffer uBuffer = uPlane.getBuffer();
|
||||||
|
ByteBuffer vBuffer = vPlane.getBuffer();
|
||||||
|
|
||||||
|
// Full size Y channel and quarter size U+V channels.
|
||||||
|
int numPixels = (int) (width * height * 1.5f);
|
||||||
|
byte[] nv21 = new byte[numPixels];
|
||||||
|
int idY = 0;
|
||||||
|
int idUV = width * height;
|
||||||
|
int uvWidth = width / 2;
|
||||||
|
int uvHeight = height / 2;
|
||||||
|
|
||||||
|
// Copy Y & UV channel.
|
||||||
|
// NV21 format is expected to have YYYYVU packaging.
|
||||||
|
// The U/V planes are guaranteed to have the same row stride and pixel stride.
|
||||||
|
int uvRowStride = uPlane.getRowStride();
|
||||||
|
int uvPixelStride = uPlane.getPixelStride();
|
||||||
|
int yRowStride = yPlane.getRowStride();
|
||||||
|
int yPixelStride = yPlane.getPixelStride();
|
||||||
|
for(int y = 0; y < height; ++y) {
|
||||||
|
int yOffset = y * yRowStride;
|
||||||
|
int uvOffset = y * uvRowStride;
|
||||||
|
|
||||||
|
for (int x = 0; x < width; ++x) {
|
||||||
|
nv21[idY++] = yBuffer.get(yOffset + x * yPixelStride);
|
||||||
|
|
||||||
|
if (y < uvHeight && x < uvWidth) {
|
||||||
|
int bufferIndex = uvOffset + (x * uvPixelStride);
|
||||||
|
// V channel.
|
||||||
|
nv21[idUV++] = vBuffer.get(bufferIndex);
|
||||||
|
// U channel.
|
||||||
|
nv21[idUV++] = uBuffer.get(bufferIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nv21;
|
||||||
|
}
|
||||||
|
|
||||||
|
YuvImage toYuvImage(Image image) {
|
||||||
|
if (image.getFormat() != ImageFormat.YUV_420_888) {
|
||||||
|
throw new IllegalArgumentException("Invalid image format");
|
||||||
|
}
|
||||||
|
|
||||||
|
int width = image.getWidth();
|
||||||
|
int height = image.getHeight();
|
||||||
|
|
||||||
|
// Order of U/V channel guaranteed, read more:
|
||||||
|
// https://developer.android.com/reference/android/graphics/ImageFormat#YUV_420_888
|
||||||
|
Image.Plane yPlane = image.getPlanes()[0];
|
||||||
|
Image.Plane uPlane = image.getPlanes()[1];
|
||||||
|
Image.Plane vPlane = image.getPlanes()[2];
|
||||||
|
|
||||||
|
ByteBuffer yBuffer = yPlane.getBuffer();
|
||||||
|
ByteBuffer uBuffer = uPlane.getBuffer();
|
||||||
|
ByteBuffer vBuffer = vPlane.getBuffer();
|
||||||
|
|
||||||
|
// Full size Y channel and quarter size U+V channels.
|
||||||
|
int numPixels = (int) (width * height * 1.5f);
|
||||||
|
byte[] nv21 = new byte[numPixels];
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
// Copy Y channel.
|
||||||
|
int yRowStride = yPlane.getRowStride();
|
||||||
|
int yPixelStride = yPlane.getPixelStride();
|
||||||
|
for(int y = 0; y < height; ++y) {
|
||||||
|
for (int x = 0; x < width; ++x) {
|
||||||
|
nv21[index++] = yBuffer.get(y * yRowStride + x * yPixelStride);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy VU data; NV21 format is expected to have YYYYVU packaging.
|
||||||
|
// The U/V planes are guaranteed to have the same row stride and pixel stride.
|
||||||
|
int uvRowStride = uPlane.getRowStride();
|
||||||
|
int uvPixelStride = uPlane.getPixelStride();
|
||||||
|
int uvWidth = width / 2;
|
||||||
|
int uvHeight = height / 2;
|
||||||
|
|
||||||
|
for(int y = 0; y < uvHeight; ++y) {
|
||||||
|
for (int x = 0; x < uvWidth; ++x) {
|
||||||
|
int bufferIndex = (y * uvRowStride) + (x * uvPixelStride);
|
||||||
|
// V channel.
|
||||||
|
nv21[index++] = vBuffer.get(bufferIndex);
|
||||||
|
// U channel.
|
||||||
|
nv21[index++] = uBuffer.get(bufferIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new YuvImage(
|
||||||
|
nv21, ImageFormat.NV21, width, height, /* strides= */ null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,7 +5,6 @@ import android.util.Log;
|
|||||||
|
|
||||||
import com.astatin3.scoutingapp2025.Utils.frcMatch;
|
import com.astatin3.scoutingapp2025.Utils.frcMatch;
|
||||||
import com.astatin3.scoutingapp2025.Utils.frcTeam;
|
import com.astatin3.scoutingapp2025.Utils.frcTeam;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStreamWriter;
|
import java.io.OutputStreamWriter;
|
||||||
@@ -78,10 +77,10 @@ public final class fileEditor {
|
|||||||
|
|
||||||
|
|
||||||
public static byte[] getByteBlock(byte[] bytes, int start, int end){
|
public static byte[] getByteBlock(byte[] bytes, int start, int end){
|
||||||
byte[] dataBlock = new byte[end-start] ;
|
byte[] dataBlock = new byte[end-start];
|
||||||
|
|
||||||
for(int a=start;a<end;a++){
|
for(int a=start;a<end;a++){
|
||||||
Log.i("test", start+", "+a+", "+end);
|
// Log.i("test", start+", "+a+", "+end);
|
||||||
dataBlock[a-start] = bytes[a];
|
dataBlock[a-start] = bytes[a];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,9 +112,11 @@ public final class fileEditor {
|
|||||||
byte[] buffer = new byte[maxCompressedBlockSize];
|
byte[] buffer = new byte[maxCompressedBlockSize];
|
||||||
|
|
||||||
|
|
||||||
|
while (inflater.getRemaining() > 0) {
|
||||||
while (!inflater.finished()) {
|
|
||||||
int decompressedSize = inflater.inflate(buffer);
|
int decompressedSize = inflater.inflate(buffer);
|
||||||
|
if (decompressedSize == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
outputStream.write(buffer, 0, decompressedSize);
|
outputStream.write(buffer, 0, decompressedSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ public class TransferFragment extends Fragment {
|
|||||||
alert.setCancelable(true);
|
alert.setCancelable(true);
|
||||||
alert.create().show();
|
alert.create().show();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
|
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
|
||||||
@@ -53,7 +54,7 @@ public class TransferFragment extends Fragment {
|
|||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
binding.selectLayout.setVisibility(View.GONE);
|
binding.selectLayout.setVisibility(View.GONE);
|
||||||
binding.scannerLayout.setVisibility(View.VISIBLE);
|
binding.scannerLayout.setVisibility(View.VISIBLE);
|
||||||
binding.scannerLayout.start(binding);
|
binding.scannerLayout.start(binding, getViewLifecycleOwner());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
binding.TBAButton.setOnClickListener(new View.OnClickListener() {
|
binding.TBAButton.setOnClickListener(new View.OnClickListener() {
|
||||||
|
|||||||
@@ -15,8 +15,10 @@ import androidx.constraintlayout.widget.ConstraintLayout;
|
|||||||
|
|
||||||
import com.astatin3.scoutingapp2025.databinding.FragmentTransferBinding;
|
import com.astatin3.scoutingapp2025.databinding.FragmentTransferBinding;
|
||||||
import com.astatin3.scoutingapp2025.fileEditor;
|
import com.astatin3.scoutingapp2025.fileEditor;
|
||||||
|
|
||||||
import com.google.zxing.BarcodeFormat;
|
import com.google.zxing.BarcodeFormat;
|
||||||
import com.google.zxing.EncodeHintType;
|
import com.google.zxing.EncodeHintType;
|
||||||
|
import com.google.zxing.MultiFormatWriter;
|
||||||
import com.google.zxing.WriterException;
|
import com.google.zxing.WriterException;
|
||||||
import com.google.zxing.common.BitMatrix;
|
import com.google.zxing.common.BitMatrix;
|
||||||
import com.google.zxing.qrcode.QRCodeWriter;
|
import com.google.zxing.qrcode.QRCodeWriter;
|
||||||
@@ -38,7 +40,7 @@ public class generatorView extends ConstraintLayout {
|
|||||||
|
|
||||||
private final int maxQrCount = 256; //The max number that can be stored in a byte
|
private final int maxQrCount = 256; //The max number that can be stored in a byte
|
||||||
|
|
||||||
private final int maxQrSpeed = 20;
|
private final int maxQrSpeed = 5;
|
||||||
private final int minQrSpeed = 300 + maxQrSpeed - 1;
|
private final int minQrSpeed = 300 + maxQrSpeed - 1;
|
||||||
|
|
||||||
private int minQrSize = 0;
|
private int minQrSize = 0;
|
||||||
@@ -64,32 +66,42 @@ public class generatorView extends ConstraintLayout {
|
|||||||
super(context, attributeSet);
|
super(context, attributeSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Bitmap generateQrCode(String myCodeText) throws WriterException {
|
private Bitmap generateQrCode(String contents) throws WriterException {
|
||||||
|
|
||||||
QRCodeWriter qrCodeWriter = new QRCodeWriter();
|
final int size = 512;
|
||||||
|
|
||||||
|
if (contents == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
Map<EncodeHintType, Object> hints = new EnumMap<EncodeHintType, Object>(EncodeHintType.class);
|
Map<EncodeHintType, Object> hints = new EnumMap<EncodeHintType, Object>(EncodeHintType.class);
|
||||||
|
|
||||||
|
// The Charset must be UTF-8, Or data will not be transferred properly. IDK why.
|
||||||
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
|
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
|
||||||
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); // H = 30% damage
|
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);
|
||||||
// hints.put(EncodeHintType.QR_COMPACT, true);
|
|
||||||
hints.put(EncodeHintType.MARGIN, 0); /* default = 4 */
|
hints.put(EncodeHintType.MARGIN, 0); /* default = 4 */
|
||||||
|
MultiFormatWriter writer = new MultiFormatWriter();
|
||||||
|
|
||||||
int size = 512;
|
BitMatrix result;
|
||||||
|
try {
|
||||||
BitMatrix bitMatrix = qrCodeWriter.encode(myCodeText, BarcodeFormat.QR_CODE, size, size, hints);
|
result = writer.encode(contents, BarcodeFormat.QR_CODE, size, size, hints);
|
||||||
|
} catch (IllegalArgumentException iae) {
|
||||||
int width = bitMatrix.getWidth();
|
// Unsupported format
|
||||||
int height = bitMatrix.getHeight();
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
int width = result.getWidth();
|
||||||
|
int height = result.getHeight();
|
||||||
int[] pixels = new int[width * height];
|
int[] pixels = new int[width * height];
|
||||||
for (int y = 0; y < height; y++) {
|
for (int y = 0; y < height; y++) {
|
||||||
int offset = y * width;
|
int offset = y * width;
|
||||||
for (int x = 0; x < width; x++) {
|
for (int x = 0; x < width; x++) {
|
||||||
pixels[offset + x] = bitMatrix.get(x, y) ? Color.BLACK : Color.WHITE;
|
pixels[offset + x] = result.get(x, y) ? Color.BLACK : Color.WHITE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
|
Bitmap bitmap = Bitmap.createBitmap(width, height,
|
||||||
|
Bitmap.Config.ARGB_8888);
|
||||||
bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
|
bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
|
||||||
|
|
||||||
return bitmap;
|
return bitmap;
|
||||||
@@ -132,6 +144,8 @@ public class generatorView extends ConstraintLayout {
|
|||||||
StandardCharsets.ISO_8859_1) +
|
StandardCharsets.ISO_8859_1) +
|
||||||
|
|
||||||
compressedBlock;
|
compressedBlock;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// byte[] tempData = fileEditor.compress(inputData);
|
// byte[] tempData = fileEditor.compress(inputData);
|
||||||
@@ -209,6 +223,7 @@ public class generatorView extends ConstraintLayout {
|
|||||||
String.valueOf(fileEditor.byteToChar(qrCount-1)) +
|
String.valueOf(fileEditor.byteToChar(qrCount-1)) +
|
||||||
data.substring(start, end)
|
data.substring(start, end)
|
||||||
));
|
));
|
||||||
|
// alert("title", ""+(qrCount-1));
|
||||||
}catch (WriterException e){
|
}catch (WriterException e){
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@@ -222,7 +237,6 @@ public class generatorView extends ConstraintLayout {
|
|||||||
|
|
||||||
private void updateQr(){
|
private void updateQr(){
|
||||||
qrImage.setImageBitmap(qrBitmaps.get(qrIndex));
|
qrImage.setImageBitmap(qrBitmaps.get(qrIndex));
|
||||||
Log.i("test", qrIndex+", "+qrCount);
|
|
||||||
if(qrDelay > 0) {
|
if(qrDelay > 0) {
|
||||||
this.qrIndex += 1;
|
this.qrIndex += 1;
|
||||||
if (this.qrIndex >= this.qrCount) {
|
if (this.qrIndex >= this.qrCount) {
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ public class qrOverlayView extends View {
|
|||||||
int[] barColors;
|
int[] barColors;
|
||||||
private Paint paint;
|
private Paint paint;
|
||||||
private final int barHeight = 50;
|
private final int barHeight = 50;
|
||||||
private final int barMargin = 5;
|
|
||||||
|
|
||||||
public qrOverlayView(Context context) {
|
public qrOverlayView(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
@@ -63,12 +62,14 @@ public class qrOverlayView extends View {
|
|||||||
|
|
||||||
final int top = 0;
|
final int top = 0;
|
||||||
final int bottom = barHeight;
|
final int bottom = barHeight;
|
||||||
|
final int margin = 5*(int)((double)width/getWidth());
|
||||||
|
|
||||||
for(int i=0;i<barColors.length;i++){
|
for(int i=0;i<barColors.length;i++){
|
||||||
|
|
||||||
final int num = barColors[i];
|
final int num = barColors[i];
|
||||||
|
|
||||||
int c = Color.RED;
|
int c = Color.RED;
|
||||||
|
|
||||||
if(num == 2){
|
if(num == 2){
|
||||||
c = Color.GREEN;
|
c = Color.GREEN;
|
||||||
}else if(num == 1){
|
}else if(num == 1){
|
||||||
@@ -79,8 +80,8 @@ public class qrOverlayView extends View {
|
|||||||
p.setColor(c);
|
p.setColor(c);
|
||||||
|
|
||||||
canvas.drawRect(new Rect(
|
canvas.drawRect(new Rect(
|
||||||
(i*width)+barMargin, top+barMargin,
|
(i*width), top,
|
||||||
((i+1)*width)-barMargin, bottom-barMargin
|
((i+1)*width), bottom
|
||||||
), p);
|
), p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,49 +1,101 @@
|
|||||||
package com.astatin3.scoutingapp2025.ui.transfer;
|
package com.astatin3.scoutingapp2025.ui.transfer;
|
||||||
|
|
||||||
|
import static android.view.Surface.ROTATION_0;
|
||||||
|
import static androidx.core.math.MathUtils.clamp;
|
||||||
|
|
||||||
import android.app.ActionBar;
|
import android.app.ActionBar;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.BitmapFactory;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.ColorMatrix;
|
||||||
|
import android.graphics.ColorMatrixColorFilter;
|
||||||
|
import android.graphics.ImageFormat;
|
||||||
|
import android.graphics.Paint;
|
||||||
import android.graphics.PointF;
|
import android.graphics.PointF;
|
||||||
|
import android.graphics.YuvImage;
|
||||||
|
import android.media.Image;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.SystemClock;
|
||||||
|
import android.renderscript.Element;
|
||||||
|
import android.renderscript.RenderScript;
|
||||||
|
import android.renderscript.ScriptIntrinsicYuvToRGB;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.util.Size;
|
||||||
|
import android.view.Surface;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.widget.FrameLayout;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.OptIn;
|
||||||
|
import androidx.camera.core.AspectRatio;
|
||||||
|
import androidx.camera.core.Camera;
|
||||||
|
import androidx.camera.core.CameraSelector;
|
||||||
|
import androidx.camera.core.ExperimentalGetImage;
|
||||||
|
import androidx.camera.core.ImageAnalysis;
|
||||||
|
import androidx.camera.core.ImageProxy;
|
||||||
|
import androidx.camera.core.Preview;
|
||||||
|
import androidx.camera.core.impl.CameraFilters;
|
||||||
|
import androidx.camera.lifecycle.ProcessCameraProvider;
|
||||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||||
|
import androidx.core.app.ActivityCompat;
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.lifecycle.Lifecycle;
|
||||||
|
import androidx.lifecycle.LifecycleOwner;
|
||||||
|
|
||||||
|
import com.astatin3.scoutingapp2025.YuvConvertor;
|
||||||
import com.astatin3.scoutingapp2025.databinding.FragmentTransferBinding;
|
import com.astatin3.scoutingapp2025.databinding.FragmentTransferBinding;
|
||||||
import com.astatin3.scoutingapp2025.fileEditor;
|
import com.astatin3.scoutingapp2025.fileEditor;
|
||||||
import com.dlazaro66.qrcodereaderview.QRCodeReaderView;
|
|
||||||
|
|
||||||
|
import com.dlazaro66.qrcodereaderview.QRCodeReaderView;
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
import java.util.zip.DataFormatException;
|
import java.util.zip.DataFormatException;
|
||||||
|
|
||||||
|
//public class scannerView extends androidx.appcompat.widget.AppCompatImageView {
|
||||||
public class scannerView extends ConstraintLayout {
|
public class scannerView extends ConstraintLayout {
|
||||||
public static class fixedQRCodeReaderView extends QRCodeReaderView {
|
// public static class fixedQRCodeReaderView extends QRCodeReaderView {
|
||||||
public fixedQRCodeReaderView(Context context) {
|
// public fixedQRCodeReaderView(Context context) {
|
||||||
super(context, null);
|
// super(context, null);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
private QRCodeReaderView qrCodeReaderView;
|
private QRCodeReaderView qrCodeReaderView;
|
||||||
private qrOverlayView qrOverlayView;
|
private qrOverlayView qrOverlayView;
|
||||||
private String[] qrDataArr;
|
private Handler uiHandler;
|
||||||
|
private ScriptIntrinsicYuvToRGB script;
|
||||||
|
private YuvConvertor yuvConvertor;
|
||||||
|
|
||||||
private int randID;
|
// private class codeReadListener implements QRCodeReaderView.OnQRCodeReadListener {
|
||||||
|
// @Override
|
||||||
private class codeReadListener implements QRCodeReaderView.OnQRCodeReadListener {
|
// public void onQRCodeRead(String text, PointF[] points) {
|
||||||
@Override
|
// qrOverlayView.setPoints(points);
|
||||||
public void onQRCodeRead(String text, PointF[] points) {
|
//
|
||||||
qrOverlayView.setPoints(points);
|
//// alert("Info", ""+(fileEditor.byteFromChar(text.charAt(3))+1));
|
||||||
|
//
|
||||||
compileData(
|
// compileData(
|
||||||
fileEditor.byteFromChar(text.charAt(0)),
|
// fileEditor.byteFromChar(text.charAt(0)),
|
||||||
fileEditor.byteFromChar(text.charAt(1)),
|
// fileEditor.byteFromChar(text.charAt(1)),
|
||||||
fileEditor.byteFromChar(text.charAt(2)),
|
// fileEditor.byteFromChar(text.charAt(2)),
|
||||||
(fileEditor.byteFromChar(text.charAt(3))+1),
|
// (fileEditor.byteFromChar(text.charAt(3))+1),
|
||||||
text.substring(4)
|
// text.substring(4)
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
private void alert(String title, String content) {
|
private void alert(String title, String content) {
|
||||||
AlertDialog.Builder alert = new AlertDialog.Builder(getContext());
|
AlertDialog.Builder alert = new AlertDialog.Builder(getContext());
|
||||||
@@ -62,39 +114,185 @@ public class scannerView extends ConstraintLayout {
|
|||||||
super(context, attributeSet);
|
super(context, attributeSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void start(FragmentTransferBinding binding){
|
private float scale = 0;
|
||||||
qrCodeReaderView = new QRCodeReaderView(getContext());
|
private double threshhold = 0.5;
|
||||||
this.addView(qrCodeReaderView);
|
private FragmentTransferBinding binding;
|
||||||
ConstraintLayout.LayoutParams qrCodeReaderViewParams = (ConstraintLayout.LayoutParams) qrCodeReaderView.getLayoutParams();
|
private LifecycleOwner lifecycle;
|
||||||
qrCodeReaderViewParams.width = ActionBar.LayoutParams.MATCH_PARENT;
|
|
||||||
qrCodeReaderViewParams.height = ActionBar.LayoutParams.MATCH_PARENT;
|
|
||||||
qrCodeReaderView.setLayoutParams(qrCodeReaderViewParams);
|
|
||||||
|
|
||||||
qrOverlayView = new qrOverlayView(getContext());
|
private void setImage(Bitmap bmp){
|
||||||
qrOverlayView.bringToFront();
|
if(scale == 0) {
|
||||||
this.addView(qrOverlayView);
|
scale = ((float) ((View) getParent()).getWidth() / bmp.getWidth()) * ((float) 16 / 9);
|
||||||
ConstraintLayout.LayoutParams pointsOverlayViewParams = (ConstraintLayout.LayoutParams) qrCodeReaderView.getLayoutParams();
|
setScaleX(scale);
|
||||||
pointsOverlayViewParams.width = ActionBar.LayoutParams.MATCH_PARENT;
|
setScaleY(scale);
|
||||||
pointsOverlayViewParams.height = ActionBar.LayoutParams.MATCH_PARENT;
|
}
|
||||||
qrOverlayView.setLayoutParams(pointsOverlayViewParams);
|
binding.scannerImage.setImageBitmap(bmp);
|
||||||
|
binding.scannerThreshold.bringToFront();
|
||||||
|
|
||||||
qrCodeReaderView.startCamera();
|
|
||||||
|
|
||||||
// qrCodeReaderView = (QRCodeReaderView) binding.qrdecoderview;
|
|
||||||
qrCodeReaderView.setOnQRCodeReadListener(new codeReadListener());
|
|
||||||
// qrCodeReaderView.setQRDecodingEnabled(true);
|
|
||||||
qrCodeReaderView.setAutofocusInterval(2000L);
|
|
||||||
// qrCodeReaderView.setFrontCamera();
|
|
||||||
qrCodeReaderView.setBackCamera();
|
|
||||||
qrCodeReaderView.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
qrCodeReaderView.forceAutoFocus();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Bitmap toGreyscale(Bitmap originalBitmap){
|
||||||
|
int width = originalBitmap.getWidth();
|
||||||
|
int height = originalBitmap.getHeight();
|
||||||
|
|
||||||
|
Bitmap oneBitBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
|
||||||
|
Canvas canvas = new Canvas(oneBitBitmap);
|
||||||
|
Paint paint = new Paint();
|
||||||
|
paint.setColorFilter(new ColorMatrixColorFilter(new ColorMatrix(new float[] {
|
||||||
|
0.299f, 0.587f, 0.114f, 0, 0,
|
||||||
|
0.299f, 0.587f, 0.114f, 0, 0,
|
||||||
|
0.299f, 0.587f, 0.114f, 0, 0,
|
||||||
|
0, 0, 0, 1, 0
|
||||||
|
})));
|
||||||
|
|
||||||
|
canvas.drawBitmap(originalBitmap, 0, 0, paint);
|
||||||
|
|
||||||
|
int[] pixels = new int[width * height];
|
||||||
|
oneBitBitmap.getPixels(pixels, 0, width, 0, 0, width, height);
|
||||||
|
|
||||||
|
int[] oneBitPixels = new int[width * height];
|
||||||
|
int threshold = 128; // Adjust this value to change the threshold
|
||||||
|
|
||||||
|
for (int i = 0; i < pixels.length; i++) {
|
||||||
|
int pixel = pixels[i];
|
||||||
|
int red = Color.red(pixel);
|
||||||
|
int green = Color.green(pixel);
|
||||||
|
int blue = Color.blue(pixel);
|
||||||
|
int average = (red + green + blue) / 3;
|
||||||
|
oneBitPixels[i] = (average > threshold) ? Color.WHITE : Color.BLACK;
|
||||||
|
}
|
||||||
|
|
||||||
|
oneBitBitmap.setPixels(oneBitPixels, 0, width, 0, 0, width, height);
|
||||||
|
|
||||||
|
return oneBitBitmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void start(FragmentTransferBinding binding, LifecycleOwner lifecycle){
|
||||||
|
this.binding = binding;
|
||||||
|
this.lifecycle = lifecycle;
|
||||||
|
yuvConvertor = new YuvConvertor(getContext(), 1280, 720);
|
||||||
|
|
||||||
|
uiHandler = new Handler();
|
||||||
|
|
||||||
|
// IntentIntegrator integrator = IntentIntegrator.forSupportFragment(TransferFragment);
|
||||||
|
// integrator.setPrompt("Scan a QR code");
|
||||||
|
// integrator.setBeepEnabled(true);
|
||||||
|
// integrator.setOrientationLocked(true);
|
||||||
|
// integrator.setCaptureActivity(CaptureActivity.class);
|
||||||
|
// integrator.initiateScan();
|
||||||
|
|
||||||
|
|
||||||
|
// ScanOptions options = new ScanOptions();
|
||||||
|
// options.setDesiredBarcodeFormats(ScanOptions.QR_CODE);
|
||||||
|
// options.setPrompt("Scan a barcode");
|
||||||
|
// options.setCameraId(0); // Use a specific camera of the device
|
||||||
|
// options.setBeepEnabled(false);
|
||||||
|
// options.setBarcodeImageEnabled(true);
|
||||||
|
// barcodeLauncher.launch(options);
|
||||||
|
|
||||||
|
// qrCodeReaderView = new QRCodeReaderView(getContext());
|
||||||
|
// this.addView(qrCodeReaderView);
|
||||||
|
// ConstraintLayout.LayoutParams qrCodeReaderViewParams = (ConstraintLayout.LayoutParams) qrCodeReaderView.getLayoutParams();
|
||||||
|
// qrCodeReaderViewParams.width = ActionBar.LayoutParams.MATCH_PARENT;
|
||||||
|
// qrCodeReaderViewParams.height = ActionBar.LayoutParams.MATCH_PARENT;
|
||||||
|
// qrCodeReaderView.setLayoutParams(qrCodeReaderViewParams);
|
||||||
|
//
|
||||||
|
// qrOverlayView = new qrOverlayView(getContext());
|
||||||
|
// qrOverlayView.bringToFront();
|
||||||
|
// this.addView(qrOverlayView);
|
||||||
|
// ConstraintLayout.LayoutParams pointsOverlayViewParams = (ConstraintLayout.LayoutParams) qrCodeReaderView.getLayoutParams();
|
||||||
|
// pointsOverlayViewParams.width = ActionBar.LayoutParams.MATCH_PARENT;
|
||||||
|
// pointsOverlayViewParams.height = ActionBar.LayoutParams.MATCH_PARENT;
|
||||||
|
// qrOverlayView.setLayoutParams(pointsOverlayViewParams);
|
||||||
|
//
|
||||||
|
// Map<DecodeHintType, Object> hints = new EnumMap<DecodeHintType, Object>(DecodeHintType.class);
|
||||||
|
// hints.put(DecodeHintType.POSSIBLE_FORMATS, BarcodeFormat.QR_CODE);
|
||||||
|
// hints.put(DecodeHintType.PURE_BARCODE, Boolean.TRUE);
|
||||||
|
//// hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
|
||||||
|
//
|
||||||
|
// qrCodeReaderView.setDecodeHints(hints);
|
||||||
|
//
|
||||||
|
//// qrCodeReaderView = (QRCodeReaderView) binding.qrdecoderview;
|
||||||
|
// qrCodeReaderView.setOnQRCodeReadListener(new codeReadListener());
|
||||||
|
//// qrCodeReaderView.setQRDecodingEnabled(true);
|
||||||
|
// qrCodeReaderView.setAutofocusInterval(2000L);
|
||||||
|
//// qrCodeReaderView.setFrontCamera();
|
||||||
|
// qrCodeReaderView.setBackCamera();
|
||||||
|
// qrCodeReaderView.setOnClickListener(new View.OnClickListener() {
|
||||||
|
// @Override
|
||||||
|
// public void onClick(View v) {
|
||||||
|
// qrCodeReaderView.forceAutoFocus();
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// qrCodeReaderView.startCamera();
|
||||||
|
|
||||||
|
ListenableFuture<ProcessCameraProvider> cameraProviderFuture
|
||||||
|
= ProcessCameraProvider.getInstance(this.getContext());
|
||||||
|
|
||||||
|
cameraProviderFuture.addListener(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
ProcessCameraProvider cameraProvider = cameraProviderFuture.get();
|
||||||
|
bindPreview(cameraProvider);
|
||||||
|
} catch (ExecutionException | InterruptedException e) {
|
||||||
|
// No errors need to be handled for this Future.
|
||||||
|
// This should never be reached.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, ContextCompat.getMainExecutor(this.getContext()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void bindPreview(@NonNull ProcessCameraProvider cameraProvider) {
|
||||||
|
|
||||||
|
Preview preview = new Preview.Builder()
|
||||||
|
.setTargetAspectRatio(AspectRatio.RATIO_16_9)
|
||||||
|
.setTargetRotation(Surface.ROTATION_180)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
CameraSelector cameraSelector = new CameraSelector.Builder()
|
||||||
|
.requireLensFacing(CameraSelector.LENS_FACING_BACK)
|
||||||
|
// .addCameraFilter(CameraFilters.NON)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
ExecutorService executor = Executors.newSingleThreadExecutor();
|
||||||
|
|
||||||
|
ImageAnalysis imageAnalysis = new ImageAnalysis.Builder()
|
||||||
|
// .setTargetResolution(new Size(224, 224))
|
||||||
|
.setOutputImageRotationEnabled(false)
|
||||||
|
.setTargetAspectRatio(AspectRatio.RATIO_16_9)
|
||||||
|
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
|
||||||
|
imageAnalysis.setAnalyzer(executor, new ImageAnalysis.Analyzer() {
|
||||||
|
@OptIn(markerClass = ExperimentalGetImage.class) @Override
|
||||||
|
public void analyze(@NonNull ImageProxy image) {
|
||||||
|
Image img = Objects.requireNonNull(image.getImage());
|
||||||
|
Log.i("test", img.getWidth() + ", " + img.getHeight());
|
||||||
|
final Bitmap bmp = yuvConvertor.toBitmap(img);
|
||||||
|
uiHandler.post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
setImage(toGreyscale(bmp));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
image.close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
cameraProvider.unbindAll();
|
||||||
|
|
||||||
|
Camera camera = cameraProvider.bindToLifecycle((LifecycleOwner)lifecycle,
|
||||||
|
cameraSelector, imageAnalysis, preview);
|
||||||
|
|
||||||
|
// preview.setSurfaceProvider(binding.previewView.getSurfaceProvider());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private String[] qrDataArr;
|
||||||
|
private int qrScannedCount;
|
||||||
|
private int[] barColors;
|
||||||
|
private int randID;
|
||||||
|
private int prevQrIndex;
|
||||||
private void compileData(int dataVersion, int randID, int qrIndex, int qrCount, String qrData){
|
private void compileData(int dataVersion, int randID, int qrIndex, int qrCount, String qrData){
|
||||||
if(dataVersion != fileEditor.internalDataVersion){
|
if(dataVersion != fileEditor.internalDataVersion){
|
||||||
alert("Error", "Incorrect data version");
|
alert("Error", "Incorrect data version");
|
||||||
@@ -105,6 +303,9 @@ public class scannerView extends ConstraintLayout {
|
|||||||
if(randID != this.randID){
|
if(randID != this.randID){
|
||||||
this.randID = randID;
|
this.randID = randID;
|
||||||
qrDataArr = new String[qrCount];
|
qrDataArr = new String[qrCount];
|
||||||
|
Log.i("title", ""+qrCount);
|
||||||
|
barColors = new int[qrCount];
|
||||||
|
prevQrIndex = qrIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean updated;
|
final boolean updated;
|
||||||
@@ -112,29 +313,16 @@ public class scannerView extends ConstraintLayout {
|
|||||||
if(qrDataArr[qrIndex] == null) {
|
if(qrDataArr[qrIndex] == null) {
|
||||||
qrDataArr[qrIndex] = qrData;
|
qrDataArr[qrIndex] = qrData;
|
||||||
updated = true;
|
updated = true;
|
||||||
|
qrScannedCount += 1;
|
||||||
}else{
|
}else{
|
||||||
updated = false;
|
updated = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int count = 0;
|
barColors[prevQrIndex] = 2;
|
||||||
int[] barColors = new int[qrCount];
|
barColors[qrIndex] = 1;
|
||||||
|
|
||||||
for(int i =0;i<qrCount;i++){
|
|
||||||
if(qrDataArr[i] != null){
|
|
||||||
barColors[i] = 2;
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(i == qrIndex){
|
|
||||||
barColors[i] = 1;
|
|
||||||
}else if(qrDataArr[i] == null) {
|
|
||||||
barColors[i] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
qrOverlayView.setBar(barColors);
|
qrOverlayView.setBar(barColors);
|
||||||
|
|
||||||
if(updated && count >= qrCount){
|
if(updated && qrScannedCount >= qrCount){
|
||||||
|
|
||||||
// I guess String.join does not like non-ascii text
|
// I guess String.join does not like non-ascii text
|
||||||
String compiledData = "";
|
String compiledData = "";
|
||||||
@@ -142,31 +330,29 @@ public class scannerView extends ConstraintLayout {
|
|||||||
compiledData += qrDataArr[i];
|
compiledData += qrDataArr[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
byte[] compiledBytes = compiledData.getBytes(StandardCharsets.ISO_8859_1);
|
byte[] compiledBytes = compiledData.getBytes(StandardCharsets.ISO_8859_1);
|
||||||
|
// alert(count+", "+compiledData.length()+", "+compiledBytes.length, ""+fileEditor.fromBytes(fileEditor.getByteBlock(compiledBytes, 0,2),2));
|
||||||
// alert("completed", new String(fileEditor.decompress(compiledBytes), StandardCharsets.ISO_8859_1));
|
// alert("completed", new String(fileEditor.decompress(compiledBytes), StandardCharsets.ISO_8859_1));
|
||||||
alert("completed", blockUncompress(compiledBytes));
|
alert("completed", blockUncompress(compiledBytes));
|
||||||
}catch (Exception e){
|
}catch (Exception e){
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
prevQrIndex = qrIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String blockUncompress(byte[] data) throws DataFormatException {
|
private static String blockUncompress(byte[] data) throws DataFormatException {
|
||||||
String uncompressedData = "";
|
String uncompressedData = "";
|
||||||
int curIndex = 0;
|
int curIndex = 0;
|
||||||
while(curIndex < data.length){
|
while(curIndex < data.length){
|
||||||
final int blockLength = fileEditor.fromBytes(fileEditor.getByteBlock(data, curIndex, curIndex+2), 2);
|
|
||||||
|
|
||||||
Log.i("test", ""+blockLength);
|
final int blockLength = fileEditor.fromBytes(fileEditor.getByteBlock(data, curIndex, curIndex+2), 2);
|
||||||
|
|
||||||
uncompressedData += new String(
|
uncompressedData += new String(
|
||||||
fileEditor.decompress(
|
fileEditor.decompress(
|
||||||
fileEditor.getByteBlock(
|
fileEditor.getByteBlock(data, curIndex+2, curIndex+blockLength+2)
|
||||||
data, curIndex+2, curIndex+blockLength+2)
|
), StandardCharsets.ISO_8859_1);
|
||||||
), StandardCharsets.ISO_8859_1
|
|
||||||
);
|
|
||||||
|
|
||||||
curIndex += blockLength+2;
|
curIndex += blockLength+2;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -129,21 +129,58 @@
|
|||||||
|
|
||||||
</com.astatin3.scoutingapp2025.ui.transfer.generatorView>
|
</com.astatin3.scoutingapp2025.ui.transfer.generatorView>
|
||||||
|
|
||||||
|
|
||||||
<com.astatin3.scoutingapp2025.ui.transfer.scannerView
|
<com.astatin3.scoutingapp2025.ui.transfer.scannerView
|
||||||
android:id="@+id/scannerLayout"
|
android:id="@+id/scannerLayout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
tools:visibility="gone" />
|
app:layout_constraintTop_toBottomOf="parent"
|
||||||
|
tools:layout_editor_absoluteX="-62dp"
|
||||||
|
tools:visibility="visible">
|
||||||
|
|
||||||
|
|
||||||
|
<SeekBar
|
||||||
|
android:id="@+id/scannerThreshold"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:layout_marginBottom="60dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"/>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/scannerImage"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="fill_parent"
|
||||||
|
android:layout_centerInParent="true"
|
||||||
|
android:adjustViewBounds="true"
|
||||||
|
android:rotation="90"
|
||||||
|
android:scaleType="fitCenter"
|
||||||
|
android:scaleX="1"
|
||||||
|
android:scaleY="1"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:context=".TransferFragment" />
|
||||||
|
|
||||||
|
<!-- <Switch-->
|
||||||
|
<!-- android:id="@+id/switch1"-->
|
||||||
|
<!-- android:layout_width="wrap_content"-->
|
||||||
|
<!-- android:layout_height="wrap_content"-->
|
||||||
|
<!-- android:text="Switch"-->
|
||||||
|
<!-- tools:ignore="UseSwitchCompatOrMaterialXml" />-->
|
||||||
|
|
||||||
|
|
||||||
|
</com.astatin3.scoutingapp2025.ui.transfer.scannerView>
|
||||||
|
|
||||||
<com.astatin3.scoutingapp2025.ui.transfer.TBAView
|
<com.astatin3.scoutingapp2025.ui.transfer.TBAView
|
||||||
android:id="@+id/TBAView"
|
android:id="@+id/TBAView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_marginBottom="57dp"
|
|
||||||
android:fillViewport="true"
|
android:fillViewport="true"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
|||||||
Reference in New Issue
Block a user