Я пытаюсь интегрировать сопряжение устройств Companion для сопряжения моего устройства Bluetooth с другим устройством. Одно из моих устройств использует Android 15, а другое — Android 16. Я включил службу определения местоположения. Вот мой код
Я пытаюсь интегрировать сопряжение устройств Companion для сопряжения моего устройства Bluetooth с другим устройством. Одно из моих устройств использует Android 15, а другое — Android 16. Я включил службу определения местоположения. Вот мой код [code]class MainActivity : AppCompatActivity() {
private var isBluetoothEnabled = false private var isClient = false
private val bluetoothPermissionLauncher = registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions -> val allGranted = permissions.all { it.value } if (allGranted) { enableBluetooth() // You can now safely start pairing or communication } else { isBluetoothEnabled = false } }
private fun checkAndRequestBluetoothPermissions() { val neededPermissions = mutableListOf() Log.i("here123","1") when { Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { // Android 12 (API 31–32) neededPermissions.add(Manifest.permission.BLUETOOTH_CONNECT) neededPermissions.add(Manifest.permission.BLUETOOTH_SCAN) }
else -> { // Android 11 and below — no runtime permissions needed return } } Log.i("here123","2") val notGranted = neededPermissions.filter { ContextCompat.checkSelfPermission(this, it) != PackageManager.PERMISSION_GRANTED } Log.i("here123","3") if (notGranted.isNotEmpty()) { Log.i("here123","4") bluetoothPermissionLauncher.launch(notGranted.toTypedArray()) } else { Log.i("here123","5") enableBluetooth() } }
fun isLocationServiceEnabled(): Boolean { val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) || locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER) }
private fun enableBluetooth(){ if (!mBluetoothAdapter.isEnabled) { Log.i("here123","6") val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE) Log.i("here123","7") enableBluetoothLauncher.launch(enableBtIntent) } else { isBluetoothEnabled = true } }
private val enableBluetoothLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> isBluetoothEnabled = if (result.resultCode == RESULT_OK) { // User enabled Bluetooth true } else { // User cancelled or Bluetooth not enabled false } Log.i("here123","8")
if (!isLocationServiceEnabled()) { val intent = Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS) startActivity(intent) }
Log.i("here123","9") }
val classicBluetoothDeviceFilter = BluetoothDeviceFilter.Builder() .build()
val leBluetoothDeviceFilter = BluetoothLeDeviceFilter.Builder() .build()
private val pairingRequest: AssociationRequest = AssociationRequest.Builder() .addDeviceFilter(classicBluetoothDeviceFilter) .addDeviceFilter(leBluetoothDeviceFilter) .setSingleDevice(false) .build() private val deviceManager: CompanionDeviceManager by lazy { getSystemService(COMPANION_DEVICE_SERVICE) as CompanionDeviceManager } val mBluetoothAdapter: BluetoothAdapter by lazy { val java = BluetoothManager::class.java getSystemService(java)!!.adapter } val executor: Executor = Executor { it.run() }
private val chooserLauncher = registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) { result -> if (result.resultCode == RESULT_OK) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) { val deviceToPair: BluetoothDevice? = result.data?.getParcelableExtra(CompanionDeviceManager.EXTRA_DEVICE) val isConnected = deviceToPair?.createBond() Toast.makeText(this, "Connected: $isConnected", Toast.LENGTH_SHORT).show()
findViewById(R.id.connect).setOnClickListener { if(isBluetoothEnabled && isLocationServiceEnabled()){ findDevices() } else { Toast.makeText(this, "Please grant bluetooth permissions", Toast.LENGTH_SHORT).show() }
}
findViewById(R.id.send).setOnClickListener { if(isBluetoothEnabled && isLocationServiceEnabled()){ isClient = true val pairedDevices = mBluetoothAdapter.bondedDevices val device = pairedDevices.firstOrNull() // You can filter by name/MAC if (device != null) { ConnectThread(device).start() } else { Toast.makeText(this, "No paired devices found", Toast.LENGTH_SHORT).show() } } else { Toast.makeText(this, "Please grant bluetooth permissions and enable location ", Toast.LENGTH_SHORT).show() } }
findViewById(R.id.receive).setOnClickListener { if(isBluetoothEnabled && isLocationServiceEnabled()){ isClient = false AcceptThread().start() } else { Toast.makeText(this, "Please grant bluetooth permissions and enable location", Toast.LENGTH_SHORT).show() } } }
private fun findDevices() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { deviceManager.associate( pairingRequest, executor, object : CompanionDeviceManager.Callback() { // Called when a device is found. Launch the IntentSender so the user // can select the device they want to pair with. override fun onAssociationPending(intentSender: IntentSender) { chooserLauncher.launch(IntentSenderRequest.Builder(intentSender).build()) }
override fun onAssociationCreated(associationInfo: AssociationInfo) { // An association is created. Log.i("Hereeee3", associationInfo.toString()) val associationId = associationInfo.id val macAddress = associationInfo.deviceMacAddress
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { val isConnected = associationInfo.associatedDevice?.bluetoothDevice?.createBond() Toast.makeText(this@MainActivity, "Connected: $isConnected", Toast.LENGTH_SHORT).show() }
}
override fun onFailure(errorMessage: CharSequence?) { Log.i("Hereeee4", errorMessage.toString()) } }) } else { deviceManager.associate( pairingRequest, object : CompanionDeviceManager.Callback() { // Called when a device is found. Launch the IntentSender so the user // can select the device they want to pair with. override fun onDeviceFound(intentSender: IntentSender) { chooserLauncher.launch(IntentSenderRequest.Builder(intentSender).build()) }
fun cancel() { try { shouldLoop = false mmServerSocket?.close() } catch (e: IOException) { Log.e("Hereeee9", "Could not close the server socket", e) } } }
private inner class ConnectThread(device: BluetoothDevice) : Thread() { private val mmSocket: BluetoothSocket? by lazy(LazyThreadSafetyMode.NONE) { device.createRfcommSocketToServiceRecord(MY_UUID) }
override fun run() { mBluetoothAdapter.cancelDiscovery()
try { mmSocket?.connect() // Log.i("BluetoothClient", "Connected to ${device.name}") mmSocket?.let { manageMyConnectedSocket(it) } } catch (e: IOException) { // Log.e("BluetoothClient", "Could not connect to ${device.name}", e) try { mmSocket?.close() } catch (closeException: IOException) { Log.e("Hereeee10", "Could not close client socket", closeException) } } }
fun cancel() { try { mmSocket?.close() } catch (e: IOException) { Log.e("Hereeee11", "Could not close client socket", e) } } }
private var connectedThread: MyBluetoothService.ConnectedThread? = null
private fun manageMyConnectedSocket(socket: BluetoothSocket) { val bluetoothService = MyBluetoothService(handler) connectedThread = bluetoothService.ConnectedThread(socket) connectedThread?.start()
if (isClient) { // when (msg.what) { MESSAGE_READ -> { val readBuf = msg.obj as ByteArray val receivedMessage = String(readBuf, 0, msg.arg1) Log.i("Hereeee12", "Received: $receivedMessage") Toast.makeText(this, "Received: $receivedMessage", Toast.LENGTH_SHORT).show() true }
MESSAGE_WRITE -> { Log.i("Hereeee13", "Data sent successfully") true }