Automating System Apps with Appium — iOS and Android

Lana Begunova
6 min readDec 11, 2023

Let’s explore how to automate a certain kind of app, an app built into the phone OS itself. The great thing about Appium’s technology is that depending on the Appium driver we use, we are free to automate apps other than the app we built. We can automate any app that happens to be on the device, including built-in or system apps.

System Apps on iOS and Android
System Apps on iOS

On iOS, system apps are apps like the Calendar, Settings app, or Maps app. Our app might interact with some of these built-in apps, so it’s often useful to be able to automate them too. The trick to automating system apps on iOS is to know the bundle ID of the app. The bundle ID is a unique identifier given to each app by its developer. In the case of Apple apps, their bundle IDs start with com.apple. The lists that show the bundle IDs of each app for each version of iOS are available online.

Bundle ID for iOS

To launch a system app instead of an app we built, we need to adjust our capabilities. For our test app, we use app capabilities to point to a URL or a local file path where an app file may be downloaded or retrieved. But we can actually use a bundle ID instead of this. So we can put in the bundle ID of any built-in app or other app that happens to be installed on the simulator and it will work.

Cap for launching an iOS system app.
# capability for using your own app
CAPS = {
"platformName": "iOS",
...,
"appium:app": "/path/to/test.ipa"
}
# or
CAPS.setdefault("appium:app", "/path/to/test.ipa")
# capability for using a system app
CAPS = {
"platformName": "iOS",
...,
"appium:app": "com.apple.Preferences"
}
# or
CAPS.setdefault("appium:app", "com.apple.Preferences")

Android also has system apps, like the Contacts, the Settings app, etc. Sometimes Google apps like Photos also come by default on many phones.

System Apps on Android

Android apps, like iOS apps, have a unique ID for every application. In the world of Android, however, this is called a package ID instead of a bundle ID. We need this piece of information to launch system apps on Android.

However, there is one more piece of information we need for Android as well, and that is something called an activity. Android apps can be split up into multiple activities, and the Android system needs to know which one we want to start.

In the below table, we can see the package ID and appropriate activity name used for launching a variety of Android system apps. For example, to launch the Settings app, we’ll need both the package ID of com.android.settings and the activity name of .Settings.

Package ID and Activity for Android

To actually launch a system app on Android, we need to adjust our capabilities just like we did for iOS. Typically, we use the app capability to specify an APK file to download or retrieve. But now, instead of using the app capability, we use the combination of two other capabilities, appPackage and appActivity. We put the package ID as the value of the appPackage capability and the launch activity as the value for the appActivity capability.

Caps for launching an Android system app.
# capability for using your own app
CAPS = {
"platformName": "Android",
...,
"appium:app": "/path/to/test.apk"
}
# or
CAPS.setdefault("appium:app", "/path/to/test.app")
# capabilities for using a system app
CAPS = {
"platformName": "Android",
...,
"appium:appPackage": "com.android.settings",
"appium:appActivity": ".Settings"
}
# or
CAPS.setdefault("appium:appPackage": "com.android.settings")
CAPS.setdefault("appium:appActivity": ".Settings")

It’s time to write this up in Python and see how it works. Let’s make sure we have our iOS simulator and Android emulator up and running. Then, move onto writing a script to launch the Settings app on each of them.

Launch mobile devices and start the Appium server.

In my PyCharm editor, I’m working with files system_apps_android.py and system_apps_ios.py. We have all the usual boilerplate, except we don’t have a list of any app URLs for downloading by Appium. That’s because we’re going to automate built-in system apps.

The typical capabilities we use in our Android and iOS setups will not work as they stand, so let’s fix that. First, let’s fill out our Android capabilities. What we want here is the appPackage and appActivity capabilities, so we’ll add those.

We’ll use the appPackage capability to launch the Settings app, which has the package ID of com.android.settings. We’re also going to add the appActivity capability whose value should be .Settings. We’re using the values we saw in the post earlier.

Now, we need to do the same task for iOS by adding an appropriate app capability. So we’ll add the app capability with the value of com.apple.Preferences.

Since we just care about launching the apps and not doing anything else with them at this point, I’m just going to add a little sleep to make sure we see that the app has launched. So I’ll write time.sleep and wait for five seconds.

But we also want to do something, so we’ll just print out the source of each app, so we can inspect it manually after the test is complete and satisfy ourselves that Appium was able to see inside the system app just fine. So let’s print out to console the native page source of the application, which we get by calling driver.page_source. We’re done writing code, so let’s give this a whirl.

First, let’s run the Android version of the test. We have our Android emulator and Appium server up and running. I will run command python3 system_apps_android.py in the terminal. We can observe that Appium has indeed launched the Settings app on this emulator.

View HD video recording here: https://youtu.be/tnDiCR8lUdk

Now, let’s check out iOS. We will run command python3 system_apps_ios.py to kick off the test. And we will see Appium starting a session. And we’ve loaded the Settings application here as expected.

And if we go back to PyCharm IDE, we will see that not only did the test execute without issues, but indeed we have printed out a XML output here, which shows the native elements that comprise the Settings app on the iOS simulator.

View HD video recording here: https://youtu.be/0UqPioH1l10.

So with Appium, we can certainly automate all aspects of the device, even apps we didn’t write ourselves.

🔗 Python code, XML output, GIFs: https://github.com/lana-20/appium-system-apps

🔗 Test execution videos: https://youtu.be/tnDiCR8lUdk (Android) and https://youtu.be/0UqPioH1l10 (iOS).

Happy testing and debugging!

I welcome any comments and contributions to the subject. Connect with me on LinkedIn, X , GitHub, or Insta.

--

--

Lana Begunova

I am a QA Automation Engineer passionate about discovering new technologies and learning from it. The processes that connect people and tech spark my curiosity.