Почему при сопряжении устройств Companion не удается обнаружить мое устройство?Android

Форум для тех, кто программирует под Android
Ответить
Anonymous
 Почему при сопряжении устройств Companion не удается обнаружить мое устройство?

Сообщение Anonymous »

Я пытаюсь интегрировать сопряжение устройств Companion для сопряжения моего устройства Bluetooth с другим устройством. Одно из моих устройств использует Android 15, а другое — Android 16. Я включил службу определения местоположения. Вот мой код

Код: Выделить всё

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()

} else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.TIRAMISU) {
val deviceToPair: BluetoothDevice? = result.data?.getParcelableExtra(
CompanionDeviceManager.EXTRA_DEVICE,
BluetoothDevice::class.java
)
val isConnected = deviceToPair?.createBond()
Toast.makeText(this, "Connected: $isConnected", Toast.LENGTH_SHORT).show()
}
} else {
Log.i("Hereeee2", "User cancelled device selection")
}
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContentView(R.layout.activity_main)
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
}

checkAndRequestBluetoothPermissions()

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())
}

override fun onFailure(error: CharSequence?) {
Log.i("Hereeee41", error.toString())
}
}, null
)
}
}

private val NAME = "MyBluetoothApp"
private val MY_UUID: UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB") // SPP UUID

private inner class AcceptThread : Thread() {
private val mmServerSocket: BluetoothServerSocket? by lazy(LazyThreadSafetyMode.NONE) {
mBluetoothAdapter.listenUsingInsecureRfcommWithServiceRecord(NAME, MY_UUID)
}

var shouldLoop = true

override fun run() {
// Keep listening until exception occurs or a socket is returned.

while (shouldLoop) {
val socket: BluetoothSocket? = try {
mmServerSocket?.accept()
} catch (e: IOException) {
Log.e("Hereeee8", "Socket's accept() method failed", e)
shouldLoop = false
null
}
socket?.also {
manageMyConnectedSocket(it)
mmServerSocket?.close()
shouldLoop = false
}
}
}

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
}

MESSAGE_TOAST -> {
Toast.makeText(this, msg.data.getString("toast"), Toast.LENGTH_SHORT).show()
true
}

else ->  false
}
}

companion object {
private const val TAG = "Hereeee22"
const val MESSAGE_READ = 0
const val MESSAGE_WRITE = 1
const val MESSAGE_TOAST = 2
}

private inner class MyBluetoothService(private val handler: Handler) {

inner class ConnectedThread(private val mmSocket: BluetoothSocket) : Thread() {

private val mmInStream: InputStream = mmSocket.inputStream
private val mmOutStream: OutputStream = mmSocket.outputStream
private val mmBuffer: ByteArray = ByteArray(1024)

override fun run() {
var numBytes: Int
while (true) {
numBytes = try {
mmInStream.read(mmBuffer)
} catch (e: IOException) {
Log.d(TAG, "Input stream was disconnected", e)
break
}

val readMsg = handler.obtainMessage(
MESSAGE_READ, numBytes, -1, mmBuffer.clone() // clone buffer
)
readMsg.sendToTarget()
}
}

fun write(bytes: ByteArray) {
try {
mmOutStream.write(bytes)
val writtenMsg = handler.obtainMessage(MESSAGE_WRITE, -1, -1, bytes)
writtenMsg.sendToTarget()
} catch (e: IOException) {
Log.e(TAG, "Error occurred when sending data", e)
val writeErrorMsg = handler.obtainMessage(MESSAGE_TOAST)
val bundle = Bundle().apply {
putString("toast", "Couldn't send data to the other device")
}
writeErrorMsg.data = bundle
handler.sendMessage(writeErrorMsg)
}
}

fun cancel() {
try {
mmSocket.close()
} catch (e: IOException) {
Log.e(TAG, "Could not close the connect socket", e)
}
}
}

fun startCommunication(socket: BluetoothSocket) {
ConnectedThread(socket).start()
}
}

}
Я также добавил необходимое разрешение в AndroidManifest Я вижу другие устройства, но не то, которое мне нужно
Изображение

Я также включил Bluetooth и определение местоположения на другом устройстве
Вот полный исходный код

Подробнее здесь: https://stackoverflow.com/questions/798 ... -my-device
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Android»