mirror of
https://github.com/Team4388/RidgeScout.git
synced 2026-06-08 16:28:00 -06:00
Fix code scanning sliders and remove asynctask
This commit is contained in:
@@ -33,21 +33,4 @@ https://www.thebluealliance.com/avatars
|
||||
|Match scouting interface|Field editor|Teams data viewer|
|
||||
|-|-|-|
|
||||
||||
|
||||
|
||||
|
||||
<!--
|
||||
Things:
|
||||
- Added verbosity on could not find team number error
|
||||
- Tally counter now has more visible font (@style/TextAppearance.MaterialComponents.Headline6)
|
||||
- Match scouting title bar's background now fills its container (There was a small gap before)
|
||||
- Added border around match title bar buttons
|
||||
- Changed the rescout color to be a less obnoxious blue
|
||||
- Removed blank space above pit scouting team selector
|
||||
- Added new scouting indicator for pit scouting
|
||||
- TBA now sometimes does not let you download all of the team images, go to https://www.thebluealliance.com/avatars in a web browser to try to fix this
|
||||
- Moved dropdown title text box slightly farther up
|
||||
- Added downwards pointing triangle to dropdown
|
||||
- Removed slight gap in icon of the team option
|
||||
- Add headers to settings
|
||||
- Moved field edit buttons into the scroll view, so there is no overlap
|
||||
-->
|
||||
z
|
||||
@@ -49,8 +49,6 @@ public class TBAEventFragment extends Fragment {
|
||||
|
||||
private final int year = SettingsManager.getYearNum();
|
||||
|
||||
private ProgressDialog loadingDialog;
|
||||
|
||||
private static JSONObject eventData = null;
|
||||
public static void setEventData(JSONObject j){
|
||||
eventData = j;
|
||||
@@ -74,7 +72,7 @@ public class TBAEventFragment extends Fragment {
|
||||
|
||||
Table.setStretchAllColumns(true);
|
||||
|
||||
startLoading("Loading Teams and Matches...");
|
||||
AlertManager.startLoading("Loading Teams and Matches...");
|
||||
Table.removeAllViews();
|
||||
Table.setStretchAllColumns(true);
|
||||
Table.bringToFront();
|
||||
@@ -92,7 +90,7 @@ public class TBAEventFragment extends Fragment {
|
||||
final RequestTask rq1 = new RequestTask();
|
||||
rq1.onResult(matchesStr -> {
|
||||
matchTable(matchesStr, teamsStr, eventData);
|
||||
stopLoading();
|
||||
AlertManager.stopLoading();
|
||||
return null;
|
||||
});
|
||||
rq1.execute((TBAAddress + "event/" + matchKey + "/matches"), TBAHeader);
|
||||
@@ -375,12 +373,12 @@ public class TBAEventFragment extends Fragment {
|
||||
|
||||
}catch (JSONException j){
|
||||
AlertManager.error("Failed Downloading", j);
|
||||
stopLoading();
|
||||
AlertManager.stopLoading();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean saveData(ArrayList<frcMatch> matchData, JSONArray teamData, JSONObject eventData){
|
||||
startLoading("Saving data...");
|
||||
AlertManager.startLoading("Saving data...");
|
||||
|
||||
Thread t = new Thread(() -> {
|
||||
try {
|
||||
@@ -431,31 +429,15 @@ public class TBAEventFragment extends Fragment {
|
||||
AlertManager.toast("Saved!");
|
||||
|
||||
getActivity().runOnUiThread(() -> findNavController(this).navigate(R.id.action_navigation_tba_event_to_navigation_transfer));
|
||||
stopLoading();
|
||||
AlertManager.stopLoading();
|
||||
|
||||
}catch(Exception j) {
|
||||
AlertManager.error(j);
|
||||
stopLoading();
|
||||
AlertManager.stopLoading();
|
||||
}
|
||||
});
|
||||
t.start();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void startLoading(String title){
|
||||
getActivity().runOnUiThread(() -> {
|
||||
if(loadingDialog != null && loadingDialog.isShowing())
|
||||
loadingDialog.dismiss();
|
||||
loadingDialog = ProgressDialog.show(getActivity(), title, "Please wait...");
|
||||
});
|
||||
}
|
||||
|
||||
private void stopLoading(){
|
||||
getActivity().runOnUiThread(() -> {
|
||||
if (loadingDialog != null)
|
||||
loadingDialog.cancel();
|
||||
loadingDialog = null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
package com.ridgebotics.ridgescout.ui.transfer.codes;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.os.AsyncTask;
|
||||
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
import com.google.zxing.EncodeHintType;
|
||||
import com.google.zxing.MultiFormatWriter;
|
||||
import com.google.zxing.WriterException;
|
||||
import com.google.zxing.common.BitMatrix;
|
||||
import com.ridgebotics.ridgescout.utility.AlertManager;
|
||||
import com.ridgebotics.ridgescout.utility.FileEditor;
|
||||
import com.ridgebotics.ridgescout.utility.TaskRunner;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class CodeGenTask implements Callable<List<Bitmap>> {
|
||||
// private Function<List<Bitmap>, String> resultFunction = null;
|
||||
//
|
||||
// @Override
|
||||
// protected List<Bitmap> doInBackground(String... strings) {
|
||||
//
|
||||
|
||||
//
|
||||
// return new ArrayList<>();
|
||||
// }
|
||||
//
|
||||
//
|
||||
// public void onResult(Function<List<Bitmap>, String> func) {
|
||||
// this.resultFunction = func;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// @Override
|
||||
// protected void onPostExecute(List<Bitmap> result) {
|
||||
// super.onPostExecute(result);
|
||||
// if(resultFunction != null){
|
||||
// resultFunction.apply(result);
|
||||
// }
|
||||
// }
|
||||
|
||||
private final String data;
|
||||
private final int randID;
|
||||
private final int qrSize;
|
||||
private final int qrCount;
|
||||
|
||||
public CodeGenTask(String data, int randID, int qrSize, int qrCount) {
|
||||
this.data = data;
|
||||
this.randID = randID;
|
||||
this.qrSize = qrSize;
|
||||
this.qrCount = qrCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Bitmap> call() {
|
||||
List<Bitmap> qrBitmaps = new ArrayList<>();
|
||||
|
||||
for(int i=0;i<=((data.length()+1)/qrSize);i++){
|
||||
final int start = i*qrSize;
|
||||
int end = (i+1)*qrSize;
|
||||
if(end >= data.length()){
|
||||
end = data.length();
|
||||
}
|
||||
try {
|
||||
// alert("test", ""+Math.ceil((double)data.length()/(double)qrSize));
|
||||
qrBitmaps.add(generateQrCode(
|
||||
FileEditor.byteToChar(FileEditor.internalDataVersion, FileEditor.lengthHeaderBytes) +
|
||||
String.valueOf(FileEditor.byteToChar(randID, FileEditor.lengthHeaderBytes)) +
|
||||
FileEditor.byteToChar(i, FileEditor.lengthHeaderBytes) +
|
||||
FileEditor.byteToChar(qrCount - 1, FileEditor.lengthHeaderBytes) +
|
||||
data.substring(start, end)
|
||||
));
|
||||
// alert("title", ""+(qrCount-1));
|
||||
}catch (WriterException e){
|
||||
AlertManager.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
return qrBitmaps;
|
||||
}
|
||||
|
||||
private Bitmap generateQrCode(String contents) throws WriterException {
|
||||
|
||||
final int size = 512;
|
||||
|
||||
if (contents == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Map<EncodeHintType, Object> hints = new EnumMap<>(EncodeHintType.class);
|
||||
|
||||
// The Charset must be UTF-8, Or data will not be transferred properly. IDK why.
|
||||
hints.put(EncodeHintType.CHARACTER_SET, "ISO-8859-1");
|
||||
// hints.put(EncodeHintType.);
|
||||
hints.put(EncodeHintType.MARGIN, 0); /* default = 4 */
|
||||
MultiFormatWriter writer = new MultiFormatWriter();
|
||||
|
||||
BitMatrix result;
|
||||
try {
|
||||
result = writer.encode(contents, BarcodeFormat.DATA_MATRIX, size, size, hints);
|
||||
} catch (IllegalArgumentException e) {
|
||||
// Unsupported format
|
||||
AlertManager.error(e);
|
||||
return null;
|
||||
}
|
||||
|
||||
int width = result.getWidth();
|
||||
int height = result.getHeight();
|
||||
int[] pixels = new int[width * height];
|
||||
for (int y = 0; y < height; y++) {
|
||||
int offset = y * width;
|
||||
for (int x = 0; x < width; x++) {
|
||||
pixels[offset + x] = result.get(x, y) ? Color.BLACK : Color.WHITE;
|
||||
}
|
||||
}
|
||||
|
||||
Bitmap bitmap = Bitmap.createBitmap(width, height,
|
||||
Bitmap.Config.ARGB_8888);
|
||||
bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
}
|
||||
+55
-99
@@ -4,6 +4,7 @@ import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.os.CountDownTimer;
|
||||
import android.os.Handler;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
@@ -23,10 +24,12 @@ import com.google.zxing.EncodeHintType;
|
||||
import com.google.zxing.MultiFormatWriter;
|
||||
import com.google.zxing.WriterException;
|
||||
import com.google.zxing.common.BitMatrix;
|
||||
import com.ridgebotics.ridgescout.utility.TaskRunner;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
@@ -38,23 +41,27 @@ public class CodeGeneratorView extends Fragment {
|
||||
private TextView qrIndexN;
|
||||
private TextView qrIndexD;
|
||||
|
||||
private final int maxQrCount = 256; //The max number that can be stored in a byte
|
||||
private static final int maxQrCount = 256; //The max number that can be stored in a byte
|
||||
|
||||
private static final int maxQrSize = 800;
|
||||
|
||||
|
||||
private static final int maxQrSpeed = 50;
|
||||
private static final int minQrSpeed = 1000;
|
||||
private static final int defaultQrDelay = 12;
|
||||
|
||||
|
||||
private final int maxQrSpeed = 5;
|
||||
private final int minQrSpeed = 300 + maxQrSpeed - 1;
|
||||
|
||||
private int minQrSize = 0;
|
||||
private final int maxQrSize = 800;
|
||||
private int qrSize = 200;
|
||||
|
||||
private final int defaultQrDelay = 419;
|
||||
private int qrDelay = 0;
|
||||
private double qrDelay = 0;
|
||||
private int qrIndex = 0;
|
||||
|
||||
private CountDownTimer timer;
|
||||
private int qrCount = 0;
|
||||
|
||||
private ArrayList<Bitmap> qrBitmaps;
|
||||
private List<Bitmap> qrBitmaps = new ArrayList<>();
|
||||
|
||||
private FragmentTransferCodeSenderBinding binding;
|
||||
|
||||
@@ -85,75 +92,29 @@ public class CodeGeneratorView extends Fragment {
|
||||
}
|
||||
|
||||
minQrSize = Math.round((float)compressed.length() / maxQrCount)+1;
|
||||
|
||||
qrSizeSlider.setMax(maxQrSize-minQrSize);
|
||||
qrSpeedSlider.setMax((minQrSpeed-maxQrSpeed)*2);
|
||||
|
||||
qrSizeSlider.setProgress(minQrSize+qrSize);
|
||||
qrSpeedSlider.setProgress(defaultQrDelay+5);
|
||||
qrSize += minQrSize;
|
||||
|
||||
sendData(compressed);
|
||||
|
||||
qrSpeedSlider.setMax(maxQrSpeed*2);
|
||||
qrSpeedSlider.setProgress(maxQrSpeed + defaultQrDelay);
|
||||
|
||||
qrSizeSlider.setMax(maxQrSize-minQrSize);
|
||||
qrSizeSlider.setProgress(qrSize-minQrSize);
|
||||
|
||||
startLoop();
|
||||
|
||||
return binding.getRoot();
|
||||
}
|
||||
|
||||
|
||||
private Bitmap generateQrCode(String contents) throws WriterException {
|
||||
|
||||
final int size = 512;
|
||||
|
||||
if (contents == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Map<EncodeHintType, Object> hints = new EnumMap<>(EncodeHintType.class);
|
||||
|
||||
// The Charset must be UTF-8, Or data will not be transferred properly. IDK why.
|
||||
hints.put(EncodeHintType.CHARACTER_SET, "ISO-8859-1");
|
||||
// hints.put(EncodeHintType.);
|
||||
hints.put(EncodeHintType.MARGIN, 0); /* default = 4 */
|
||||
MultiFormatWriter writer = new MultiFormatWriter();
|
||||
|
||||
BitMatrix result;
|
||||
try {
|
||||
result = writer.encode(contents, BarcodeFormat.DATA_MATRIX, size, size, hints);
|
||||
} catch (IllegalArgumentException e) {
|
||||
// Unsupported format
|
||||
AlertManager.error(e);
|
||||
return null;
|
||||
}
|
||||
|
||||
int width = result.getWidth();
|
||||
int height = result.getHeight();
|
||||
int[] pixels = new int[width * height];
|
||||
for (int y = 0; y < height; y++) {
|
||||
int offset = y * width;
|
||||
for (int x = 0; x < width; x++) {
|
||||
pixels[offset + x] = result.get(x, y) ? Color.BLACK : Color.WHITE;
|
||||
}
|
||||
}
|
||||
|
||||
Bitmap bitmap = Bitmap.createBitmap(width, height,
|
||||
Bitmap.Config.ARGB_8888);
|
||||
bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
|
||||
private void sendData(String data){
|
||||
|
||||
|
||||
|
||||
qrCount = (data.length()/qrSize)+1;
|
||||
qrIndexD.setText(String.valueOf(qrCount));
|
||||
|
||||
// alert("size", ""+binding.qrSizeSlider.getProgress()+"\n"+binding.qrSizeSlider.getMax());
|
||||
|
||||
qrSpeedSlider.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
|
||||
@Override
|
||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
||||
qrDelay = -(minQrSpeed - progress - maxQrSpeed + 1);
|
||||
qrDelay = ((double) progress /maxQrSpeed) - 1;
|
||||
}
|
||||
@Override
|
||||
public void onStartTrackingTouch(SeekBar seekBar) {}
|
||||
@@ -176,40 +137,20 @@ public class CodeGeneratorView extends Fragment {
|
||||
}
|
||||
});
|
||||
|
||||
// qrSizeSlider.setProgress(qr);
|
||||
AlertManager.startLoading("Generating codes...");
|
||||
|
||||
qrBitmaps = new ArrayList<>();
|
||||
new TaskRunner().executeAsync(new CodeGenTask(data, new Random().nextInt(255), qrSize, qrCount), result -> {
|
||||
qrBitmaps = result;
|
||||
AlertManager.stopLoading();
|
||||
qrIndex = 0;
|
||||
});
|
||||
|
||||
int randID = new Random().nextInt(255);
|
||||
|
||||
for(int i=0;i<=((data.length()+1)/qrSize);i++){
|
||||
final int start = i*qrSize;
|
||||
int end = (i+1)*qrSize;
|
||||
if(end >= data.length()){
|
||||
end = data.length();
|
||||
}
|
||||
try {
|
||||
// alert("test", ""+Math.ceil((double)data.length()/(double)qrSize));
|
||||
qrBitmaps.add(generateQrCode(
|
||||
FileEditor.byteToChar(FileEditor.internalDataVersion, FileEditor.lengthHeaderBytes) +
|
||||
String.valueOf(FileEditor.byteToChar(randID, FileEditor.lengthHeaderBytes)) +
|
||||
FileEditor.byteToChar(i, FileEditor.lengthHeaderBytes) +
|
||||
FileEditor.byteToChar(qrCount - 1, FileEditor.lengthHeaderBytes) +
|
||||
data.substring(start, end)
|
||||
));
|
||||
// alert("title", ""+(qrCount-1));
|
||||
}catch (WriterException e){
|
||||
AlertManager.error(e);
|
||||
}
|
||||
}
|
||||
qrIndex = 0;
|
||||
if(timer != null){
|
||||
timer.cancel();
|
||||
}
|
||||
qrLoop();
|
||||
}
|
||||
|
||||
private void updateQr(){
|
||||
if(qrBitmaps.isEmpty())
|
||||
return;
|
||||
|
||||
qrImage.setImageBitmap(qrBitmaps.get(qrIndex));
|
||||
if(qrDelay > 0) {
|
||||
this.qrIndex += 1;
|
||||
@@ -226,13 +167,28 @@ public class CodeGeneratorView extends Fragment {
|
||||
qrIndexN.setText(String.valueOf(qrIndex+1));
|
||||
}
|
||||
|
||||
private void qrLoop(){
|
||||
timer = new CountDownTimer(minQrSpeed-Math.abs(qrDelay)+1, 1000) {
|
||||
public void onTick(long millisUntilFinished) {}
|
||||
public void onFinish() {
|
||||
updateQr();
|
||||
qrLoop();
|
||||
private void startLoop() {
|
||||
|
||||
|
||||
final Handler handler = new Handler();
|
||||
Runnable runnable = new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try{
|
||||
updateQr();
|
||||
}
|
||||
catch (Exception e) {
|
||||
AlertManager.error(e);
|
||||
}
|
||||
finally{
|
||||
double a = ((double) maxQrSpeed) / (Math.abs(qrDelay));
|
||||
a = Math.min(Math.max(a, maxQrSpeed), minQrSpeed);
|
||||
handler.postDelayed(this, (long) a);
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
};
|
||||
|
||||
handler.post(runnable);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ public class CodeOverlayView extends View {
|
||||
}
|
||||
}
|
||||
if(barColors != null){
|
||||
final double width = getWidth()/barColors.length;
|
||||
final double width = (double) getWidth() /barColors.length;
|
||||
|
||||
final int top = 0;
|
||||
final int bottom = barHeight;
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.ridgebotics.ridgescout.utility;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.widget.Toast;
|
||||
@@ -113,4 +114,22 @@ public class AlertManager {
|
||||
});
|
||||
}
|
||||
|
||||
private static ProgressDialog loadingDialog;
|
||||
|
||||
public static void startLoading(String title){
|
||||
((Activity) context).runOnUiThread(() -> {
|
||||
if(loadingDialog != null && loadingDialog.isShowing())
|
||||
loadingDialog.dismiss();
|
||||
loadingDialog = ProgressDialog.show(context, title, "Please wait...");
|
||||
});
|
||||
}
|
||||
|
||||
public static void stopLoading(){
|
||||
((Activity) context).runOnUiThread(() -> {
|
||||
if (loadingDialog != null)
|
||||
loadingDialog.cancel();
|
||||
loadingDialog = null;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -398,9 +398,10 @@ public final class FileEditor {
|
||||
Arrays.sort(filenames, (o1, o2) -> {
|
||||
try {
|
||||
if (!o1.contains("-") || !o2.contains("-"))
|
||||
return 0;
|
||||
return Integer.valueOf(o1.split("-")[1]).compareTo(Integer.valueOf(o2.split("-")[1]));
|
||||
return o2.compareTo(o1);
|
||||
return Integer.valueOf(o1.split("-")[1].split("\\.")[0]).compareTo(Integer.valueOf(o2.split("-")[1].split("\\.")[0]));
|
||||
} catch (Exception e) {
|
||||
AlertManager.error(e);
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.ridgebotics.ridgescout.utility;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
// https://stackoverflow.com/questions/58767733/the-asynctask-api-is-deprecated-in-android-11-what-are-the-alternatives
|
||||
public class TaskRunner {
|
||||
private final Executor executor = Executors.newSingleThreadExecutor(); // change according to your requirements
|
||||
private final Handler handler = new Handler(Looper.getMainLooper());
|
||||
|
||||
public interface Callback<R> {
|
||||
void onComplete(R result);
|
||||
}
|
||||
|
||||
public <R> void executeAsync(Callable<R> callable, Callback<R> callback) {
|
||||
executor.execute(() -> {
|
||||
final R result;
|
||||
try {
|
||||
result = callable.call();
|
||||
handler.post(() -> {
|
||||
callback.onComplete(result);
|
||||
});
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user