Making a phone call in Robot Framework Appium

How to make a phone call in Robot Framework Appium?

Hi

Are you asking for the coded solution, or have you come into some trouble when trying to do it? assuming you have set up your device and so forth, you can do something similar to the below:

*** Settings ***
Library     Collections
Library     String

*** Keywords ***
Enter Phone Number 
    [Arguments]        ${phone_number}   
    &{dct_numbers}=     Create Dictionary    
    ...    num1=one     
    ...    mum2=two     
    ...    num3=three     
    ...    num4=four     
    ...    num5=five     
    ...    num6=six     
    ...    num7=seven     
    ...    num8=eight     
    ...    num9=nine     
    ...    num0=zero 
    
    @{lst_num}=       String.Split String To Characters     ${phone_number}  
    FOR    ${num}     IN      @{lst_num}
        AppiumLibrary.Click Element        id=com.samsung.android.contacts:id/${dct_numbers.num${num}}        # Click numbers
    END

*** Test Cases ***
Test Case 1  
    AppiumLibrary.Activate Application    com.samsung.android.contacts                           # Opens contacts
    AppiumLibrary.Click Element    id=com.samsung.android.contacts:id/floating_action_button     # Click green floating button
    Enter Phone Number        phone_number=07791176178
    AppiumLibrary.Click Element        id=com.samsung.android.contacts:id/dialButtonImage        # Click dial 

In the example above, activating the application with id=* for my device (locators above may differ for you) and this should open contacts, then I click upon a floating button that opens the keypad on my device, pass the phone number and then click each key (I have not tested this, but the general basis will be the same once you understand the path your device takes)

Note: Ive never had the need to make a phone call on a device with Appium, and this was thrown together quickly for a given example based on a real device I use to automate against, so the ids may differ, my key pad ids for the numbers show as …/one …/two and so forth at the end of the id value to why Ive used a dictionary, the above has been put together as a quick example, there are probably cleaner ways of throwing it all together. I would also make use of AppiumLibrary.Wait Until Element Is Visible between the views and handle it appropriately as you would.

I hope that helps atleast

Note: Link to code playground - I have also not added AppiumLibrary to the *** Settings *** I’m sure you have that all set up already.

2 Likes

Hi, Daryl !
Thanks for the prompt response.
I had a few queries to ask:

  1. I had use open application keyword instead of activate application, it works fine on emulator but when i try to run it on a physical device(relame c15 Quantium Edition) connected to laptop via cable, i get the below error:
    java.lang.SecurityException: adb clearing user data is forbidden.
    at com.android.server.pm.ColorClearDataProtectManager.interceptClearUserDataIfNeeded(ColorClearDataProtectManager.java:87) at com.android.server.pm.OppoBasePackageManagerService$OppoPackageManagerInternalImpl.interceptClearUserDataIfNeeded(OppoBasePackageManagerService.java:5 00) …

2: when i try to “ls” the data folder in either emulator or physical device i get the below the error:
ls: .: Permission denied

When i try to run command “sudo ls”, it gives;
/system/bin/sh: sudo: inaccessible or not found

3: How to detect, when i call a person whether he pick the call or not?

Your prompt response would be appreciated.

Hi

You’d have to share a little code to get a better idea on how you have your setup, but I think the below should answer all:

Activate Application activates the application if it is not running or is running in the background, whereas Open Application Opens a new application to given Appium server, I dont use them interchangeable I will open my application without an app in my current project, and then activate an application there after, an example below for how I have that setup:

# Test Setup            AppiumLibrary.Open Application  http://127.0.0.1:4723/wd/hub      platformName=${ANDROID_PLATFORM_NAME}    automationName=${ANDROID_AUTOMATION_NAME}
# ...                   autoGrantPermissions=true     noReset=true     fullReset=false      skipUnlock=false     appium:chromedriverExecutable=/path/to/chromedriver     appium:newCommandTimeout=150

And then run the keyword Activate Application to jump from and to applications while I’m connected to the device while closing the applications as I go or via a test teardown (but it really is down to what your trying to achieve).

Point 1 - The error your seeing could be as simple as this part: noReset=true fullReset=true I tend to use fullRest=false, but you’d have to have a play, but you do mention the " open application keyword instead of activate application" which activate application only takes a single argument of app_id, so if you have switched open application out for that and kept all your arguments, then that may be why as well, my example above to your og post was a way off opening contacts while you had a connection and carrying out making a call (well for how my device handles it)

Point 2 - From what I understand, you need root access for most real devices, so if your device isn’t rooted, then you wont be able to access it with what your trying to do as well as other Adb commands, whereas on emulators you wont have such problems, I have also had root issues with transferring file via adb in the past and I have had to code together some windows UI automation to do what I needed, As though I could easily root my device, the use of my automation wouldnt be against rooted devices (but if you root the device, you’d want to have a good look and read into it before doing so, but again really depends on your use case)

Point 3 is as simple as once you make the call by clicking, the state/view should change, and when its answered, you’d likely need to call another device and answer, capture the view while making the call and once answered, grab the automation IDs for what you need, and then build out your logic, AppiumLibrary.Wait Until Element Is Visible etc… Wait Until Element Is Visible take a timeout argument, so set that accordingly, but youd want to factor in answer phone, etc… but the general basis is the same.

I Hope that helps

2 Likes

Hi Daryl,

I have successfully made a phone call to a number using appium , but now the problem is how do I detect whether the person has picked the call or not.
I tried one method, which is when a person picks a call the timer shows up in phone app as can be seen in (2.jpeg), but when i try to find to find the locator of it using uiautomatorviewer, i get the below error message:

Error while obtaining Ui hierarchy XML file: com.android.ddmlib.SyncException:Remote object does not exist!

Let me know if any alternative method would work.

1 Like

Hi

You might be able to get around the error “Ui hierarchy XML file: com.android.ddmlib.SyncException:Remote object” by closing of uiautomatorviewer and then reopening, and then trying to capture while that call is happening, I have had this happen occasionally (not with a call, but when state changes), or you could try the “Device Screenshot (uiautomator dump)” second option in the app, or if that is what you are using, then try the third option “Device Screensgit with Compressed Hierarchy (uiautomator dump --compreseed)” but at times ive had one work over the other:
image

You can also try using the adb command:

adb shell dumpsys activity <package>/<activity>

So for me, the package name is com.samsung.android.contacts

adb shell dumpsys activity com.samsung.android.contacts 

The dump is not so pretty, but it will return all …id/value so you may find it in that if the app aint working, and it will look something like the below:

Failing that I can probably find a sim and give it a go at capturing it myself to see what changes, but it could be due to that number changing in real time to why it can’t capture it, maybe ending the call (not sure if the numbered value will remain after) and then try capturing the id for that value, as it should ideally be the same id, as you’d really only be looking to see if it existed in the first instance.

I will try to get a SIM, though

1 Like

I tried "Device Screenshot (uiautomator dump) ", it does take a screenshot but i can’t see the locator of the timer(call duration) as can be seen in the attached snap.

I also tried the dumpsys method but can’t figure it out.

Yeah you might not be able to then due to the nature of the element, I have a sim but away from my desk. But when I’m back il have a look.

Then please give me an update.

Hi

It wasnt as painful as I thought it might have been. You will need to use the adb command to get the dump rather than the uiautomatorviewer due to the state it goes into.

adb shell dumpsys activity <package>/<activity>

my package/activity name was: com.android.incallui.InCallActivity

To get the activity, as I wasnt able to via uiautomatorviewer due to how it is behaving here, so I made an active call, and while active, I ran a basic test that did the below:

*** Test Cases ***
Test - call
    [Tags]  call-answered-test
    ${act}=    AppiumLibrary.Get Activity
    Log To Console    \n${act}

image

Then I called the command via adb adb shell dumpsys activity com.android.incallui.InCallActivity

The first part of the activity is what you are after in the dump^, as highlighted above, com.samsung.android.incallui and then I used the appium keyword AppiumLibrary.Get Webelements to determine how many elements, tbh, I got lazy and just took the first one from the list returned; in most cases, there was only one element (but you can clean this up, just wanted to keep to the steps I took so you can follow along).

So in terms of my elapsed time, I was able to get it with the below:

@{elasped_time}=    AppiumLibrary.Get Webelements    id=com.samsung.android.incallui:id/elapsedTime
Log To Console    ${elasped_time}[0]
${elasped_time_value}=    AppiumLibrary.Get Text    ${elasped_time}[0]
Log To Console    elasped:${elasped_time_value}

image

my device screen just for visibility:

Note: My screenshot elapsed time (top left) wont align to my output as was taken at the start and ran few times after (just incase you’re wondering)

Anyways, that dump from adb will give you all the ID values (copy to notepad if you must, notepad++ is a solid choice, remove the crap and then just go through it). You’ll just want to play around with it, but once you can interact with one, then you should be good. Hopefully, this process above follows easily, and I’d like to hope the package name is the same, but looking at your screenshot shared, it looks like it may be the below:
image

But youll be able to confirm that with the adb dump :slight_smile:

Thanksad

1 Like

I am able to get the activity and then run dumpsys command in cmd, now the problem is that the locator we pass to get webelements isn’t found. i think that in my case “Get WebElements id=com.google.android.dialer:id/elapsedTime” is incorrect.

Output of dumpsys command:
TASK 10216:com.google.android.dialer id=25 userId=0
ACTIVITY com.google.android.dialer/com.android.dialer.incall.activity.ui.InCallActivity 368dcf5 pid=31948
Local Activity 9ef6adf State:

My Code:

${elapsed_time}=  AppiumLibrary.Get WebElements  id=com.google.android.dialer:id/elapsedTime
Log    ${elapsed_time}
${elasped_time_value}=  AppiumLibrary.Get Text    ${elapsed_time}[0]
Log  elasped:${elasped_time_value}

dumpsys command output is give below:

how you identify the locator "id=com.samsung.android.incallui:id/elapsedTime " ???

If you mind attaching the whole output il be able to take a look. Thanks

1 Like

Here is the whole output attached in a text file.

(Attachment log.txt is missing)

Here is the detail log.

log.robot (20.8 KB)

Just to confirm, when you ran the dump, the activity value was what was returned from the below in your own test:

${act}=    AppiumLibrary.Get Activity
Log To Console    \n${act}

If not, then could I ask you to do that and then have the returned value run via that adb command while the call is active? just a little unsure due to the last responses if you ran and got your own and ran your own values over my values as they wont likely match your device.

Thank you kindly

1 Like

${act}= AppiumLibrary.Get Activity Log To Console \n${act}
The above code returns : “com.android.dialer.incall.activity.ui.InCallActivity”

and when i ran the command: “adb shell dumpsys activity com.android.dialer.incall.activity.ui.InCallActivity” it gives the attached output.

log.robot (20.8 KB)

Thanks

You may find this is it, there is nothing else that points/reads towards that element in the dump:

com.google.android.dialer:id/contactgrid_bottom_timer

Other than that, you might find you won’t be able to get that element, but even like where I were able to get that value, its still impossible to know if its a real person or just the answer phone (obviously, I don’t know the use case behind it), but worth trying the below and seeing what it returns.

@{timer}=    AppiumLibrary.Get Webelements    id=com.google.android.dialer:id/contactgrid_bottom_timer
Log To Console    ${timer}[0]
${timer_value}=    AppiumLibrary.Get Text    ${timer}[0]
Log To Console    timer_value:${timer_value}

But if that doesnt work, I dont think there is much more I can add (I took a good look online, and there seem to be others with similar experiences) - The device I have is a Samsung device, so if this is device limited, then it is possible to do so with a Samsung at least.

1 Like

Thank you so much for your help!
Always looking to explore robot framework and its libraries.
Would be good if you recommend some widely/popular used libraries in tech.

1 Like

Hi, Daryl,

How can I utilize Robot Framework and its libraries within a Java environment? Specifically, I aim to automate interactions with the Notepad application on Windows through a Maven project in Java. How can I accomplish this?

If using the standalone Robot Framework, leveraging the Windows library makes it straightforward. However, my concern lies in achieving the same functionality within a Java context. I would greatly appreciate your prompt response.