In my project we have a case, where a phone call is launched. We were using using following method to end active call (press on the red headphone button).
func endCallNow() {
let springboardApp = XCUIApplication(bundleIdentifier: "com.apple.springboard")
print(springboardApp.debugDescription)
springboardApp.buttons["End call"].tap()
}
This approach comes from this website https://beepscore.com/xcuitest-ios-app-phone-call/
It works perfectly well on iOS 12 and 13, but on iOS 14 "End call" button is not found in the view hierarchy.
This is what I get from springboardApp.debugDescription on iOS < 14:
Attributes: Application, pid: 1419, label: ' '
Element subtree:
→Application, 0x280c49180, pid: 1419, label: ' '
Window, 0x280c4b560, {{0.0, 0.0}, {320.0, 568.0}}
Other, 0x280c4b800, {{0.0, 0.0}, {320.0, 568.0}}
Other, 0x280c497a0, {{0.0, 0.0}, {320.0, 568.0}}
Window, 0x280c48380, {{0.0, 0.0}, {320.0, 568.0}}
Other, 0x280c48ee0, {{0.0, 0.0}, {320.0, 568.0}}
Window, 0x280c48fc0, {{0.0, 0.0}, {640.0, 1136.0}}
Other, 0x280c49880, {{0.0, 0.0}, {640.0, 1136.0}}
Window, 0x280c49960, {{0.0, 0.0}, {640.0, 1136.0}}
Other, 0x280c49a40, {{0.0, 0.0}, {640.0, 1136.0}}
Other, 0x280c49b20, {{0.0, 0.0}, {640.0, 1136.0}}
Other, 0x280c49c00, {{0.0, 0.0}, {640.0, 1136.0}}
Other, 0x280c49ce0, {{0.0, 0.0}, {640.0, 1136.0}}
Other, 0x280c49dc0, {{0.0, 0.0}, {640.0, 1136.0}}
Other, 0x280c49ea0, {{0.0, 0.0}, {640.0, 1136.0}}
Other, 0x280c49f80, {{0.0, 0.0}, {640.0, 1136.0}}
Other, 0x280c4b020, {{0.0, 0.0}, {640.0, 1136.0}}
Other, 0x280c4b2c0, {{0.0, 0.0}, {640.0, 1136.0}}
Other, 0x280c4b3a0, {{0.0, 0.0}, {640.0, 1136.0}}
Other, 0x280c4b100, {{0.0, 0.0}, {640.0, 1136.0}}
Other, 0x280c4b1e0, {{0.0, 0.0}, {640.0, 1136.0}}
Window, 0x280c4a4c0, {{0.0, 0.0}, {320.0, 568.0}}
Other, 0x280c4ae60, {{0.0, 0.0}, {320.0, 568.0}}
Other, 0x280c4af40, {{0.0, 0.0}, {320.0, 568.0}}
Other, 0x280c4aca0, {{0.0, 0.0}, {320.0, 568.0}}
Other, 0x280c4ad80, {{0.0, 0.0}, {320.0, 568.0}}
Other, 0x280c4aae0, {{0.0, 0.0}, {320.0, 568.0}}
Other, 0x280c4abc0, {{0.0, 0.0}, {320.0, 568.0}}
Other, 0x280c4a920, {{0.0, 0.0}, {320.0, 568.0}}
Other, 0x280c4aa00, {{0.0, 0.0}, {320.0, 568.0}}
Other, 0x280c4a760, {{0.0, 0.0}, {320.0, 568.0}}
Other, 0x280c42f40, {{0.0, 0.0}, {320.0, 568.0}}
Other, 0x280c43480, {{0.0, 0.0}, {320.0, 568.0}}
Other, 0x280c42920, {{0.0, 0.0}, {320.0, 568.0}}
Other, 0x280c42220, {{0.0, 0.0}, {320.0, 568.0}}
Other, 0x280c424c0, {{0.0, 0.0}, {320.0, 568.0}}
Other, 0x280c42bc0, {{0.0, 0.0}, {320.0, 568.0}}
Other, 0x280c42300, {{0.0, 0.0}, {320.0, 568.0}}
Other, 0x280c41c00, {{0.0, 0.0}, {320.0, 568.0}}
Other, 0x280c41dc0, {{0.0, 0.0}, {320.0, 568.0}}
Other, 0x280c4a840, {{0.0, 0.0}, {320.0, 568.0}}
StatusBar, 0x280c4a5a0, {{0.0, 0.0}, {320.0, 20.0}}
Window, 0x280c4a680, {{0.0, 0.0}, {320.0, 568.0}}
StatusBar, 0x280c4a060, {{0.0, 0.0}, {320.0, 20.0}}
Window (Main), 0x280c4a140, {{0.0, 0.0}, {320.0, 568.0}}
Other, 0x280c4a300, {{0.0, 0.0}, {320.0, 568.0}}
Other, 0x280c4a3e0, {{0.0, 0.0}, {320.0, 568.0}}
Other, 0x280c4a220, {{0.0, 0.0}, {320.0, 568.0}}
Other, 0x280c4b8e0, {{0.0, 0.0}, {320.0, 568.0}}
Other, 0x280c4b9c0, {{0.0, 0.0}, {320.0, 568.0}}
Other, 0x280c4baa0, {{0.0, 0.0}, {320.0, 568.0}}
Other, 0x280c4bb80, {{0.0, 0.0}, {320.0, 568.0}}
Other, 0x280c4bc60, {{0.0, 0.0}, {320.0, 568.0}}
StatusBar, 0x280c4bd40, {{0.0, 0.0}, {320.0, 20.0}}
Other, 0x280c4be20, {{0.0, 0.0}, {320.0, 20.0}}
Other, 0x280c4bf00, {{0.0, 0.0}, {320.0, 20.0}}
Other, 0x280c46f40, {{6.5, 4.5}, {16.5, 10.5}}, label: 'Mobile Data', value: 4 of 4 bars, signa...
StaticText, 0x280c472c0, {{27.0, 3.0}, {30.0, 14.5}}, label: 'PLAY'
Other, 0x280c4c000, {{61.0, 4.5}, {15.5, 11.0}}, identifier: '3 of 3 Wi-Fi bars', value: SSID, 3 of 3 Wi-Fi...
StaticText, 0x280c4c0e0, {{143.5, 3.0}, {33.0, 14.5}}, label: '12:23'
Image, 0x280c4c1c0, {{223.5, 4.5}, {12.5, 11.5}}, label: 'Orientation Locked'
Image, 0x280c4c2a0, {{240.0, 4.5}, {10.0, 11.0}}, label: 'Location tracking on'
StaticText, 0x280c4c380, {{254.0, 3.0}, {34.5, 14.5}}, label: '100 %'
Other, 0x280c4c460, {{290.5, 4.0}, {24.0, 11.5}}, label: '100 % battery power', value: Charging
Other, 0x280c4c540, {{0.0, 0.0}, {320.0, 568.0}}
Other, 0x280c4c620, {{0.0, 0.0}, {320.0, 568.0}}
Other, 0x280c4c700, {{0.0, 0.0}, {320.0, 568.0}}
RemotePlaceholder, 0x280c4c7e0, pid: 1419, {{0.0, 0.0}, {320.0, 568.0}}
Other, 0x280c4c8c0, {{0.0, 0.0}, {320.0, 568.0}}
Other, 0x280c4c9a0, {{0.0, 0.0}, {320.0, 568.0}}
Other, 0x280c4ca80, {{0.0, 0.0}, {320.0, 568.0}}
Other, 0x280c4cb60, {{0.0, 0.0}, {320.0, 568.0}}
Other, 0x280c4cc40, {{0.0, 0.0}, {320.0, 568.0}}
Other, 0x280c4cd20, {{0.0, 0.0}, {320.0, 568.0}}
Other, 0x280c4ce00, {{0.0, 0.0}, {320.0, 568.0}}
Other, 0x280c4cee0, {{0.0, 0.0}, {320.0, 568.0}}
Other, 0x280c4cfc0, {{0.0, 0.0}, {320.0, 568.0}}
Other, 0x280c4d0a0, {{0.0, 0.0}, {320.0, 568.0}}
Other, 0x280c4d180, {{0.0, 0.0}, {320.0, 568.0}}
Other, 0x280c4d260, {{0.0, -27.5}, {320.0, 126.0}}
Other, 0x280c4d340, {{0.0, -1.5}, {320.0, 100.0}}, identifier: 'PHSingleCallParticipantLabelView'
StaticText, 0x280c4d420, {{24.0, 37.5}, {272.0, 43.0}}, identifier: 'PHMarqueeView', label: '+49 30 991918720'
Other, 0x280c4d500, {{135.0, 81.0}, {50.0, 21.5}}
Button, 0x280c4d5e0, {{135.0, 81.0}, {50.0, 21.5}}, identifier: 'PHSingleCallParticipantLabelView_StatusLabel', label: '00:02'
Other, 0x280c4d6c0, {{0.0, 167.0}, {320.0, 210.0}}
Button, 0x280c4d7a0, {{22.5, 167.0}, {75.0, 75.0}}, label: 'mute'
StaticText, 0x280c4d880, {{41.5, 248.0}, {37.0, 20.0}}, label: 'mute'
Button, 0x280c4d960, {{122.5, 167.0}, {75.0, 75.0}}, label: 'keypad'
StaticText, 0x280c41ce0, {{133.5, 248.0}, {53.0, 20.0}}, label: 'keypad'
Button, 0x280c42a00, {{222.5, 167.0}, {75.0, 75.0}}, label: 'speaker'
StaticText, 0x280c41ea0, {{231.0, 248.0}, {58.0, 20.0}}, label: 'speaker'
Button, 0x280c42060, {{22.5, 282.0}, {75.0, 75.0}}, label: 'add call'
StaticText, 0x280c42ae0, {{31.5, 363.0}, {57.0, 20.0}}, label: 'add call'
Button, 0x280c42680, {{122.5, 282.0}, {75.0, 75.0}}, label: 'FaceTime video'
StaticText, 0x280c43640, {{125.5, 363.0}, {69.0, 20.0}}, label: 'FaceTime'
Button, 0x280c438e0, {{222.5, 282.0}, {75.0, 75.0}}, label: 'contacts'
StaticText, 0x280c43d40, {{228.0, 363.0}, {64.0, 20.0}}, label: 'contacts'
Other, 0x280c43e20, {{0.0, 339.0}, {320.0, 229.0}}
Button, 0x280c43f00, {{50.0, 455.0}, {30.0, 32.0}}, Disabled
StaticText, 0x280c439c0, {{50.0, 455.0}, {0.0, 0.0}}
Button, 0x280c43aa0, {{124.0, 435.0}, {72.0, 72.0}}, label: 'End call'
StaticText, 0x280c43c60, {{124.0, 435.0}, {0.0, 0.0}}
Window, 0x280c43b80, {{0.0, 0.0}, {320.0, 568.0}}
Other, 0x280c43800, {{0.0, 0.0}, {320.0, 568.0}}
Other, 0x280c43720, {{0.0, 0.0}, {320.0, 568.0}}
Other, 0x280c42ca0, {{0.0, 568.0}, {320.0, 216.0}}
RemotePlaceholder, 0x280c42840, pid: 1419, {{0.0, 0.0}, {320.0, 568.0}}
Other, 0x280c42760, {{0.0, 0.0}, {320.0, 568.0}}
Other, 0x280c50000, {{0.0, 0.0}, {320.0, 568.0}}
Window, 0x280c500e0, {{0.0, 0.0}, {320.0, 568.0}}
Other, 0x280c501c0, {{0.0, 0.0}, {320.0, 568.0}}
RemotePlaceholder, 0x280c502a0, pid: 1419, {{0.0, 0.0}, {320.0, 568.0}}
Other, 0x280c50380, {{0.0, 0.0}, {320.0, 568.0}}
Window, 0x280c50460, {{0.0, 0.0}, {320.0, 568.0}}
Other, 0x280c50540, {{0.0, 0.0}, {320.0, 568.0}}
Path to element:
→Application, 0x280c49180, pid: 1419, label: ' '
Query chain:
→Find: Application 'com.apple.springboard'
Output: {
Application, pid: 1419, label: ' '
}
^ You can see that the end call button is at the bottom of view hierarchy.
And this is what’s printed for iOS 14.2:
Attributes: Application, pid: 60, label: ' '
Element subtree:
→Application, 0x2807b90a0, pid: 60, label: ' '
Window, 0x2807b8620, {{0.0, 0.0}, {375.0, 812.0}}
Other, 0x2807a4460, {{0.0, 0.0}, {375.0, 812.0}}
Other, 0x2807a4540, {{0.0, 0.0}, {375.0, 812.0}}
Other, 0x2807a42a0, {{0.0, 0.0}, {375.0, 812.0}}
Other, 0x2807a4700, {{0.0, 0.0}, {375.0, 812.0}}
Other, 0x2807a47e0, {{0.0, 0.0}, {375.0, 812.0}}
Window, 0x2807a56c0, {{0.0, 0.0}, {375.0, 812.0}}
Other, 0x2807a57a0, {{0.0, 0.0}, {375.0, 812.0}}
Window, 0x2807a48c0, {{0.0, 0.0}, {1125.0, 2436.0}}
Other, 0x2807a4d20, {{0.0, 0.0}, {1125.0, 2436.0}}
Window, 0x2807a4e00, {{0.0, 0.0}, {1125.0, 2436.0}}
Other, 0x2807a55e0, {{0.0, 0.0}, {1125.0, 2436.0}}
Other, 0x2807a5500, {{0.0, 0.0}, {1125.0, 2436.0}}
Other, 0x2807a4ee0, {{0.0, 0.0}, {1125.0, 2436.0}}
Other, 0x2807a4fc0, {{0.0, 0.0}, {1125.0, 2436.0}}
Other, 0x2807a50a0, {{0.0, 0.0}, {1125.0, 2436.0}}
Other, 0x2807a5180, {{0.0, 0.0}, {1125.0, 2436.0}}
Other, 0x2807a5420, {{0.0, 0.0}, {1125.0, 2436.0}}
Other, 0x2807a5340, {{0.0, 0.0}, {1125.0, 2436.0}}
Other, 0x2807a5260, {{0.0, 0.0}, {1125.0, 2436.0}}
Other, 0x2807a49a0, {{0.0, 0.0}, {1125.0, 2436.0}}
Other, 0x2807a4a80, {{0.0, 0.0}, {1125.0, 2436.0}}
Other, 0x2807a4c40, {{0.0, 0.0}, {1125.0, 2436.0}}
Other, 0x2807a4b60, {{0.0, 0.0}, {1125.0, 2436.0}}
Other, 0x2807a4620, {{0.0, 0.0}, {1125.0, 2436.0}}
Window (Main), 0x2807b8540, {{0.0, 0.0}, {375.0, 812.0}}
Other, 0x2807b8d20, {{0.0, 0.0}, {375.0, 812.0}}
Other, 0x2807b9340, {{0.0, 0.0}, {375.0, 812.0}}
Other, 0x2807b9420, {{0.0, 0.0}, {375.0, 812.0}}
Other, 0x2807b8460, {{0.0, 0.0}, {375.0, 812.0}}
Other, 0x2807b9500, {{0.0, 0.0}, {375.0, 812.0}}
Other, 0x2807b82a0, {{0.0, 0.0}, {375.0, 812.0}}
Other, 0x2807b8380, {{0.0, 0.0}, {375.0, 812.0}}
Other, 0x2807b8fc0, {{0.0, 0.0}, {375.0, 812.0}}
Other, 0x2807b8ee0, {{0.0, 0.0}, {375.0, 812.0}}
Other, 0x2807b8700, {{0.0, 0.0}, {375.0, 812.0}}
Other, 0x2807b87e0, {{0.0, 0.0}, {375.0, 812.0}}
Other, 0x2807a0620, {{0.0, 0.0}, {375.0, 812.0}}
Other, 0x2807a08c0, {{0.0, 0.0}, {375.0, 812.0}}
Other, 0x2807a1960, {{0.0, 0.0}, {375.0, 812.0}}
Other, 0x2807a1880, {{0.0, 0.0}, {375.0, 812.0}}
Other, 0x2807a15e0, {{0.0, 0.0}, {375.0, 812.0}}
Other, 0x2807a09a0, {{0.0, 0.0}, {375.0, 812.0}}
Other, 0x2807a0c40, {{0.0, 0.0}, {375.0, 812.0}}
Other, 0x2807a0d20, {{0.0, 0.0}, {375.0, 812.0}}, identifier: 'Home Grabber'
Other, 0x2807a0e00, {{120.7, 799.0}, {134.0, 5.0}}
Other, 0x2807a1260, {{185.0, 799.0}, {5.0, 5.0}}
Other, 0x2807a1340, {{0.0, 0.0}, {375.0, 812.0}}
Other, 0x2807a1a40, {{0.0, 0.0}, {375.0, 812.0}}
Other, 0x2807a1420, {{0.0, 0.0}, {375.0, 812.0}}
Other, 0x2807a1500, {{0.0, 0.0}, {375.0, 812.0}}
StatusBar, 0x2807a16c0, {{0.0, 0.0}, {375.0, 44.0}}
Other, 0x2807a17a0, {{0.0, 0.0}, {375.0, 44.0}}
Other, 0x2807a0ee0, {{0.0, 0.0}, {375.0, 44.0}}
StaticText, 0x2807a0fc0, {{20.0, 14.0}, {40.3, 18.0}}, label: '12:28'
Image, 0x2807a1180, {{63.0, 17.7}, {10.7, 10.7}}, label: 'Location tracking on'
Other, 0x2807a10a0, {{294.0, 17.7}, {17.0, 10.7}}, label: 'Mobile Data', value: 3 of 4 bars, signa...
Other, 0x2807a0b60, {{316.0, 17.3}, {15.3, 11.0}}, identifier: '3 of 3 Wi-Fi bars', value: SSID, 3 of 3 Wi-Fi...
Other, 0x2807a0a80, {{336.3, 17.3}, {24.3, 11.3}}, label: '96% battery power', value: Charging
Window, 0x2807a0700, {{0.0, 0.0}, {375.0, 812.0}}
StatusBar, 0x2807a1b20, {{0.0, 0.0}, {375.0, 44.0}}
Window, 0x2807a1c00, {{0.0, 0.0}, {375.0, 812.0}}
Other, 0x2807a1ce0, {{0.0, 0.0}, {375.0, 812.0}}
Other, 0x2807a1dc0, {{0.0, 0.0}, {375.0, 812.0}}
Other, 0x2807a1ea0, {{0.0, 812.0}, {375.0, 233.0}}
Window, 0x2807a1f80, {{0.0, 0.0}, {375.0, 812.0}}
Other, 0x2807a2060, {{0.0, 0.0}, {375.0, 812.0}}
Window, 0x2807adf80, {{0.0, 0.0}, {375.0, 812.0}}
Other, 0x2807ae060, {{0.0, 0.0}, {375.0, 812.0}}
Window, 0x2807aea00, {{0.0, 0.0}, {375.0, 812.0}}
Other, 0x2807aeae0, {{0.0, 0.0}, {375.0, 812.0}}
Other, 0x2807aebc0, {{299.5, 6.5}, {4.3, 4.3}}, label: 'Microphone in use'
Path to element:
→Application, 0x2807b90a0, pid: 60, label: ' '
Query chain:
→Find: Application 'com.apple.springboard'
Output: {
Application, pid: 60, label: ' '
}
It looks like there are no phone call app buttons, labels in debugDescription. I can see controls of the top status bar only (wifi, battery levels etc).
Does anyone encountered similar problem in iOS 14 automation and give some hints on how to solve that?
Is there maybe a dedicated app that handles calls in iOS 14+, and it’s not springboard anymore?
Thank you for any hints! 🙂
2
Answers
You can try to inspect what application is displayed by reading Apple’s Console application output.
Probably, you need to interact with the Phone application instead of Springboard
Bundle identifiers of iOS apps:
https://github.com/rzakhar/XCTApps/blob/master/Sources/XCTApps/iOS.swift
Not sure if this is exactly the same problem, but I encountered something similar when automating phone calls. In the end I found that once the "Call" button is pressed, the app that handles the call is not the same as the one that dialed the number.
I accessed the call app which has bundle id "com.apple.InCallService", then I was able to press the "End call" button.