mirror of
https://github.com/adelphes/android-dev-ext.git
synced 2025-12-25 10:58:42 +00:00
* upgrade package-lock.jsons * upgrade debugadapter package * upgrade debugprotocol package * upgrade long package * upgrade unzipper package * upgrade uuid package * upgrade ws package * upgrade xpath package * update dev dependencies * fix eslint config to allow newer language features (async shorthand functions and optional catch parameters) * fix import type declarations * update eslint * remove unsupported stopOnEntry properties * code tidy - fix warnings, separate type imports from value imports, remove unused code * report stack on adb connection error and default host name to 127.0.0.1 * fix imported types in jdwp * lang server tidyups * add a new helper for creating android API library cache file * update the android API cache file to 34 * bump to version 1.4.0
99 lines
3.2 KiB
JavaScript
99 lines
3.2 KiB
JavaScript
const fs = require('fs');
|
|
const dom = require('xmldom').DOMParser;
|
|
const unzipper = require('unzipper');
|
|
const xpath = require('xpath');
|
|
|
|
const { decode_binary_xml } = require('./apk-decoder');
|
|
|
|
/**
|
|
* Extracts and decodes the compiled AndroidManifest.xml from an APK
|
|
* @param {string} apk_fpn file path to APK
|
|
* @returns {Promise<string>}
|
|
*/
|
|
async function extractManifestFromAPK(apk_fpn) {
|
|
const data = await extractFileFromAPK(apk_fpn, /^AndroidManifest\.xml$/);
|
|
return decode_binary_xml(data);
|
|
}
|
|
|
|
|
|
/**
|
|
* Extracts a single file from an APK
|
|
* @param {string} apk_fpn
|
|
* @param {RegExp} file_match
|
|
*/
|
|
function extractFileFromAPK(apk_fpn, file_match) {
|
|
return new Promise((resolve, reject) => {
|
|
const file_chunks = [];
|
|
let cb_once = (err, data) => {
|
|
cb_once = () => {};
|
|
err ? reject(err) : resolve(data);
|
|
}
|
|
fs.createReadStream(apk_fpn)
|
|
.pipe(unzipper.ParseOne(file_match))
|
|
.on('data', chunk => {
|
|
file_chunks.push(chunk);
|
|
})
|
|
.once('error', err => {
|
|
cb_once(err);
|
|
})
|
|
.once('end', () => {
|
|
cb_once(null, Buffer.concat(file_chunks));
|
|
});
|
|
})
|
|
}
|
|
|
|
|
|
/**
|
|
* Parses a manifest file to extract package, activities and launch activity
|
|
* @param {string} xml AndroidManifest XML text
|
|
*/
|
|
function parseManifest(xml) {
|
|
const result = {
|
|
/**
|
|
* The package name
|
|
*/
|
|
package: '',
|
|
/**
|
|
* the list of Activities stored in the manifest
|
|
* @type {string[]}
|
|
*/
|
|
activities: [],
|
|
/**
|
|
* the name of the Activity with:
|
|
* - intent-filter action = android.intent.action.MAIN and
|
|
* - intent-filter category = android.intent.category.LAUNCHER
|
|
*/
|
|
launcher: '',
|
|
}
|
|
const doc = new dom().parseFromString(xml);
|
|
const attributeValue = (/** @type {xpath.SelectedValue} */ selectedValue) => {
|
|
return xpath.isAttribute(selectedValue) ? selectedValue.value : '';
|
|
};
|
|
// extract the package name from the manifest
|
|
const pkg_xpath = '/manifest/@package';
|
|
result.package = attributeValue(xpath.select1(pkg_xpath, doc));
|
|
const android_select = xpath.useNamespaces({"android": "http://schemas.android.com/apk/res/android"});
|
|
|
|
// extract a list of all the (named) activities declared in the manifest
|
|
const activity_xpath = '/manifest/application/activity/@android:name';
|
|
const activity_nodes = android_select(activity_xpath, doc);
|
|
if (Array.isArray(activity_nodes)) {
|
|
result.activities = activity_nodes.map(n => attributeValue(n));
|
|
}
|
|
|
|
// extract the default launcher activity
|
|
const launcher_xpath = '/manifest/application/activity[intent-filter/action[@android:name="android.intent.action.MAIN"] and intent-filter/category[@android:name="android.intent.category.LAUNCHER"]]/@android:name';
|
|
const launcher_nodes = android_select(launcher_xpath, doc);
|
|
// should we warn if there's more than one?
|
|
if (Array.isArray(launcher_nodes) && launcher_nodes.length >= 1) {
|
|
result.launcher = attributeValue(launcher_nodes[0]);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
module.exports = {
|
|
extractManifestFromAPK,
|
|
parseManifest,
|
|
}
|