appium-android-driver
Version:
Android UiAutomator and Chrome support for Appium
346 lines • 13.4 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.startActivity = startActivity;
exports.mobileStartActivity = mobileStartActivity;
exports.mobileBroadcast = mobileBroadcast;
exports.mobileStartService = mobileStartService;
exports.mobileStopService = mobileStopService;
const lodash_1 = __importDefault(require("lodash"));
const driver_1 = require("appium/driver");
const support_1 = require("@appium/support");
const NO_VALUE_ARG_TYPE = 'sn';
const SUPPORTED_EXTRA_TYPES = [
's',
NO_VALUE_ARG_TYPE,
'z',
'i',
'l',
'f',
'u',
'cn',
'ia',
'ial',
'la',
'lal',
'fa',
'fal',
'sa',
'sal',
];
/**
* Starts an Android activity.
*
* @deprecated Use {@link mobileStartActivity} instead.
* @param appPackage The package name of the application to start.
* @param appActivity The activity name to start.
* @param appWaitPackage The package name to wait for. Defaults to `appPackage` if not provided.
* @param appWaitActivity The activity name to wait for. Defaults to `appActivity` if not provided.
* @param intentAction The intent action to use.
* @param intentCategory The intent category to use.
* @param intentFlags The intent flags to use.
* @param optionalIntentArguments Optional intent arguments.
* @param dontStopAppOnReset If `true`, does not stop the app on reset. If not provided, uses the capability value.
* @returns Promise that resolves when the activity is started.
*/
async function startActivity(appPackage, appActivity, appWaitPackage, appWaitActivity, intentAction, intentCategory, intentFlags, optionalIntentArguments, dontStopAppOnReset) {
this.log.debug(`Starting package '${appPackage}' and activity '${appActivity}'`);
// dontStopAppOnReset is both an argument here, and a desired capability
// if the argument is set, use it, otherwise use the cap
if (!support_1.util.hasValue(dontStopAppOnReset)) {
dontStopAppOnReset = !!this.opts.dontStopAppOnReset;
}
const args = {
pkg: appPackage,
activity: appActivity,
waitPkg: appWaitPackage || appPackage,
waitActivity: appWaitActivity || appActivity,
action: intentAction,
category: intentCategory,
flags: intentFlags,
optionalIntentArguments,
stopApp: !dontStopAppOnReset,
};
this._cachedActivityArgs = this._cachedActivityArgs || {};
this._cachedActivityArgs[`${args.waitPkg}/${args.waitActivity}`] = args;
await this.adb.startApp(args);
}
/**
* Starts an Android activity using the activity manager.
*
* @param wait Set it to `true` if you want to block the method call
* until the activity manager's process returns the control to the system.
* `false` by default.
* @param stop Set it to `true` to force stop the target
* app before starting the activity. `false` by default.
* @param windowingMode The windowing mode to launch the activity into.
* Check https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/app/WindowConfiguration.java
* for more details on possible windowing modes (constants starting with `WINDOWING_MODE_`).
* @param activityType The activity type to launch the activity as.
* Check https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/app/WindowConfiguration.java
* for more details on possible activity types (constants starting with `ACTIVITY_TYPE_`).
* @param display The display identifier to launch the activity into.
* @param user The user ID for which the activity is started.
* @param intent The name of the activity intent to start, for example
* `com.some.package.name/.YourActivitySubClassName`.
* @param action Action name.
* @param pkg Package name.
* @param uri Unified resource identifier.
* @param mimeType Mime type.
* @param identifier Optional identifier.
* @param component Component name.
* @param categories One or more category names.
* @param extras Optional intent arguments. Must be represented as array of arrays,
* where each subarray item contains two or three string items: value type, key name and the value itself.
* See {@link IntentOpts} for supported value types.
* @param flags Intent startup-specific flags as a hexadecimal string.
* @returns Promise that resolves to the command output string.
*/
async function mobileStartActivity(wait, stop, windowingMode, activityType, display, user, intent, action, pkg, uri, mimeType, identifier, component, categories, extras, flags) {
const cmd = [
'am',
'start-activity',
];
if (!lodash_1.default.isNil(user)) {
cmd.push('--user', String(user));
}
if (wait) {
cmd.push('-W');
}
if (stop) {
cmd.push('-S');
}
if (!lodash_1.default.isNil(windowingMode)) {
cmd.push('--windowingMode', String(windowingMode));
}
if (!lodash_1.default.isNil(activityType)) {
cmd.push('--activityType', String(activityType));
}
if (!lodash_1.default.isNil(display)) {
cmd.push('--display', String(display));
}
cmd.push(...parseIntentSpec({
intent,
action,
package: pkg,
uri,
mimeType,
identifier,
component,
categories,
extras,
flags,
}));
return await this.adb.shell(cmd);
}
/**
* Sends a broadcast intent to the Android system.
*
* @param receiverPermission Require receiver to hold the given permission.
* @param allowBackgroundActivityStarts Whether the receiver may start activities even if in the background.
* @param user The user ID for which the broadcast is sent.
* The `current` alias assumes the current user ID. `all` by default.
* @param intent The name of the activity intent to broadcast, for example
* `com.some.package.name/.YourServiceSubClassName`.
* @param action Action name.
* @param pkg Package name.
* @param uri Unified resource identifier.
* @param mimeType Mime type.
* @param identifier Optional identifier.
* @param component Component name.
* @param categories One or more category names.
* @param extras Optional intent arguments. Must be represented as array of arrays,
* where each subarray item contains two or three string items: value type, key name and the value itself.
* See {@link IntentOpts} for supported value types.
* @param flags Intent startup-specific flags as a hexadecimal string.
* @returns Promise that resolves to the command output string.
*/
async function mobileBroadcast(receiverPermission, allowBackgroundActivityStarts, user, intent, action, pkg, uri, mimeType, identifier, component, categories, extras, flags) {
const cmd = ['am', 'broadcast'];
if (!lodash_1.default.isNil(user)) {
cmd.push('--user', String(user));
}
if (receiverPermission) {
cmd.push('--receiver-permission', receiverPermission);
}
if (allowBackgroundActivityStarts) {
cmd.push('--allow-background-activity-starts');
}
cmd.push(...parseIntentSpec({
intent,
action,
package: pkg,
uri,
mimeType,
identifier,
component,
categories,
extras,
flags,
}));
return await this.adb.shell(cmd);
}
/**
* Starts an Android service.
*
* @param foreground Set it to `true` if your service must be started as foreground service.
* This option is ignored if the API level of the device under test is below 26 (Android 8).
* @param user The user ID for which the service is started.
* The `current` user id is used by default.
* @param intent The name of the activity intent to start, for example
* `com.some.package.name/.YourServiceSubClassName`.
* @param action Action name.
* @param pkg Package name.
* @param uri Unified resource identifier.
* @param mimeType Mime type.
* @param identifier Optional identifier.
* @param component Component name.
* @param categories One or more category names.
* @param extras Optional intent arguments. Must be represented as array of arrays,
* where each subarray item contains two or three string items: value type, key name and the value itself.
* See {@link IntentOpts} for supported value types.
* @param flags Intent startup-specific flags as a hexadecimal string.
* @returns Promise that resolves to the command output string.
*/
async function mobileStartService(foreground, user, intent, action, pkg, uri, mimeType, identifier, component, categories, extras, flags) {
const cmd = ['am'];
cmd.push(foreground ? 'start-foreground-service' : 'start-service');
if (!lodash_1.default.isNil(user)) {
cmd.push('--user', String(user));
}
cmd.push(...parseIntentSpec({
intent,
action,
package: pkg,
uri,
mimeType,
identifier,
component,
categories,
extras,
flags,
}));
return await this.adb.shell(cmd);
}
/**
* Stops an Android service.
*
* @param user The user ID for which the service is stopped.
* @param intent The name of the activity intent to stop, for example
* `com.some.package.name/.YourServiceSubClassName`.
* @param action Action name.
* @param pkg Package name.
* @param uri Unified resource identifier.
* @param mimeType Mime type.
* @param identifier Optional identifier.
* @param component Component name.
* @param categories One or more category names.
* @param extras Optional intent arguments. Must be represented as array of arrays,
* where each subarray item contains two or three string items: value type, key name and the value itself.
* See {@link IntentOpts} for supported value types.
* @param flags Intent startup-specific flags as a hexadecimal string.
* @returns Promise that resolves to the command output string.
* If the service was already stopped, returns the error message.
*/
async function mobileStopService(user, intent, action, pkg, uri, mimeType, identifier, component, categories, extras, flags) {
const cmd = [
'am',
'stop-service',
];
if (!lodash_1.default.isNil(user)) {
cmd.push('--user', String(user));
}
cmd.push(...parseIntentSpec({
intent,
action,
package: pkg,
uri,
mimeType,
identifier,
component,
categories,
extras,
flags,
}));
try {
return await this.adb.shell(cmd);
}
catch (e) {
// https://github.com/appium/appium-uiautomator2-driver/issues/792
const err = e;
if (err.code === 255 && err.stderr?.includes('Service stopped')) {
return err.stderr;
}
throw e;
}
}
// #region Internal helpers
function parseIntentSpec(opts = {}) {
const { intent, action, uri, mimeType, identifier, categories, component, extras, flags } = opts;
const resultArgs = [];
if (intent) {
resultArgs.push(intent);
}
if (action) {
resultArgs.push('-a', action);
}
if (uri) {
resultArgs.push('-d', uri);
}
if (mimeType) {
resultArgs.push('-t', mimeType);
}
if (!lodash_1.default.isNil(identifier)) {
resultArgs.push('-i', identifier);
}
if (categories) {
if (lodash_1.default.isArray(categories)) {
resultArgs.push(...lodash_1.default.flatMap(categories.map((cName) => ['-c', cName])));
}
else {
resultArgs.push('-c', categories);
}
}
if (component) {
resultArgs.push('-n', component);
}
if (opts.package) {
resultArgs.push('-p', opts.package);
}
if (extras) {
if (!lodash_1.default.isArray(extras)) {
throw new driver_1.errors.InvalidArgumentError(`'extras' must be an array`);
}
for (const item of extras) {
if (!lodash_1.default.isArray(item)) {
throw new driver_1.errors.InvalidArgumentError(`Extra argument '${item}' must be an array`);
}
const [type, key, value] = item;
if (!SUPPORTED_EXTRA_TYPES.includes(type)) {
throw new driver_1.errors.InvalidArgumentError(`Extra argument type '${type}' is not known. ` +
`Supported intent argument types are: ${SUPPORTED_EXTRA_TYPES.join(', ')}`);
}
if (lodash_1.default.isEmpty(key) || (lodash_1.default.isString(key) && lodash_1.default.trim(key) === '')) {
throw new driver_1.errors.InvalidArgumentError(`Extra argument's key in '${JSON.stringify(item)}' must be a valid string identifier`);
}
if (type === NO_VALUE_ARG_TYPE) {
resultArgs.push(`--e${type}`, key);
}
else if (lodash_1.default.isUndefined(value)) {
throw new driver_1.errors.InvalidArgumentError(`Intent argument type '${type}' in '${JSON.stringify(item)}' requires a ` +
`valid value to be provided`);
}
else {
resultArgs.push(`--e${type}`, key, value);
}
}
}
if (flags) {
resultArgs.push('-f', flags);
}
return resultArgs;
}
// #endregion
//# sourceMappingURL=intent.js.map