大家好我正在开发Android应用程序,需要连接到ble设备并通过ble发送数据。我已经尝试扫描并在列表上显示扫描的设备工作正常。问题是连接到扫描的设备。这是我的主要活动代码的一部分。
public class main_activity extends Activity implements BluetoothLeUart.Callback{
public ImageButton fabbutton;
Activity activity;
private ArrayAdapter<String> adapter;
private ArrayList<String> liste,devicedata;
private ListView list;
public EditText input;
String name,address,Devicename,Deviceaddress,datadevicename;
private BluetoothGatt mBluetoothGatt;
public static String SelectedDeviceName;
private BluetoothAdapter mBluetoothAdapter;
public ArrayList<BluetoothDevice> dev;
private Handler mHandler;
private static final int REQUEST_ENABLE_BT = 1;
private static final long SCAN_PERIOD = 10000;
BluetoothLeUart uart = new BluetoothLeUart(this);
public static BluetoothDevice device;
private BluetoothGatt mGatt;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_activity);
fabbutton = (ImageButton) findViewById(R.id.fabbutton);
activity = this;
mHandler = new Handler();
final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
scanLeDevice(true);
mActionBar.setTitle(Html.fromHtml("<font color='#727272'>Board List</font>"));
list = (ListView) findViewById(R.id.list);
liste = new ArrayList<String>();
liste.clear();
adapter = new ArrayAdapter<String>(list.getContext(), android.R.layout.simple_list_item_1, liste);
list.setAdapter(adapter);
// On Click Listener for Paired BLE Device List
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
SelectedDeviceName = list.getItemAtPosition(position).toString();
String[] splitString = SelectedDeviceName.split(" ");
Devicename = splitString[0];
Deviceaddress = splitString[1];
device = mBluetoothAdapter.getRemoteDevice(Deviceaddress);
Toast.makeText(getApplicationContext(),device.toString(),Toast.LENGTH_SHORT).show();
//device.connectGatt(getApplicationContext(), true, gattCallback);
uart.connectFirstAvailable();// this is where i start connecting process.
}
});
这是我的BluetoothLeUart类的代码
public class BluetoothLeUart extends BluetoothGattCallback implements BluetoothAdapter.LeScanCallback {
public String mDeviceAddress;
// UUIDs for UART service and associated characteristics.
public static UUID UART_UUID = UUID.fromString("6E400001-B5A3-F393-E0A9-E50E24DCCA9E");
public static UUID TX_UUID = UUID.fromString("6E400002-B5A3-F393-E0A9-E50E24DCCA9E");
public static UUID RX_UUID = UUID.fromString("6E400003-B5A3-F393-E0A9-E50E24DCCA9E");
// UUID for the UART BTLE client characteristic which is necessary for notifications.
public static UUID CLIENT_UUID = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
// UUIDs for the Device Information service and associated characeristics.
public static UUID DIS_UUID = UUID.fromString("0000180a-0000-1000-8000-00805f9b34fb");
public static UUID DIS_MANUF_UUID = UUID.fromString("00002a29-0000-1000-8000-00805f9b34fb");
public static UUID DIS_MODEL_UUID = UUID.fromString("00002a24-0000-1000-8000-00805f9b34fb");
public static UUID DIS_HWREV_UUID = UUID.fromString("00002a26-0000-1000-8000-00805f9b34fb");
public static UUID DIS_SWREV_UUID = UUID.fromString("00002a28-0000-1000-8000-00805f9b34fb");
// Internal UART state.
private Context context;
private WeakHashMap<Callback, Object> callbacks;
private BluetoothAdapter adapter;
private BluetoothGatt gatt;
private BluetoothGattCharacteristic tx;
private BluetoothGattCharacteristic rx;
private boolean connectFirst;
private boolean writeInProgress; // Flag to indicate a write is currently in progress
// Device Information state.
private BluetoothGattCharacteristic disManuf;
private BluetoothGattCharacteristic disModel;
private BluetoothGattCharacteristic disHWRev;
private BluetoothGattCharacteristic disSWRev;
private boolean disAvailable;
// Queues for characteristic read (synchronous)
private Queue<BluetoothGattCharacteristic> readQueue;
// Interface for a BluetoothLeUart client to be notified of UART actions.
public interface Callback {
public void onConnected(BluetoothLeUart uart);
public void onConnectFailed(BluetoothLeUart uart);
public void onDisconnected(BluetoothLeUart uart);
public void onReceive(BluetoothLeUart uart, BluetoothGattCharacteristic rx);
public void onDeviceFound(BluetoothDevice device);
public void onDeviceInfoAvailable();
}
public BluetoothLeUart(Context context) {
super();
this.context = context;
this.callbacks = new WeakHashMap<Callback, Object>();
this.adapter = BluetoothAdapter.getDefaultAdapter();
this.gatt = null;
this.tx = null;
this.rx = null;
this.disManuf = null;
this.disModel = null;
this.disHWRev = null;
this.disSWRev = null;
this.disAvailable = false;
this.connectFirst = false;
this.writeInProgress = false;
this.readQueue = new ConcurrentLinkedQueue<BluetoothGattCharacteristic>();
}
// Return instance of BluetoothGatt.
public BluetoothGatt getGatt() {
return gatt;
}
// Return true if connected to UART device, false otherwise.
public boolean isConnected() {
return (tx != null && rx != null);
}
public String getDeviceInfo() {
if (tx == null || !disAvailable ) {
// Do nothing if there is no connection.
return "";
}
StringBuilder sb = new StringBuilder();
sb.append("Manufacturer : " + disManuf.getStringValue(0) + "\n");
sb.append("Model : " + disModel.getStringValue(0) + "\n");
sb.append("Firmware : " + disSWRev.getStringValue(0) + "\n");
return sb.toString();
};
public boolean deviceInfoAvailable() { return disAvailable; }
// Send data to connected UART device.
public void send(byte[] data) {
if (tx == null || data == null || data.length == 0) {
// Do nothing if there is no connection or message to send.
return;
}
// Update TX characteristic value. Note the setValue overload that takes a byte array must be used.
tx.setValue(data);
writeInProgress = true; // Set the write in progress flag
gatt.writeCharacteristic(tx);
// ToDo: Update to include a timeout in case this goes into the weeds
while (writeInProgress); // Wait for the flag to clear in onCharacteristicWrite
}
public void registerCallback(Callback callback) {
callbacks.put(callback, null);
}
public void unregisterCallback(Callback callback) {
callbacks.remove(callback);
}
// Disconnect to a device if currently connected.
public void disconnect() {
if (gatt != null) {
gatt.disconnect();
}
gatt = null;
tx = null;
rx = null;
}
// Stop any in progress UART device scan.
public void stopScan() {
if (adapter != null) {
adapter.stopLeScan(this);
}
}
// Start scanning for BLE UART devices. Registered callback's onDeviceFound method will be called
// when devices are found during scanning.
public void startScan() {
if (adapter != null) {
adapter.startLeScan(this);
Toast.makeText(context,"Entered",Toast.LENGTH_SHORT).show();
}
}
// Connect to the first available UART device.
public void connectFirstAvailable() {
// Disconnect to any connected device.
disconnect();
// Stop any in progress device scan.
stopScan();
// Start scan and connect to first available device.
connectFirst = true;
startScan();
}
// Handlers for BluetoothGatt and LeScan events.
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
super.onConnectionStateChange(gatt, status, newState);
if (newState == BluetoothGatt.STATE_CONNECTED) {
if (status == BluetoothGatt.GATT_SUCCESS) {
// Connected to device, start discovering services.
if (!gatt.discoverServices()) {
// Error starting service discovery.
connectFailure();
}
}
else {
// Error connecting to device.
connectFailure();
}
}
else if (newState == BluetoothGatt.STATE_DISCONNECTED) {
// Disconnected, notify callbacks of disconnection.
rx = null;
tx = null;
notifyOnDisconnected(this);
}
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
super.onServicesDiscovered(gatt, status);
// Notify connection failure if service discovery failed.
if (status == BluetoothGatt.GATT_FAILURE) {
connectFailure();
return;
}
// Save reference to each UART characteristic.
tx = gatt.getService(UART_UUID).getCharacteristic(TX_UUID);
rx = gatt.getService(UART_UUID).getCharacteristic(RX_UUID);
// Setup notifications on RX characteristic changes (i.e. data received).
// First call setCharacteristicNotification to enable notification.
if (!gatt.setCharacteristicNotification(rx, true)) {
// Stop if the characteristic notification setup failed.
connectFailure();
return;
}
// Next update the RX characteristic's client descriptor to enable notifications.
BluetoothGattDescriptor desc = rx.getDescriptor(CLIENT_UUID);
if (desc == null) {
// Stop if the RX characteristic has no client descriptor.
connectFailure();
return;
}
desc.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
if (!gatt.writeDescriptor(desc)) {
// Stop if the client descriptor could not be written.
connectFailure();
return;
}
// Notify of connection completion.
notifyOnConnected(this);
}
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
super.onCharacteristicChanged(gatt, characteristic);
notifyOnReceive(this, characteristic);
}
@Override
public void onCharacteristicRead (BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicRead(gatt, characteristic, status);
if (status == BluetoothGatt.GATT_SUCCESS) {
//Log.w("DIS", characteristic.getStringValue(0));
// Check if there is anything left in the queue
BluetoothGattCharacteristic nextRequest = readQueue.poll();
if(nextRequest != null){
// Send a read request for the next item in the queue
gatt.readCharacteristic(nextRequest);
}
else {
// We've reached the end of the queue
disAvailable = true;
notifyOnDeviceInfoAvailable();
}
}
else {
//Log.w("DIS", "Failed reading characteristic " + characteristic.getUuid().toString());
}
}
@Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicWrite(gatt, characteristic, status);
if (status == BluetoothGatt.GATT_SUCCESS) {
// Log.d(TAG,"Characteristic write successful");
}
writeInProgress = false;
}
@Override
public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
Toast.makeText(context, "onLe Entered", Toast.LENGTH_SHORT).show();
if (!parseUUIDs(scanRecord).contains(UART_UUID)) {
return;
}
// Notify registered callbacks of found device.
notifyOnDeviceFound(device);
// Connect to first found device if required.
if (connectFirst) {
// Stop scanning for devices.
// Prevent connections to future found devices.
if (mDeviceAddress.equals(device.getAddress())) {
stopScan();
connectFirst = false;
// Connect to device.
gatt = device.connectGatt(context, true, this);
}
}
}
// Private functions to simplify the notification of all callbacks of a certain event.
private void notifyOnConnected(BluetoothLeUart uart) {
for (Callback cb : callbacks.keySet()) {
if (cb != null) {
cb.onConnected(uart);
}
}
}
private void notifyOnConnectFailed(BluetoothLeUart uart) {
for (Callback cb : callbacks.keySet()) {
if (cb != null) {
cb.onConnectFailed(uart);
}
}
}
private void notifyOnDisconnected(BluetoothLeUart uart) {
for (Callback cb : callbacks.keySet()) {
if (cb != null) {
cb.onDisconnected(uart);
}
}
}
private void notifyOnReceive(BluetoothLeUart uart, BluetoothGattCharacteristic rx) {
for (Callback cb : callbacks.keySet()) {
if (cb != null ) {
cb.onReceive(uart, rx);
}
}
}
private void notifyOnDeviceFound(BluetoothDevice device) {
for (Callback cb : callbacks.keySet()) {
if (cb != null) {
cb.onDeviceFound(device);
}
}
}
private void notifyOnDeviceInfoAvailable() {
for (Callback cb : callbacks.keySet()) {
if (cb != null) {
cb.onDeviceInfoAvailable();
}
}
}
// Notify callbacks of connection failure, and reset connection state.
private void connectFailure() {
rx = null;
tx = null;
notifyOnConnectFailed(this);
}
private List<UUID> parseUUIDs(final byte[] advertisedData) {
List<UUID> uuids = new ArrayList<UUID>();
int offset = 0;
while (offset < (advertisedData.length - 2)) {
int len = advertisedData[offset++];
if (len == 0)
break;
int type = advertisedData[offset++];
switch (type) {
case 0x02: // Partial list of 16-bit UUIDs
case 0x03: // Complete list of 16-bit UUIDs
while (len > 1) {
int uuid16 = advertisedData[offset++];
uuid16 += (advertisedData[offset++] << 8);
len -= 2;
uuids.add(UUID.fromString(String.format("%08x-0000-1000-8000-00805f9b34fb", uuid16)));
}
break;
case 0x06:// Partial list of 128-bit UUIDs
case 0x07:// Complete list of 128-bit UUIDs
// Loop through the advertised 128-bit UUID's.
while (len >= 16) {
try {
// Wrap the advertised bits and order them.
ByteBuffer buffer = ByteBuffer.wrap(advertisedData, offset++, 16).order(ByteOrder.LITTLE_ENDIAN);
long mostSignificantBit = buffer.getLong();
long leastSignificantBit = buffer.getLong();
uuids.add(new UUID(leastSignificantBit,
mostSignificantBit));
} catch (IndexOutOfBoundsException e) {
// Defensive programming.
//Log.e(LOG_TAG, e.toString());
continue;
} finally {
// Move the offset to read the next uuid.
offset += 15;
len -= 16;
}
}
break;
default:
offset += (len - 1);
break;
}
}
return uuids;
}
}
这是我的BluetoothLeService类的代码
public class BluetoothLeService extends Service {
private final static String TAG = BluetoothLeService.class.getSimpleName();
private BluetoothManager mBluetoothManager;
private BluetoothAdapter mBluetoothAdapter;
private String mBluetoothDeviceAddress;
public BluetoothGatt mBluetoothGatt;
private int mConnectionState =STATE_DISCONNECTED;
private static final int STATE_DISCONNECTED = 0;
private static final int STATE_CONNECTING = 1;
private static final int STATE_CONNECTED = 2;
public final static String ACTION_GATT_CONNECTED =
"com.example.bluetooth.le.ACTION_GATT_CONNECTED";
public final static String ACTION_GATT_DISCONNECTED =
"com.example.bluetooth.le.ACTION_GATT_DISCONNECTED";
public final static String ACTION_GATT_SERVICES_DISCOVERED =
"com.example.bluetooth.le.ACTION_GATT_SERVICES_DISCOVERED";
public final static String ACTION_DATA_AVAILABLE =
"com.example.bluetooth.le.ACTION_DATA_AVAILABLE";
public final static String EXTRA_DATA =
"com.example.bluetooth.le.EXTRA_DATA";
// UUIDs for UART service and associated characteristics.
public static UUID UART_UUID = UUID.fromString("6E400001-B5A3-F393-E0A9-E50E24DCCA9E");
public static UUID TX_UUID = UUID.fromString("6E400002-B5A3-F393-E0A9-E50E24DCCA9E");
public static UUID RX_UUID = UUID.fromString("6E400003-B5A3-F393-E0A9-E50E24DCCA9E");
// UUID for the UART BTLE client characteristic which is necessary for notifications.
public static UUID CLIENT_UUID = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
// UUIDs for the Device Information service and associated characeristics.
public static UUID DIS_UUID = UUID.fromString("0000180a-0000-1000-8000-00805f9b34fb");
public static UUID DIS_MANUF_UUID = UUID.fromString("00002a29-0000-1000-8000-00805f9b34fb");
public static UUID DIS_MODEL_UUID = UUID.fromString("00002a24-0000-1000-8000-00805f9b34fb");
public static UUID DIS_HWREV_UUID = UUID.fromString("00002a26-0000-1000-8000-00805f9b34fb");
public static UUID DIS_SWREV_UUID = UUID.fromString("00002a28-0000-1000-8000-00805f9b34fb");
// Implements callback methods for GATT events that the app cares about. For example,
// connection change and services discovered.
public final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
String intentAction;
if (newState == BluetoothProfile.STATE_CONNECTED) {
Log.i("STATE CONNECTED", "OK");
intentAction = ACTION_GATT_CONNECTED;
mConnectionState = STATE_CONNECTED;
broadcastUpdate(intentAction);
Log.i("STATE CONNECTED BROADCAST SENT - DISCOVERING SERVICES", "OK");
// Attempts to discover services after successful connection.
mBluetoothGatt.discoverServices();
Log.i("AFTER DISCOVER SERVICES", "OK");
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
Log.i("STATE DISCONNECTED", "OK");
intentAction = ACTION_GATT_DISCONNECTED;
mConnectionState = STATE_DISCONNECTED;
Log.i(TAG, "Disconnected from GATT server.");
broadcastUpdate(intentAction);
Log.i("STATE DISCONNECTED BROADCAST SENT", "OK");
}
if(mConnectionState==123334){
}
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
Log.i("GATT SUCCESS - SERVICES DISCOVERED", "OK");
} else {
Log.w(TAG, "onServicesDiscovered received: " + status);
}
}
@Override
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic,
int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
}
}
@Override
public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
}
};
private void broadcastUpdate(final String action) {
final Intent intent = new Intent(action);
sendBroadcast(intent);
Log.i("INTENT SENT", "OK");
}
private void broadcastUpdate(final String action, final BluetoothGattCharacteristic characteristic) {
final Intent intent = new Intent(action);
// For all other profiles, writes the data formatted in HEX.
final byte[] data = characteristic.getValue();
if (data != null && data.length > 0) {
final StringBuilder stringBuilder = new StringBuilder(data.length);
for(byte byteChar : data)
stringBuilder.append(String.format("%02X ", byteChar));
intent.putExtra(EXTRA_DATA, new String(data) + "\n" + stringBuilder.toString());
}
sendBroadcast(intent);
}
public class LocalBinder extends Binder {
public BluetoothLeService getService() {
return BluetoothLeService.this;
}
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
@Override
public boolean onUnbind(Intent intent) {
close();
return super.onUnbind(intent);
}
private final IBinder mBinder = new LocalBinder();
public boolean initialize() {
// For API level 18 and above, get a reference to BluetoothAdapter through
// BluetoothManager.
if (mBluetoothManager == null) {
mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
if (mBluetoothManager == null) {
Log.e(TAG, "Unable to initialize BluetoothManager.");
return false;
}
}
mBluetoothAdapter = mBluetoothManager.getAdapter();
if (mBluetoothAdapter == null) {
Log.e(TAG, "Unable to obtain a BluetoothAdapter.");
return false;
}
return true;
}
public boolean connect(final String address) {
if (mBluetoothAdapter == null || address == null) {
Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
return false;
}
// Previously connected device. Try to reconnect.
if (mBluetoothDeviceAddress != null && address.equals(mBluetoothDeviceAddress)
&& mBluetoothGatt != null) {
Log.d(TAG, "Trying to use an existing mBluetoothGatt for connection.");
if (mBluetoothGatt.connect()) {
mConnectionState = STATE_CONNECTING;
return true;
} else {
return false;
}
}
final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
if (device == null) {
Log.w(TAG, "Device not found. Unable to connect.");
return false;
}
// We want to directly connect to the device, so we are setting the autoConnect
// parameter to false.
mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
Log.d(TAG, "Trying to create a new connection.");
mBluetoothDeviceAddress = address;
mConnectionState = STATE_CONNECTING;
return true;
}
public void disconnect() {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.disconnect();
}
public void close() {
if (mBluetoothGatt == null) {
return;
}
mBluetoothGatt.close();
mBluetoothGatt = null;
}
public void readCharacteristic(BluetoothGattCharacteristic characteristic) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.readCharacteristic(characteristic);
}
public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic,
boolean enabled) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
}
public List<BluetoothGattService> getSupportedGattServices() {
if (mBluetoothGatt == null) return null;
return mBluetoothGatt.getServices();
}
}
答案 0 :(得分:0)
targetSdkVersion
的目标版本是什么?我有类似的问题,并将build.gradle
更改为
defaultConfig {
applicationId "com.XXX.XXXr"
minSdkVersion 21
targetSdkVersion 22
versionCode 1
versionName "1.0"
}
它解决了这个问题,但我还有其他一些需要解决的问题......
答案 1 :(得分:0)
在我的案例中(Adafruit羽毛BLE)以下工作
public static String LOG_TAG = "Adafruit Ind";
public static UUID UART_UUID = UUID.fromString("6e400001-b5a3-f393-e0a9-e50e24dcca9e");
public static UUID TX_UUID = UUID.fromString("6e400002-b5a3-f393-e0a9-e50e24dcca9e");
public static UUID RX_UUID = UUID.fromString("6e400003-b5a3-f393-e0a9-e50e24dcca9e");
public static UUID CLIENT_UUID = UUID.fromString("00002902-0000-1000-8000-00805F9B34FB");
public static UUID DIS_UUID = UUID.fromString("000001530-1212-EFDE-1523-785FEABCD123");
public static UUID DIS_MANUF_UUID = UUID.fromString("00002A29-0000-1000-8000-00805F9B34FB");
public static UUID DIS_MODEL_UUID = UUID.fromString("00002A24-0000-1000-8000-00805F9B34FB");
public static UUID DIS_HWREV_UUID = UUID.fromString("00002A26-0000-1000-8000-00805F9B34FB");
public static UUID DIS_SWREV_UUID = UUID.fromString("00002A28-0000-1000-8000-00805F9B34FB");