我正在尝试制作一个可以切换连接到 BLE 设备的 LED 的应用程序。当我尝试扫描设备并连接到它不起作用的服务时。在 LE Scan 上使用变量“mBTdevice”始终显示空值
这是我的 code.java 文件
package org.bluetooth.bledemo;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.UUID;
import android.os.Bundle;
import android.os.Handler;
import android.app.Activity;
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.content.Context;
import android.content.pm.PackageManager;
import android.view.MenuItem;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.ToggleButton;
import android.support.v4.app.NavUtils;
import com.epsilonteknologies.smartlight.R;
/* this activity's purpose is to show how to use particular type of devices in easy and fast way */
public class SmartLight extends Activity {
private Handler mHandler = null;
private BluetoothManager mBTManager = null;
private BluetoothAdapter mBTAdapter = null;
private BluetoothDevice mBTDevice = null;
private BluetoothGatt mBTGatt = null;
private BluetoothGattService mBTService = null;
private boolean mScanning=false;
private BluetoothGattCharacteristic mBTValueCharacteristic = null;
// UUDI of Smart Light:
final static private UUID mSmartLightServiceUuid = BleDefinedUUIDs.Service.SMART_LIGHT;
final static private UUID mSmartLightCharacteristicUuid = BleDefinedUUIDs.Characteristic.SMART_LIGHT_ON_OFF;
private EditText mConsole = null;
private TextView mTextView = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_smartlight);
mConsole = (EditText) findViewById(R.id.hr_console_item);
log("Creating activity");
// Show the Up button in the action bar.
getActionBar().setDisplayHomeAsUpEnabled(true);
setTitle("Smart Light");
mConsole = (EditText) findViewById(R.id.hr_console_item);
mTextView = (TextView) findViewById(R.id.sl_text_view);
mHandler = new Handler();
log("Activity created");
}
/*@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
NavUtils.navigateUpFromSameTask(this);
return true;
}
return super.onOptionsItemSelected(item);
}*/
@Override
protected void onResume() {
super.onResume();
log("Resuming activity");
// first check if BT/BLE is available and enabled
if(initBt() == false) return;
if(isBleAvailable() == false) return;
if(isBtEnabled() == false) return;
connectToDevice();
// then start discovering devices around
startSearchingForSL();
log("Activity resumed");
}
/*@Override
protected void onPause() {
super.onPause();
disableNotificationForSL();
disconnectFromDevice();
closeGatt();
};*/
private boolean initBt() {
mBTManager = (BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE);
if(mBTManager != null) mBTAdapter = mBTManager.getAdapter();
return (mBTManager != null) && (mBTAdapter != null);
}
private boolean isBleAvailable() {
log("Checking if BLE hardware is available");
boolean hasBle = getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE);
if(hasBle && mBTManager != null && mBTAdapter != null) {
log("BLE hardware available");
}
else {
log("BLE hardware is missing!");
return false;
}
return true;
}
private boolean isBtEnabled() {
log("Checking if BT is enabled");
if(mBTAdapter.isEnabled()) {
log("BT is enabled");
}
else {
log("BT is disabled. Use Setting to enable it and then come back to this app");
return false;
}
return true;
}
private void startSearchingForSL() {
// we define what kind of services found device needs to provide. In our case we are interested only in
// Smart Light Service
final UUID[] uuids = new UUID[] {mSmartLightServiceUuid};
mBTAdapter.startLeScan(uuids, mDeviceFoundCallback);
// results will be returned by callback
log("Search for devices providing Smart Light service started");
// please, remember to add timeout for that scan
Runnable timeout = new Runnable() {
@Override
public void run() {
if(mBTAdapter.isDiscovering() == false) return;
stopSearchingForSL();
}
};
mHandler.postDelayed(timeout, 20000); //20 seconds
}
private void stopSearchingForSL() {
mBTAdapter.stopLeScan(mDeviceFoundCallback);
log("Searching for devices with Smart Light service stopped");
}
private void connectToDevice() {
log("Connecting to the device NAME: " + mBTDevice.getName() + " HWADDR: " + mBTDevice.getAddress());
//mBTGatt = mBTDevice.connectGatt(this, true, mGattCallback);
}
private void disconnectFromDevice() {
log("Disconnecting from device");
if(mBTGatt != null) mBTGatt.disconnect();
}
private void closeGatt() {
if(mBTGatt != null) mBTGatt.close();
mBTGatt = null;
}
private void discoverServices() {
log("Starting discovering services");
mBTGatt.discoverServices();
}
private void getSLService() {
log("Getting Smart Light Service");
mBTService = mBTGatt.getService(mSmartLightServiceUuid);
if(mBTService == null) {
log("Could not get Smart Light Service");
}
else {
log("Smart Light Service successfully retrieved");
setSLCharacteristic();
}
}
private void setSLCharacteristic() {
log("Getting Smart Light On-Off characteristic");
mBTValueCharacteristic = mBTService.getCharacteristic(mSmartLightCharacteristicUuid);
final ToggleButton mTogBut = (ToggleButton) findViewById(R.id.toggleButton1);
if(mBTValueCharacteristic == null) {
log("Could not find Smart Light On-Off Characteristic");
}
else {
log("Smart Light On-Off characteristic retrieved properly");
enableNotificationForSL();
}
mTogBut.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (mTogBut.isChecked()){
mBTValueCharacteristic.setValue("1");
}else{
mBTValueCharacteristic.setValue("2");
}
}
});
}
private void enableNotificationForSL() {
log("Enabling notification for Smart Light");
boolean success = mBTGatt.setCharacteristicNotification(mBTValueCharacteristic, true);
if(!success) {
log("Enabling notification failed!");
return;
}
BluetoothGattDescriptor descriptor = mBTValueCharacteristic.getDescriptor(BleDefinedUUIDs.Descriptor.CHAR_CLIENT_CONFIG);
if(descriptor != null) {
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
mBTGatt.writeDescriptor(descriptor);
log("Notification enabled");
}
else {
log("Could not get descriptor for characteristic! Notification are not enabled.");
}
}
private void disableNotificationForSL() {
log("Disabling notification for Smart Light");
boolean success = mBTGatt.setCharacteristicNotification(mBTValueCharacteristic, false);
if(!success) {
log("Disabling notification failed!");
return;
}
BluetoothGattDescriptor descriptor = mBTValueCharacteristic.getDescriptor(BleDefinedUUIDs.Descriptor.CHAR_CLIENT_CONFIG);
if(descriptor != null) {
descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
mBTGatt.writeDescriptor(descriptor);
log("Notification disabled");
}
else {
log("Could not get descriptor for characteristic! Notification could be still enabled.");
}
}
private void getAndDisplaySLValue() {
byte[] raw = mBTValueCharacteristic.getValue();
int index = ((raw[0] & 0x01) == 1) ? 2 : 1;
int format = (index == 1) ? BluetoothGattCharacteristic.FORMAT_UINT8 : BluetoothGattCharacteristic.FORMAT_UINT16;
int value = mBTValueCharacteristic.getIntValue(format, index);
final String description = value + " bpm";
runOnUiThread(new Runnable() {
@Override
public void run() {
mTextView.setText(description);
}
});
}
public BluetoothAdapter.LeScanCallback mDeviceFoundCallback =
new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
runOnUiThread(new Runnable() {
@Override
public void run() {
SmartLight.this.mBTDevice=device;
log("Device with Smart Light service discovered. HW Address: " + device.getAddress());
//stopSearchingForSL();
connectToDevice();
}
});
}
};
/* callbacks called for any action on HR Device */
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
if (newState == BluetoothProfile.STATE_CONNECTED) {
log("Device connected");
discoverServices();
}
else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
log("Device disconnected");
}
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if(status == BluetoothGatt.GATT_SUCCESS) {
log("Services discovered");
getSLService();
}
else {
log("Unable to discover services");
}
}
@Override
public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic)
{
if(characteristic.equals(mBTValueCharacteristic)) {
getAndDisplaySLValue();
}
}
/* the rest of callbacks are not interested for us */
@Override
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic,
int status) {}
@Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {};
@Override
public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {};
};
// put new logs into the UI console
private void log(final String txt) {
if(mConsole == null) return;
final String timestamp = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss.SSS", Locale.US).format(new Date());
runOnUiThread(new Runnable() {
@Override
public void run() {
mConsole.setText(timestamp + " : " + txt + "\n" + mConsole.getText());
}
});
}
}
这是我的 xml 文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="org.bluetooth.bledemo.SmartLight" >
<TextView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="0"
android:gravity="center_horizontal"
android:text="@string/activity_name" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0" >
<TextView
android:id="@+id/textView20"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:clickable="false"
android:gravity="top"
android:text="@string/status"
android:textColor="#888"
android:textSize="12sp" />
<TextView
android:id="@+id/sl_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:textColor="#666"
android:textSize="28sp"
android:textStyle="bold" />
</LinearLayout>
<ToggleButton
android:id="@+id/toggleButton1"
android:layout_width="280dp"
android:layout_height="37dp"
android:layout_gravity="center_horizontal"
android:gravity="center"
android:text="@string/ToggleButton"
android:textOff="OFF"
android:textOn="ON"
android:textSize="50sp" />
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0"
android:text="Console:"
android:textColor="#888"
android:textSize="12sp" />
<EditText
android:id="@+id/hr_console_item"
android:layout_width="281dp"
android:layout_height="315dp"
android:ems="10"
android:enabled="false"
android:gravity="top"
android:inputType="textMultiLine"
android:textSize="12sp" >
<requestFocus />
</EditText>
</LinearLayout>