How to maintain context switching between two activity?

Hi All,

I have tricky scenario, where you perform at some event some view of your native application. In subsequent step you switch to some other activity. And after performing some activity on other activity you moved back to your orignal app with the last activity. So is there any way to do so? I tried to launch other activity from my main application, but while moving back to orignal app it lost context.

So for example:

  1. Assume you are at whatsapp conversation screen
  2. You perform changes on android setting app
  3. You want to be continue with conversation screen

so is there any way to do?

Thanks,
Priyank Shah

It depends upon how you started the android settings app. If you gave yourself access to adb to launch the intent from there, you could do something similar to get back to your app.

Alternatively, you can use the appium driver to bring up your app:

log.info 'Starting activity.'
app_hash = {
    app_package: app_package,
    app_activity: app_activity
}
appium_driver.start_activity app_hash

Or, if you got to settings through a link in your app, you could use
appium_driver.driver.press_keycode 4

Hi Priyank,

You can use adb shell am start -n com.package.name/com.package.name.ActivityName . You can find out more here

Other than adb there is a solution with selendroid(if you are ok with that). BackgroundApp() and resumeApp() functions to switch between different AUT. here you can get the sample code and problem description.

Thanks,
Donald

@willosser : i tried by saving activity name before switching other activity,
String lastActivityName = driver.getCurrentActivity();
driver.startActivity(<pkg 1>,<activity 1>);
driver.startActivity(lastPkg,lastActivity) ; – so basically it launched activity but its just like you run adb shell am start -n com.package.name/com.package.name.ActivityName , which does not have any info about last context.
@Donald: I think the first approach will not work because adb does not have any info about your last activity. Well i did not check with selendroid. so I will try and let you know.

Thanks,
Priyank Shah

1 Like

@Priyank_Shah, getCurrentActivity does not return the fully qualified activity. i.e. it returns com.package.name.Activity.Name instead of com.package.name/com.package.name.ActivityName, using your example.

You likely passed the package and activity name to the Appium server as capabilities, so you should be able to use these values again to restart it. It ends up calling that adb command as you noticed, so if you want to call it that way as Donald suggested, that should also work.

Hi Priyank,

I tried this with android activity manager and it worked for me.

  1. Use apktool to extract contents of apk with command java -jar d -f aut.apk
  2. locate AndroidManifest.xml file.
  3. The AndroidManifest.xml file can be opened in any text editor. I recommend one with syntax highlighting.
  4. Search for the Keyword “LAUNCHER” and note down the activity name associated with it.This activity should be started when the user taps the application icon in the Launcher (handles specific intent Category called LAUNCHER).

Something like

<activity android:name="your.app.package.name.MainActivityName">
  <intent-filter>
   <action android:name="android.intent.action.MAIN" />
   <category android:name="android.intent.category.LAUNCHER" />
  </intent-filter>
</activity> 

Now run command adb shell am start your.app.package.name/.MainActivityName which will display something like this

 Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=your.app.package.name/.MainActivity } in std o/p .

Note : Please separate package name and main activity name in command with a forward slash followed by dot.

If you see a warning message like “Warning: Activity not started, its current task has been brought to the front” that means you have done it- congratulations :smile: .

In addition with this people can run adb shell am start -a android.intent.action.MAIN -c android.intent.category.HOME to send the app in backgroud(many people asked this question before)

// Another easy way to press home key . This works for me in android
_driver.sendKeyEvent(AndroidKeyCode.HOME);

Easy way I tried its working, but u need java client v3.1

package Appium;

import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.android.AndroidKeyCode;
import java.io.IOException;
import java.net.URL;
import java.util.List;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.remote.CapabilityType;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;

public class ContextSwitchBetween2Activity{

public static AndroidDriver<WebElement> _driver;

@BeforeClass
public void setUpAppium() throws InterruptedException, IOException {
	
	DesiredCapabilities capabilities = new DesiredCapabilities();   
	AppCapabilitiesSetUp(capabilities);
	System.out.println("Before calling appium");
	_driver = new AndroidDriver<WebElement>(new URL("http://127.0.0.1:4725/wd/hub"), capabilities);
	System.out.println("After calling appium");		
	
}

@Test
public void ContextSwitchBetween2ActivityTest() throws InterruptedException{
	
	// Wait for first app to load
	By webView = By.className("android.webkit.WebView");
    WebDriverWait wait = new WebDriverWait(_driver,300);
	wait.until(ExpectedConditions.visibilityOfElementLocated(webView));
    
	// Start Second app
	String appPackage="appPackage2";
	String appActivity="appActivity2";
	_driver.startActivity(appPackage2,appActivity2);	
	
	// Press Home Key
	_driver.sendKeyEvent(AndroidKeyCode.HOME);
	
	// KEYCODE_APP_SWITCH
	_driver.sendKeyEvent(0x000000bb);
	
	// Tap our first app
	List<WebElement> elem = _driver.findElements(By.className("android.widget.FrameLayout"));
	for (int i=0;i<elem.size()-1;i++){
		System.out.println("elem.get(i).getAttribute(name) :: " + elem.get(i).getAttribute("name")) ;
		if (elem.get(i).getAttribute("name").equals("App Name 1 text")){
			System.out.println("Tapping :: " + elem.get(i).getAttribute("name")) ;
			_driver.tap(1, elem.get(i), 100);
			break;
		}
		
	}			
	Thread.sleep(4000);
}

@AfterClass(alwaysRun=true)
public void teardown(){
	_driver.quit();
}

public DesiredCapabilities AppCapabilitiesSetUp(DesiredCapabilities cap){
	cap.setCapability(CapabilityType.BROWSER_NAME,"");
	cap.setCapability("platformVersion","4.4.4");
	cap.setCapability("platformName","Android");
	cap.setCapability("deviceName","deviceName");
	cap.setCapability("appPackage","appPackage1");
	cap.setCapability("appActivity","appActivity1");						
	return cap;
	
}

}