@@ -650,6 +650,11 @@ class AirPodsService : Service(), SharedPreferences.OnSharedPreferenceChangeList
650650 connectionReceiver = object : BroadcastReceiver () {
651651 override fun onReceive (context : Context ? , intent : Intent ? ) {
652652 if (intent?.action == AirPodsNotifications .AIRPODS_CONNECTION_DETECTED ) {
653+ if (::socket.isInitialized && socket.isConnected) {
654+ Log .d(TAG , " Connection broadcast received but socket already connected, ignoring" )
655+ return
656+ }
657+
653658 device = if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .TIRAMISU ) {
654659 intent.getParcelableExtra(" device" , BluetoothDevice ::class .java)!!
655660 } else {
@@ -2360,6 +2365,13 @@ class AirPodsService : Service(), SharedPreferences.OnSharedPreferenceChangeList
23602365
23612366 @Suppress(" ClassName" )
23622367 private object bluetoothReceiver : BroadcastReceiver() {
2368+ private fun sendDetected (context : Context ? , name : String? , device : BluetoothDevice ) {
2369+ val intent = Intent (AirPodsNotifications .AIRPODS_CONNECTION_DETECTED )
2370+ intent.putExtra(" name" , name)
2371+ intent.putExtra(" device" , device)
2372+ context?.sendBroadcast(intent)
2373+ }
2374+
23632375 @SuppressLint(" MissingPermission" )
23642376 override fun onReceive (context : Context ? , intent : Intent ) {
23652377 val bluetoothDevice = if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .TIRAMISU ) {
@@ -2375,16 +2387,20 @@ class AirPodsService : Service(), SharedPreferences.OnSharedPreferenceChangeList
23752387 ?.getString(" name" , bluetoothDevice?.name)
23762388 if (bluetoothDevice != null && ! action.isNullOrEmpty()) {
23772389 Log .d(TAG , " Received bluetooth connection broadcast: action=$action " )
2390+ val uuid = ParcelUuid .fromString(" 74ec2172-0bad-4d01-8f77-997b2be0722a" )
23782391 if (BluetoothDevice .ACTION_ACL_CONNECTED == action) {
2379- val uuid = ParcelUuid .fromString(" 74ec2172-0bad-4d01-8f77-997b2be0722a" )
2380- bluetoothDevice.fetchUuidsWithSdp()
2381- if (bluetoothDevice.uuids != null ) {
2382- if (bluetoothDevice.uuids.contains(uuid)) {
2383- val intent = Intent (AirPodsNotifications .AIRPODS_CONNECTION_DETECTED )
2384- intent.putExtra(" name" , name)
2385- intent.putExtra(" device" , bluetoothDevice)
2386- context?.sendBroadcast(intent)
2387- }
2392+ if (bluetoothDevice.uuids?.contains(uuid) == true ) {
2393+ sendDetected(context, name, bluetoothDevice)
2394+ } else {
2395+ bluetoothDevice.fetchUuidsWithSdp()
2396+ }
2397+ } else if (" android.bluetooth.device.action.UUID" == action) {
2398+ val savedMac = context?.getSharedPreferences(" settings" , MODE_PRIVATE )
2399+ ?.getString(" mac_address" , " " ) ? : " "
2400+ val matchedByMac = savedMac.isNotEmpty() && bluetoothDevice.address == savedMac
2401+ val matchedByUuid = bluetoothDevice.uuids?.contains(uuid) == true
2402+ if (matchedByUuid || matchedByMac) {
2403+ sendDetected(context, name, bluetoothDevice)
23882404 }
23892405 }
23902406 }
@@ -2642,7 +2658,7 @@ class AirPodsService : Service(), SharedPreferences.OnSharedPreferenceChangeList
26422658
26432659 @SuppressLint(" MissingPermission" , " UnspecifiedRegisterReceiverFlag" )
26442660 fun connectToSocket (
2645- adapter : BluetoothAdapter , device : BluetoothDevice , manual : Boolean = false
2661+ adapter : BluetoothAdapter , device : BluetoothDevice , manual : Boolean = false, retriesLeft : Int = if (manual) 0 else 3
26462662 ) {
26472663 Log .d(TAG , " <LogCollector:Start> Connecting to socket" )
26482664 val uuid: ParcelUuid = ParcelUuid .fromString(" 74ec2172-0bad-4d01-8f77-997b2be0722a" )
@@ -2701,6 +2717,15 @@ class AirPodsService : Service(), SharedPreferences.OnSharedPreferenceChangeList
27012717 Log .d(
27022718 TAG , " <LogCollector:Complete:Failed> Socket not connected, ${e.message} "
27032719 )
2720+ if (retriesLeft > 0 ) {
2721+ Log .d(TAG , " Retrying socket connect, $retriesLeft attempts left" )
2722+ try { socket.close() } catch (_: Exception ) {}
2723+ CoroutineScope (Dispatchers .IO ).launch {
2724+ delay(500L )
2725+ connectToSocket(adapter, device, manual, retriesLeft - 1 )
2726+ }
2727+ return @withTimeout
2728+ }
27042729 if (manual) {
27052730 sendToast(
27062731 " Couldn't connect to socket: ${e.localizedMessage} "
@@ -2715,6 +2740,15 @@ class AirPodsService : Service(), SharedPreferences.OnSharedPreferenceChangeList
27152740 }
27162741 if (! socket.isConnected) {
27172742 Log .d(TAG , " <LogCollector:Complete:Failed> Socket not connected" )
2743+ if (retriesLeft > 0 ) {
2744+ Log .d(TAG , " Retrying socket connect after timeout, $retriesLeft attempts left" )
2745+ try { socket.close() } catch (_: Exception ) {}
2746+ CoroutineScope (Dispatchers .IO ).launch {
2747+ delay(500L )
2748+ connectToSocket(adapter, device, manual, retriesLeft - 1 )
2749+ }
2750+ return
2751+ }
27182752 if (manual) {
27192753 sendToast(
27202754 " Couldn't connect to socket: timeout."
0 commit comments