繁体   English   中英

尝试编写特征时Android BLE NullPointerException

[英]Android BLE NullPointerException when trying to write characteristic

我是 Android 应用程序开发的新手,这是我第一次尝试让 Android 设备与 BLE 设备通话(它将与微控制器通话)。 目标是发送一个值,在这种情况下,字符串“green”或“blue”转换为字节,以告诉微控制器打开 LED。

由于我不精通蓝牙,我一直在网上寻找各种资源来帮助将一些代码放在一起。 现在,当我连接到设备并尝试发送信号时,我收到以下错误代码:

java.lang.NullPointerException:尝试在 com.example.andres.battle_bots.DeviceControlActivity.makeChange(DeviceControlActivity.java:366) 的空对象引用上调用虚拟方法“boolean android.bluetooth.BluetoothGattCharacteristic.setValue(byte[])”在 com.example.andres.battle_bots.DeviceControlActivity.access$800(DeviceControlActivity.java:52) 在 com.example.andres.battle_bots.DeviceControlActivity$3.onClick(DeviceControlActivity.java:151)

我不太确定我错过了什么,因为我在使用它们之前实例化了我正在使用的变量,并且仍然抛出异常。 我可能误解了我正在改编的代码。 到目前为止,我有 2 个活动,DeviceScanActivity,它扫描设备并连接,以及 DeviceControlActivity,它是主要设备交互发生和错误发生的地方。 这是代码:

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/蓝牙开发的人。 谢谢!

原来我的特征是空的,因为我从服务中收到的 UUID 不等于我的期望。 一旦我编辑了示例代码以期望与我使用的蓝牙模块关联的 UUID,代码就可以工作了。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM