1. 程式人生 > >android 解析未安裝apk中的AndroidManifest.xml以及系統原始碼分析

android 解析未安裝apk中的AndroidManifest.xml以及系統原始碼分析

package com.ljx.test;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;

import android.content.res.AXmlResourceParser;
import android.util.TypedValue;

public class AnalysisApk {

	public static void main(String[] args) {
		File file = null;
		file = new File("F:\\XXX.apk");
		ArrayList<String> mActivities = new ArrayList<String>();
		try {
			ZipFile zipFile = new ZipFile(file);
			Enumeration enumeration = zipFile.entries();
			// 獲取到apk中的AndroidManifest.xml檔案
			ZipEntry zipEntry = zipFile.getEntry(("AndroidManifest.xml"));
			AXmlResourceParser parser = new AXmlResourceParser();
			parser.open(zipFile.getInputStream(zipEntry));
			boolean flag = true;
			while (flag) {
				int event = parser.next();
				if (event == XmlPullParser.START_TAG) {

					int count = parser.getAttributeCount();

					//// 解析整個AndroidManifest.xml檔案並輸出
					// for (int i = 0; i != parser.getAttributeCount(); ++i) {
					// System.out.printf("%s%s%s=\"%s\"",
					// new StringBuilder(10),
					// getNamespacePrefix(parser.getAttributePrefix(i)),
					// parser.getAttributeName(i),
					// getAttributeValue(parser, i));
					// System.out.println();
					// }

					for (int i = 0, size = parser.getAttributeCount(); i != size; ++i) {
						// 解析整個AndroidManifest.xml檔案並輸出
						// System.out.println("tag-name " + parser.getName());
						// System.out.println("name " +
						// parser.getAttributeName(i));
						// System.out.println("value " +
						// getAttributeValue(parser,i));
						// System.out.println("");

						// 獲取應用入口activity
						if (parser.getName().endsWith("activity") && parser.getAttributeName(i).equals("name")) {
							mActivities.add(getAttributeValue(parser, i));
						}
						if (parser.getAttributeValue(i).contains("MAIN")) {
							System.out.println(mActivities.get(mActivities.size() - 1));
							return;
						}

					}
				}

			}
		} catch (ZipException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (XmlPullParserException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private static String getNamespacePrefix(String prefix) {
		if (prefix == null || prefix.length() == 0) {
			return "";
		}
		return prefix + ":";
	}

	private static String getAttributeValue(AXmlResourceParser parser, int index) {
		int type = parser.getAttributeValueType(index);
		int data = parser.getAttributeValueData(index);
		if (type == TypedValue.TYPE_STRING) {
			return parser.getAttributeValue(index);
		}
		if (type == TypedValue.TYPE_ATTRIBUTE) {
			return String.format("?%s%08X", getPackage(data), data);
		}
		if (type == TypedValue.TYPE_REFERENCE) {
			return String.format("@%s%08X", getPackage(data), data);
		}
		if (type == TypedValue.TYPE_FLOAT) {
			return String.valueOf(Float.intBitsToFloat(data));
		}
		if (type == TypedValue.TYPE_INT_HEX) {
			return String.format("0x%08X", data);
		}
		if (type == TypedValue.TYPE_INT_BOOLEAN) {
			return data != 0 ? "true" : "false";
		}
		if (type == TypedValue.TYPE_DIMENSION) {
			return Float.toString(complexToFloat(data)) + DIMENSION_UNITS[data & TypedValue.COMPLEX_UNIT_MASK];
		}
		if (type == TypedValue.TYPE_FRACTION) {
			return Float.toString(complexToFloat(data)) + FRACTION_UNITS[data & TypedValue.COMPLEX_UNIT_MASK];
		}
		if (type >= TypedValue.TYPE_FIRST_COLOR_INT && type <= TypedValue.TYPE_LAST_COLOR_INT) {
			return String.format("#%08X", data);
		}
		if (type >= TypedValue.TYPE_FIRST_INT && type <= TypedValue.TYPE_LAST_INT) {
			return String.valueOf(data);
		}
		return String.format("<0x%X, type 0x%02X>", data, type);
	}

	private static String getPackage(int id) {
		if (id >>> 24 == 1) {
			return "android:";
		}
		return "";
	}

	private static void log(StringBuilder xmlSb, String format, Object... arguments) {
		log(true, xmlSb, format, arguments);
	}

	private static void log(boolean newLine, StringBuilder xmlSb, String format, Object... arguments) {
		// System.out.printf(format,arguments);
		// if(newLine) System.out.println();
		xmlSb.append(String.format(format, arguments));
		if (newLine)
			xmlSb.append("\n");
	}

	/////////////////////////////////// ILLEGAL STUFF, DONT LOOK :)

	public static float complexToFloat(int complex) {
		return (float) (complex & 0xFFFFFF00) * RADIX_MULTS[(complex >> 4) & 3];
	}

	private static final float RADIX_MULTS[] = { 0.00390625F, 3.051758E-005F, 1.192093E-007F, 4.656613E-010F };
	private static final String DIMENSION_UNITS[] = { "px", "dip", "sp", "pt", "in", "mm", "", "" };
	private static final String FRACTION_UNITS[] = { "%", "%p", "", "", "", "", "", "" };

}

上面main方法中註釋的兩段程式碼,都是對androidManifest.xml檔案進行解析,只是輸出樣式不同,有興趣的可以自己試著寫下,然後看下輸出結果是否是我們應用的入口activity。