Skip to Content
Technical Articles
Author's profile photo Stefan Schnell

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

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.

Assigned Tags

      3 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Michelle Crapo
      Michelle Crapo

      Great explanation.  Even more opportunity to use ABAP! I love it.

      Michelle

      Author's profile photo Julian Wiesmann
      Julian Wiesmann

      Hello Stefan Schnell

      we currently have the following scenario.

      • End users open Chrome Browser on a mobile device (Android), login to SAP via SAP GUI for HTML (WEBGUI) and call a specific transaction.
      • In this transaction an open spool request (PDF) will be created in SAP Backend.
      • The spool request is converted into a PDF / BASE64 string.

      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.

      var label = 'base64_encoded_pdf_string'
      label = btoa(label)
      label = label.replace(/=/g,'_')
      
      window.location.href= 'arrowhead://x-callback-url/printencodedpdf?base64='+label

       

      Would it be possible to implement this requirement with the method that is described in your blog?

       

      Thank you in advance!

      Julian

      Author's profile photo Stefan Schnell
      Stefan Schnell

      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