diff --git a/README.md b/README.md index a3add93cd..70300e161 100644 --- a/README.md +++ b/README.md @@ -73,9 +73,10 @@ appium:intentCategory | Set an optional intent category to be applied when start appium:intentAction | Set an optional intent action to be applied when starting the given appActivity by [Activity Manager](https://developer.android.com/studio/command-line/adb#am). Dfaults to `android.intent.action.MAIN`. Please use [mobile:startActivity](#mobile-startactivity) in case you don't set an explicit value. appium:intentFlags | Set an optional intent flags to be applied when starting the given appActivity by [Activity Manager](https://developer.android.com/studio/command-line/adb#am). Defaults to `0x10200000` (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_RESET_TASK_IF_NEEDED flags). Please use [mobile:startActivity](#mobile-startactivity) in case you don't set an explicit value. appium:optionalIntentArguments | Set an optional intent arguments to be applied when starting the given appActivity by [Activity Manager](https://developer.android.com/studio/command-line/adb#am) -appium:dontStopAppOnReset | Set it to `true` if you don't want the application to be restarted if it was already running. `false` by default +appium:dontStopAppOnReset | Set it to `true` if you don't want the application to be restarted if it was already running. If `appium:noReset` is falsy, then the app under test is going to be restarted if either this capability is falsy (the default behavior) or `appium:forceAppLaunch` is set to `true`. +appium:forceAppLaunch | Set it to `true` if you want the application under test to be always forcefully restarted on session startup even if `appium:noReset` is `true`, and the app was already running. If `noReset` is falsy, then the app under test is going to be restarted if either this capability set to `true` or `appium:dontStopAppOnReset` is falsy (the default behavior). Available since driver version 2.12 appium:autoLaunch | Whether to launch the application under test automatically (`true`, the default value) after a test starts -appium:autoGrantPermissions | Whether to grant all the requested application permissions automatically when a test starts(`true`). The targetSdkVersion in the application manifest must be greater or equal to 23 and the Android version on the device under test must be greater or equal to Android 6 (API level 23) to grant permissions. Applications whose targetSdkVersion is lower than or equal to 22 must be reisntalled to grant permissions, for example, by setting the `appium:fullReset` capability as `true` for Android 6+ devices. `false` by default +appium:autoGrantPermissions | Whether to grant all the requested application permissions automatically when a test starts(`true`). The targetSdkVersion in the application manifest must be greater or equal to 23 and the Android version on the device under test must be greater or equal to Android 6 (API level 23) to grant permissions. Applications whose targetSdkVersion is lower than or equal to 22 must be reinstalled to grant permissions, for example, by setting the `appium:fullReset` capability as `true` for Android 6+ devices. If your app needs some special security permissions, like access to notifications or media recording, consider using [mobile: changePermissions](#mobile-changepermissions) extension with `appops` target. `false` by default appium:otherApps | Allows to set one or more comma-separated paths to Android packages that are going to be installed along with the main application under test. This might be useful if the tested app has dependencies appium:uninstallOtherPackages | Allows to set one or more comma-separated package identifiers to be uninstalled from the device before a test starts appium:allowTestPackages | If set to `true` then it would be possible to use packages built with the test flag for the automated testing (literally adds `-t` flag to the `adb install` command). `false` by default diff --git a/lib/desired-caps.js b/lib/desired-caps.js index cf1a8e498..65d451a0f 100644 --- a/lib/desired-caps.js +++ b/lib/desired-caps.js @@ -52,6 +52,9 @@ let uiautomatorCapConstraints = { }, disableSuppressAccessibilityService: { isBoolean: true + }, + forceAppLaunch: { + isBoolean: true } }; diff --git a/lib/driver.js b/lib/driver.js index be1bdd951..c5c9e77df 100644 --- a/lib/driver.js +++ b/lib/driver.js @@ -575,28 +575,29 @@ class AndroidUiautomator2Driver extends BaseDriver { this.log.info(`androidCoverage is configured. ` + ` Starting instrumentation of '${this.caps.androidCoverage}'...`); await this.adb.androidCoverage(this.caps.androidCoverage, appWaitPackage, appWaitActivity); - } else { - if (this.opts.noReset && await this.adb.processExists(this.opts.appPackage)) { - this.log.info(`'${this.opts.appPackage}' is already running`); - return; - } - await this.adb.startApp({ - pkg: this.opts.appPackage, - activity: this.opts.appActivity, - action: this.opts.intentAction || 'android.intent.action.MAIN', - category: this.opts.intentCategory || 'android.intent.category.LAUNCHER', - flags: this.opts.intentFlags || '0x10200000', // FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_RESET_TASK_IF_NEEDED - waitPkg: this.opts.appWaitPackage, - waitActivity: this.opts.appWaitActivity, - waitForLaunch: this.opts.appWaitForLaunch, - waitDuration: this.opts.appWaitDuration, - optionalIntentArguments: this.opts.optionalIntentArguments, - stopApp: !this.opts.dontStopAppOnReset, - retry: true, - user: this.opts.userProfile, - }); + return; } - + if (this.opts.noReset && !this.opts.forceAppLaunch + && await this.adb.processExists(this.opts.appPackage)) { + this.log.info(`'${this.opts.appPackage}' is already running and noReset is enabled. ` + + `Set forceAppLaunch capability to true if the app must be forcefully restarted on session startup.`); + return; + } + await this.adb.startApp({ + pkg: this.opts.appPackage, + activity: this.opts.appActivity, + action: this.opts.intentAction || 'android.intent.action.MAIN', + category: this.opts.intentCategory || 'android.intent.category.LAUNCHER', + flags: this.opts.intentFlags || '0x10200000', // FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_RESET_TASK_IF_NEEDED + waitPkg: this.opts.appWaitPackage, + waitActivity: this.opts.appWaitActivity, + waitForLaunch: this.opts.appWaitForLaunch, + waitDuration: this.opts.appWaitDuration, + optionalIntentArguments: this.opts.optionalIntentArguments, + stopApp: this.opts.forceAppLaunch || !this.opts.dontStopAppOnReset, + retry: true, + user: this.opts.userProfile, + }); } async deleteSession () {