我看到的错误信息是:
尝试调用虚拟方法' void android.bluetooth.le.BluetoothLeScanner.startScan(java.util.List,android.bluetooth.le.ScanSettings,android.bluetooth.le.ScanCallback)' com.example.drodo.diamondbeacons.BleDevicesActivity.startScanning(BleDevicesActivity.java:91)中的空对象引用,位于com.example.drodo.diamondbeacons.BleDevicesActivity $ 1.onClick(BleDevicesActivity.java:68)。行错误:mBluetoothLeScanner.startScan(buildScanFilters(),buildScanSettings(),mScanCallback);
这是我的代码:
public class BleDevicesActivity extends AppCompatActivity {
private Toolbar bleToolbar;
private static final String TAG = BleDevicesActivity.class.getName();
private static final long SCAN_PERIOD = 5000;
private BluetoothAdapter mBluetoothAdapter;
private BluetoothLeScanner mBluetoothLeScanner;
private ScanCallback mScanCallback;
private TextView deviceName;
private TextView deviceAddress;
private Button scanDevicesBtn;
private Handler mHandler;
public void setBluetoothAdapter(BluetoothAdapter btAdapter) {
this.mBluetoothAdapter = btAdapter;
mBluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ble_devices);
mHandler = new Handler();
bleToolbar = (Toolbar) findViewById(R.id.ble_toolbar);
setSupportActionBar(bleToolbar);
getSupportActionBar().setTitle("Ble Devices Nearby");
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
deviceName = (TextView) findViewById(R.id.device_name_text);
deviceAddress = (TextView) findViewById(R.id.device_address_text);
scanDevicesBtn = (Button) findViewById(R.id.scan_devices_btn);
scanDevicesBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startScanning();
Snackbar.make(v, "Scanning for BLE Devices Nearby", Snackbar.LENGTH_SHORT)
.setAction("Action", null).show();
}
});
}
public void startScanning() {
if (mScanCallback == null) {
Log.d(TAG, "Starting Scanning");
// Will stop the scanning after a set time.
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
stopScanning();
Toast.makeText(BleDevicesActivity.this, "Scanning Stopped", Toast.LENGTH_SHORT).show();
}
}, SCAN_PERIOD);
// Kick off a new scan.
mScanCallback = new SampleScanCallback();
mBluetoothLeScanner.startScan(buildScanFilters(), buildScanSettings(), mScanCallback);
String toastText = getString(R.string.scan_start_toast) + " "
+ TimeUnit.SECONDS.convert(SCAN_PERIOD, TimeUnit.MILLISECONDS) + " "
+ getString(R.string.seconds);
Toast.makeText(BleDevicesActivity.this, toastText, Toast.LENGTH_LONG).show();
} else {
Toast.makeText(BleDevicesActivity.this, R.string.already_scanning, Toast.LENGTH_SHORT).show();
}
}
/**
* Stop scanning for BLE Advertisements.
*/
public void stopScanning() {
Log.d(TAG, "Stopping Scanning");
// Stop the scan, wipe the callback.
mBluetoothLeScanner.stopScan(mScanCallback);
mScanCallback = null;
// Even if no new results, update 'last seen' times.
//amAdapter.notifyDataSetChanged();
}
/**
* Return a List of {@link ScanFilter} objects to filter by Service UUID.
*/
private List<ScanFilter> buildScanFilters() {
List<ScanFilter> scanFilters = new ArrayList<>();
ScanFilter.Builder builder = new ScanFilter.Builder();
builder.setServiceUuid(BleConstants.Service_UUID);
scanFilters.add(builder.build());
return scanFilters;
}
/**
* Return a {@link ScanSettings} object set to use low power (to preserve battery life).
*/
private ScanSettings buildScanSettings() {
ScanSettings.Builder builder = new ScanSettings.Builder();
builder.setScanMode(ScanSettings.SCAN_MODE_LOW_POWER);
return builder.build();
}
/**
* Custom ScanCallback object - adds to adapter on success, displays error on failure.
*/
private class SampleScanCallback extends ScanCallback {
@Override
public void onBatchScanResults(List<ScanResult> results) {
super.onBatchScanResults(results);
for (ScanResult result : results) {
String device_name = result.getDevice().getName();
String device_address = result.getDevice().getAddress();
deviceName.setText(device_name);
deviceAddress.setText(device_address);
}
}
@Override
public void onScanResult(int callbackType, ScanResult result) {
super.onScanResult(callbackType, result);
try {
ScanRecord scanRecord = result.getScanRecord();
assert scanRecord != null;
byte[] manufacturerData = scanRecord.getManufacturerSpecificData(0x0590);
assert manufacturerData != null;
double lightValue = Double.parseDouble(Arrays.toString(new byte[]{manufacturerData[0]}).replace("[", "").replace("]", ""));
double tempValue = Double.parseDouble(Arrays.toString(new byte[]{manufacturerData[1]}).replace("[", "").replace("]", ""));
double batteryValue = Integer.parseInt(Arrays.toString(new byte[]{manufacturerData[2]}).replace("[", "").replace("]", ""));
int alertPresses = Integer.parseInt(Arrays.toString(new byte[]{manufacturerData[3]}).replace("[", "").replace("]", ""));
Toast.makeText(BleDevicesActivity.this, "LIGHT: " + lightValue + " %", Toast.LENGTH_SHORT).show();
Toast.makeText(BleDevicesActivity.this, "TEMPERATURE: " + tempValue + " \u2103", Toast.LENGTH_SHORT).show();
Toast.makeText(BleDevicesActivity.this, "BATTERY LEVEL: " + batteryValue + " Volts", Toast.LENGTH_SHORT).show();
Toast.makeText(BleDevicesActivity.this, "ALERT PRESSES: " + alertPresses, Toast.LENGTH_SHORT).show();
} catch (Exception e) {
String error_message = e.getMessage();
Toast.makeText(BleDevicesActivity.this, "Error: " + error_message, Toast.LENGTH_SHORT).show();
}
}
@Override
public void onScanFailed(int errorCode) {
super.onScanFailed(errorCode);
Toast.makeText(BleDevicesActivity.this, "Scan failed with error: " + errorCode, Toast.LENGTH_LONG)
.show();
}
}
}
可能导致崩溃的原因是什么?
答案 0 :(得分:0)
这一行:
mBluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner();
正在将您的BluetoothLeScanner
实例初始化为null
。
方法getBluetoothLeScanner
仅在设备上实际开启的蓝牙时返回非null
。因此,每次都需要使用扫描程序(而不是存储引用)时调用getBluetoothLeScanner
,并在使用之前积极检查结果是否为null
。如果结果为null
,您可能需要在继续之前提示用户启用蓝牙。
在您的具体情况下,您应该:
mBluetoothLeScanner
字段; 将行mBluetoothLeScanner.startScan(buildScanFilters(), buildScanSettings(), mScanCallback);
替换为
BluetoothLeScanner scanner = mBluetoothAdapter.getBluetoothLeScanner();
if (scanner != null) {
scanner.startScan(buildScanFilters(), buildScanSettings(), mScanCallback);
} else {
// Device Bluetooth is disabled; check and prompt user to enable.
}
将行mBluetoothLeScanner.stopScan(mScanCallback);
替换为
BluetoothLeScanner scanner = mBluetoothAdapter.getBluetoothLeScanner();
if (scanner != null) {
scanner.stopScan(mScanCallback);
} else {
// Device Bluetooth is disabled; scanning should already be stopped, nothing to do here.
}