mirror of
https://github.com/Team4388/RidgeScout.git
synced 2026-06-09 08:38:03 -06:00
FINALLY get bluetooth to kind of work
This commit is contained in:
@@ -6,6 +6,15 @@
|
||||
android:name="android.hardware.camera"
|
||||
android:required="true" />
|
||||
|
||||
<uses-permission android:name="android.permission.BLUETOOTH" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
|
||||
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.CAMERA"/>
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.astatin3.scoutingapp2025;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.astatin3.scoutingapp2025.scoutingData.fields;
|
||||
@@ -25,6 +26,17 @@ public class MainActivity extends AppCompatActivity {
|
||||
private ActivityMainBinding binding;
|
||||
private BottomNavigationView navView;
|
||||
|
||||
|
||||
private void alert(String title, String content) {
|
||||
AlertDialog.Builder alert = new AlertDialog.Builder(this);
|
||||
alert.setMessage(content);
|
||||
alert.setTitle(title);
|
||||
alert.setPositiveButton("OK", null);
|
||||
alert.setCancelable(true);
|
||||
alert.create().show();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
|
||||
@@ -45,9 +57,8 @@ public class MainActivity extends AppCompatActivity {
|
||||
binding = ActivityMainBinding.inflate(getLayoutInflater());
|
||||
setContentView(binding.getRoot());
|
||||
|
||||
// try()
|
||||
navView = findViewById(R.id.nav_view);
|
||||
// Passing each menu ID as a set of Ids because each
|
||||
// menu should be considered as top level destinations.
|
||||
AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
|
||||
R.id.navigation_scouting, R.id.navigation_transfer, R.id.navigation_settings)
|
||||
.build();
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.astatin3.scoutingapp2025.SettingsVersionStack;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class sv1 extends sv0 {
|
||||
@Override
|
||||
public int getVersion() {
|
||||
@@ -27,6 +29,7 @@ public class sv1 extends sv0 {
|
||||
writeTag("match_num", "0");
|
||||
writeTag("alliance_pos", "red-1");
|
||||
writeTag("compiled_mode", "false");
|
||||
writeTag("bt_uuid", UUID.randomUUID().toString());
|
||||
}
|
||||
|
||||
public int get_match_num(){
|
||||
@@ -70,4 +73,12 @@ public class sv1 extends sv0 {
|
||||
public void set_compiled_mode(boolean state){
|
||||
writeTag("compiled_mode", state ? "true" : "false");
|
||||
}
|
||||
|
||||
public void setUUID(UUID uuid){
|
||||
writeTag("bt_uuid", uuid.toString());
|
||||
}
|
||||
|
||||
public UUID getUUID(){
|
||||
return UUID.fromString(readTag("bt_uuid"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,62 @@
|
||||
package com.astatin3.scoutingapp2025.types;
|
||||
|
||||
import com.astatin3.scoutingapp2025.utility.BuiltByteParser;
|
||||
import com.astatin3.scoutingapp2025.utility.ByteBuilder;
|
||||
import com.astatin3.scoutingapp2025.utility.fileEditor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Objects;
|
||||
|
||||
public class file {
|
||||
public static final int typecode = 255;
|
||||
public String filename;
|
||||
public byte[] data;
|
||||
|
||||
|
||||
public file(){}
|
||||
|
||||
public file(String filename){
|
||||
this(filename, fileEditor.readFile(filename));
|
||||
}
|
||||
|
||||
public file(String filename, byte[] data){
|
||||
this.filename = filename;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public byte[] encode(){
|
||||
try {
|
||||
ByteBuilder bb = new ByteBuilder()
|
||||
.addString(filename)
|
||||
.addRaw(255, Objects.requireNonNull(fileEditor.readFile(filename)));
|
||||
|
||||
return bb.build();
|
||||
|
||||
} catch (ByteBuilder.buildingException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static file decode(byte[] bytes){
|
||||
try{
|
||||
ArrayList<BuiltByteParser.parsedObject> objects = new BuiltByteParser(bytes).parse();
|
||||
|
||||
file f = new file();
|
||||
|
||||
f.filename = (String) objects.get(0).get();
|
||||
f.data = (byte[]) objects.get(1).get();
|
||||
|
||||
return f;
|
||||
|
||||
}catch (BuiltByteParser.byteParsingExeption e){
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean write(){
|
||||
if(data == null || filename == null) return false;
|
||||
return fileEditor.writeFile(filename, data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,15 +58,8 @@ public class fieldsView extends ConstraintLayout {
|
||||
filename = fields.pitsFieldsFilename;
|
||||
load_field_menu();
|
||||
});
|
||||
}
|
||||
|
||||
private TextView createTextView(String text) {
|
||||
TextView textView = new TextView(getContext());
|
||||
textView.setText(text);
|
||||
textView.setPadding(10, 10, 10, 10);
|
||||
return textView;
|
||||
}
|
||||
|
||||
private void load_field_menu() {
|
||||
values = fields.load(filename);
|
||||
binding.fieldsArea.bringToFront();
|
||||
@@ -74,24 +67,6 @@ public class fieldsView extends ConstraintLayout {
|
||||
binding.fieldsArea.setReorderingEnabled(false);
|
||||
if(values == null) return;
|
||||
|
||||
// List<TableRow> rows = new ArrayList<>();
|
||||
//
|
||||
//// Create and add rows
|
||||
// TableRow row1 = new TableRow(getContext());
|
||||
// row1.addView(createTextView("Cell 1,1"));
|
||||
// row1.addView(createTextView("Cell 1,2"));
|
||||
// rows.add(row1);
|
||||
//
|
||||
// TableRow row2 = new TableRow(getContext());
|
||||
// row2.addView(createTextView("Cell 2,1"));
|
||||
// row2.addView(createTextView("Cell 2,2"));
|
||||
// rows.add(row2);
|
||||
//
|
||||
//// Set the rows
|
||||
// binding.fieldsArea.setRows(rows);
|
||||
//
|
||||
//// Or add rows individually
|
||||
|
||||
for(int i = 0; i < values.length; i++){
|
||||
|
||||
TableRow tr = new TableRow(getContext());
|
||||
@@ -103,7 +78,6 @@ public class fieldsView extends ConstraintLayout {
|
||||
rowParams.setMargins(20,20,20,20);
|
||||
tr.setLayoutParams(rowParams);
|
||||
tr.setPadding(20,20,20,20);
|
||||
// tr.setMinimumWidth();
|
||||
tr.setBackgroundColor(background_color);
|
||||
|
||||
TextView tv = new TextView(getContext());
|
||||
@@ -118,10 +92,8 @@ public class fieldsView extends ConstraintLayout {
|
||||
|
||||
binding.fieldsArea.addView(tr);
|
||||
|
||||
// frcTeam finalTeam = team;
|
||||
int fi = i;
|
||||
tr.setOnClickListener(v -> {
|
||||
// loadTeam(finalTeam, latestSettings.settings.get_compiled_mode());
|
||||
display_fields(values[fi]);
|
||||
});
|
||||
}
|
||||
@@ -131,7 +103,10 @@ public class fieldsView extends ConstraintLayout {
|
||||
binding.fieldsArea.removeAllViews();
|
||||
binding.fieldsArea.setReorderingEnabled(true);
|
||||
|
||||
// ArrayList<TableRow> rows = new ArrayList<>();
|
||||
TextView e = null;
|
||||
binding.addButton.setOnClickListener(view -> {
|
||||
e.setText("123");
|
||||
});
|
||||
|
||||
for(int i = 0; i < version_values.length; i++){
|
||||
TableRow tr = new TableRow(getContext());
|
||||
@@ -154,17 +129,12 @@ public class fieldsView extends ConstraintLayout {
|
||||
tv.setText(version_values[i].name);
|
||||
tv.setTextSize(20);
|
||||
tr.addView(tv);
|
||||
// rows.add(tr);
|
||||
// tr.addView(tv);
|
||||
binding.fieldsArea.addView(tr);
|
||||
tr.setOnClickListener(v -> {
|
||||
|
||||
trHighlight(tr);
|
||||
});
|
||||
}
|
||||
|
||||
// binding.fieldsArea.setSlidingEnabled(true);
|
||||
// binding.fieldsArea.setRows(rows);
|
||||
}
|
||||
|
||||
private void trHighlight(TableRow self){
|
||||
|
||||
@@ -39,6 +39,8 @@ public class teamsView extends ConstraintLayout {
|
||||
com.astatin3.scoutingapp2025.databinding.FragmentDataBinding binding;
|
||||
|
||||
private static final int background_color = 0x5000ff00;
|
||||
private static final int unsaved_background_color = 0x2000ff00;
|
||||
|
||||
|
||||
String evcode;
|
||||
frcEvent event;
|
||||
|
||||
File diff suppressed because one or more lines are too long
+157
@@ -0,0 +1,157 @@
|
||||
package com.astatin3.scoutingapp2025.ui.transfer.bluetooth;
|
||||
import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothServerSocket;
|
||||
import android.bluetooth.BluetoothSocket;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Build;
|
||||
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class BluetoothReceiver {
|
||||
private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
|
||||
private static final String NAME = "BluetoothReceiverApp";
|
||||
private static final int REQUEST_ENABLE_BT = 1;
|
||||
private static final int REQUEST_PERMISSIONS = 2;
|
||||
|
||||
private Context context;
|
||||
private BluetoothAdapter bluetoothAdapter;
|
||||
private BluetoothServerSocket serverSocket;
|
||||
private BluetoothSocket socket;
|
||||
private InputStream inputStream;
|
||||
private boolean listening = false;
|
||||
private receivedData receiveddata;
|
||||
|
||||
public BluetoothReceiver(Context context, receivedData receiveddata) {
|
||||
this.context = context;
|
||||
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
|
||||
this.receiveddata = receiveddata;
|
||||
}
|
||||
|
||||
public boolean isBluetoothSupported() {
|
||||
return bluetoothAdapter != null;
|
||||
}
|
||||
|
||||
public boolean isBluetoothEnabled() {
|
||||
return bluetoothAdapter != null && bluetoothAdapter.isEnabled();
|
||||
}
|
||||
|
||||
private static final int REQUEST_BLUETOOTH_PERMISSIONS = 1;
|
||||
|
||||
public static void requestBluetoothPermissions(Activity activity) {
|
||||
List<String> permissionsNeeded = new ArrayList<>();
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
// For Android 12 and above
|
||||
if (ContextCompat.checkSelfPermission(activity, Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED) {
|
||||
permissionsNeeded.add(Manifest.permission.BLUETOOTH_SCAN);
|
||||
}
|
||||
if (ContextCompat.checkSelfPermission(activity, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
|
||||
permissionsNeeded.add(Manifest.permission.BLUETOOTH_CONNECT);
|
||||
}
|
||||
if (ContextCompat.checkSelfPermission(activity, Manifest.permission.BLUETOOTH_ADVERTISE) != PackageManager.PERMISSION_GRANTED) {
|
||||
permissionsNeeded.add(Manifest.permission.BLUETOOTH_ADVERTISE);
|
||||
}
|
||||
} else {
|
||||
// For Android 11 and below
|
||||
if (ContextCompat.checkSelfPermission(activity, Manifest.permission.BLUETOOTH) != PackageManager.PERMISSION_GRANTED) {
|
||||
permissionsNeeded.add(Manifest.permission.BLUETOOTH);
|
||||
}
|
||||
if (ContextCompat.checkSelfPermission(activity, Manifest.permission.BLUETOOTH_ADMIN) != PackageManager.PERMISSION_GRANTED) {
|
||||
permissionsNeeded.add(Manifest.permission.BLUETOOTH_ADMIN);
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
if (ContextCompat.checkSelfPermission(activity, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
|
||||
permissionsNeeded.add(Manifest.permission.ACCESS_FINE_LOCATION);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!permissionsNeeded.isEmpty()) {
|
||||
ActivityCompat.requestPermissions(activity, permissionsNeeded.toArray(new String[0]), REQUEST_BLUETOOTH_PERMISSIONS);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean hasBluetoothPermissions(Context context) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
return ContextCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_SCAN) == PackageManager.PERMISSION_GRANTED &&
|
||||
ContextCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_GRANTED &&
|
||||
ContextCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_ADVERTISE) == PackageManager.PERMISSION_GRANTED;
|
||||
} else {
|
||||
boolean hasBasicPermissions = ContextCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH) == PackageManager.PERMISSION_GRANTED &&
|
||||
ContextCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_ADMIN) == PackageManager.PERMISSION_GRANTED;
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
return hasBasicPermissions && ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
|
||||
} else {
|
||||
return hasBasicPermissions;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void startListening() throws IOException {
|
||||
if(!hasBluetoothPermissions(context)){
|
||||
requestBluetoothPermissions((Activity) context);
|
||||
return;
|
||||
}
|
||||
serverSocket = bluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
|
||||
listening = true;
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
while (listening) {
|
||||
try {
|
||||
socket = serverSocket.accept();
|
||||
inputStream = socket.getInputStream();
|
||||
// Handle incoming data here
|
||||
handleIncomingData();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
private void handleIncomingData() throws IOException {
|
||||
byte[] buffer = new byte[1024];
|
||||
int bytes;
|
||||
while (true) {
|
||||
bytes = inputStream.read(buffer);
|
||||
if (bytes != -1) {
|
||||
// Process received data here
|
||||
// receiveddata.processReceivedData(buffer, bytes);
|
||||
System.out.println(Arrays.toString(buffer));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface receivedData {
|
||||
public void processReceivedData(byte[] data, int bytes);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void stopListening() throws IOException {
|
||||
listening = false;
|
||||
if (serverSocket != null) {
|
||||
serverSocket.close();
|
||||
}
|
||||
if (socket != null) {
|
||||
socket.close();
|
||||
}
|
||||
if (inputStream != null) {
|
||||
inputStream.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
package com.astatin3.scoutingapp2025.ui.transfer.bluetooth;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.astatin3.scoutingapp2025.R;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class BluetoothReceiverView extends LinearLayout {
|
||||
private BluetoothReceiver bluetoothReceiver;
|
||||
private Button startListeningButton;
|
||||
private Button stopListeningButton;
|
||||
private TextView statusTextView;
|
||||
|
||||
public BluetoothReceiverView(Context context) {
|
||||
super(context);
|
||||
init(context);
|
||||
}
|
||||
|
||||
public BluetoothReceiverView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init(context);
|
||||
}
|
||||
|
||||
private void init(Context context) {
|
||||
LayoutInflater.from(context).inflate(R.layout.view_bluetooth_receiver, this, true);
|
||||
|
||||
// bluetoothReceiver = new BluetoothReceiver(context);
|
||||
|
||||
bluetoothReceiver = new BluetoothReceiver(context, new BluetoothReceiver.receivedData() {
|
||||
@Override
|
||||
public void processReceivedData(byte[] data, int bytes) {
|
||||
receiveFile(data,bytes);
|
||||
}
|
||||
});
|
||||
|
||||
startListeningButton = findViewById(R.id.startListeningButton);
|
||||
stopListeningButton = findViewById(R.id.stopListeningButton);
|
||||
statusTextView = findViewById(R.id.statusTextView);
|
||||
|
||||
if (!bluetoothReceiver.isBluetoothSupported()) {
|
||||
Toast.makeText(context, "Bluetooth is not supported on this device", Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!bluetoothReceiver.isBluetoothEnabled()) {
|
||||
Toast.makeText(context, "Please enable Bluetooth", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
startListeningButton.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
startListening();
|
||||
}
|
||||
});
|
||||
|
||||
stopListeningButton.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
stopListening();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void startListening() {
|
||||
try {
|
||||
bluetoothReceiver.startListening();
|
||||
statusTextView.setText("Listening for incoming connections...");
|
||||
startListeningButton.setEnabled(false);
|
||||
stopListeningButton.setEnabled(true);
|
||||
} catch (IOException e) {
|
||||
Toast.makeText(getContext(), "Failed to start listening: " + e.getMessage(), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
private void stopListening() {
|
||||
try {
|
||||
bluetoothReceiver.stopListening();
|
||||
statusTextView.setText("Not listening");
|
||||
startListeningButton.setEnabled(true);
|
||||
stopListeningButton.setEnabled(false);
|
||||
} catch (IOException e) {
|
||||
Toast.makeText(getContext(), "Failed to stop listening: " + e.getMessage(), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
private void receiveFile(byte[] data, int bytes) {
|
||||
System.out.println(Arrays.toString(data) + ", " + bytes);
|
||||
}
|
||||
|
||||
public void onDestroy() {
|
||||
try {
|
||||
bluetoothReceiver.stopListening();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
+129
@@ -0,0 +1,129 @@
|
||||
package com.astatin3.scoutingapp2025.ui.transfer.bluetooth;
|
||||
import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothSocket;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Build;
|
||||
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
public class BluetoothSender {
|
||||
private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
|
||||
private static final int REQUEST_ENABLE_BT = 1;
|
||||
private static final int REQUEST_PERMISSIONS = 2;
|
||||
|
||||
private Context context;
|
||||
private BluetoothAdapter bluetoothAdapter;
|
||||
private BluetoothSocket socket;
|
||||
private OutputStream outputStream;
|
||||
|
||||
public BluetoothSender(Context context) {
|
||||
this.context = context;
|
||||
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
|
||||
}
|
||||
|
||||
public boolean isBluetoothSupported() {
|
||||
return bluetoothAdapter != null;
|
||||
}
|
||||
|
||||
public boolean isBluetoothEnabled() {
|
||||
return bluetoothAdapter != null && bluetoothAdapter.isEnabled();
|
||||
}
|
||||
|
||||
private static final int REQUEST_BLUETOOTH_PERMISSIONS = 1;
|
||||
|
||||
public static void requestBluetoothPermissions(Activity activity) {
|
||||
List<String> permissionsNeeded = new ArrayList<>();
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
// For Android 12 and above
|
||||
if (ContextCompat.checkSelfPermission(activity, Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED) {
|
||||
permissionsNeeded.add(Manifest.permission.BLUETOOTH_SCAN);
|
||||
}
|
||||
if (ContextCompat.checkSelfPermission(activity, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
|
||||
permissionsNeeded.add(Manifest.permission.BLUETOOTH_CONNECT);
|
||||
}
|
||||
if (ContextCompat.checkSelfPermission(activity, Manifest.permission.BLUETOOTH_ADVERTISE) != PackageManager.PERMISSION_GRANTED) {
|
||||
permissionsNeeded.add(Manifest.permission.BLUETOOTH_ADVERTISE);
|
||||
}
|
||||
} else {
|
||||
// For Android 11 and below
|
||||
if (ContextCompat.checkSelfPermission(activity, Manifest.permission.BLUETOOTH) != PackageManager.PERMISSION_GRANTED) {
|
||||
permissionsNeeded.add(Manifest.permission.BLUETOOTH);
|
||||
}
|
||||
if (ContextCompat.checkSelfPermission(activity, Manifest.permission.BLUETOOTH_ADMIN) != PackageManager.PERMISSION_GRANTED) {
|
||||
permissionsNeeded.add(Manifest.permission.BLUETOOTH_ADMIN);
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
if (ContextCompat.checkSelfPermission(activity, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
|
||||
permissionsNeeded.add(Manifest.permission.ACCESS_FINE_LOCATION);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!permissionsNeeded.isEmpty()) {
|
||||
ActivityCompat.requestPermissions(activity, permissionsNeeded.toArray(new String[0]), REQUEST_BLUETOOTH_PERMISSIONS);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean hasBluetoothPermissions(Context context) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
return ContextCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_SCAN) == PackageManager.PERMISSION_GRANTED &&
|
||||
ContextCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_GRANTED &&
|
||||
ContextCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_ADVERTISE) == PackageManager.PERMISSION_GRANTED;
|
||||
} else {
|
||||
boolean hasBasicPermissions = ContextCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH) == PackageManager.PERMISSION_GRANTED &&
|
||||
ContextCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_ADMIN) == PackageManager.PERMISSION_GRANTED;
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
return hasBasicPermissions && ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
|
||||
} else {
|
||||
return hasBasicPermissions;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Set<BluetoothDevice> getPairedDevices() {
|
||||
if(!hasBluetoothPermissions(context)){
|
||||
requestBluetoothPermissions((Activity) context);
|
||||
return null;
|
||||
}
|
||||
return bluetoothAdapter.getBondedDevices();
|
||||
}
|
||||
|
||||
public void connectToDevice(BluetoothDevice device) throws IOException {
|
||||
if(!hasBluetoothPermissions(context)){
|
||||
requestBluetoothPermissions((Activity) context);
|
||||
return;
|
||||
}
|
||||
socket = device.createRfcommSocketToServiceRecord(MY_UUID);
|
||||
socket.connect();
|
||||
outputStream = socket.getOutputStream();
|
||||
}
|
||||
|
||||
public void sendData(byte[] data) throws IOException {
|
||||
if (outputStream != null) {
|
||||
outputStream.write(data);
|
||||
}
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
if (outputStream != null) {
|
||||
outputStream.close();
|
||||
}
|
||||
if (socket != null) {
|
||||
socket.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
+126
@@ -0,0 +1,126 @@
|
||||
package com.astatin3.scoutingapp2025.ui.transfer.bluetooth;
|
||||
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.Button;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ListView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.astatin3.scoutingapp2025.R;
|
||||
import com.astatin3.scoutingapp2025.utility.fileEditor;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Set;
|
||||
|
||||
public class BluetoothSenderView extends LinearLayout {
|
||||
private BluetoothSender bluetoothSender;
|
||||
private ListView deviceListView;
|
||||
private Button sendFileButton;
|
||||
private ArrayAdapter<String> deviceArrayAdapter;
|
||||
private ArrayList<BluetoothDevice> deviceList;
|
||||
private byte[] data_to_send = new byte[0];
|
||||
|
||||
public BluetoothSenderView(Context context) {
|
||||
super(context);
|
||||
init(context);
|
||||
}
|
||||
|
||||
public BluetoothSenderView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init(context);
|
||||
}
|
||||
|
||||
public void set_data(byte[] data){
|
||||
data_to_send = data;
|
||||
}
|
||||
|
||||
private void init(Context context) {
|
||||
LayoutInflater.from(context).inflate(R.layout.view_bluetooth_sender, this, true);
|
||||
|
||||
bluetoothSender = new BluetoothSender(context);
|
||||
deviceListView = findViewById(R.id.deviceListView);
|
||||
sendFileButton = findViewById(R.id.sendFileButton);
|
||||
|
||||
deviceList = new ArrayList<>();
|
||||
deviceArrayAdapter = new ArrayAdapter<>(context, android.R.layout.simple_list_item_1);
|
||||
deviceListView.setAdapter(deviceArrayAdapter);
|
||||
|
||||
if (!bluetoothSender.isBluetoothSupported()) {
|
||||
Toast.makeText(context, "Bluetooth is not supported on this device", Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!bluetoothSender.isBluetoothEnabled()) {
|
||||
Toast.makeText(context, "Please enable Bluetooth", Toast.LENGTH_SHORT).show();
|
||||
} else {
|
||||
listPairedDevices();
|
||||
}
|
||||
|
||||
deviceListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
BluetoothDevice selectedDevice = deviceList.get(position);
|
||||
try {
|
||||
bluetoothSender.connectToDevice(selectedDevice);
|
||||
Toast.makeText(context, "Connected to " + selectedDevice.getName(), Toast.LENGTH_SHORT).show();
|
||||
sendFileButton.setEnabled(true);
|
||||
} catch (IOException e) {
|
||||
Toast.makeText(context, "Failed to connect: " + e.getMessage(), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
sendFileButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
// You would typically launch a file picker here
|
||||
// For this example, we'll just send a dummy file
|
||||
sendDummyFile();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void listPairedDevices() {
|
||||
Set<BluetoothDevice> pairedDevices = bluetoothSender.getPairedDevices();
|
||||
if (pairedDevices != null && !pairedDevices.isEmpty()) {
|
||||
deviceList.addAll(pairedDevices);
|
||||
for (BluetoothDevice device : pairedDevices) {
|
||||
deviceArrayAdapter.add(device.getName() + "\n" + device.getAddress());
|
||||
}
|
||||
} else {
|
||||
Toast.makeText(getContext(), "No paired devices found", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
private void sendDummyFile() {
|
||||
try {
|
||||
for(int i = 0; i < Math.floor((double) data_to_send.length /1024); i++){
|
||||
bluetoothSender.sendData(fileEditor.getByteBlock(data_to_send, (i*1024), (i+1)*1024));
|
||||
// System.out.println(Arrays.toString(buffer));
|
||||
}
|
||||
|
||||
|
||||
Toast.makeText(getContext(), "File sent successfully", Toast.LENGTH_SHORT).show();
|
||||
} catch (IOException e) {
|
||||
Toast.makeText(getContext(), "Failed to send file: " + e.getMessage(), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
public void onDestroy() {
|
||||
try {
|
||||
bluetoothSender.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-5
@@ -1,4 +1,4 @@
|
||||
package com.astatin3.scoutingapp2025.ui.transfer;
|
||||
package com.astatin3.scoutingapp2025.ui.transfer.codes;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.AsyncTask;
|
||||
@@ -12,12 +12,8 @@ import com.google.zxing.NotFoundException;
|
||||
import com.google.zxing.RGBLuminanceSource;
|
||||
import com.google.zxing.Reader;
|
||||
import com.google.zxing.Result;
|
||||
import com.google.zxing.aztec.AztecReader;
|
||||
import com.google.zxing.common.HybridBinarizer;
|
||||
import com.google.zxing.datamatrix.DataMatrixReader;
|
||||
import com.google.zxing.maxicode.MaxiCodeReader;
|
||||
import com.google.zxing.pdf417.PDF417Reader;
|
||||
import com.google.zxing.qrcode.QRCodeReader;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.astatin3.scoutingapp2025.ui.transfer;
|
||||
package com.astatin3.scoutingapp2025.ui.transfer.codes;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.astatin3.scoutingapp2025.ui.transfer;
|
||||
package com.astatin3.scoutingapp2025.ui.transfer.codes;
|
||||
|
||||
// From https://github.com/dlazaro66/QRCodeReaderView/blob/master/samples/src/main/java/com/example/qr_readerexample/PointsOverlayView.java
|
||||
|
||||
+29
-7
@@ -1,4 +1,4 @@
|
||||
package com.astatin3.scoutingapp2025.ui.transfer;
|
||||
package com.astatin3.scoutingapp2025.ui.transfer.codes;
|
||||
|
||||
import static androidx.core.math.MathUtils.clamp;
|
||||
|
||||
@@ -26,11 +26,15 @@ import androidx.core.content.ContextCompat;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
|
||||
import com.astatin3.scoutingapp2025.databinding.FragmentTransferBinding;
|
||||
import com.astatin3.scoutingapp2025.types.file;
|
||||
import com.astatin3.scoutingapp2025.utility.BuiltByteParser;
|
||||
import com.astatin3.scoutingapp2025.utility.fileEditor;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
@@ -301,7 +305,24 @@ public class scannerView extends ConstraintLayout {
|
||||
|
||||
try {
|
||||
byte[] compiledBytes = compiledString.getBytes(StandardCharsets.ISO_8859_1);
|
||||
alert("completed", blockUncompress(compiledBytes));
|
||||
byte[] resultBytes = blockUncompress(compiledBytes);
|
||||
|
||||
String result_filenames = "";
|
||||
|
||||
BuiltByteParser bbp = new BuiltByteParser(resultBytes);
|
||||
ArrayList<BuiltByteParser.parsedObject> result = bbp.parse();
|
||||
|
||||
for(int i = 0; i < result.size(); i++){
|
||||
if(result.get(i).getType() != file.typecode) continue;
|
||||
file f = file.decode((byte[]) result.get(i).get());
|
||||
|
||||
if(f != null)
|
||||
if(f.write())
|
||||
result_filenames += f.filename + "\n";
|
||||
}
|
||||
|
||||
alert("Completed!", result_filenames);
|
||||
|
||||
}catch (Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -309,20 +330,21 @@ public class scannerView extends ConstraintLayout {
|
||||
prevQrIndex = qrIndex;
|
||||
}
|
||||
|
||||
private static String blockUncompress(byte[] data) throws DataFormatException {
|
||||
String uncompressedData = "";
|
||||
private static byte[] blockUncompress(byte[] data) throws DataFormatException {
|
||||
List<byte[]> uncompressedData = new ArrayList<>();
|
||||
int curIndex = 0;
|
||||
while(curIndex < data.length){
|
||||
|
||||
final int blockLength = fileEditor.fromBytes(fileEditor.getByteBlock(data, curIndex, curIndex+2), 2);
|
||||
|
||||
uncompressedData += new String(
|
||||
uncompressedData.add(
|
||||
fileEditor.decompress(
|
||||
fileEditor.getByteBlock(data, curIndex+2, curIndex+blockLength+2)
|
||||
), StandardCharsets.ISO_8859_1);
|
||||
)
|
||||
);
|
||||
|
||||
curIndex += blockLength+2;
|
||||
}
|
||||
return uncompressedData;
|
||||
return fileEditor.combineByteArrays(uncompressedData);
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.zip.DataFormatException;
|
||||
import java.util.zip.Deflater;
|
||||
import java.util.zip.Inflater;
|
||||
@@ -127,6 +128,33 @@ public final class fileEditor {
|
||||
return outputStream.toByteArray();
|
||||
}
|
||||
|
||||
public static byte[] combineByteArrays(List<byte[]> arrayList) {
|
||||
// Calculate the total length of the combined array
|
||||
int totalLength = arrayList.stream()
|
||||
.mapToInt(array -> array.length)
|
||||
.sum();
|
||||
|
||||
// Create a new byte array with the total length
|
||||
byte[] result = new byte[totalLength];
|
||||
|
||||
// Copy each array into the result array
|
||||
int offset = 0;
|
||||
for (byte[] array : arrayList) {
|
||||
System.arraycopy(array, 0, result, offset, array.length);
|
||||
offset += array.length;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static boolean writeFile(String filepath, byte[] data) {
|
||||
try {
|
||||
FileOutputStream output = new FileOutputStream(baseDir + filepath);
|
||||
@@ -251,6 +279,48 @@ public final class fileEditor {
|
||||
|
||||
|
||||
|
||||
|
||||
public static String[] getEventFiles(String evcode){
|
||||
File f = new File(baseDir);
|
||||
File[] files = f.listFiles();
|
||||
|
||||
if(files == null){return new String[0];}
|
||||
|
||||
ArrayList<String> outFiles = new ArrayList<>();
|
||||
outFiles.add("matches.fields");
|
||||
outFiles.add("pits.fields");
|
||||
// outFiles.add(evcode + ".eventdata");
|
||||
|
||||
for (File file : files) {
|
||||
String name = file.getName();
|
||||
if(!file.isDirectory() && name.startsWith(evcode)) {
|
||||
outFiles.add(file.getName());
|
||||
}
|
||||
}
|
||||
|
||||
String[] filenames = outFiles.toArray(new String[0]);
|
||||
|
||||
Arrays.sort(filenames, new Comparator<String>() {
|
||||
@Override
|
||||
public int compare(String o1, String o2) {
|
||||
try {
|
||||
if(!o1.contains("-") || !o2.contains("-"))
|
||||
return 0;
|
||||
return Integer.valueOf(o1.split("-")[1]).compareTo(Integer.valueOf(o2.split("-")[1]));
|
||||
} catch (Exception e){
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
return filenames;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static boolean setTeams(Context context, String key, ArrayList<frcTeam> teams){
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -6,8 +6,20 @@
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".ui.transfer.TransferFragment">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/no_event_error"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="No event has been specified\nPlease select one"
|
||||
android:textAlignment="center"
|
||||
android:textSize="20sp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/selectLayout"
|
||||
android:id="@+id/main_select_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginBottom="60dp"
|
||||
@@ -53,13 +65,122 @@
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<com.astatin3.scoutingapp2025.ui.transfer.generatorView
|
||||
android:id="@+id/generatorLayout"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/load_select_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="gone"
|
||||
tools:visibility="gone">
|
||||
|
||||
<Button
|
||||
android:id="@+id/cameraButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Camera"
|
||||
android:textSize="34sp"
|
||||
app:layout_constraintBottom_toTopOf="@+id/bluetoothButton"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/bluetoothButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Bluetooth"
|
||||
android:textSize="34sp"
|
||||
app:layout_constraintBottom_toTopOf="@+id/wifiButton"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/cameraButton" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/wifiButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="TODO"
|
||||
android:textSize="34sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/bluetoothButton" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/file_selector_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible">
|
||||
|
||||
<Button
|
||||
android:id="@+id/file_selector_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:height="48dp"
|
||||
android:text="Send"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/file_selector_searchbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:background="#D33D3D3D"
|
||||
android:ems="10"
|
||||
android:inputType="text"
|
||||
android:textColor="#FFFFFF"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginBottom="53dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/file_selector_searchbar">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TableLayout
|
||||
android:id="@+id/file_selector_table"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingTop="48dp" />
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<com.astatin3.scoutingapp2025.ui.transfer.bluetooth.BluetoothSenderView
|
||||
android:id="@+id/bluetoothSenderView"
|
||||
android:visibility="gone"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginBottom="53dp"/>
|
||||
|
||||
|
||||
<com.astatin3.scoutingapp2025.ui.transfer.bluetooth.BluetoothReceiverView
|
||||
android:id="@+id/bluetoothReceiverView"
|
||||
android:visibility="gone"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginBottom="53dp"/>
|
||||
|
||||
<com.astatin3.scoutingapp2025.ui.transfer.codes.generatorView
|
||||
android:id="@+id/generatorLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="gone"
|
||||
tools:visibility="gone">
|
||||
|
||||
<SeekBar
|
||||
android:id="@+id/qrSizeSlider"
|
||||
android:layout_width="match_parent"
|
||||
@@ -135,10 +256,10 @@
|
||||
app:layout_constraintStart_toEndOf="@+id/qrIndexSlash"
|
||||
app:layout_constraintTop_toBottomOf="@+id/qrImage" />
|
||||
|
||||
</com.astatin3.scoutingapp2025.ui.transfer.generatorView>
|
||||
</com.astatin3.scoutingapp2025.ui.transfer.codes.generatorView>
|
||||
|
||||
|
||||
<com.astatin3.scoutingapp2025.ui.transfer.scannerView
|
||||
<com.astatin3.scoutingapp2025.ui.transfer.codes.scannerView
|
||||
android:id="@+id/scannerLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
@@ -222,7 +343,7 @@
|
||||
tools:context=".TransferFragment" />
|
||||
|
||||
|
||||
</com.astatin3.scoutingapp2025.ui.transfer.scannerView>
|
||||
</com.astatin3.scoutingapp2025.ui.transfer.codes.scannerView>
|
||||
|
||||
<com.astatin3.scoutingapp2025.ui.transfer.TBAView
|
||||
android:id="@+id/TBAView"
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/statusTextView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Not listening"
|
||||
android:textSize="18sp"
|
||||
android:layout_marginBottom="16dp" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/startListeningButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Start Listening" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/stopListeningButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Stop Listening"
|
||||
android:enabled="false" />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<ListView
|
||||
android:id="@+id/deviceListView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/sendFileButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Send File"
|
||||
android:enabled="false" />
|
||||
|
||||
</LinearLayout>
|
||||
Reference in New Issue
Block a user