我真的是Bluetooth和.hex世界的新手,我正在尝试实现一个基本上包含以下内容的android应用:选择要发送的文件(.hex),进行Bluetooth扫描以查找与设备关闭的设备在智能手机上,单击列表上的所需设备(信标),然后通过蓝牙将.hex文件发送到该设备。因此,最麻烦的功能是通过蓝牙将.hex文件传输到信标设备。
直到现在,我还根据一些指南和论坛开发了此代码,但似乎无法正常工作(并且我仍然不确定如何将流启动到所选的特定设备):
public class MainActivity extends AppCompatActivity {
private static final int READ_REQUEST_CODE = 42;
private static final int SCAN_PERMISSIONS_CODE = 1;
private static final String TAG = "MyActivity";
private DevicesListAdapter adapter;
private ListView listView;
private SeekBar seekBar;
private TextView valueDB;
private ArrayList<BluetoothDevice> devicesList;
private BluetoothLeScanner scanner;
private EditText editFile;
private Uri uriFirmware;
private StringBuffer mOutStringBuffer;
private BTInterface mBtInterface;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
devicesList = new ArrayList<>();
setContentView(R.layout.activity_main);
editFile = findViewById(R.id.bt_edit_file);
final int step = 1;
int max = 100;
final int min = 40;
mBtInterface= new BTInterface();
Button startScanButton = (Button) findViewById(R.id.buttonStartScan);
startScanButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startScanForDevices();
}
});
Button stopScanButton = (Button) findViewById(R.id.buttonStopScan);
stopScanButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
scanner.stopScan(bleScanCallback);
}
});
ImageButton btnFileLookup = (ImageButton) findViewById(R.id.btn_file_lookup);
btnFileLookup.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
performFileSearch();
}
});
Log.d(TAG,"Requesting permission");
int permissionCheck = ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION);
if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,Manifest.permission.ACCESS_FINE_LOCATION)) {
} else {
ActivityCompat.requestPermissions(MainActivity.this,new String[]{Manifest.permission.ACCESS_FINE_LOCATION},SCAN_PERMISSIONS_CODE);
}
}
}
private void performFileSearch() {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
startActivityForResult(intent, READ_REQUEST_CODE);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
protected void onActivityResult(int resultCode, int responseCode, Intent data) {
super.onActivityResult(resultCode, responseCode,data);
switch (resultCode) {
case READ_REQUEST_CODE:
if (responseCode == RESULT_OK && data != null) {
Uri uri = data.getData();
fileDisplayName(uri);
uriFirmware = uri;
} else {
uriFirmware = null;
}
break;
}
}
private void fileDisplayName(Uri uri) {
Cursor cursor = getContentResolver().query(uri, null, null, null, null, null);
try {
if (cursor != null && cursor.moveToFirst()) {
String displayName = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
editFile.setText(displayName);
}
} finally {
cursor.close();
}
}
public void startScanForDevices() {
BluetoothManager bluetoothManager = (BluetoothManager) this.getSystemService(Context.BLUETOOTH_SERVICE);
BluetoothAdapter adapter = bluetoothManager.getAdapter();
scanner = adapter.getBluetoothLeScanner();
if (scanner != null) {
scanner.startScan(bleScanCallback);
} else {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Error");
builder.setMessage("Cannot start scan, might be that Bluetooth is turned off");
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
return;
}
}).create().show();
}
}
public static byte[] getBytes(Context context, Uri uri) throws IOException {
InputStream iStream = context.getContentResolver().openInputStream(uri);
try {
return getBytes(iStream);
} finally {
// close the stream
try {
iStream.close();
} catch (IOException ignored) { /* do nothing */ }
}
}
public static byte[] getBytes(InputStream inputStream) throws IOException {
byte[] bytesResult = null;
ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
try {
int len;
while ((len = inputStream.read(buffer)) != -1) {
byteBuffer.write(buffer, 0, len);
}
bytesResult = byteBuffer.toByteArray();
} finally {
// close the stream
try{ byteBuffer.close(); } catch (IOException ignored){ /* do nothing */ }
}
return bytesResult;
}
private ScanCallback bleScanCallback = new ScanCallback() {
@Override
public void onScanResult(int callbackType, ScanResult result) {
super.onScanResult(callbackType, result);
adapter = new DevicesListAdapter(MainActivity.this, R.layout.list_item, devicesList);
listView = findViewById(R.id.listView);
listView.setAdapter(adapter);
if (!devicesList.contains(result.getDevice())) {
Log.d(TAG, "Found new device: " + result.getDevice().getName() + " (" + result.getDevice().getAddress() + ")");
devicesList.add(result.getDevice());
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View v, final int position, long id) {
scanner.stopScan(bleScanCallback);
android.app.AlertDialog.Builder mBuilder = new android.app.AlertDialog.Builder(MainActivity.this);
mBuilder.setTitle("Upload .hex file");
mBuilder.setMessage("Do you want upload the file on " + devicesList.get(position).getName() + "?")
.setPositiveButton("send", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
byte[] inputData = new byte[0];
try {
inputData = getBytes(MainActivity.this, uriFirmware);
} catch (IOException e) {
e.printStackTrace();
}
mBtInterface.write(inputData);
}
})
.setNegativeButton("cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
onResume();
}
});
android.app.AlertDialog mDialog = mBuilder.create();
mDialog.show();
}
});
}
}
};
}
这是BTInterface类:
public class BTInterface {
ProgressDialog mProgressDialog;
private ConnectedThread mConnectedThread;
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket) {
Log.d(TAG, "ConnectedThread: Starting.");
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
try{
mProgressDialog.dismiss();
}catch (NullPointerException e){
e.printStackTrace();
}
try {
tmpIn = mmSocket.getInputStream();
tmpOut = mmSocket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run(){
byte[] buffer = new byte[1024];
int bytes;
while (true) {
try {
bytes = mmInStream.read(buffer);
String incomingMessage = new String(buffer, 0, bytes);
Log.d(TAG, "InputStream: " + incomingMessage);
} catch (IOException e) {
Log.e(TAG, "write: Error reading Input Stream. " + e.getMessage() );
break;
}
}
}
public void write(byte[] bytes) {
try {
mmOutStream.write(bytes);
} catch (IOException e) {
Log.e(TAG, "write: Error writing to output stream. " + e.getMessage() );
}
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) { }
}
}
private void connected(BluetoothSocket mmSocket, BluetoothDevice mmDevice) {
Log.d(TAG, "connected: Starting.");
mConnectedThread = new ConnectedThread(mmSocket);
mConnectedThread.start();
}
public void write(byte[] out) {
ConnectedThread r;
Log.d(TAG, "write: Write Called.");
mConnectedThread.write(out);
}
}
当我单击“发送”时,应用崩溃,并显示以下错误:
Attempt to invoke virtual method 'void com.example.safectoryfu.helper.BTInterface$ConnectedThread.write(byte[])' on a null object reference