Android 4.3および4.4で正常に動作するアプリケーションがあります。アプリケーションはカスタムBluetoothデバイスに接続して通信します。
Nexus 5をLollipopにフラッシュした後、突然デバイスに接続できなくなりました。接続結果は常に133です。これはログです:
D/BluetoothGatt﹕ connect() - device: 00:07:80:04:1A:5A, auto: true
D/BluetoothGatt﹕ registerApp()
D/BluetoothGatt﹕ registerApp() - UUID=xxxxxx-xxxx-xxxxx-xxxx-xxxxxxxx
D/BluetoothGatt﹕ onClientRegistered() - status=0 clientIf=6
D/BluetoothGatt﹕ onClientConnectionState() - status=133 clientIf=6 device=00:07:80:04:1A:5A
私のコード:
public boolean connect(final String address) {
if (mBluetoothAdapter == null || address == null) {
return false;
}
Handler handler = new Handler(Looper.getMainLooper());
// Previously connected device. Try to reconnect.
if (mBluetoothDeviceAddress != null
&& address.equals(mBluetoothDeviceAddress)
&& mBluetoothGatt != null) {
handler.post(new Runnable() {
@Override
public void run() {
if (mBluetoothGatt.connect()) {
mConnectionState = STATE_CONNECTING;
}
}
});
if (mConnectionState == STATE_CONNECTING) {
return true;
} else {
return false;
}
}
final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
if (device == null) {
return false;
}
handler.post(new Runnable() {
@Override
public void run() {
mBluetoothGatt = device.connectGatt(BluetoothConnectService.this, true, mGattCallback);
}
});
mBluetoothDeviceAddress = address;
mConnectionState = STATE_CONNECTING;
return true;
}
誰かがこれについて何か考えがありますか?
だから私は問題がロリポップのトランスポートの選択であることがわかりました。
ご覧のとおり ここ の変化
BluetoothDevice.connectGatt(Context context, boolean autoConnect, BluetoothGattCallback callback)
関数が呼び出しています
BluetoothDevice.connectGatt(Context context, boolean autoConnect, BluetoothGattCallback callback, int transport)
トランスポートをTRANSPORT_AUTOに設定します。
私の場合は常にTRANSPORT_LEを使用するため(値は2)
コードから2番目のメソッドを呼び出して、トランスポートをTRANSPORT_LEに設定しようとしました。理由は不明ですが、直接呼び出すことができないため、リフレクションを使用して呼び出しています。今までこれは私にとってはうまくいきます。
if(TTTUtilities.isLollipopOrAbove()) {
// Little hack with reflect to use the connect gatt with defined transport in Lollipop
Method connectGattMethod = null;
try {
connectGattMethod = device.getClass().getMethod("connectGatt", Context.class, boolean.class, BluetoothGattCallback.class, int.class);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
try {
mBluetoothGatt = (BluetoothGatt) connectGattMethod.invoke(device, BluetoothConnectService.this, false, mGattCallback, TRANSPORT_LE);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
} else {
mBluetoothGatt = device.connectGatt(BluetoothConnectService.this, true, mGattCallback);
}
私の答えについて質問がある場合は、コメントでお気軽に質問してください。
ありがとうございました。
Xamarin同じ問題を抱えているユーザーの場合、少し異なる解決策があります。 Nexus 7 Android 6、XamarinクロスプラットフォームSDKを使用した場合も同じ問題が発生しました。TRANSPORT_LEを使用すると問題が修正されました。Reflectionを使用してメソッドを署名で取得するのではなく(機能しません) )、Reflectionを使用して、一致する名前が見つかるまですべてのメソッドを繰り返すことができます。以下のコードを参照してください。
BluetoothDevice bd = (BluetoothDevice)device.NativeDevice;
Java.Lang.Reflect.Method[] methods = bd.Class.GetDeclaredMethods();
foreach (Java.Lang.Reflect.Method possibleConnectGattMethod in methods)
{
// Find matching method name connectGatt and then invoke it with TRANSPORT_LE
}
リフレクションを使用してconnectGattメソッドを自分で呼び出すことは賢明なことではないと思います。プライベート関数は更新によっていつでも変更される可能性があるため、アプリケーションにバグが残ります。
そしてとにかく、適切なフラグがペリフェラルアドバタイズメントパケットに設定されている場合、TRANSPORT_AUTOは望ましい方法でペリフェラルに接続しようとする必要があります。周辺機器がTRANSPORT_BREDRモードをサポートしていない場合は、広告データに設定してセントラルに通知する必要がある標準フラグ「BrEdrNotSupported」があります。
どんなBLEICを使っていますか? CC254xの場合は、周辺機器のソフトウェアスタックの問題に関連している可能性があります。
https://e2e.ti.com/support/wireless_connectivity/f/538/t/40124