我对android不太了解。我正在尝试通过BLE发送数据。我的代码如下->。我是从互联网https://developer.android.com/guide/topics/connectivity/bluetooth-le#read
获得的如何正确调用此方法-> mBluetoothService.mBluetoothGatt = device.connectGatt(cntxt,false,mBluetoothService.mGattCallback);此行崩溃。
public class BluetoothLeService extends Service {
private final static String TAG = BluetoothLeService.class.getSimpleName();
public BluetoothManager mBluetoothManager;
public BluetoothAdapter mBluetoothAdapter;
public String mBluetoothDeviceAddress;
public BluetoothGatt mBluetoothGatt;
private int mConnectionState = STATE_DISCONNECTED;
private final IBinder mBinder = new LocalBinder();
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";
public final static UUID UUID_HEART_RATE_MEASUREMENT =
UUID.fromString(SampleGattAttributes.HEART_RATE_MEASUREMENT);
// Various callback methods defined by the BLE API.
public final BluetoothGattCallback mGattCallback =
new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status,
int newState) {
String intentAction;
if (newState == BluetoothProfile.STATE_CONNECTED) {
intentAction = ACTION_GATT_CONNECTED;
mConnectionState = STATE_CONNECTED;
broadcastUpdate(intentAction);
Log.i(TAG, "Connected to GATT server.");
Log.i(TAG, "Attempting to start service discovery:" +
mBluetoothGatt.discoverServices());
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
intentAction = ACTION_GATT_DISCONNECTED;
mConnectionState = STATE_DISCONNECTED;
Log.i(TAG, "Disconnected from GATT server.");
broadcastUpdate(intentAction);
}
}
@Override
// New services discovered
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
//broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
for (BluetoothGattService gattService : gatt.getServices()) {
Log.i(TAG, "onServicesDiscovered: ---------------------");
Log.i(TAG, "onServicesDiscovered: service=" + gattService.getUuid());
for (BluetoothGattCharacteristic characteristic : gattService.getCharacteristics()) {
Log.i(TAG, "onServicesDiscovered: characteristic=" + characteristic.getUuid());
if (characteristic.getUuid().toString().equals("0000ffe9-0000-1000-8000-00805f9b34fb")) {
Log.w(TAG, "onServicesDiscovered: found LED");
String originalString = "560D0F0600F0AA";
byte[] b = hexStringToByteArray(originalString);
characteristic.setValue(b); // call this BEFORE(!) you 'write' any stuff to the server
mBluetoothGatt.writeCharacteristic(characteristic);
Log.i(TAG, "onServicesDiscovered: , write bytes?! " + byteToHexStr(b));
}
}
}
broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
} else {
Log.w(TAG, "onServicesDiscovered received: " + status);
}
}
@Override
// Result of a characteristic read operation
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic,
int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
byte[] data = characteristic.getValue();
System.out.println("reading");
System.out.println(new String(data));
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
}
}
//...
};
private void broadcastUpdate(final String action) {
final Intent intent = new Intent(action);
sendBroadcast(intent);
}
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;
}
public static String byteToHexStr(byte[] bytes) {
StringBuilder builder = new StringBuilder();
for (byte b: bytes) {
builder.append(String.format("%02x", b));
}
return builder.toString();
}
private void broadcastUpdate(final String action,
final BluetoothGattCharacteristic characteristic) {
final Intent intent = new Intent(action);
// This is special handling for the Heart Rate Measurement profile. Data
// parsing is carried out as per profile specifications.
if (UUID_HEART_RATE_MEASUREMENT.equals(characteristic.getUuid())) {
int flag = characteristic.getProperties();
int format = -1;
if ((flag & 0x01) != 0) {
format = BluetoothGattCharacteristic.FORMAT_UINT16;
Log.d(TAG, "Heart rate format UINT16.");
} else {
format = BluetoothGattCharacteristic.FORMAT_UINT8;
Log.d(TAG, "Heart rate format UINT8.");
}
final int heartRate = characteristic.getIntValue(format, 1);
Log.d(TAG, String.format("Received heart rate: %d", heartRate));
intent.putExtra(EXTRA_DATA, String.valueOf(heartRate));
} else {
// 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 {
BluetoothLeService getService() {
return BluetoothLeService.this;
}
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return mBinder;/*return null;*/
}
//...
}
我从外部这样调用此类方法->
public class DeviceScanActivity extends AppCompatActivity/*ListActivity*/ {
//private LeDeviceListAdapter mLeDeviceListAdapter;
public BluetoothAdapter mBluetoothAdapter;
public /*final*/ BluetoothManager mBluetoothManager;
/*=(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);;*/
private BluetoothLeService mBluetoothService;//= new BluetoothLeService();
public Context cntxt;
ArrayList<ViewHolder> arrayOfUsers2 = new ArrayList<ViewHolder>();
private boolean mScanning;
private boolean mBounded;
private Handler mHandler;
ArrayList<String> mylist = new ArrayList<String>();
private static final int REQUEST_ENABLE_BT = 1;
// Stops scanning after 10 seconds.
private static final long SCAN_PERIOD = 50000;
private static final int PERMISSION_REQUEST_COARSE_LOCATION = 456;
UsersAdapter adapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//getActionBar().setTitle("abc");
mHandler = new Handler();
//this.requestPermissions(rqPerm,req);
requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, PERMISSION_REQUEST_COARSE_LOCATION);
// Use this check to determine whether BLE is supported on the device. Then you can
// selectively disable BLE-related features.
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
finish();
}
// Initializes a Bluetooth adapter. For API level 18 and above, get a reference to
// BluetoothAdapter through BluetoothManager.
/*final BluetoothManager*/ mBluetoothManager =
(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = mBluetoothManager.getAdapter();
// Checks if Bluetooth is supported on the device.
if (mBluetoothAdapter == null ) {
Toast.makeText(this, R.string.error_bluetooth_not_supported, Toast.LENGTH_SHORT).show();
finish();
return;
}
if( !mBluetoothAdapter.isEnabled())
{
Intent enableBluetooth = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(getIntent(), 1);
}
// Construct the data source
ArrayList<ViewHolder> arrayOfUsers = new ArrayList<ViewHolder>();
// Create the adapter to convert the array to views
adapter = new UsersAdapter(this, arrayOfUsers);
cntxt=this.getApplicationContext();
Intent i = new Intent(this, BluetoothLeService.class);
bindService(this.getIntent(), mConnection, BIND_AUTO_CREATE);; //if checked, start service
ListView listView = (ListView) findViewById(R.id.mobile_list);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
ViewHolder entry= (ViewHolder) parent.getAdapter().getItem(position);
String address = entry.deviceAddress;
final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
Toast.makeText(cntxt, address, Toast.LENGTH_SHORT).show();
//mBluetoothService.mBluetoothDeviceAddress=address;
//mBluetoothService.mBluetoothManager=mBluetoothManager;
mBluetoothService.mBluetoothAdapter = mBluetoothAdapter;
mBluetoothService.mBluetoothGatt = device.connectGatt(cntxt, false, mBluetoothService.mGattCallback);
//Toast.makeText(this, R.string.error_bluetooth_not_supported, Toast.LENGTH_SHORT).show();
}});
ViewHolder newUser2 = new ViewHolder("adtv2","vvg2");
adapter.add(newUser2);
}
ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
//Toast.makeText(Client.this, "Service is disconnected", 1000).show();
mBounded = false;
mBluetoothService = null;
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//Toast.makeText(Client.this, "Service is connected", 1000).show();
mBounded = true;
BluetoothLeService.LocalBinder mLocalBinder = (BluetoothLeService.LocalBinder)service;
mBluetoothService = mLocalBinder.getService();
}
};
private void scanLeDevice(final boolean enable) {
if (enable) {
// Stops scanning after a pre-defined scan period.
ViewHolder newUser2 = new ViewHolder("adtv2","vvg2");
adapter.add(newUser2);
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
mScanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
Iterator<ViewHolder> it=arrayOfUsers2.iterator();
while(it.hasNext()) {
ViewHolder currentX = it.next();
adapter.add(currentX);
}
// Do something with the value
}
}, SCAN_PERIOD);
mScanning = true;
mBluetoothAdapter.startLeScan(mLeScanCallback);
} else {
mScanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
}
//invalidateOptionsMenu();
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
switch (requestCode) {
case PERMISSION_REQUEST_COARSE_LOCATION: {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Permission granted, yay! Start the Bluetooth device scan.
scanLeDevice(true);
} else {
// Alert the user that this application requires the location permission to perform the scan.
}
}
}
}
// Device scan callback.
private BluetoothAdapter.LeScanCallback mLeScanCallback =
new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
runOnUiThread(new Runnable() {
@Override
public void run() {
//mLeDeviceListAdapter.addDevice(device);
//mLeDeviceListAdapter.notifyDataSetChanged();
//ViewHolder newUser = new ViewHolder("Nathan", "San Diego");
String deviceName=null, deviceAddress=null;
if(device!=null)
deviceName= device.getName();
if (!(deviceName != null && deviceName.length() > 0))
deviceName = "unknown device";
if(device!=null)
deviceAddress= device.getAddress();
ViewHolder newUser = new ViewHolder(deviceName, deviceAddress);
ViewHolder newUser2 = new ViewHolder("adtv","vvg");
if(!arrayOfUsers2.contains(newUser))
arrayOfUsers2.add(newUser);
//adapter.add(newUser);
}
});
}
};
public class UsersAdapter extends ArrayAdapter<ViewHolder> {
public UsersAdapter(Context context, ArrayList<ViewHolder> users) {
super(context, 0, users);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// Get the data item for this position
ViewHolder user = getItem(position);
// Check if an existing view is being reused, otherwise inflate the view
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.bt_details, parent, false);
}
// Lookup view for data population
TextView tvName = (TextView) convertView.findViewById(R.id.DeviceName);
TextView tvHome = (TextView) convertView.findViewById(R.id.DeviceAddress);
// Populate the data into the template view using the data object
tvName.setText(user.deviceName);
tvHome.setText(user.deviceAddress);
// Return the completed view to render on screen
return convertView;
}
}
public class ViewHolder {
String deviceName;
String deviceAddress;
public ViewHolder(String device, String __address) {
this.deviceName =device;
this.deviceAddress= __address;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ViewHolder a = (ViewHolder) o;
return Objects.equals(deviceAddress, a.deviceAddress);
}
}
}
我在其中获得扫描设备结果的列表。单击该列表的任何元素后,我将调用AdapterView.OnItemClickListener()。然后如何发送消息到设备。如何读取这些日志消息。如何知道代码是否已发送消息。如何在其他设备上接收消息。我已经完成了BLE扫描,可以正常工作。但是这里没有添加代码。
日志猫的报告如下
FATAL EXCEPTION: main
Process: com.example.root.securityalert, PID: 27945
java.lang.NullPointerException: Attempt to read from field 'android.bluetooth.BluetoothGattCallback com.example.root.securityalert.BluetoothLeService.mGattCallback' on a null object reference
at com.example.root.securityalert.DeviceScanActivity$1.onItemClick(DeviceScanActivity.java:115)
at android.widget.AdapterView.performItemClick(AdapterView.java:310)
at android.widget.AbsListView.performItemClick(AbsListView.java:1156)
at android.widget.AbsListView$PerformClick.run(AbsListView.java:3147)
at android.widget.AbsListView$3.run(AbsListView.java:4062)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6165)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:888)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:778)
我也尝试过使用代码
public class BluetoothSendRecv extends BluetoothGattCallback{
public BluetoothManager mBluetoothManager;
public BluetoothAdapter mBluetoothAdapter;
public String mBluetoothDeviceAddress;
public BluetoothGatt mBluetoothGatt;
private int mConnectionState = STATE_DISCONNECTED;
// private final IBinder mBinder = new BluetoothLeService.LocalBinder();
public Context cntxt;
.......
UUID.fromString(SampleGattAttributes.HEART_RATE_MEASUREMENT);
// Various callback methods defined by the BLE API.
public final BluetoothGattCallback mGattCallback =
new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status,
int newState) {
String intentAction;
if (newState == BluetoothProfile.STATE_CONNECTED) {
intentAction = ACTION_GATT_CONNECTED;
mConnectionState = STATE_CONNECTED;
broadcastUpdate(intentAction);
Log.i(TAG, "Connected to GATT server.");
Log.i(TAG, "Attempting to start service discovery:" +
mBluetoothGatt.discoverServices());
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
intentAction = ACTION_GATT_DISCONNECTED;
mConnectionState = STATE_DISCONNECTED;
Log.i(TAG, "Disconnected from GATT server.");
broadcastUpdate(intentAction);
}
}
@Override
// New services discovered
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
//broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
for (BluetoothGattService gattService : gatt.getServices()) {
Log.i(TAG, "onServicesDiscovered: ---------------------");
Log.i(TAG, "onServicesDiscovered: service=" + gattService.getUuid());
for (BluetoothGattCharacteristic characteristic : gattService.getCharacteristics()) {
Log.i(TAG, "onServicesDiscovered: characteristic=" + characteristic.getUuid());
if (characteristic.getUuid().toString().equals("0000fee9-0000-1000-8000-00805f9b34fb"/*0000ffe9-0000-1000-8000-00805f9b34fb"*/)) {
Log.w(TAG, "onServicesDiscovered: found LED");
String originalString = "560D0F0600F0AA";
byte[] b = hexStringToByteArray(originalString);
characteristic.setValue(b); // call this BEFORE(!) you 'write' any stuff to the server
mBluetoothGatt.writeCharacteristic(characteristic);
//Toast.makeText(this., "R.string.error_bluetooth_not_supported", Toast.LENGTH_SHORT).show();
//finish()
System.out.println("Writing Mithun");
Toast.makeText(cntxt, originalString, Toast.LENGTH_SHORT).show();
Log.i(TAG, "onServicesDiscovered: , write bytes?! " + byteToHexStr(b));
}
}
}
broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
} else {
Log.w(TAG, "onServicesDiscovered received: " + status);
}
}
@Override
// Result of a characteristic read operation
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic,
int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
byte[] data = characteristic.getValue();
System.out.println("reading");
System.out.println(new String(data));
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
}
}
//...
};
private void broadcastUpdate(final String action) {
final Intent intent = new Intent(action);
//sendBroadcast(intent);
}
.....
}
Then logcat report is as follows aaaa
D/BluetoothGatt: onClientConnectionState() - status=0 clientIf=6 device=CC:1E:39:39:62:1C
I/ContentValues: Connected to GATT server.
D/BluetoothGatt: discoverServices() - device: CC:1E:39:39:62:1C
I/ContentValues: Attempting to start service discovery:true
D/BluetoothGatt: onSearchComplete() = Device=CC:1E:39:39:62:1C Status=0
I/ContentValues: onServicesDiscovered: ---------------------
I/ContentValues: onServicesDiscovered: service=00001800-0000-1000-8000-00805f9b34fb
I/ContentValues: onServicesDiscovered: characteristic=00002a00-0000-1000-8000-00805f9b34fb
I think this condition is not fullfilled
if(characteristic.getUuid().toString().equals("0000fee9-0000-1000-8000-00805f9b34fb"/*0000ffe9-0000-1000-8000-00805f9b34fb"*/))
答案 0 :(得分:0)
我认为您必须在尝试连接之前添加“扫描”方法。这是ble体系结构的规则。
Rheumatology
如果建立了Ble Device:
$( document ).ready(function() { //wait until body loads
//Inputs that determine what fields to show
var appttype = $('#secureform input:select[name=AppointmentType]');
var physician = document.getElementById("physician");
appttype.change(function(){ //when the Appointment Type changes
var value=this.value;
physician.addClass('hidden'); //hide everything and reveal as needed
if (value === 'Orthopedic' || value === 'Rheumatology'){
physician.removeClass('hidden'); //show doctors
}
else {}
});
});