Technical Articles
How to Control Native Android Apps with ABAP
Business processes are not longer realized exclusively in the SAP GUI for Windows only. More and more, steps are also being taken on other UIs on other devices. In this blog post I describe the possibility how to control native apps and web apps on a virtual Android device with ABAP via PowerShell.
To realize this scenario I use the same approach which I described e.g. here and here. The bridge between the SAP system and the virtual device builds a chain of libraries and applications. It starts with SAPIENs ActiveXPoshV3 library to connect PowerShell from SAP. The PowerShell script, which contains the procedure, is stored as include development object on the SAP backend system. An ABAP report loads this script and executes it. The script uses the Appium client libraries to connect an Appium server which connects a virtual device from Android Studio.
Preparation
- Download and install Android Studio
- Download and install Appium
- Download and install Appium Client libraries
- Download and install SAPIENs ActiveXPoshV3
Code Preparation
Here a PowerShell script to control the Android calculator app. Store it as include in your SAP system. It is very easy to understand. It loads the client libraries, sets the necessary capabilities like device name, app etc. and do some activities. It adds 6 to 9, multiplies 166 with 9 and writes the result to the screen.
#-Begin-----------------------------------------------------------------
#-Includes------------------------------------------------------------
$Path = "C:\Program Files\Appium"
[Void][System.Reflection.Assembly]::LoadFrom($Path + "\appium-dotnet-driver.dll")
[Void][System.Reflection.Assembly]::LoadFrom($Path + "\Castle.Core.dll")
[Void][System.Reflection.Assembly]::LoadFrom($Path + "\Newtonsoft.Json.dll")
[Void][System.Reflection.Assembly]::LoadFrom($Path + "\WebDriver.dll")
[Void][System.Reflection.Assembly]::LoadFrom($Path + "\WebDriver.Support.dll")
#-Sub Main------------------------------------------------------------
Function Main() {
[OpenQA.Selenium.Remote.DesiredCapabilities]$Capabilities = `
[OpenQA.Selenium.Remote.DesiredCapabilities]::new();
$Capabilities.SetCapability([OpenQA.Selenium.Appium.Enums.MobileCapabilityType]::`
DeviceName, "emulator-5554");
$Capabilities.SetCapability([OpenQA.Selenium.Appium.Enums.MobileCapabilityType]::`
PlatformVersion, "8.1.0");
$Capabilities.SetCapability([OpenQA.Selenium.Appium.Enums.MobileCapabilityType]::`
PlatformName, "Android");
$Capabilities.SetCapability([OpenQA.Selenium.Appium.Enums.AndroidMobileCapabilityType]::`
AppPackage, "com.android.calculator2");
$Capabilities.SetCapability([OpenQA.Selenium.Appium.Enums.AndroidMobileCapabilityType]::`
AppActivity, "com.android.calculator2.Calculator");
[System.Uri]$Uri = [System.Uri]::new("http://127.0.0.1:4723/wd/hub");
$Driver = `
[OpenQA.Selenium.Appium.Android.AndroidDriver[OpenQA.Selenium.Appium.AppiumWebElement]]::`
new($Uri, $Capabilities);
If ($Driver -eq $null) {
Return;
}
$Driver.FindElementById("com.android.calculator2:id/digit_9").Click();
$Driver.FindElementById("com.android.calculator2:id/op_add").Click();
$Driver.FindElementById("com.android.calculator2:id/digit_6").Click();
$Driver.FindElementById("com.android.calculator2:id/eq").Click();
$Result = $Driver.FindElementById("com.android.calculator2:id/result").Text;
Write-Host "Das Ergebnis ist " $Result;
$Driver.FindElementByAccessibilityId("clear").Click();
$Driver.FindElementById("com.android.calculator2:id/digit_1").Click();
$Driver.FindElementById("com.android.calculator2:id/digit_6").Click();
$Driver.FindElementById("com.android.calculator2:id/digit_6").Click();
$Driver.FindElementByAccessibilityId("multiply").Click();
$Driver.FindElementById("com.android.calculator2:id/digit_9").Click();
$Driver.FindElementByAccessibilityId("equals").Click();
$Result = $Driver.FindElementById("com.android.calculator2:id/result").Text;
Write-Host "Das Ergebnis ist " $Result;
$Driver.CloseApp();
$Driver.Quit();
}
#-Main----------------------------------------------------------------
Main
#-End-------------------------------------------------------------------
Here a script to control the Chrome browser on Android. Store it as include in your SAP system too. It is also very easy to understand. It does the same as the script above but here we control the browser. We call Google search, type the word Selenium into the field and press enter.
#-Begin-----------------------------------------------------------------
#-Includes------------------------------------------------------------
$Path = "C:\Program Files\Appium"
[Void][System.Reflection.Assembly]::LoadFrom($Path + "\appium-dotnet-driver.dll")
[Void][System.Reflection.Assembly]::LoadFrom($Path + "\Castle.Core.dll")
[Void][System.Reflection.Assembly]::LoadFrom($Path + "\Newtonsoft.Json.dll")
[Void][System.Reflection.Assembly]::LoadFrom($Path + "\WebDriver.dll")
[Void][System.Reflection.Assembly]::LoadFrom($Path + "\WebDriver.Support.dll")
#-Sub Main------------------------------------------------------------
Function Main() {
[OpenQA.Selenium.Remote.DesiredCapabilities]$Capabilities = `
[OpenQA.Selenium.Remote.DesiredCapabilities]::new();
$Capabilities.SetCapability("deviceName", "emulator-5554");
$Capabilities.SetCapability("platformVersion", "8.1.0");
$Capabilities.SetCapability("browserName", "Chrome")
$Capabilities.SetCapability("platformName", "Android");
[System.Uri]$Uri = [System.Uri]::new("http://127.0.0.1:4723/wd/hub");
$Driver = `
[OpenQA.Selenium.Appium.Android.AndroidDriver[OpenQA.Selenium.Appium.AppiumWebElement]]::`
new($Uri, $Capabilities);
If ($Driver -eq $null) {
Return;
}
$Driver.Navigate().GoToUrl("https://www.google.de");
$Driver.FindElementByName("q").SendKeys("Selenium");
$Driver.FindElementByName("q").SendKeys([OpenQA.Selenium.Keys]::Enter);
Start-Sleep -Seconds 5
$Driver.CloseApp();
$Driver.Quit();
}
#-Main----------------------------------------------------------------
Main
#-End-------------------------------------------------------------------
ABAP Code Preparation and Execution
To execute these scripts with the following report you need the class zActiveXPoshV3 from here in your SAP system.This report loads an include z_posh_appium_app, the first script from above and executes it. But before start your Android Studio with a new empty project and a virtual device. And then start your Appium server.
If your infrastructure runs you can execute this report.
"-Begin-----------------------------------------------------------------
REPORT Z_APPIUM.
DATA:
lo_posh TYPE REF TO zactivexposhv3,
lv_pscode TYPE string,
lv_result TYPE string,
lt_result TYPE STANDARD TABLE OF string
.
CREATE OBJECT lo_posh.
CHECK lo_posh->load_lib( ) = lo_posh->mc_true.
CHECK lo_posh->get_is_powershell_installed( ) = lo_posh->mc_true.
CHECK lo_posh->init( iv_load_profiles = lo_posh->mc_false ) = 0.
lo_posh->set_outputmode( lo_posh->mc_outputbuffer ).
lo_posh->set_outputwidth( 132 ).
lo_posh->clear_output( ).
lv_pscode = lo_posh->read_incl_as_string( iv_incl_name = 'Z_POSH_APPIUM_APP' ).
lo_posh->execute( lv_pscode ).
lv_result = lo_posh->get_outputstring( ).
lo_posh->clear_output( ).
lt_result = lo_posh->outputstring_to_table( iv_outputstring = lv_result ).
LOOP AT lt_result INTO lv_result.
WRITE: / lv_result.
ENDLOOP.
lo_posh->free_lib( ).
"-End-------------------------------------------------------------------
Here an image of the running report with the script as include in the SE80.
The result is as expected.
Conclusion
As you can see it is possible to control Android devices from SAP. You can do it synchronously and with direct bidirectional communication between the script and the ABAP report, function module or method. So you can use this approach inside test processes e.g. in the context of eCATT. This opens the gate wide for very interesting integration scenarios.
Great explanation. Even more opportunity to use ABAP! I love it.
Michelle
Hello Stefan Schnell
we currently have the following scenario.
Our requirement:
The file content should be printed on a mobile printer that is connected to the mobile device.
For printing we use the app MobiPrint (ArrowHead). According to MobiPrint the file content can be printed with the app if we execute the following JavaScript code.
Would it be possible to implement this requirement with the method that is described in your blog?
Thank you in advance!
Julian
Hello Julian Wiesmann,
in my opinion not, because my approach bases on SAP GUI for Windows, with its ActiveX interface, which is not available on SAP GUI for HTML.
Best regards
Stefan