mirror of
https://github.com/adelphes/android-dev-ext.git
synced 2025-12-24 02:19:15 +00:00
Version 1 (#83)
* replace jq-promises with native Promises * updates to use native promises and async await * Fix variable errors, remove extra parameters and correct export declaratons * refactor launch request to use async/await * fix running debugger on custom ADB port * remove unused files * move socket_ended check to ensure we don't loop reading 0 bytes * refactor logcat code and ensure disconnect status is passed on to webview * Fix warnings * Clean up util and remove unused functions * convert Debugger into a class * update jsconfig target to es2018 and enable checkJS * more updates to use async/await and more readable refactoring. - added type definitions and debugger classes - improved expression evaluation - refactored expressions into parsing, evaluation and variable assignment - fixed invoking methods with parameters - added support for static method invokes - improved exception display reliability - refactored launch into smaller functions - refactored utils into smaller modules - removed redundant code - converted JDWP functions to classes * set version 1.0.0 and update dependencies * add changelog notes
This commit is contained in:
95
src/manifest.js
Normal file
95
src/manifest.js
Normal file
@@ -0,0 +1,95 @@
|
||||
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);
|
||||
// extract the package name from the manifest
|
||||
const pkg_xpath = '/manifest/@package';
|
||||
result.package = xpath.select1(pkg_xpath, doc).value;
|
||||
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 (activity_nodes) {
|
||||
result.activities = activity_nodes.map(n => n.value);
|
||||
}
|
||||
|
||||
// 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 (launcher_nodes && launcher_nodes.length >= 1) {
|
||||
result.launcher = launcher_nodes[0].value
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
extractManifestFromAPK,
|
||||
parseManifest,
|
||||
}
|
||||
Reference in New Issue
Block a user