Skip to content

Commit

Permalink
fix: Do not prefix activity with package name if it already exists (#787
Browse files Browse the repository at this point in the history
)
  • Loading branch information
mykola-mokhnach authored Jan 9, 2025
1 parent 4b95444 commit 6395d58
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 54 deletions.
130 changes: 77 additions & 53 deletions lib/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ export function isScreenOnFully (dumpsys) {
* Builds command line representation for the given
* application startup options
*
* @param {Record<string, any>} startAppOptions - Application options mapping
* @param {StartCmdOptions} startAppOptions - Application options mapping
* @param {number} apiLevel - The actual OS API level
* @returns {string[]} The actual command line array
*/
Expand All @@ -349,16 +349,17 @@ export function buildStartCmd (startAppOptions, apiLevel) {
category,
stopApp,
flags,
optionalIntentArguments,
} = startAppOptions;
const cmd = ['am', (apiLevel < 26) ? 'start' : 'start-activity'];
if (util.hasValue(user)) {
cmd.push('--user', user);
cmd.push('--user', `${user}`);
}
if (waitForLaunch) {
cmd.push('-W');
}
if (activity && pkg) {
cmd.push('-n', `${pkg}/${activity}`);
cmd.push('-n', activity.startsWith(`${pkg}/`) ? activity : `${pkg}/${activity}`);
}
if (stopApp && apiLevel >= 15) {
cmd.push('-S');
Expand All @@ -372,56 +373,8 @@ export function buildStartCmd (startAppOptions, apiLevel) {
if (flags) {
cmd.push('-f', flags);
}
if (startAppOptions.optionalIntentArguments) {
// expect optionalIntentArguments to be a single string of the form:
// "-flag key"
// "-flag key value"
// or a combination of these (e.g., "-flag1 key1 -flag2 key2 value2")

// take a string and parse out the part before any spaces, and anything after
// the first space
let parseKeyValue = function (str) {
str = str.trim();
let space = str.indexOf(' ');
if (space === -1) {
return str.length ? [str] : [];
} else {
return [str.substring(0, space).trim(), str.substring(space + 1).trim()];
}
};

// cycle through the optionalIntentArguments and pull out the arguments
// add a space initially so flags can be distinguished from arguments that
// have internal hyphens
let optionalIntentArguments = ` ${startAppOptions.optionalIntentArguments}`;
let re = / (-[^\s]+) (.+)/;
while (true) {
let args = re.exec(optionalIntentArguments);
if (!args) {
if (optionalIntentArguments.length) {
// no more flags, so the remainder can be treated as 'key' or 'key value'
cmd.push.apply(cmd, parseKeyValue(optionalIntentArguments));
}
// we are done
break;
}

// take the flag and see if it is at the beginning of the string
// if it is not, then it means we have been through already, and
// what is before the flag is the argument for the previous flag
let flag = args[1];
let flagPos = optionalIntentArguments.indexOf(flag);
if (flagPos !== 0) {
let prevArgs = optionalIntentArguments.substring(0, flagPos);
cmd.push.apply(cmd, parseKeyValue(prevArgs));
}

// add the flag, as there are no more earlier arguments
cmd.push(flag);

// make optionalIntentArguments hold the remainder
optionalIntentArguments = args[2];
}
if (optionalIntentArguments) {
cmd.push(...parseOptionalIntentArguments(optionalIntentArguments));
}
return cmd;
}
Expand Down Expand Up @@ -1106,6 +1059,64 @@ export async function readPackageManifest(apkPath) {
return result;
}

/**
*
* @param {string} value expect optionalIntentArguments to be a single string of the form:
* "-flag key"
* "-flag key value"
* or a combination of these (e.g., "-flag1 key1 -flag2 key2 value2")
* @returns {string[]}
*/
function parseOptionalIntentArguments(value) {
// take a string and parse out the part before any spaces, and anything after
// the first space
/** @type {(str: string) => string[]} */
const parseKeyValue = (str) => {
str = str.trim();
const spacePos = str.indexOf(' ');
if (spacePos < 0) {
return str.length ? [str] : [];
} else {
return [str.substring(0, spacePos).trim(), str.substring(spacePos + 1).trim()];
}
};

// cycle through the optionalIntentArguments and pull out the arguments
// add a space initially so flags can be distinguished from arguments that
// have internal hyphens
let optionalIntentArguments = ` ${value}`;
const re = / (-[^\s]+) (.+)/;
/** @type {string[]} */
const result = [];
while (true) {
const args = re.exec(optionalIntentArguments);
if (!args) {
if (optionalIntentArguments.length) {
// no more flags, so the remainder can be treated as 'key' or 'key value'
result.push(...parseKeyValue(optionalIntentArguments));
}
// we are done
return result;
}

// take the flag and see if it is at the beginning of the string
// if it is not, then it means we have been through already, and
// what is before the flag is the argument for the previous flag
const flag = args[1];
const flagPos = optionalIntentArguments.indexOf(flag);
if (flagPos !== 0) {
const prevArgs = optionalIntentArguments.substring(0, flagPos);
result.push(...parseKeyValue(prevArgs));
}

// add the flag, as there are no more earlier arguments
result.push(flag);

// make optionalIntentArguments hold the remainder
optionalIntentArguments = args[2];
}
}

/**
* @typedef {Object} InstallOptions
* @property {boolean} [allowTestPackages=false] - Set to true in order to allow test
Expand All @@ -1122,3 +1133,16 @@ export async function readPackageManifest(apkPath) {
* @property {boolean} [partialInstall=false] - Install apks partially. It is used for 'install-multiple'.
* https://android.stackexchange.com/questions/111064/what-is-a-partial-application-install-via-adb
*/

/**
* @typedef {Object} StartCmdOptions
* @property {number|string} [user]
* @property {boolean} [waitForLaunch]
* @property {string} [pkg]
* @property {string} [activity]
* @property {string} [action]
* @property {string} [category]
* @property {boolean} [stopApp]
* @property {string} [flags]
* @property {string} [optionalIntentArguments]
*/
23 changes: 22 additions & 1 deletion test/unit/helper-specs.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@ import _ from 'lodash';


describe('helpers', withMocks({fs}, function (mocks) {
let chai;

before(async function () {
chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');

chai.should();
chai.use(chaiAsPromised.default);
});

afterEach(function () {
mocks.verify();
});
Expand Down Expand Up @@ -107,7 +117,7 @@ describe('helpers', withMocks({fs}, function (mocks) {
});

describe('buildStartCmd', function () {
let startOptions = {
const startOptions = {
pkg: 'com.something',
activity: '.SomeActivity'
};
Expand All @@ -120,6 +130,17 @@ describe('helpers', withMocks({fs}, function (mocks) {
let cmd = buildStartCmd(startOptions, 26);
cmd[1].should.eql('start-activity');
});
it('should not repeat package name', function () {
let cmd = buildStartCmd({
pkg: 'com.package',
activity: 'com.package/.activity',
}, 20);
cmd.includes('com.package/.activity').should.be.true;
});
it('should inlcude package name', function () {
let cmd = buildStartCmd(startOptions, 20);
cmd.includes(`${startOptions.pkg}/${startOptions.activity}`).should.be.true;
});
it('should parse optionalIntentArguments with single key', function () {
let cmd = buildStartCmd(_.defaults({optionalIntentArguments: '-d key'}, startOptions), 20);
cmd[cmd.length - 2].should.eql('-d');
Expand Down

0 comments on commit 6395d58

Please sign in to comment.