Android14でBLEデバイスとの接続切断動作を行うと、そのデバイスの検知ができなくなる

実現したいこと

Android14からBLE通信に関する不具合が生じている。

内容は、一度BLEモジュールとBluetoothGattよりConnectしたあと、一度切断してもう一度ScanCallbackを登録してもそのデバイスが検知されなくなるという不具合である。

この問題についてBluetoothLeScanner.startScanで、ScanSettinngsを設定した場合にこの不具合は発生しなくなることがわかった。Scansettingsには何を設定しても不具合は解消される。

しかし、なぜ不具合が解消されるのかがわからないため、理由を知りたい。

該当のソースコード

Java

1package com.example.ble_detect_validation;2 3import androidx.appcompat.app.AppCompatActivity;4import androidx.core.app.ActivityCompat;5import androidx.core.content.ContextCompat;6 7import android.Manifest;8import android.annotation.SuppressLint;9import android.bluetooth.BluetoothAdapter;10import android.bluetooth.BluetoothDevice;11import android.bluetooth.BluetoothGatt;12import android.bluetooth.BluetoothGattCallback;13import android.bluetooth.BluetoothManager;14import android.bluetooth.BluetoothProfile;15import android.bluetooth.le.BluetoothLeScanner;16import android.bluetooth.le.ScanCallback;17import android.bluetooth.le.ScanResult;18import android.bluetooth.le.ScanSettings;19import android.content.Context;20import android.content.Intent;21import android.content.pm.PackageManager;22import android.os.Build;23import android.os.Bundle;24import android.util.Log;25import android.view.View;26import android.widget.Button;27import android.widget.Toast;28 29 30import java.util.ArrayList;31import java.util.List;32import java.util.UUID;33 34public class MainActivity extends AppCompatActivity {35 private static final int PERMISSION_REQUEST_CODE = 1;36 private static final int REQUEST_ENABLE_BT = 1;37 private List<BluetoothDevice> _bluetoothLeDeviceList;38 private final static String NAME_KEY = "デバイス名";39 private BluetoothManager _manager;40 private BluetoothAdapter _adapter;41 private BluetoothLeScanner _scaner;42 private BluetoothGatt _gatt;43 private Context _context;44 45 @SuppressLint("MissingPermission")46 @Override47 protected void onCreate(Bundle savedInstanceState) {48 super.onCreate(savedInstanceState);49 setContentView(R.layout.activity_main);50 Button button = findViewById(R.id.button);51 _manager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);52 _adapter = _manager.getAdapter();53 _scaner = _adapter.getBluetoothLeScanner();54 _bluetoothLeDeviceList = new ArrayList<>();55 56 requestPermission();57 58 _context = this;59 60 _scaner.startScan(_scanCallBack);61 62 button.setOnClickListener(new View.OnClickListener() {63 @SuppressLint("MissingPermission")64 @Override65 public void onClick(View v) {66 ScanSettings.Builder builder = new ScanSettings.Builder();67 builder.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY);68 ScanSettings scanSettings = builder.build();69 _manager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);70 _adapter = _manager.getAdapter();71 _scaner = _adapter.getBluetoothLeScanner();72 _scanCallBack = new ScanCallback() {73 @SuppressLint("MissingPermission")74 @Override75 public void onScanResult(int callbackType, ScanResult result) {76 super.onScanResult(callbackType, result);77 BluetoothDevice bleDevice = result.getDevice();78 79 if( (null== bleDevice) || (null==bleDevice.getName()) ){80 return;81 }82 Log.e("BLE", bleDevice.getName());83 if (!bleDevice.getName().contains(NAME_KEY)) {84 return;85 }86 if( _bluetoothLeDeviceList.contains(bleDevice) ){87 return;88 }89 _bluetoothLeDeviceList.add(bleDevice);90 Toast.makeText(_context, bleDevice.getName(), Toast.LENGTH_SHORT).show();91 92 if(bleDevice.getName().equals("デバイス名")){93 _gatt = bleDevice.connectGatt(_context, false, gattCallback);94 }95 96 }97 };98 _scaner.startScan(null,scanSettings,_scanCallBack);99 }100 });101 102 }103 private ScanCallback _scanCallBack = new ScanCallback() {104 @SuppressLint("MissingPermission")105 @Override106 public void onScanResult(int callbackType, ScanResult result) {107 super.onScanResult(callbackType, result);108 BluetoothDevice bleDevice = result.getDevice();109 110 if( (null== bleDevice) || (null==bleDevice.getName()) ){111 return;112 }113 Log.e("BLE", bleDevice.getName());114 if (!bleDevice.getName().contains(NAME_KEY)) {115 return;116 }117 if( _bluetoothLeDeviceList.contains(bleDevice) ){118 return;119 }120 _bluetoothLeDeviceList.add(bleDevice);121 Toast.makeText(_context, bleDevice.getName(), Toast.LENGTH_SHORT).show();122 123 if(bleDevice.getName().equals("デバイス名")){124 _gatt = bleDevice.connectGatt(_context, false, gattCallback);125 _scaner.stopScan(_scanCallBack);126 _scanCallBack = null;127 _scaner = null;128 _adapter = null;129 _manager = null;130 131 }132 133 }134 };135 136 private final BluetoothGattCallback gattCallback = new BluetoothGattCallback() {137 @SuppressLint("MissingPermission")138 @Override139 public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {140 if (newState == BluetoothProfile.STATE_CONNECTED) {141 Log.e("connect", "connect");142 } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {143 Log.e("connect", "disconnect");144 145 cleanupBluetoothGatt();146 }147 }148 };149 150 @SuppressLint("MissingPermission")151 private void requestPermission() {152 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {153 if (!(ContextCompat.checkSelfPermission(this, android.Manifest.permission.BLUETOOTH_SCAN) == PackageManager.PERMISSION_GRANTED &&154 ContextCompat.checkSelfPermission(this, android.Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_GRANTED &&155 ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED)) {156 ActivityCompat.requestPermissions(this,157 new String[]{158 android.Manifest.permission.BLUETOOTH_SCAN,159 android.Manifest.permission.BLUETOOTH_CONNECT,160 android.Manifest.permission.ACCESS_FINE_LOCATION 161 },162 PERMISSION_REQUEST_CODE);163 }164 } else {165 if (!(ContextCompat.checkSelfPermission(this, android.Manifest.permission.BLUETOOTH) == PackageManager.PERMISSION_GRANTED &&166 ContextCompat.checkSelfPermission(this, android.Manifest.permission.BLUETOOTH_ADMIN) == PackageManager.PERMISSION_GRANTED &&167 ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED)) {168 ActivityCompat.requestPermissions(this,169 new String[]{170 android.Manifest.permission.BLUETOOTH,171 android.Manifest.permission.BLUETOOTH_ADMIN,172 Manifest.permission.ACCESS_FINE_LOCATION 173 },174 PERMISSION_REQUEST_CODE);175 }176 177 }178 if (_adapter == null) {179 } else if (!_adapter.isEnabled()) {180 Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);181 startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);182 }183 }184 185 @SuppressLint("MissingPermission")186 private void cleanupBluetoothGatt() {187 if (_gatt != null) {188 _gatt.close();189 _gatt = null;190 Log.i("BluetoothGattCallback", "BluetoothGatt instance has been closed and set to null.");191 }192 }193 194}

試したこと

不具合の出る場合とでない場合のLogcatを見比べたり、公式を調べた

補足情報(FW/ツールのバージョンなど)

端末のBluetooth設定のON/OFFを行うと不具合が発生しなくなるため、おそらくキャッシュを削除すると不具合の解消になりそうだった。
しかし、ScanSettingでキャッシュが削除されていそうな記述を見つけられなかった。

コメントを投稿

0 コメント