[Android]教你如何获取未安装应用的ResolveInfo(非反射,手动解析)

原理:

原理不多说,看下安卓源码就知道了。
首先得到AssetManager,然后用AssetManager的openXmlResourceParser方法获取XmlResourceParser,通过XmlResourceParser开始解析APK内的AndroidManifest.xml文件

解决方案:

直接上代码吧,很简单。
package com.example.linetest;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import org.xmlpull.v1.XmlPullParser;

import android.annotation.SuppressLint;
import android.content.IntentFilter;
import android.content.res.AssetManager;
import android.content.res.XmlResourceParser;
import android.os.PatternMatcher;
import android.text.TextUtils;

public class IntentFilterParser {

	String apkPath;

	public IntentFilterParser(String apkPath) {
		this.apkPath = apkPath;
	}

	public Map<String, IntentFilter> getIntentFilter() {
		Map<String, IntentFilter> intentFilters = new HashMap<String, IntentFilter>();
		AssetManager assetManager = null;
		XmlResourceParser parser = null;
		try {
			assetManager = AssetManager.class.newInstance();
			Method method = AssetManager.class.getDeclaredMethod("addAssetPath", String.class);
			method.invoke(assetManager, apkPath);
			parser = assetManager.openXmlResourceParser(ANDROID_MANIFEST_FILENAME);
			parseManifest(parser, intentFilters);
			parser.close();
			assetManager.close();
			parser = null;
			assetManager = null;
		} catch (Exception e) {

		} finally {
			if (parser != null) {
				parser.close();
				parser = null;
			}
			if (assetManager != null) {
				assetManager.close();
				assetManager = null;
			}
		}
		return intentFilters;
	}

	private void parseManifest(XmlResourceParser parser, Map<String, IntentFilter> intentFilters) throws Exception {
		int outerDepth = parser.getDepth();
		int type;
		while ((type = parser.next()) != XmlPullParser.END_DOCUMENT && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
			if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
				continue;
			}
			String tagName = parser.getName();
			if (tagName == null) {
				continue;
			}
			if (tagName.equals("activity") || tagName.equals("receiver") || tagName.equals("service")) {
				String activityName = parser.getAttributeValue(ANDROID_RESOURCES, "name");
				if (activityName != null) {
					parseActivity(activityName, intentFilters, parser);
				}
			}
		}
	}

	private void parseActivity(String activityName, Map<String, IntentFilter> intentFilters, XmlResourceParser parser) throws Exception {
		int outerDepth = parser.getDepth();
		int type;
		while ((type = parser.next()) != XmlPullParser.END_DOCUMENT && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
			if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
				continue;
			}
			String tagName = parser.getName();
			if (tagName == null) {
				continue;
			}

			if (tagName.equals("intent-filter")) {
				IntentFilter mFilter = new IntentFilter();
				intentFilters.put(activityName, mFilter);
				parseIntentFilter(mFilter, parser);
			}
		}
	}

	/**
	 * 解析Intent-Filter字段
	 * 
	 * @param mFilter
	 * @param attrs
	 * @throws Exception
	 */
	@SuppressLint("NewApi")
	private void parseIntentFilter(IntentFilter mFilter, XmlResourceParser attrs) throws Exception {
		int outerDepth = attrs.getDepth();
		int type;
		while ((type = attrs.next()) != XmlPullParser.END_DOCUMENT && (type != XmlPullParser.END_TAG || attrs.getDepth() > outerDepth)) {
			if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
				continue;
			}
			String nodeName = attrs.getName();
			if (nodeName == null) {
				continue;
			}

			if (nodeName.equals("action")) {
				String value = attrs.getAttributeValue(ANDROID_RESOURCES, "name");
				if (!TextUtils.isEmpty(value)) {
					mFilter.addAction(value);
				}
			} else if (nodeName.equals("category")) {
				String value = attrs.getAttributeValue(ANDROID_RESOURCES, "name");
				if (!TextUtils.isEmpty(value)) {
					mFilter.addCategory(value);
				}
			} else if (nodeName.equals("data")) {
				/**
				 * Specify a URI authority host that is handled, as per
				 * IntentFilter.addDataAuthority() . [string]
				 */
				String host = attrs.getAttributeValue(ANDROID_RESOURCES, "host");
				/**
				 * Specify a URI authority port that is handled, as per
				 * IntentFilter.addDataAuthority() . [string]
				 */

				String port = attrs.getAttributeValue(ANDROID_RESOURCES, "port");
				if (!TextUtils.isEmpty(host) && !TextUtils.isEmpty(port)) {
					mFilter.addDataAuthority(host, port);
				}

				/**
				 * Specify a URI scheme that is handled, as per
				 * IntentFilter.addDataScheme() . [string]
				 */
				String scheme = attrs.getAttributeValue(ANDROID_RESOURCES, "scheme");
				if (!TextUtils.isEmpty(scheme)) {
					mFilter.addDataScheme(scheme);
				}

				/**
				 * Specify a URI path that must exactly match, as per
				 * IntentFilter.addDataPath() with PATTERN_LITERAL. [string]
				 */
				String path = attrs.getAttributeValue(ANDROID_RESOURCES, "path");
				if (!TextUtils.isEmpty(path)) {
					mFilter.addDataPath(path, PatternMatcher.PATTERN_LITERAL);
				}
				/**
				 * Specify a URI path that must be a prefix to match, as per
				 * IntentFilter.addDataPath() with PATTERN_PREFIX. [string]
				 */
				String pathPrefix = attrs.getAttributeValue(ANDROID_RESOURCES, "pathPrefix");
				if (!TextUtils.isEmpty(pathPrefix)) {
					mFilter.addDataPath(pathPrefix, PatternMatcher.PATTERN_PREFIX);
				}

				/**
				 * Specify a URI path that matches a simple pattern, as per
				 * IntentFilter.addDataPath() with PATTERN_SIMPLE_GLOB. [string]
				 */
				String pathPattern = attrs.getAttributeValue(ANDROID_RESOURCES, "pathPattern");
				if (!TextUtils.isEmpty(pathPattern)) {
					mFilter.addDataPath(pathPattern, PatternMatcher.PATTERN_SIMPLE_GLOB);
				}

				/**
				 * Specify a MIME type that is handled, as per
				 * IntentFilter.addDataType() . [string]
				 */
				String mimeType = attrs.getAttributeValue(ANDROID_RESOURCES, "mimeType");
				if (!TextUtils.isEmpty(mimeType)) {
					mFilter.addDataType(mimeType);
				}

				if (android.os.Build.VERSION.SDK_INT >= 19) {
					/**
					 * Specify a URI scheme specific part that must exactly
					 * match, as per IntentFilter.addDataSchemeSpecificPart()
					 * with PATTERN_LITERAL. [string]
					 */
					String ssp = attrs.getAttributeValue(ANDROID_RESOURCES, "ssp");
					mFilter.addDataSchemeSpecificPart(ssp, PatternMatcher.PATTERN_LITERAL);

					/**
					 * Specify a URI scheme specific part that must be a prefix
					 * to match, as per IntentFilter.addDataSchemeSpecificPart()
					 * with PATTERN_PREFIX. [string]
					 */
					String sspPrefix = attrs.getAttributeValue(ANDROID_RESOURCES, "sspPrefix");
					mFilter.addDataSchemeSpecificPart(sspPrefix, PatternMatcher.PATTERN_PREFIX);

					/**
					 * Specify a URI scheme specific part that matches a simple
					 * pattern, as per IntentFilter.addDataSchemeSpecificPart()
					 * with PATTERN_SIMPLE_GLOB. [string]
					 */
					String sspPattern = attrs.getAttributeValue(ANDROID_RESOURCES, "sspPattern");
					mFilter.addDataSchemeSpecificPart(sspPattern, PatternMatcher.PATTERN_SIMPLE_GLOB);
				}
			}
		}
	}

	private static final String ANDROID_RESOURCES = "http://schemas.android.com/apk/res/android";
	private static final String ANDROID_MANIFEST_FILENAME = "AndroidManifest.xml";

}


郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。