UNPKG

appium-adb-test

Version:

Android Debug Bridge interface

149 lines (140 loc) 5.97 kB
import { exec } from 'teen_process'; import log from '../logger.js'; import { getAndroidPlatformAndPath, unzipFile, assertZipArchive } from '../helpers.js'; import { system, fs } from 'appium-support'; import path from 'path'; const helperJarPath = path.resolve(__dirname, '..', '..', '..', 'jars'); let manifestMethods = {}; // android:process= may be defined in AndroidManifest.xml // http://developer.android.com/reference/android/R.attr.html#process // note that the process name when used with ps must be truncated to the last 15 chars // ps -c com.example.android.apis becomes ps -c le.android.apis manifestMethods.processFromManifest = async function (localApk) { try { await this.initAapt(); log.info("Retrieving process from manifest"); let args = ['dump', 'xmltree', localApk, 'AndroidManifest.xml']; let {stdout} = await exec(this.binaries.aapt, args); let result = null; let lines = stdout.split("\n"); let applicationRegex = new RegExp(/\s+E: application \(line=\d+\).*/); let applicationFound = false; let attributeRegex = new RegExp(/\s+A: .+/); let processRegex = new RegExp(/\s+A: android:process\(0x01010011\)="([^"]+).*"/); for (let line of lines) { if (!applicationFound) { if (applicationRegex.test(line)) { applicationFound = true; } } else { let notAttribute = !attributeRegex.test(line); // process must be an attribute after application. if (notAttribute) { break; } let process = processRegex.exec(line); // this is an application attribute process. if (process && process.length > 1) { result = process[1]; // must trim to last 15 for android's ps binary if (result.length > 15) { result = result.substr(result.length - 15); } break; } } } return result; } catch (e) { log.errorAndThrow(`processFromManifest failed. Original error: ${e.message}`); } }; manifestMethods.packageAndLaunchActivityFromManifest = async function (localApk) { try { await this.initAapt(); log.info("Extracting package and launch activity from manifest"); let args = ['dump', 'badging', localApk]; let {stdout} = await exec(this.binaries.aapt, args); let apkPackage = new RegExp(/package: name='([^']+)'/g).exec(stdout); if (apkPackage && apkPackage.length >= 2) { apkPackage = apkPackage[1]; } else { apkPackage = null; } let apkActivity = new RegExp(/launchable-activity: name='([^']+)'/g).exec(stdout); if (apkActivity && apkActivity.length >= 2) { apkActivity = apkActivity[1]; } else { let outputPath = path.resolve(this.tmpDir, apkPackage); let getLaunchActivity = ['-jar', this.jars['appium_apk_tools.jar'], 'printLaunchActivity', this.opts.app, outputPath]; let {stdout, stderr} = await exec('java', getLaunchActivity); if (stderr) { log.errorAndThrow(`Cannot parse launchActivity from manifest: ${stderr}`); } let act = new RegExp(/Launch activity parsed:([^']+)/g).exec(stdout); if (act && act.length >= 2) { apkActivity = act[1]; } } log.debug(`badging package: ${apkPackage}`); log.debug(`badging act: ${apkActivity}`); return {apkPackage, apkActivity}; } catch (e) { log.errorAndThrow(`packageAndLaunchActivityFromManifest failed. Original error: ${e.message}`); } }; manifestMethods.compileManifest = async function (manifest, manifestPackage, targetPackage) { log.debug(`Compiling manifest ${manifest}`); let {platform, platformPath} = await getAndroidPlatformAndPath(); if (!platform) { return new Error("Required platform doesn't exist (API level >= 17)"); } log.debug('Compiling manifest.'); try { let args = ['package', '-M', manifest, '--rename-manifest-package', manifestPackage, '--rename-instrumentation-target-package', targetPackage, '-I', path.resolve(platformPath, 'android.jar'), '-F', manifest + '.apk', '-f']; await exec(this.binaries.aapt, args); log.debug("Compiled manifest"); } catch (err) { log.errorAndThrow(`Error compiling manifest. Original error: ${err.message}`); } }; manifestMethods.insertManifest = async function (manifest, srcApk, dstApk) { log.debug(`Inserting manifest, src: ${srcApk} dst: ${dstApk}`); try { await unzipFile(`${manifest}.apk`); await fs.copyFile(srcApk, dstApk); log.debug("Testing new tmp apk"); await assertZipArchive(dstApk); log.debug("Moving manifest"); if (system.isWindows()) { let java = path.resolve(process.env.JAVA_HOME, 'bin', 'java'); let args = ['-jar', path.resolve(helperJarPath, 'move_manifest.jar'), dstApk, manifest]; await exec(java, args); } else { // Insert compiled manifest into /tmp/appPackage.clean.apk // -j = keep only the file, not the dirs // -m = move manifest into target apk. await exec('zip', ['-j', '-m', dstApk, manifest]); } log.debug("Inserted manifest."); } catch (e) { log.errorAndThrow(`Error inserting manifest. Original error: ${e.message}`); } }; manifestMethods.hasInternetPermissionFromManifest = async function (localApk) { try { await this.initAapt(); log.debug("Checking if has internet permission from manifest"); let {stdout} = await exec(this.binaries.aapt, ['dump', 'badging', localApk]); return new RegExp(/uses-permission:.*'android.permission.INTERNET'/).test(stdout); } catch (e) { log.errorAndThrow(`Error checking internet permission for manifest. Original error: ${e.message}`); } }; export default manifestMethods;