adafruit / adafruit/Adafruit_Android_BLE_UART

After 8 transmissions the application stops broadcasting (Android 10)

Open
#9 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Java
Stars
70
Forks
49
PR merge metrics
No merged PRs in 30d

Description

I am working on an application that ties together with some embedded software.
At present I am able to send messages to the device but after exactly 8 messages (regardless of different payload sizes) the system stops receiving new messages.
It doesn't seem to be an issue on the embedded side as I can continuously send messages from a 3rd party app that I used to debug and test all of this functionality in the first place with no upper limit to the number of messages accepted.

Also if I connect to the device with a second phone running the same app I am able to send another 8 messages before that instance suffers the same fate.

Excuse my atrocious code but this is how I am using this class from my activity, perhaps I am using it incorrectly?

`import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.app.ProgressDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentSender;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.text.Editable;
import android.text.InputFilter;
import android.text.TextWatcher;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.Spinner;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.gms.common.api.ApiException;
import com.google.android.gms.common.api.ResolvableApiException;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.location.LocationSettingsRequest;
import com.google.android.gms.location.LocationSettingsResponse;
import com.google.android.gms.location.LocationSettingsStatusCodes;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
//import com.microchip.blecommunicator.com.atmel.Attributes.Constants;
//import com.microchip.blecommunicator.com.atmel.Connection.BLEConnection;

//import com.google.android.things.bluetooth.BluetoothConnectionManager;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;

public class CalibrateLightsActivity extends AppCompatActivity implements BluetoothLeUart.Callback {

private int selectedProfile = 0;
private int lightCount;
private int stepSize = 50;
private boolean stepSizeLegal = true;
private boolean isConnected = false;
boolean lightState = false;

private int messageCounter = 0;

// Bluetooth stuff
BTConnectionService mBluetoothConnection;
private static final UUID MY_UUID_INSECURE = UUID.fromString("8ce255c0-200a-11e0-ac64-0800200c9a66");
// private static final UUID HALO_SERVICE_UUID = UUID.fromString("49535343-fe7d-4ae5-8fa9-9fafd205e455");
// private static final UUID HALO_CHARTERISTIC_UUID = UUID.fromString("49535343-1e4d-4bd9-ba61-23c647249616");

private static final UUID UART_TRANSPARENT_SERVICE = UUID.fromString("49535343-FE7D-4AE5-8FA9-9FAFD205E455");
private static final UUID UART_TX_CHAR = UUID.fromString("49535343-1E4D-4BD9-BA61-23C647249616");
private static final UUID UART_RX_CHAR = UUID.fromString("49535343-1e4d-4bd9-ba61-23c647249616");

private RecyclerView mRVCalibrate;
private LightConfigAdapter mLightConfigAdapter;
private RecyclerView.LayoutManager mLightConfigLayoutManager;
ArrayList myLights = new ArrayList<>();

Spinner spnrProfileSelector;
Button btnReset, btnConfirm;
DiscoveredDevice targetDevice;
TextView tvCalibrateTitle, tvBondStatus, tvConnectStatus, tvTargetDevice;
EditText etStepSize;
Switch connectSwitch;
ImageView ivLightToggle;

private static final int REQUEST_CHECK_SETTINGS = 111;
private static LocationManager mLocationManager;

// Bluetooth stuff
private BluetoothAdapter mBluetoothAdapter;
private BluetoothDevice mMasterControlUnit;

BluetoothGattCallback BluetoothResponseHandler;
BluetoothGatt mBluetoothGatt;
BluetoothGattService mGattService;
BluetoothGattCharacteristic mTargetCharacteristic;
List mGCList;

// ADAFRUIT ATTEMPT
// Bluetooth LE UART instance. This is defined in BluetoothLeUart.java.
private BluetoothLeUart uart;

private void maintainBTConnection()
{
// messageCounter++;
// if (messageCounter >= 7)
// {
// // Clean up callbacks
// uart.unregisterCallback(this);
// uart.disconnect();
// // Disable UI callbacks
// unregisterReceiver(mBondStateReceiver);
// unregisterReceiver(mConnectReceiver);
// unregisterReceiver(mDisconnectReceiver);
// unpairDevice(mMasterControlUnit);
//
// // RE-INITIATE CONNECTION
//
// IntentFilter connectFilter = new IntentFilter(BluetoothDevice.ACTION_ACL_CONNECTED);
// registerReceiver(mConnectReceiver,connectFilter);
// IntentFilter disconnectFilter = new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED);
// registerReceiver(mDisconnectReceiver,connectFilter);
// IntentFilter bondFilter = new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
// registerReceiver(mBondStateReceiver,connectFilter);
//
// uart = new BluetoothLeUart(getApplicationContext(), mMasterControlUnit);
// Toast.makeText(getApplicationContext(), "Cleaning Bluetooth Buffer", Toast.LENGTH_LONG).show();
// uart.registerCallback(this);
// uart.justFingConnect();
//
//
// messageCounter = 0;
// }
}

public static final String appName = "FHO003";

// Connected state reciever
IntentFilter connectFilter;

public static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i+1), 16));
}
return data;
}

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_calibrate_lights);

mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

Bundle extras = getIntent().getExtras();
targetDevice = getIntent().getParcelableExtra("Discovered Device"); // Unpack device from intent.
mMasterControlUnit = targetDevice.mScanResult.getDevice();
// tvBondStatus = findViewById(R.id.tvBondStatus);
tvConnectStatus = findViewById(R.id.tvConnectStatus);
connectSwitch = findViewById(R.id.switchConnect);
tvTargetDevice = findViewById(R.id.tvTargetDevice);

lightCount = extras.getInt("lights");// Unpack number of lights from intent
Log.d("MyDebug Calibrate", "Number of lights: "+ lightCount);
tvCalibrateTitle = findViewById(R.id.tvCalibrateTitle);
tvCalibrateTitle.setText("Calibrate System ("+lightCount+ " Lights)");

BuildETStepSize();
BuildProfileSpinner();
BuildButtons();
BuildLightControlRV();

connectSwitch.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {

if (connectSwitch.isChecked())
{
Log.d("MyDebug Calibrate switch connect", "Switch Activated");

// TODO: Try to connect

// isConnected = GetConnectStatus(mMasterControlUnit);
if (!isConnected)
{
UpdateConnectStrings(isConnected);
uart.justFingConnect();
}
}
else
{
Log.d("MyDebug Calibrate switch connect", "Switch Deactivated");
uart.disconnect();
isConnected = false; //GetConnectStatus(mMasterControlUnit);
UpdateConnectStrings(isConnected);
}
}

});

UpdateConnectStrings(false);

// Initialize UART.
mBluetoothAdapter.cancelDiscovery();
uart = new BluetoothLeUart(getApplicationContext(), mMasterControlUnit);
}//OnCreate

private void BuildETStepSize() {
etStepSize = findViewById(R.id.etStepSIze);
etStepSize.setFilters(new InputFilter[]{new InputFilterMinMax("1","255")});
etStepSize.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {

}

@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {

}

@Override
public void afterTextChanged(Editable s) {
String stepSizeString = etStepSize.getText().toString();
if ( (stepSizeString != null) && (!stepSizeString.equals("")) )
{
stepSize = Integer.parseInt(stepSizeString);
stepSizeLegal = true;
Log.d("MyDebug myCalibrate StepSize", "New Stepsize: " + stepSize);
}
else
{
stepSizeLegal = false; //PREVENT INCREMENT DECREMENT COMMANDS BEING ALLOWED WHILST STEPSIZE IS NOT LEGAL
Log.d("MyDebug myCalibrate StepSize", "Stepsize not legal");
}
Log.d("MyDebug myCalibrate StepSize", "Resulting Stepsize: " + stepSize);

}
});
}
private void BuildButtons()
{
// Reset Button
btnReset = findViewById(R.id.btnReset);
btnReset.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(getApplicationContext(),"Resetting lights to initialisation position", Toast.LENGTH_LONG).show();
byte[] message;
message = hexStringToByteArray("0104FFFA");
// If this causes issues ensure lightcount has been set correctly
uart.send(message); // Send a message to the master control unit telling it to set all lights to 0 position.
maintainBTConnection();
}
});

// Confirm Button
btnConfirm= findViewById(R.id.btnConfirm);
btnConfirm.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v)
{
Toast.makeText(getApplicationContext(),"Saving current positions to profile " + (selectedProfile + 1), Toast.LENGTH_LONG).show(); // Could lose the +1?

byte[] message;
String messageHexString = "0505";
messageHexString += String.format("%02X", selectedProfile);
messageHexString += String.format("%02X", lightCount);
byte[] arrayNoCS = hexStringToByteArray(messageHexString); // CONVERT string to byte array,
byte finalByte = BitbashTools.CalculateCheckSum(arrayNoCS); // get checksum from array
String checkSumHexS = String.format("%02X", finalByte); // Get hexs for checksum
messageHexString += checkSumHexS; // Append checksum to array string
message = hexStringToByteArray(messageHexString); // and Convert array to hex string
uart.send(message); // Send message to master telling it to save the current position of each light to the EEPROM
maintainBTConnection();
}

});

ivLightToggle = findViewById(R.id.ivLightToggle);
ivLightToggle.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
byte[] message;
if (lightState == false)
{
// turn lights on
message = hexStringToByteArray("0704ffFC");
lightState = true;
}
else
{
// turn lights off
message = hexStringToByteArray("07040003");
lightState = false;
}

uart.send(message);
maintainBTConnection();
}
});
}
private void BuildLightControlRV()
{
// Build light RV
for (int i = 0; i < lightCount; i++)
{
LightConfig light = new LightConfig(i);
myLights.add(light);
}

mRVCalibrate = findViewById(R.id.rvLightList);
mRVCalibrate.setHasFixedSize(true);
mLightConfigLayoutManager = new LinearLayoutManager(getBaseContext());
mLightConfigAdapter = new LightConfigAdapter(myLights);
//private DividerItemDecoration theSplitta(, DividerItemDecoration.HORIZONTAL);

mRVCalibrate.setLayoutManager(mLightConfigLayoutManager);
mRVCalibrate.setAdapter(mLightConfigAdapter);

mLightConfigAdapter.setOnItemClickListener(new LightConfigAdapter.OnItemClickListener() {
@Override
public void onItemClick(int position) {
// This is for the whole card, no action is needed here.
}

@Override
public void onUpClick(int position) {
if (stepSizeLegal) {
// IncrementAngle(position)

byte[] message;
String messageHexString = "0305";
messageHexString += String.format("%02X", position);
messageHexString += String.format("%02X", stepSize);
byte[] arrayNoCS = hexStringToByteArray(messageHexString); // CONVERT string to byte array,
byte finalByte = BitbashTools.CalculateCheckSum(arrayNoCS); // get checksum from array
String checkSumHexS = String.format("%02X", finalByte); // Get hexs for checksum
messageHexString += checkSumHexS; // Append checksum to array string
message = hexStringToByteArray(messageHexString); // and Convert array to hex string

Toast.makeText(getApplicationContext(), "Incrementing light " + position + " by " + stepSize, Toast.LENGTH_SHORT).show();

uart.send(message); //
maintainBTConnection();
} else {
Toast.makeText(getApplicationContext(), "StepSize Value not allowed", Toast.LENGTH_SHORT).show();
}
}

@Override
public void onDownClick(int position) {
if (stepSizeLegal)
{
// TODO: DecrementAngle(position)
byte[] message;
String messageHexString = "0405";
messageHexString += String.format("%02X", position);
messageHexString += String.format("%02X", stepSize);
byte[] arrayNoCS = hexStringToByteArray(messageHexString); // CONVERT string to byte array,
byte finalByte = BitbashTools.CalculateCheckSum(arrayNoCS); // get checksum from array
String checkSumHexS = String.format("%02X", finalByte); // Get hexs for checksum
messageHexString += checkSumHexS; // Append checksum to array string
message = hexStringToByteArray(messageHexString); // and Convert array to hex string
// uart.send(message); //

Toast.makeText(getApplicationContext(), "Decrementing light " + position + " by " + stepSize, Toast.LENGTH_SHORT).show();

uart.send(message); //
maintainBTConnection();
} else {
Toast.makeText(getApplicationContext(), "StepSize Value not allowed", Toast.LENGTH_SHORT).show();
}
}
});
}
private void BuildProfileSpinner()
{
// Set up Spinner
spnrProfileSelector = findViewById(R.id.spnrProfiles);
ArrayAdapter spinnerAdapter = ArrayAdapter.createFromResource(this,R.array.profiles, android.R.layout.simple_spinner_item);
spinnerAdapter.setDropDownViewResource(R.layout.support_simple_spinner_dropdown_item);
spnrProfileSelector.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView parent, View view, int position, long id) {
profileSwitch(position); // SEND SWITCH ACTIVE PROFILE COMMAND TO MASTER UNIT
}

@Override
public void onNothingSelected(AdapterView parent) {} /// We don't care about this
});
spnrProfileSelector.setAdapter(spinnerAdapter);
}
public void profileSwitch(int profile)
{
selectedProfile = profile;
// TODO: TELL THE LIGHT SYSTEM WE ARE JUMPING TO A DIFFERENT PROFILE
byte[] message;
String messageHexString = "0205";
messageHexString += String.format("%02X", profile);
messageHexString += String.format("%02X", lightCount);
byte[] arrayNoCS = hexStringToByteArray(messageHexString); // CONVERT string to byte array,
byte finalByte = BitbashTools.CalculateCheckSum(arrayNoCS); // get checksum from array
String checkSumHexS = String.format("%02X", finalByte); // Get hexs for checksum
messageHexString += checkSumHexS; // Append checksum to array string
message = hexStringToByteArray(messageHexString); // and Convert array to hex string

Toast.makeText(getApplicationContext(), "Switching to profile " +(profile+1) + ", assigning " + lightCount + " lights to temporary profile", Toast.LENGTH_SHORT).show();

uart.send(message); //SWITCH TO TEMP PROFILE
maintainBTConnection();

Log.d("MyDebug Calibrate", "Profile selected: " + profile + " (Called "+(profile+1) + ")");
}

@Override
protected void onResume() {
super.onResume();

// RequestGPS(); // todo: This broke. We need a new one.
RequestBluetooth();
mBluetoothAdapter.cancelDiscovery(); // Save memory, make sure we aren't still searching0
// isConnected = false;

etStepSize.setText(etStepSize.toString());

IntentFilter connectFilter = new IntentFilter(BluetoothDevice.ACTION_ACL_CONNECTED);
registerReceiver(mConnectReceiver,connectFilter);
IntentFilter disconnectFilter = new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED);
registerReceiver(mDisconnectReceiver,connectFilter);
IntentFilter bondFilter = new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
registerReceiver(mBondStateReceiver,connectFilter);

Toast.makeText(getApplicationContext(), "ATTEMPTING CONNECTION", Toast.LENGTH_LONG).show();
uart.registerCallback(this);
uart.justFingConnect();
//
}

@Override
protected void onStop() {
super.onStop();
uart.unregisterCallback(this);
uart.disconnect();
}

private BroadcastReceiver mConnectReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.d("MyDebug Calibrate Connect", "Device Connected");
isConnected = true;
UpdateConnectStrings(isConnected);
}
};

private BroadcastReceiver mDisconnectReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.d("MyDebug Calibrate Connect", "Device Disconnected");
isConnected = false;
UpdateConnectStrings(isConnected);
}
};

private BroadcastReceiver mBondStateReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.d("MyDebug Calibrate Connect", "BondState Changed");
if (mMasterControlUnit.getBondState() == BluetoothDevice.BOND_BONDED)
{
Log.d("MyDebug Calibrate Connect", "BondState Bonded");
}
if (mMasterControlUnit.getBondState() == BluetoothDevice.BOND_BONDING)
{
Log.d("MyDebug Calibrate Connect", "BondState Bonding");
}
if (mMasterControlUnit.getBondState() == BluetoothDevice.BOND_NONE)
{
Log.d("MyDebug Calibrate Connect", "BondState NONE");
}
}
};

private Boolean GetConnectStatus(BluetoothDevice device) {
try {
Method m = device.getClass().getMethod("isConnected", (Class[]) null);
boolean connected = (boolean) m.invoke(device, (Object[]) null);
isConnected = connected;
return connected;
} catch (Exception e) {
throw new IllegalStateException(e);
}
}

@Override
protected void onDestroy()
{
super.onDestroy();
// TODO: Unregister recievers

unregisterReceiver(mBondStateReceiver);
unregisterReceiver(mConnectReceiver);
unregisterReceiver(mDisconnectReceiver);
unpairDevice(mMasterControlUnit);
}

public void RequestBluetooth()
{
final BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (!bluetoothAdapter.isEnabled())
{
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, 69);
Toast.makeText(getApplicationContext(), "Bluetooth Turned ON", Toast.LENGTH_SHORT).show();
}
}
public static boolean isGpsEnabled(){
return mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
}
public void RequestGPS()
{
if(!isGpsEnabled()){
LocationRequest locationRequest = LocationRequest.create();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
.addLocationRequest(locationRequest);

builder.setAlwaysShow(true); //this displays dialog box like Google Maps with two buttons - OK and NO,THANKS

Task task;
task = LocationServices.getSettingsClient(this).checkLocationSettings(builder.build());

task.addOnCompleteListener(new OnCompleteListener() {
@Override
public void onComplete(Task task) {
try {
LocationSettingsResponse response = task.getResult(ApiException.class);
// All location settings are satisfied. The client can initialize location
// requests here.
} catch (ApiException exception) {
switch (exception.getStatusCode()) {
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
// Location settings are not satisfied. But could be fixed by showing the
// user a dialog.
try {
// Cast to a resolvable exception.
ResolvableApiException resolvable = (ResolvableApiException) exception;
// Show the dialog by calling startResolutionForResult(),
// and check the result in onActivityResult().
resolvable.startResolutionForResult(
CalibrateLightsActivity.this,
REQUEST_CHECK_SETTINGS);
} catch (IntentSender.SendIntentException e) {
// Ignore the error.
} catch (ClassCastException e) {
// Ignore, should be an impossible error.
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
// Location settings are not satisfied. However, we have no way to fix the
// settings so we won't show the dialog.
break;
}
}
}
});
} else {
//Toast.makeText(getApplicationContext(), "Location enabled, this is a security requirement of bluetooth communication.", Toast.LENGTH_LONG).show();
}
}

public void UpdateConnectStrings(boolean Connected)
{
connectSwitch.setActivated(false);

tvTargetDevice.setText("Target Device: " + targetDevice.mScanResult.getDevice().getName());
String connectionString;
tvConnectStatus.setText(getString(R.string.connectStatus) + " Undetermined");
if (Connected == true)
{
Log.d("MyDebug Calibrate Switch", "I should activate");
connectionString = " Connected";
connectSwitch.setChecked(true);
}
else
{
Log.d("MyDebug Calibrate Switch", "I should unswitch");
connectionString = " Not Connected";
connectSwitch.setChecked(false);
}

if (connectSwitch.isChecked())
{
connectSwitch.setText("Disconnect");
}
else
{
connectSwitch.setText("Connect");
}
tvConnectStatus.setText(getString(R.string.connectStatus) + connectionString);

connectSwitch.setActivated(true);
}

private void unpairDevice(BluetoothDevice device) {
try {
Method m = device.getClass()
.getMethod("removeBond", (Class[]) null);
m.invoke(device, (Object[]) null);
} catch (Exception e) {
Log.e("MyDebug Calibrate Connect", "Removing bond failed: " + e.getMessage());
}
}

// ADAFRUIT METHODS
// Write some text to the messages text view.
// Care is taken to do this on the main UI thread so writeLine can be called from any thread
// (like the BTLE callback).

// TODO: ADAPT THIS TO ALLOW MESSAGES TO BE PASSED TO THIS ACTIVITY
private void writeLine(final CharSequence text) {
runOnUiThread(new Runnable() {
@Override
public void run() {
// messages.append(text);
// messages.append("\n");

// TODO: PARSE RESPONSES FROM THE TARGET (IF ANY)
}
});
}

// UART Callback event handlers.
@Override
public void onConnected(BluetoothLeUart uart) {
// Called when UART device is connected and ready to send/receive data.
// writeLine("Connected!");
// Enable the send button
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), "CONNECTION ESTABLISHED", Toast.LENGTH_LONG).show();
isConnected = true;
UpdateConnectStrings(true);

//TODO: WE PROBABLY NEED TO SEND SET PROFILE - WHEN THE CONNECTION IS ESTABLISHED
}
});
}

@Override
public void onConnectFailed(BluetoothLeUart uart) {
// Called when some error occured which prevented UART connection from completing.
writeLine("Error connecting to device!");
runOnUiThread(new Runnable() {
@Override
public void run() {
isConnected = false;
UpdateConnectStrings(false);
Toast.makeText(getApplicationContext(), "CONNECTION FAILED", Toast.LENGTH_LONG).show();
}
});
}

@Override
public void onDisconnected(BluetoothLeUart uart) {
// Called when the UART device disconnected.

runOnUiThread(new Runnable() {
@Override
public void run() {
isConnected = false;
UpdateConnectStrings(false);
Toast.makeText(getApplicationContext(), "DISCONNECTED", Toast.LENGTH_LONG).show();

}
});
}

@Override
public void onReceive(BluetoothLeUart uart, BluetoothGattCharacteristic rx) {

// Called when data is received by the UART.
Toast.makeText(getApplicationContext(), "Received: " + rx.getValue().toString(), Toast.LENGTH_LONG).show();
// writeLine("Received: " + rx.getStringValue(0));
// TODO: PARSE THIS DATA
}

@Override
public void onDeviceFound(BluetoothDevice device) {
// Called when a UART device is discovered (after calling startScan).
// writeLine("Found device : " + device.getAddress());
// writeLine("Waiting for a connection ...");

if (device.equals(mMasterControlUnit))
{
Toast.makeText(getApplicationContext(), "TARGET DEVICE FOUND, ATTEMPTING CONNECTION", Toast.LENGTH_LONG).show();
uart.stopScan();
}
else
{
Toast.makeText(getApplicationContext(), "DEVICE FOUND, ISN'T RELEVANT", Toast.LENGTH_LONG).show();
}

}

@Override
public void onDeviceInfoAvailable() {

// writeLine(uart.getDeviceInfo()); // DON'T NEED THIS?
}
}`

Contributor guide

No contributing guide indexed for this repository

Research direction

Start by reproducing the Android 10 failure and tracing the send and callback flow from CalibrateLightsActivity through BluetoothLeUart.java, especially uart.send() and maintainBTConnection(). Done means the application can send more than eight transmissions without stopping, while the existing third-party app behavior remains unaffected.

Written by the indexing model from the issue text.

Assessment

Tech stack
android, java
Domain
mobile
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
28/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.