我尝试了所有方法,但无法连接到其他蓝牙设备。我执行以下步骤:
我可以找到所有设备,但无法连接到我想要的设备。不幸的是我找不到完整的例子
这是我使用的代码:
import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanResult;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;
import java.util.List;
import java.util.Map;
import java.util.UUID;
public class MainActivity extends AppCompatActivity {
BluetoothManager btManager;
BluetoothAdapter btAdapter;
BluetoothLeScanner btScanner;
Button startScanningButton;
Button stopScanningButton;
TextView peripheralTextView;
BluetoothGatt bluetoothGatt;
BluetoothDevice device;
private final static int REQUEST_ENABLE_BT = 1;
private static final int PERMISSION_REQUEST_COARSE_LOCATION = 2;
private boolean mEchoInitialized;
private static final String TAG = "ClientActivity";
//
// private ActivityClientBinding mBinding;
private boolean mScanning;
private Handler mHandler;
private Handler mLogHandler;
private Map<String, BluetoothDevice> mScanResults;
private boolean mConnected;
private ScanCallback mScanCallback;
public static String SERVICE_STRING = "7D2EA28A-F7BD-485A-BD9D-92AD6ECFE93E";
public static UUID SERVICE_UUID = UUID.fromString(SERVICE_STRING);
public static String CHARACTERISTIC_ECHO_STRING = "7D2EBAAD-F7BD-485A-BD9D-92AD6ECFE93E";
public static UUID CHARACTERISTIC_ECHO_UUID = UUID.fromString(CHARACTERISTIC_ECHO_STRING);
public static final long SCAN_PERIOD = 5000;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
peripheralTextView = (TextView) findViewById(R.id.PeripheralTextView);
peripheralTextView.setMovementMethod(new ScrollingMovementMethod());
startScanningButton = (Button) findViewById(R.id.StartScanButton);
startScanningButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
startScanning();
}
});
stopScanningButton = (Button) findViewById(R.id.StopScanButton);
stopScanningButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
stopScanning();
}
});
stopScanningButton.setVisibility(View.INVISIBLE);
btManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
btAdapter = btManager.getAdapter();
btScanner = btAdapter.getBluetoothLeScanner();
if (btAdapter != null && !btAdapter.isEnabled()) {
Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
}
// Make sure we have access coarse location enabled, if not, prompt the user to enable it
if (this.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("This app needs location access");
builder.setMessage("Please grant location access so this app can detect peripherals.");
builder.setPositiveButton(android.R.string.ok, null);
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, PERMISSION_REQUEST_COARSE_LOCATION);
}
});
builder.show();
}
}
@Override
protected void onResume() {
super.onResume();
// Check low energy support
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
// Get a newer device
// logError("No LE Support.");
finish();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
private ScanCallback leScanCallback = new ScanCallback() {
@Override
public void onScanResult(int callbackType, ScanResult result) {
// Log.d("ci sono",result.getDevice().getName());
if (result.getDevice().getName() != null && result.getDevice().getName().contains("A-"))
stopScanning();
// peripheralTextView.append("Device Name: " + result.getDevice().getName() + " rssi: " + result.getRssi() + "\n");
// auto scroll for text view
// final int scrollAmount = peripheralTextView.getLayout().getLineTop(peripheralTextView.getLineCount()) - peripheralTextView.getHeight();
// if there is no need to scroll, scrollAmount will be <=0
// if (scrollAmount > 0)
// peripheralTextView.scrollTo(0, scrollAmount);
connectDevice(result.getDevice());
// bluetoothGatt = result.getDevice().connectGatt(MainActivity.this, false, gattClientCallback);
}
};
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case PERMISSION_REQUEST_COARSE_LOCATION: {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
System.out.println("coarse location permission granted");
} else {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Functionality limited");
builder.setMessage("Since location access has not been granted, this app will not be able to discover beacons when in the background.");
builder.setPositiveButton(android.R.string.ok, null);
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
}
});
builder.show();
}
return;
}
}
}
public void startScanning() {
System.out.println("start scanning");
peripheralTextView.setText("");
startScanningButton.setVisibility(View.INVISIBLE);
stopScanningButton.setVisibility(View.VISIBLE);
AsyncTask.execute(new Runnable() {
@Override
public void run() {
btScanner.startScan(leScanCallback);
}
});
}
public void stopScanning() {
System.out.println("stopping scanning");
peripheralTextView.append("Stopped Scanning");
startScanningButton.setVisibility(View.VISIBLE);
stopScanningButton.setVisibility(View.INVISIBLE);
AsyncTask.execute(new Runnable() {
@Override
public void run() {
btScanner.stopScan(leScanCallback);
}
});
}
private void connectDevice(BluetoothDevice device) {
// log("Connecting to " + device.getAddress());
GattClientCallback gattClientCallback = new GattClientCallback();
bluetoothGatt = device.connectGatt(this, false, gattClientCallback);
}
protected void onStop() {
// call the superclass method first
super.onStop();
Log.d("spegni", "bluetooth");
btScanner.stopScan(leScanCallback);
}
private class GattClientCallback extends BluetoothGattCallback {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
super.onConnectionStateChange(gatt, status, newState);
// log("onConnectionStateChange newState: " + newState);
if (status == BluetoothGatt.GATT_FAILURE) {
// logError("Connection Gatt failure status " + status);
disconnectGattServer();
return;
} else if (status != BluetoothGatt.GATT_SUCCESS) {
// handle anything not SUCCESS as failure
// logError("Connection not GATT sucess status " + status);
disconnectGattServer();
return;
}
if (newState == BluetoothProfile.STATE_CONNECTED) {
// log("Connected to device " + gatt.getDevice().getAddress());
setConnected(true);
gatt.discoverServices();
Log.d("discoverRiuscito", "onServicesDiscovered " + status + " " + gatt.discoverServices()
+ " " + gatt.getServices());
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
// log("Disconnected from device");
disconnectGattServer();
}
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
super.onServicesDiscovered(gatt, status);
if (status != BluetoothGatt.GATT_SUCCESS) {
// log("Device service discovery unsuccessful, status " + status);
return;
}
List<BluetoothGattCharacteristic> matchingCharacteristics = BluetoothUtils.findCharacteristics(gatt);
if (matchingCharacteristics.isEmpty()) {
// logError("Unable to find characteristics.");
return;
}
// log("Initializing: setting write type and enabling notification");
for (BluetoothGattCharacteristic characteristic : matchingCharacteristics) {
characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);
enableCharacteristicNotification(gatt, characteristic);
}
}
@Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicWrite(gatt, characteristic, status);
if (status == BluetoothGatt.GATT_SUCCESS) {
// log("Characteristic written successfully");
} else {
// logError("Characteristic write unsuccessful, status: " + status);
disconnectGattServer();
}
}
@Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicRead(gatt, characteristic, status);
if (status == BluetoothGatt.GATT_SUCCESS) {
// log("Characteristic read successfully");
readCharacteristic(characteristic);
} else {
// logError("Characteristic read unsuccessful, status: " + status);
// Trying to read from the Time Characteristic? It doesnt have the property or permissions
// set to allow this. Normally this would be an error and you would want to:
// disconnectGattServer();
}
}
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
super.onCharacteristicChanged(gatt, characteristic);
// log("Characteristic changed, " + characteristic.getUuid().toString());
readCharacteristic(characteristic);
}
private void enableCharacteristicNotification(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
boolean characteristicWriteSuccess = gatt.setCharacteristicNotification(characteristic, true);
if (characteristicWriteSuccess) {
// log("Characteristic notification set successfully for " + characteristic.getUuid().toString());
if (BluetoothUtils.isEchoCharacteristic(characteristic)) {
initializeEcho();
}
} else {
// logError("Characteristic notification set failure for " + characteristic.getUuid().toString());
}
}
private void readCharacteristic(BluetoothGattCharacteristic characteristic) {
byte[] messageBytes = characteristic.getValue();
// log("Read: " + StringUtils.byteArrayInHexFormat(messageBytes));
String message = StringUtils.stringFromBytes(messageBytes);
if (message == null) {
// logError("Unable to convert bytes to string");
return;
}
// log("Received message: " + message);
}
}
public void setConnected(boolean connected) {
mConnected = connected;
}
private void sendMessage() {
BluetoothGattCharacteristic characteristic = BluetoothUtils.findEchoCharacteristic(bluetoothGatt);
if (characteristic == null) {
return;
}
String message = "2";
byte[] messageBytes = StringUtils.bytesFromString(message);
if (messageBytes.length == 0) {
return;
}
characteristic.setValue(messageBytes);
boolean success = bluetoothGatt.writeCharacteristic(characteristic);
if (success) {
// log("Wrote: " + StringUtils.byteArrayInHexFormat(messageBytes));
} else {
// logError("Failed to write data");
}
}
public void initializeEcho() {
mEchoInitialized = true;
}
private class BtleScanCallback extends ScanCallback {
private Map<String, BluetoothDevice> mScanResults;
BtleScanCallback(Map<String, BluetoothDevice> scanResults) {
mScanResults = scanResults;
}
@Override
public void onScanResult(int callbackType, ScanResult result) {
addScanResult(result);
}
@Override
public void onBatchScanResults(List<ScanResult> results) {
for (ScanResult result : results) {
addScanResult(result);
}
}
@Override
public void onScanFailed(int errorCode) {
}
private void addScanResult(ScanResult result) {
BluetoothDevice device = result.getDevice();
String deviceAddress = device.getAddress();
mScanResults.put(deviceAddress, device);
}
}
public void disconnectGattServer() {
mConnected = false;
mEchoInitialized = false;
if (bluetoothGatt != null) {
bluetoothGatt.disconnect();
bluetoothGatt.close();
}
}
}```