Я работаю над приложением, которое может подключаться к устройству adafruit flora BLE для получения информации от него. Я хочу, чтобы приложение отображало список найденных устройств, и при нажатии на элемент в представлении списка устанавливается соединение и данные могут быть получены. В конечном счете, я хочу перенести указанные данные в другой вид деятельности в режиме реального времени (если это возможно). Происходят некоторые вещи, которые я не понимаю, и я надеюсь, что кто-то может пролить свет на это.
- При сканировании устройств в списке отображаются их, но их кратно каждому.
- По какой-то причине
onPause
и onResume
делают вид списка сбойным (отображает устройства, а затем удаляет их)
- Как узнать, когда есть соединение?
- Когда в моем коде есть getRemoteDevice, я получаю ошибку времени выполнения (попытка вызвать виртуальный метод 'android.bluetooth.BluetoothDevice android.bluetooth.BluetoothAdapter.getRemoteDevice (java.lang.String)' для ссылки на нулевой объект)
- Когда я пытаюсь использовать фильтры и настройки в методе startScan, в моем списке ничего не появляется, я также пробовал нулевые фильтры с настройками и все еще ничего.
import android.annotation.SuppressLint;
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.BluetoothProfile;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.content.Intent;
import android.os.Build;
import android.os.ParcelUuid;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import no.nordicsemi.android.support.v18.scanner.BluetoothLeScannerCompat;
import no.nordicsemi.android.support.v18.scanner.ScanFilter;
import no.nordicsemi.android.support.v18.scanner.ScanResult;
import no.nordicsemi.android.support.v18.scanner.ScanSettings;
public class BluetoothDiscovery extends AppCompatActivity {
private String TAG = "Bluetooth Device";
private int REQUEST_ENABLE_BT = 5;
private BluetoothAdapter mBluetoothAdapter;
private BluetoothLeScannerCompat scanner;
private ScanSettings settings;
private UUID baseUUID = UUID.fromString("6e400001-b5a3-f393-e0a9-e50e24dcca9e"); // service UUID
private UUID txUUID = UUID.fromString("6e400002-b5a3-f393-e0a9-e50e24dcca9e"); // TX UUID characteristic
private UUID rxUUID = UUID.fromString("6e400003-b5a3-f393-e0a9-e50e24dcca9e"); // RX UUID characteristic
private ScanFilter scanFilter;
private BluetoothDevice device, mdevice;
private BluetoothGatt mGatt;
private boolean mScanning = false;
private ArrayList<deviceShowFormat> foundDevices = new ArrayList<>();
formattingAdapter BTadapter;
Button scanButton;
TextView fancyWords;
ListView deviceList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bluetooth_discovery);
mBluetoothAdapter.getDefaultAdapter();
scanButton = findViewById(R.id.scanButt);
scanButton.setText(getString(R.string.notScanning));
fancyWords = findViewById(R.id.discoverText);
fancyWords.setText(getString(R.string.nonScanTitle));
deviceList = findViewById(R.id.deviceList);
BTadapter = new formattingAdapter(BluetoothDiscovery.this, foundDevices);
deviceList.setAdapter(BTadapter);
scanner = BluetoothLeScannerCompat.getScanner();
settings = new ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_BALANCED).setReportDelay(500).build();
scanFilter = new ScanFilter.Builder().setServiceUuid(new ParcelUuid(baseUUID)).build();
//scanner.startScan(Arrays.asList(scanFilter), settings, mScanCallback);
deviceList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@SuppressLint("LongLogTag")
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
deviceShowFormat mBTDevice = foundDevices.get(i);
BluetoothDevice Device = mBTDevice.get_device();
String deviceName = mBTDevice.get_device_name();
String deviceAddress = mBTDevice.get_device_address();
Log.d(TAG, "Selected device: " + Device.toString());
Log.d(TAG, "Selected device name: " + deviceName);
Log.d(TAG, "Selected device address: " + deviceAddress);
//BluetoothDevice deviceConnect = mBluetoothAdapter.getRemoteDevice(deviceAddress);
//deviceConnect.createBond();
mGatt = Device.connectGatt(BluetoothDiscovery.this, false, mGattCallback);
Toast.makeText(BluetoothDiscovery.this, "Selected device: " + deviceName, Toast.LENGTH_SHORT).show();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
Device.createBond();
}
Log.d(TAG, "" + Device.getBondState());
if(Device.getBondState() == BluetoothDevice.BOND_BONDED){
Toast.makeText(BluetoothDiscovery.this, "Bluetooth device connected successfully", Toast.LENGTH_SHORT).show();
}
mGatt.getServices();
mGatt.getConnectedDevices();
Log.d("THIS IS THE DEVICES UUID", String.valueOf(Device.getUuids()));
Log.d("DEVICE SERVICES", String.valueOf(mGatt.getServices()));
}
});
}
private final no.nordicsemi.android.support.v18.scanner.ScanCallback mScanCallback = new no.nordicsemi.android.support.v18.scanner.ScanCallback() {
@Override
public void onScanResult(int callbackType, ScanResult result) {
super.onScanResult(callbackType, result);
Log.i("onScanResult", "device detected");
device = result.getDevice();
String deviceName = device.getName();
String deviceAddress = device.getAddress();
Log.d(TAG, "Scanned device: " + device.toString());
Log.d(TAG, "Scanned device name: " + deviceName);
Log.d(TAG, "Scanned device address: " + deviceAddress);
foundDevices.add(new deviceShowFormat(device, deviceName, deviceAddress));
BTadapter.notifyDataSetChanged();
}
};
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
super.onConnectionStateChange(gatt, status, newState);
Log.i("onConnectionStateChange", "State Changed from: " + status + " to " + newState);
if (newState == BluetoothProfile.STATE_CONNECTED){
Toast.makeText(BluetoothDiscovery.this, "Attempting service discovery", Toast.LENGTH_SHORT).show();
Log.i("onConnectionStateChange", "Attempting service discovery: " + gatt.discoverServices());
gatt.discoverServices();
} else if (newState == BluetoothProfile.STATE_DISCONNECTED){
Toast.makeText(BluetoothDiscovery.this, "Connection has been terminated", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status){
super.onServicesDiscovered(gatt, status);
Log.i("onServicesDiscovered", "Hey, we found a service");
if (status != BluetoothGatt.GATT_SUCCESS){
// Handle error
Log.d("onServicesDiscovered" , "" + status);
return;
}
BluetoothGattCharacteristic characteristic = gatt.getService(baseUUID).getCharacteristic(rxUUID);
gatt.setCharacteristicNotification(characteristic, true);
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(txUUID);
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
gatt.writeDescriptor(descriptor);
}
@Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status){
Log.i("onCharacteristicRead", "Characteristic has been read");
readCounterCharacteristic(characteristic);
}
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
if (mGatt.writeCharacteristic(characteristic)){
Log.d("Characteristic changed", "Possibly looking for a write");
}
if (mGatt.readCharacteristic(characteristic)){
readCounterCharacteristic(characteristic);
}
}
private void readCounterCharacteristic(BluetoothGattCharacteristic characteristic){
if (mGatt.readCharacteristic(characteristic)){
byte[] data = characteristic.getValue();
Log.d("READ DATA", data.toString());
}
// if (rxUUID.equals(characteristic.getUuid())){
// //byte[] data = characteristic.getValue();
// byte[] data = mGatt.readCharacteristic(characteristic);
// //int value = Ints.fromByteArray(data);
// Log.d("READ DATA", data.toString());
// }
}
};
public void toggleScan(View view){
mScanning = !mScanning;
if(mScanning){
scanner.startScan(mScanCallback); //Arrays.asList(scanFilter) null, settings,
scanButton.setText(getString(R.string.scanInProgress));
fancyWords.setText(getString(R.string.ScanTitle));
} else {
scanner.stopScan(mScanCallback);
scanButton.setText(getString(R.string.notScanning));
}
}
// @Override
// public void onPause(){
// super.onPause();
//
//// if(mScanning){
//// mScanning = !mScanning;
// scanner.stopScan(mScanCallback);
//// }
//
// //Empty Adapter
// //BTadapter.clear();
// //BTadapter.notifyDataSetChanged();
//
// //mdevice = device;
//
// }
//
// @Override
// public void onResume(){
// super.onResume();
//
// if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
// Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
// startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
// }
//
// //device = mdevice;
// }
}
Код является вторым действием в моем приложении, в первом Bluetooth инициализируется и что-нет. Приведенный выше код работает, но я не получаю никаких данных с устройства и не уверен, что оно действительно подключено. из логов, показанных в коде, я получаю:
Logcat
Logcat2
Ресурсы, которые я использую:
https://github.com/NordicSemiconductor/Android-Scanner-Compat-Library
https://learn.adafruit.com/introducing-the-adafruit-bluefruit-le-uart-friend/uart-service
http://nilhcem.com/android-things/bluetooth-low-energy