Ich versuche, eine Verbindung zu einem Bluetooth-Gerät auf Android herzustellen. Ich erhalte den Status 133 in meinem Handler onClientConnectionState
. Ich bekomme diesen Fehler nicht immer - manchmal verbindet es sich gut. Ich bin nicht in der Lage gewesen zu sagen, was das Problem auslöst. Ich hatte es sogar sofort nach dem Neustart des Geräts und meiner Repro-App.Android Bluetooth Fehler 133
Ich bin mir dessen bewusst einige Fragen und Lösungsvorschläge für dieses Problem, einschließlich (von here, here und here):
- den UI-Thread für alle BT-APIs verwenden
- sicher sein, schließen das GATT wenn fertig
Aber ich mache all das. Außerdem ist mein Gerät ein Nexus 5 (läuft Lollipop), das nach einigen nicht einmal die BT-Interaktionen benötigt, um auf dem UI-Thread zu sein.
Ich habe eine möglichst einfache Repro erstellt. Es ist in C#, aber die Java-Äquivalent sollte klar sein:
[Activity(Label = "BluetoothGatt133ErrorRepro", MainLauncher = true, Icon = "@drawable/icon")]
public class MainActivity : Activity
{
protected override void OnCreate(Android.OS.Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);
var button = FindViewById<Button>(Resource.Id.button);
button.Click += this.OnClick;
}
private async void OnClick(object sender, EventArgs e)
{
Action<string> log = message => Console.WriteLine($"***** #{Environment.CurrentManagedThreadId} {message}");
log("Beginning");
var bluetoothManager = (BluetoothManager)Application.Context.GetSystemService(Context.BluetoothService);
var adapter = bluetoothManager.Adapter;
var scanner = adapter.BluetoothLeScanner;
var callback = new Callback();
var filters = new List<ScanFilter>();
var settings = new ScanSettings.Builder()
.SetScanMode(global::Android.Bluetooth.LE.ScanMode.LowLatency)
.Build();
log("Starting scan");
scanner.StartScan(filters, settings, callback);
var result = await callback.Result;
log($"Got device: {result.Device.Name}");
var remoteDevice = adapter.GetRemoteDevice(result.Device.Address);
var gattCallback = new GattCallback(log);
log("Connecting GATT");
var gatt = remoteDevice.ConnectGatt(Application.Context, true, gattCallback);
gatt.Connect();
await gattCallback.Result;
log("Disconnecting GATT");
gatt.Close();
gatt.Dispose();
}
private sealed class Callback : ScanCallback
{
private readonly TaskCompletionSource<ScanResult> result;
public Callback()
{
this.result = new TaskCompletionSource<ScanResult>();
}
public Task<ScanResult> Result => this.result.Task;
public override void OnBatchScanResults(IList<ScanResult> results)
{
foreach (var result in results)
{
this.HandleResult(result);
}
}
public override void OnScanResult(ScanCallbackType callbackType, ScanResult result)
{
this.HandleResult(result);
}
public override void OnScanFailed(ScanFailure errorCode)
{
this.result.TrySetException(new InvalidOperationException($"Failed with error code {errorCode}."));
}
private void HandleResult(ScanResult result)
{
if (result.Device.Name.Contains("elided"))
{
this.result.TrySetResult(result);
}
}
}
private sealed class GattCallback : BluetoothGattCallback
{
private readonly Action<string> log;
private readonly TaskCompletionSource<bool> result;
public GattCallback(Action<string> log)
{
this.log = log;
this.result = new TaskCompletionSource<bool>();
}
public Task<bool> Result => this.result.Task;
public override void OnConnectionStateChange(BluetoothGatt gatt, GattStatus status, ProfileState newState)
{
this.log($"Connection state changed to {newState} with status {status}.");
this.result.TrySetResult(true);
}
}
}
Und hier ist die Ausgabe von diesem ausgeführt wird (ich habe auch von Android BluetoothGatt Quelle in den Ausgang links):
***** #1 Beginning
***** #1 Starting scan
07-01 11:53:21.458 D/BluetoothLeScanner(10377): onClientRegistered() - status=0 clientIf=5
***** #1 Got device: elided
***** #1 Connecting GATT
07-01 11:53:22.833 D/BluetoothGatt(10377): connect() - device: 00:00:DE:AD:BE:EF, auto: true
07-01 11:53:22.833 D/BluetoothGatt(10377): registerApp()
07-01 11:53:22.833 D/BluetoothGatt(10377): registerApp() - UUID=fa5bce8a-416d-47fe-9a8a-e44156f7e865
07-01 11:53:22.834 D/BluetoothGatt(10377): onClientRegistered() - status=0 clientIf=6
07-01 11:53:24.622 D/BluetoothGatt(10377): onClientConnectionState() - status=133 clientIf=6 device=00:00:DE:AD:BE:EF
***** #4 Connection state changed to Disconnected with status 133.
***** #1 Disconnecting GATT
07-01 11:53:24.707 D/BluetoothGatt(10377): close()
07-01 11:53:24.707 D/BluetoothGatt(10377): unregisterApp() - mClientIf=6
Wie Sie können Sehen Sie, meine gesamte Interaktion mit dem Bluetooth-Stack findet im Hauptthread (# 1) statt. Aber trotzdem empfange ich den Status 133 in meinem onClientConnectionState
Handler.
Mein Manifest hat diese Berechtigungen:
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
ich mit dem neuesten Eibisch Tooling bin kompilieren und bin Targeting Eibisch mit einem Mindestziel von 4.0.3 (API-Ebene 15).
Was könnte das verursachen?
Können Sie uns sagen, welche Berechtigungen Sie in Ihrer Manifestdatei haben? Könnten Sie auch versuchen, den Scan zu stoppen, bevor Sie die Verbindung herstellen? – Zomb
^^ upvoted für den Scan-Vorschlag zu stoppen, hat nicht bemerkt, dass – Submersed
@Zomb Habe mehr Details zu meiner Frage hinzugefügt. Es funktioniert anscheinend heute Morgen gut für mich, aber ich muss versuchen, den Scan-Trick zu stoppen, wenn das nächste Mal auftaucht. –