BLE connectGatt()方法在BluetoothGattCallback中没有报告任何内容...?

4
请问有人能检查一下这段代码的问题吗?我已经实现了一个服务并传递了一个 BluetoothDevice 对象给它(通过 intent 传递 BluetoothDevice 对象时没有错误/问题)。然后,在 onStartCommand() 中,我调用了 deviceToConnect.connectGatt(this,false,mGattCallback)。但是我的 BluetoothGattCallback() 没有起作用(没有打印任何内容)。代码简单明了。请问有人可以帮我调试一下吗?
编辑:我正在 MainActivity() 中进行 Le 设备扫描,并将设备对象传递给一个连接设备的服务。
public class PairedBleService extends Service
{
    private BluetoothGatt mConnectedGatt;
    @Override
    public void onCreate() {
        // TODO Auto-generated method stub
        super.onCreate();
        Toast.makeText(this, "Service Started", Toast.LENGTH_SHORT).show();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // TODO Auto-generated method stub
        super.onStartCommand(intent, flags, startId);

        BluetoothDevice deviceToConnect = (BluetoothDevice) intent.getParcelableExtra(DEVICE_TO_CONNECT);
        mConnectedGatt = deviceToConnect.connectGatt(this, false, mGattCallback);

        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        // TODO Auto-generated method stub
        Toast.makeText(this, "Service End", Toast.LENGTH_SHORT).show();
        super.onDestroy();
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        return null;
    }

    private BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {

    @Override
    public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
        if (status == BluetoothGatt.GATT_SUCCESS && newState == BluetoothProfile.STATE_CONNECTED) {
            Toast.makeText(getApplicationContext(), "Peripheral connected", Toast.LENGTH_LONG).show();
        } else if (status == BluetoothGatt.GATT_SUCCESS && newState == BluetoothProfile.STATE_DISCONNECTED) {
            Toast.makeText(getApplicationContext(), "Peripheral Disconnected", Toast.LENGTH_LONG).show();
        } else if (status != BluetoothGatt.GATT_SUCCESS) {
            gatt.disconnect();
        }
    }
}

编辑:我试图使用标准的Android蓝牙软件连接我的信标(外设),并且我能够建立连接。但是它要求输入配对密码,一旦输入密码就会连接并显示在已配对的蓝牙设备中。是否有像connectGatt这样的方法可以向用户询问“配对密码”... 我无法理解我错过了什么。


你在哪里扫描设备? - Osman Esen
我在我的活动中进行了扫描,并将BluetoothDevice对象传递到服务中以连接它。 - doga
你是否已经放置了一个无条件的Toast或在onConnectionStateChange中记录,以确保它被调用了吗? - Douglas Jones
嗨@DouglasJones...我也试过了,但没有可打印的Toast消息...请看问题的编辑部分...也许它会有所帮助。 - doga
你有解决方案吗?我也遇到了同样的问题。 - user1443721
3个回答

1

我遇到了类似的问题。我通过MAC地址检索BluetoothDevice,该地址在用户之前的扫描后保存到SharedPrefs中,以便我们在打开应用程序时自动连接到此设备。

获取BluetoothDevice后,我调用device.connectGatt(...),但回调永远不会被触发,连接尝试将永远挂起。

原来Android OS中有一个内部蓝牙设备缓存。重新启动手机并切换蓝牙开关似乎可以清除此缓存,并且任何过去的扫描结果都不再存在于缓存中。

如果您尝试使用不再缓存中的BluetoothDevice调用device.connectGatt(...),则connectGatt调用将永远挂起,您的回调函数也不会被触发。

相反,您需要检查BluetoothDevicetype。如果类型为BluetoothDevice.DEVICE_TYPE_UNKNOWN,则需要在尝试连接之前执行BLE扫描,因为设备不再位于缓存中。

这是我的代码片段,可以彻底解决此问题!

//Retrieve the MAC address of the device you want to connect to...in my case I used SharedPreferences
val pairedMacAddress = AppPreferences.getStringPreference(this, AppPreferences.PREF_BT_MAC_ADDRESS)
val savedBleDevice = bluetoothManager.adapter.getRemoteDevice(pairedMacAddress)
Timber.i("BluetoothDevice type is: ${savedBleDevice.type}")

// Saved BLE device is no longer in the device cache, we need to scan for devices again in order to autoconnect.
if (savedBleDevice.type == BluetoothDevice.DEVICE_TYPE_UNKNOWN) {

    Timber.i("Scanning for BLE devices since the saved BLE device is no longer in the system's BT cache.")

    val macAddressFilter = ScanFilter.Builder()
            .setDeviceAddress(pairedMacAddress)
            .build()

    val scanSettings = ScanSettings.Builder()
            .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
            .build()

    bluetoothManager.adapter.bluetoothLeScanner.startScan(listOf(macAddressFilter), scanSettings, object : ScanCallback() {
        override fun onScanResult(callbackType: Int, result: ScanResult) {

            Timber.w("Got scan results!")

            with(result.device) {
                Timber.i("Found BLE device! Name: ${name ?: "Unnamed"}, address: $address, going to connect now.")
                startBleConnection(this) // This calls device.connectGatt()
            }
        }

        override fun onScanFailed(errorCode: Int) {
            Timber.e("onScanFailed: code $errorCode")
        }
    })
} else {
    Timber.i("Saved BluetoothDevice is still in the BT cache. Auto-connecting!")
    startBleConnection(savedBleDevice) // This calls device.connectGatt()
}

在Android上使用蓝牙很有趣 - 祝你好运!


因为我使用的是bt经典扫描仪,然后设备被保存为类型=1=经典,导致连接gatt无法与其正常工作。 - Amin Keshavarzian

1
编辑确实有帮助。您想要在应用程序内进行配对...
自API 19(4.4)以来,BluetoothDevice具有createBond()方法,因此这排除了4.3,这是第一个BLE Android版本,但剩下的并不多。
这应该会弹出用户的PIN对话框。设备成功绑定后,您可以进行连接。要知道绑定何时完成或未完成,您需要拥有一个已注册以侦听ACTION_BOND_STATE_CHANGEDBroadcastReceiver。传入的Intent具有EXTRA_BOND_STATE,可以是BOND_BONDEDBOND_BONDING_BOND_NONE

因此,在您的onStartCommand中,您希望getBondState(),如果是BOND_NON,则需要createBond()。如果是BOND_BONDING,您需要等待使用BroadcastReceiver建立绑定,一旦绑定成功就可以连接。如果是BOND_BONDED,则可以连接。


1
你的onBind方法返回了null,因此你的主活动无法与你的服务通信。
你的代码应该如下所示,
@PairedBleService
public class LocalBinder extends Binder 
{
    PairedBleService getService() 
    {
        return PairedBleService.this;
    };
};

@Override
public IBinder onBind(Intent intent) 
{
    // TODO Auto-generated method stub
    return mBinder;
};

private final IBinder mBinder = new LocalBinder();

主要活动
//put this inside onServiceConnected

PairedBleService bleService = ((PairedBleService.LocalBinder) service).getService();

// Your code for connecting with BLE device
....................................
....................................

谢谢您的回复,Vikram。但是我还无法理解...因为我能够连接到服务,但BluetoothGattCallback没有调用,即onConnectionStateChange()中的Toast消息没有显示... - doga

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接