android 不解压 读写,如何在不解压的情况下, 分析AndroidManifest文件

该博客介绍了一种方法,通过将APK视为ZIP文件来读取AndroidManifest.xml,然后使用AXMLPrinter.jar工具解码XML,进一步解析获取manifest文件下的节点,特别是metadata信息。这个过程涉及文件遍历、压缩文件操作、XML解析和数据提取。

1. 思路:

apk其实就是一个压缩文件, zipFile 可以在不解压的情况下, 读取压缩包的文件.

2.遍历找到AndroidManifest.xml文件写入流中,此时的文件是乱码的, 下一步是解码.

通过Android提供的AXMLPrinter.jar工具解码, 把, 查看AXMLPrinter.jar源码, 可以接受一个输入流.把主类复制过来, 修改代码.

4.把解码后的文件写入到InputStream中, 待用.

5.上一步解码后的流, 通过DocumentBuilderFactory进行解析, 获取manifest文件下的结点.

2. 代码实现

首先获取到apk文件, 遍历找到AndroidManifest.xml

File[] files = new File(apksDir).listFiles();

for (int i = 0; i < files.length; i++) {

String filePath = files[i].getAbsolutePath();

String fileName = files[i].getName();

if (!filePath.endsWith(".apk")) {

continue;

}

if (fileNameCheck("AndroidManifest.xml", filePath)) {

String packageValue = readZipFile(filePath, fileName);

}

}

/**

* 检查apk中是否有对应的文件

*

* @param fileName

* 要校验的文件

* @param fileRoot

* 应用存放的根目录

* @return 存在: true

*/

public static boolean fileNameCheck(String fileName, String fileRoot) throws IOException {

List slf_fileList = new ArrayList();

slf_fileList = getZipFile(fileRoot);

// for (int i = 0; i < slf_fileList.size(); i++) {

// System.out.println("---" + slf_fileList.get(i));

//

// }

return slf_fileList.contains(fileName);

}

/**

* 获取apk包的所有文件

*

* @param rootName

* apk包存放的根目录

* @return

*/

public static List getZipFile(String rootName) throws IOException {

List list = new ArrayList();

ZipFile slf_zipFile = null;

try {

slf_zipFile = new ZipFile(rootName);

} catch (IOException e) {

// TODO 自动生成 catch 块

e.printStackTrace();

}

Enumeration> e = slf_zipFile.entries();

while (e.hasMoreElements()) {

ZipEntry slf_zipEntry = (ZipEntry) e.nextElement();

if (!slf_zipEntry.isDirectory()) {

String filename = slf_zipEntry.getName().substring(slf_zipEntry.getName().lastIndexOf("/") + 1, slf_zipEntry.getName().length());

list.add(filename);

}

}

slf_zipFile.close();

return list;

}

获取到AndroidManifest.xml文件,调用AMPrinter解码, 得到流.

public static String readZipFile(String file, String fileName) {

try {

ZipFile zf = new ZipFile(file);

String packageValue = null;

InputStream in = new BufferedInputStream(new FileInputStream(file));

ZipInputStream zin = new ZipInputStream(in);

ZipEntry ze;

while ((ze = zin.getNextEntry()) != null) {

if (ze.isDirectory()) {

} else {

if (ze.getName().equals("AndroidManifest.xml")) {

long size = ze.getSize();

// System.out.println(file + " -- " + ze.getName()

// + " size: " + size);

if (size > 0) {

InputStream is = zf.getInputStream(ze);

AMPrinter.decodeXML(is);

// Thread.sleep(1000);

InputStream decodeIs = AMPrinter.getDecodeIs();

packageValue = ManifestParser.getMetadataKeyFromApk(decodeIs);

}

}

}

}

zin.closeEntry();

return packageValue;

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

return null;

}

调用getMetaDataKey()方法解析,(这里可以获取到任何结点, 根据你的需求来), 这里只获取metadata结点和package.

/**

* 获取结点属性

*

* @param is

* 传入流

* @return

* @throws ParserConfigurationException

* @throws SAXException

* @throws IOException

*/

public static String getMetadataKeyFromApk(InputStream is) {

try {

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();

DocumentBuilder builder = dbf.newDocumentBuilder();

Document doc = builder.parse(is);

String packageValue = findPackage(doc);

// write2File(resultFile,package1);

System.out.println("package: " + packageValue);

NodeList permissionList = doc.getElementsByTagName("meta-data");

List metadatas = new ArrayList<>();

for (int i = 0; i < permissionList.getLength(); i++) {

Node permission = permissionList.item(i);

String metadataKey = (permission.getAttributes()).item(0)

.getNodeValue();

String metadataValue = (permission.getAttributes()).item(1)

.getNodeValue();

if (metadataKey.toUpperCase().contains("CHANNEL")){

metadatas.add(metadataKey + " = " + metadataValue);

//System.out.println(metadataKey + " = " + metadataValue);

}

}

if(metadatas.size() != 0)

resultMap.put(packageValue, metadatas);

return packageValue;

} catch (ParserConfigurationException e) {

e.printStackTrace();

} catch (SAXException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

return null;

}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值