尝试写入特征时出现Android BLE NullPointerException
我是Android应用程序开发的新手,这是我第一次尝试让Android设备与BLE设备(将与微控制器通信)通信。目标是发送一个值,在本例中,字符串“绿色”或“蓝色”转换为字节,以通知微控制器打开LED 由于我对蓝牙不太精通,我一直在网上寻找各种来源,以帮助整合一些代码。现在,当我连接到设备并试图发送信号时,我得到以下错误代码: java.lang.NullPointerException:尝试在com.example.andres.battle_bots.DeviceControlActivity.makeChange(DeviceControlActivity.java:366)上的空对象引用上调用虚拟方法“boolean android.bluetooth.BluetoothGattCharacteristic.setValue(字节[])”在com.example.andres.battle_bots.DeviceControlActivity.access$800(DeviceControlActivity.java:52)在com.example.andres.battle_bots.DeviceControlActivity$3.onClick(DeviceControlActivity.java:151) 我不太确定我遗漏了什么,因为我在使用之前实例化了我正在使用的变量,并且仍然抛出异常。有可能我误解了我正在修改的代码。到目前为止,我有两个活动,DeviceScanActivity,它扫描设备和连接,DeviceControlActivity,它是发生设备内交互并发生错误。以下是代码:尝试写入特征时出现Android BLE NullPointerException,android,nullpointerexception,arduino,bluetooth-lowenergy,characteristics,Android,Nullpointerexception,Arduino,Bluetooth Lowenergy,Characteristics,我是Android应用程序开发的新手,这是我第一次尝试让Android设备与BLE设备(将与微控制器通信)通信。目标是发送一个值,在本例中,字符串“绿色”或“蓝色”转换为字节,以通知微控制器打开LED 由于我对蓝牙不太精通,我一直在网上寻找各种来源,以帮助整合一些代码。现在,当我连接到设备并试图发送信号时,我得到以下错误代码: java.lang.NullPointerException:尝试在com.example.andres.battle_bots.DeviceControlActivit
import android.app.Activity;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ExpandableListView;
import android.widget.ImageButton;
import android.widget.SeekBar;
import android.widget.SimpleExpandableListAdapter;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
public class DeviceControlActivity extends Activity {
private final static String TAG = DeviceControlActivity.class.getSimpleName();
public static final String EXTRAS_DEVICE_NAME = "DEVICE_NAME";
public static final String EXTRAS_DEVICE_ADDRESS = "DEVICE_ADDRESS";
private int[] RGBFrame = {0, 0, 0};
private TextView isSerial;
private TextView mConnectionState;
private TextView mDataField;
private String mDeviceName;
private String mDeviceAddress;
// private ExpandableListView mGattServicesList;
private BluetoothLeService mBluetoothLeService;
private boolean mConnected = false;
private BluetoothGattCharacteristic characteristicTX;
private BluetoothGattCharacteristic characteristicRX;
public final static UUID HM_RX_TX =
UUID.fromString(SampleGattAttributes.HM_RX_TX);
private final String LIST_NAME = "NAME";
private final String LIST_UUID = "UUID";
// Code to manage Service lifecycle.
private final ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder service) {
mBluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService();
if (!mBluetoothLeService.initialize()) {
Log.e(TAG, "Unable to initialize Bluetooth");
finish();
}
// Automatically connects to the device upon successful start-up initialization.
mBluetoothLeService.connect(mDeviceAddress);
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
mBluetoothLeService = null;
}
};
// Handles various events fired by the Service.
// ACTION_GATT_CONNECTED: connected to a GATT server.
// ACTION_GATT_DISCONNECTED: disconnected from a GATT server.
// ACTION_GATT_SERVICES_DISCOVERED: discovered GATT services.
// ACTION_DATA_AVAILABLE: received data from the device. This can be a result of read
// or notification operations.
private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) {
mConnected = true;
updateConnectionState(R.string.connected);
invalidateOptionsMenu();
} else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) {
mConnected = false;
updateConnectionState(R.string.disconnected);
invalidateOptionsMenu();
clearUI();
} else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) {
// Show all the supported services and characteristics on the user interface.
displayGattServices(mBluetoothLeService.getSupportedGattServices());
} else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) {
displayData(intent.getStringExtra(mBluetoothLeService.EXTRA_DATA));
}
}
};
private void clearUI() {
// mDataField.setText(R.string.no_data);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Intent intent = getIntent();
mDeviceName = intent.getStringExtra(EXTRAS_DEVICE_NAME);
mDeviceAddress = intent.getStringExtra(EXTRAS_DEVICE_ADDRESS);
getActionBar().setTitle(mDeviceName);
getActionBar().setDisplayHomeAsUpEnabled(true);
Intent gattServiceIntent = new Intent(this, BluetoothLeService.class);
bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);
ImageButton U1 = (ImageButton) findViewById(R.id.up_btn1);
U1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//Do something with Bluetooth
if(mBluetoothLeService != null) {
String codeGreen = "green";
makeChange(codeGreen);
}
}
});
ImageButton R1 = (ImageButton) findViewById(R.id.right_btn1);
R1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//Do something with Bluetooth
}
});
ImageButton D1 = (ImageButton) findViewById(R.id.down_btn1);
D1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//Do something with Bluetooth
}
});
ImageButton L1 = (ImageButton) findViewById(R.id.left_btn1);
L1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//Do something with Bluetooth
}
});
ImageButton U2 = (ImageButton) findViewById(R.id.up_btn2);
U2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(mBluetoothLeService != null) {
String codeBlue = "blue";
makeChange(codeBlue);
}
}
});
ImageButton R2 = (ImageButton) findViewById(R.id.right_btn2);
R2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//Do something with Bluetooth
}
});
ImageButton D2 = (ImageButton) findViewById(R.id.down_btn2);
D2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//Do something with Bluetooth
}
});
ImageButton L2 = (ImageButton) findViewById(R.id.left_btn2);
L2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//Do something with Bluetooth
}
});
ImageButton BLE = (ImageButton) findViewById(R.id.ble_btn);
BLE.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//Do something with Bluetooth
Intent intent = new Intent(DeviceControlActivity.this, com.example.andres.battle_bots.DeviceScanActivity.class);
startActivity(intent);
}
});
ImageButton Options = (ImageButton) findViewById(R.id.options_btn);
Options.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//Do something with Bluetooth
}
});
// Sets up UI references.
// ((TextView) findViewById(R.id.device_address)).setText(mDeviceAddress);
// mConnectionState = (TextView) findViewById(R.id.connection_state);
// is serial present?
// isSerial = (TextView) findViewById(R.id.isSerial);
/*
mDataField = (TextView) findViewById(R.id.data_value);
mRed = (SeekBar) findViewById(R.id.seekRed);
mGreen = (SeekBar) findViewById(R.id.seekGreen);
mBlue = (SeekBar) findViewById(R.id.seekBlue);
readSeek(mRed, 0);
readSeek(mGreen, 1);
readSeek(mBlue, 2);
*/
}
@Override
protected void onResume() {
super.onResume();
registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter());
if (mBluetoothLeService != null) {
final boolean result = mBluetoothLeService.connect(mDeviceAddress);
Log.d(TAG, "Connect request result=" + result);
}
}
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(mGattUpdateReceiver);
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(mServiceConnection);
mBluetoothLeService = null;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.gatt_services, menu);
if (mConnected) {
menu.findItem(R.id.menu_connect).setVisible(false);
menu.findItem(R.id.menu_disconnect).setVisible(true);
} else {
menu.findItem(R.id.menu_connect).setVisible(true);
menu.findItem(R.id.menu_disconnect).setVisible(false);
}
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_connect:
mBluetoothLeService.connect(mDeviceAddress);
return true;
case R.id.menu_disconnect:
mBluetoothLeService.disconnect();
return true;
case android.R.id.home:
onBackPressed();
return true;
}
return super.onOptionsItemSelected(item);
}
private void updateConnectionState(final int resourceId) {
runOnUiThread(new Runnable() {
@Override
public void run() {
// mConnectionState.setText(resourceId);
}
});
}
private void displayData(String data) {
if (data != null) {
mDataField.setText(data);
}
}
// Demonstrates how to iterate through the supported GATT Services/Characteristics.
// In this sample, we populate the data structure that is bound to the ExpandableListView
// on the UI.
private void displayGattServices(List<BluetoothGattService> gattServices) {
if (gattServices == null) return;
String uuid = null;
String unknownServiceString = getResources().getString(R.string.unknown_service);
ArrayList<HashMap<String, String>> gattServiceData = new ArrayList<HashMap<String, String>>();
// Loops through available GATT Services.
for (BluetoothGattService gattService : gattServices) {
HashMap<String, String> currentServiceData = new HashMap<String, String>();
uuid = gattService.getUuid().toString();
currentServiceData.put(
LIST_NAME, SampleGattAttributes.lookup(uuid, unknownServiceString));
// If the service exists for HM 10 Serial, say so.
if (SampleGattAttributes.lookup(uuid, unknownServiceString) == "HM 10 Serial") {
// isSerial.setText("Yes, serial :-)");
} else {
// isSerial.setText("No, serial :-(");
}
currentServiceData.put(LIST_UUID, uuid);
gattServiceData.add(currentServiceData);
// get characteristic when UUID matches RX/TX UUID
characteristicTX = gattService.getCharacteristic(BluetoothLeService.UUID_HM_RX_TX);
characteristicRX = gattService.getCharacteristic(BluetoothLeService.UUID_HM_RX_TX);
}
}
private static IntentFilter makeGattUpdateIntentFilter() {
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothLeService.ACTION_GATT_CONNECTED);
intentFilter.addAction(BluetoothLeService.ACTION_GATT_DISCONNECTED);
intentFilter.addAction(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED);
intentFilter.addAction(BluetoothLeService.ACTION_DATA_AVAILABLE);
return intentFilter;
}
// on change of bars write char
private void makeChange(String str) {
Log.d(TAG, "Sending result=" + str);
final byte[] tx = str.getBytes();
if (mConnected) {
characteristicTX.setValue(tx);
mBluetoothLeService.writeCharacteristic(characteristicTX);
mBluetoothLeService.setCharacteristicNotification(characteristicRX, true);
Log.d(TAG,"Success");
}
else
{
Log.d(TAG,"Failed");
}
}
}
导入android.app.Activity;
导入android.bluetooth.BluetoothGattCharacteristic;
导入android.bluetooth.BluetoothGattService;
导入android.content.BroadcastReceiver;
导入android.content.ComponentName;
导入android.content.Context;
导入android.content.Intent;
导入android.content.IntentFilter;
导入android.content.ServiceConnection;
导入android.os.Bundle;
导入android.os.IBinder;
导入android.util.Log;
导入android.view.Menu;
导入android.view.MenuItem;
导入android.view.view;
导入android.widget.ExpandableListView;
导入android.widget.ImageButton;
导入android.widget.SeekBar;
导入android.widget.SimpleExpandableListAdapter;
导入android.widget.TextView;
导入java.util.ArrayList;
导入java.util.HashMap;
导入java.util.List;
导入java.util.UUID;
公共类设备ControlActivity扩展活动{
私有最终静态字符串标记=DeviceControlActivity.class.getSimpleName();
公共静态最终字符串EXTRAS\u DEVICE\u NAME=“DEVICE\u NAME”;
公共静态最终字符串EXTRAS\u DEVICE\u ADDRESS=“DEVICE\u ADDRESS”;
私有int[]RGBFrame={0,0,0};
私有文本视图是串行的;
私有文本视图mConnectionState;
私有文本视图mDataField;
私有字符串mDeviceName;
私有字符串mDeviceAddress;
//私有可扩展列表视图mGattServicesList;
私人蓝牙服务mBluetoothLeService;
私有布尔值mConnected=false;
私人蓝牙GATT特征特征TX;
私人蓝牙GATT特征特征Rx;
公共最终静态UUID HM_RX_TX=
UUID.fromString(samplegattatattributes.HM_RX_TX);
私有最终字符串列表\u NAME=“NAME”;
私有最终字符串列表\u UUID=“UUID”;
//用于管理服务生命周期的代码。
专用最终ServiceConnection mServiceConnection=新ServiceConnection(){
@凌驾
服务连接上的公共无效(组件名称组件名称,IBinder服务){
mBluetoothLeService=((BluetoothLeService.LocalBinder)服务).getService();
如果(!mBluetoothLeService.initialize()){
Log.e(标记“无法初始化蓝牙”);
完成();
}
//成功启动初始化后自动连接到设备。
mBluetoothLeService.connect(mDeviceAddress);
}
@凌驾
ServiceDisconnected上的公共无效(ComponentName ComponentName){
mBluetoothLeService=null;
}
};
//处理服务触发的各种事件。
//操作\u GATT\u已连接:连接到GATT服务器。
//操作\u GATT\u断开连接:从GATT服务器断开连接。
//行动\u GATT\u服务\u发现:发现的GATT服务。
//操作\u数据\u可用:从设备接收数据。这可能是读取的结果
//或通知操作。
private final BroadcastReceiver mGattUpdateReceiver=新的BroadcastReceiver(){
@凌驾
公共void onReceive(上下文、意图){
最后一个字符串action=intent.getAction();
if(蓝牙服务动作\关贸总协定\连接的相等动作){
mConnected=true;
updateConnectionState(R.string.connected);
无效操作菜单();
}else if(蓝牙服务操作\u GATT\u断开连接。等于(操作)){
mConnected=false;
updateConnectionState(R.string.disconnected);
无效操作菜单();
clearUI();
}else if(BluetoothLeService.ACTION\u GATT\u SERVICES\u DISCOVERED.equals(ACTION)){
//在用户界面上显示所有支持的服务和特性。
displayGattServices(mBluetoothLeService.getSupportedGattServices());
}else if(BluetoothLeService.ACTION\u DATA\u AVAILABLE.equals(ACTION)){
显示数据(intent.getStringExtra(mBluetoothLeService.EXTRA_数据));
}
}
};
私有void clearUI(){
//mDataField.setText(R.string.no_数据);
}
@凌驾
创建时的公共void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
最终意图=getIntent();
mDeviceName=intent.getStringExtra(附加设备名称);
mDeviceAddress=intent.getStringExtra(附加设备地址);
getActionBar().setTitle(