Android Open Source - apk_manifest_parser Apk Manifest Parser






From Project

Back to project page apk_manifest_parser.

License

The source code is released under:

Apache License

If you think the Android project apk_manifest_parser listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package org.bbs.apkparser;
// www.j a va2s  .com
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import org.bbs.apkparser.PackageInfoX.ActivityInfoX;
import org.bbs.apkparser.PackageInfoX.ApplicationInfoX;
import org.bbs.apkparser.PackageInfoX.IntentInfoX;
import org.bbs.apkparser.PackageInfoX.ServiceInfoX;
import org.bbs.apkparser.PackageInfoX.UsesSdkX;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.ComponentInfo;
import android.content.pm.PackageItemInfo;
import android.content.pm.ServiceInfo;
import android.content.res.AssetManager;
import android.content.res.XmlResourceParser;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;

@SuppressLint("NewApi")
public class ApkManifestParser {
  private static final String ATTR_SHARED_USER_LABEL = "sharedUserLabel";

  private static final String ATTR_SHARED_USER_ID = "sharedUserId";

  static final String TAG = ApkManifestParser.class.getSimpleName();

  private static final String ANDROID_NS = "http://schemas.android.com/apk/res/android";
  private static final String TAG_SERVICE = "service";
  private static final String ATTR_BACKUP_AGENT = "backupAgent";
  private static final String ATTR_ALLOW_TASK_REPARENTING = "allowTaskReparenting";
  private static final String ATTR_DEBUGGABLE = "debuggable";
  private static final String ATTR_PROCESS = "process";
  private static final String TAG_META_DATA = "meta-data";
  private static final String ATTR_BANNER = "banner";
  private static final String ATTR_LOGO = "logo";
  private static final String TAG_USES_SDK = "uses-sdk";
  private static final String ATTR_RESOURCE = "resource";
  private static final String ATTR_VALUE = "value";
  private static final String ATTR_ICON = "icon";
  private static final String ATTR_THEME = "theme";
  private static final String ATTR_LABEL = "label";
  private static final String TAG_CATEGORY = "category";
  private static final String TAG_INTENT_FILTER = "intent-filter";
  private static final String TAG_ACTION = "action";
  private static final String TAG_ACTIVITY = "activity";
  private static final String ATTR_VERSION_NAME = "versionName";
  private static final String ATTR_VERSION_CODE = "versionCode";
  private static final String TAG_APPLICATION = "application";
  private static final String ATTR_NAME = "name";
  private static final String ATTR_PACKAGE = "package";
  private static final String TAG_MANIFEST = "manifest";
  
  private static final boolean LOG_UN_HANDLED_ITEM = false;
  

  public static PackageInfoX parseAPk(Context context, String apkFile) {
    return parseAPk(context, apkFile, true);
  }

  public static PackageInfoX parseAPk(Context context, String apkFile, boolean resolve) {
    PackageInfoX info = new PackageInfoX();
    
    AssetManager assets;
    XmlResourceParser parser = null;
    try {
      assets = AssetManager.class.getConstructor(null).newInstance(null);
      Method method = assets.getClass().getMethod("addAssetPath",
          new Class[] { String.class });
      int cookie = (Integer) method.invoke(assets, apkFile);
      parser = assets
          .openXmlResourceParser(cookie, "AndroidManifest.xml");
      parseApk(parser, info);
      if (resolve) {
        resolveParsedApk(info, apkFile);
      }
      
//      parser = assets.openXmlResourceParser(cookie, "AndroidManifest.xml");
//      dumpParser(parser);
      info.dump();

      return info;
    } catch (InstantiationException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (IllegalAccessException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (IllegalArgumentException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (InvocationTargetException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (NoSuchMethodException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (IOException e) {
      // TODO Auto-generated catch block
      // e.printStackTrace();
      // } catch (ClassNotFoundException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }

    return null;
  }

  private static void resolveParsedApk(PackageInfoX info, String apkFile) {
    info.applicationInfo.publicSourceDir = apkFile;
    info.applicationInfo.sourceDir = apkFile;
    
    ApplicationInfo appInfo = info.applicationInfo;
    
    appInfo.packageName = info.packageName;
    if (!TextUtils.isEmpty(appInfo.name)) {
      if (!appInfo.name.contains(".")) {
        appInfo.name = appInfo.packageName + "." + appInfo.name;
      } else if (appInfo.name.startsWith(".")) {
        appInfo.name = appInfo.packageName + "" + appInfo.name;
      }
    }
    appInfo.className = appInfo.name;
    
    if (info.mUsesSdk != null) {
      UsesSdkX sdk = info.mUsesSdk;

      if (sdk.mMaxSdkVersion == 0) {
        sdk.mMaxSdkVersion = sdk.mTargetSdkVersion;
      }
      if (sdk.mTargetSdkVersion == 0) {
        sdk.mTargetSdkVersion = sdk.mMaxSdkVersion;
      }
      
      if (sdk.mMaxSdkVersion > 0) {
        appInfo.targetSdkVersion = sdk.mTargetSdkVersion;
      }
    }
    
    if (info.activities != null && info.activities.length > 0) {
      for (ActivityInfo a : info.activities) {
        ActivityInfoX comX = (ActivityInfoX) a;
        comX.mPackageInfo = info;
        if (comX.theme == 0 && appInfo.theme > 0) {
          comX.theme = appInfo.theme;
        }

        resolveComponentInfo((ApplicationInfoX) appInfo, comX);
      }
    }    
    
    if (info.services != null && info.services.length > 0) {
      for (ServiceInfo a : info.services) {
        ServiceInfoX comX = (ServiceInfoX) a;
        comX.mPackageInfo = info;

        resolveComponentInfo((ApplicationInfoX) appInfo, comX);
      }
    }
  }
  
  private static void resolveComponentInfo(ApplicationInfoX appInfo, ComponentInfo cInfo) {
    cInfo.labelRes = cInfo.labelRes != 0 ? cInfo.labelRes : appInfo.labelRes;
    cInfo.nonLocalizedLabel = !TextUtils.isEmpty(cInfo.nonLocalizedLabel) ? cInfo.nonLocalizedLabel : appInfo.nonLocalizedLabel;
    cInfo.packageName = appInfo.packageName;
    
    if (!TextUtils.isEmpty(cInfo.name) && 
        (cInfo.name.startsWith(".") || !cInfo.name.contains("."))) {
      String D = !cInfo.name.contains(".") ? "." : "";
      cInfo.name = appInfo.packageName + D + cInfo.name;
    }
  }

  private static void parseApk(XmlResourceParser parser, PackageInfoX info) {
    int eventType;
    try {
      eventType = parser.getEventType();
      while (eventType != XmlPullParser.END_DOCUMENT) {
        String tag = parser.getName();
        if (eventType == XmlPullParser.START_DOCUMENT) {
        } else if (eventType == XmlPullParser.START_TAG) {
          if (TAG_MANIFEST.equals(tag)) {
            parserManifest(parser, info);
          } 
        } else if (eventType == XmlPullParser.END_TAG) {
        } else if (eventType == XmlPullParser.TEXT) {
        }

        final int attCount = parser.getAttributeCount();
        for (int i = 0; i < attCount; i++) {
          String attName = parser.getAttributeName(i);
          String attValue = parser.getAttributeValue(i);
        }

        eventType = parser.next();
      }
    } catch (XmlPullParserException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }

  private static void parserManifest(XmlResourceParser parser,
      PackageInfoX info) throws XmlPullParserException, IOException {
    // parse attr
    final int attCount = parser.getAttributeCount();
    for (int i = 0; i < attCount; i++) {
      String attName = parser.getAttributeName(i);
      String attValue = parser.getAttributeValue(i);
      if (ATTR_PACKAGE.equals(attName)) {
        info.packageName = attValue;
      } else if (ATTR_VERSION_NAME.equals(attName)) {
        info.versionName = attName;
      } else if (ATTR_VERSION_CODE.equals(attName)) {
        info.versionCode = Integer.parseInt(attValue);
      } else if (ATTR_SHARED_USER_ID.equals(attName)) {
        info.sharedUserId = (attValue);
      } else if (ATTR_SHARED_USER_LABEL.equals(attName)) {
        info.sharedUserLabel = toResId(attValue);
//      } else if ("installLocation".equals(attName)) {
//        info.installLocation = toResId(attValue);
      } else {
        if (LOG_UN_HANDLED_ITEM) {
          Log.w(TAG, "un-handled att: " + attName + "=" + attValue);
        }
      }
    }
    
    // parse sub-element
    int type;
    int outerDepth = parser.getDepth();
    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 (TAG_APPLICATION.equals(tagName)) {
        parseApplication(parser, info);
      } else if (TAG_USES_SDK.equals(tagName)) {
        parseUsesSdk(parser, info);
      } else {
        if (LOG_UN_HANDLED_ITEM) {
          Log.w(TAG, "un-handled tag: " + tagName);
        }
      }
    }

  }
  
  private static int toResId(String attValue) {
    if (attValue.startsWith("")) {
      return Integer.parseInt(attValue.substring(1));
    }
    
    throw new RuntimeException("res attValue must start with @.");
//    return -1;
  }
  
  private static boolean toBoolean(String attValue) {
    if ("true".equals(attValue))   {
      return true;
    }
    return false;
  }

  private static void parseUsesSdk(XmlResourceParser parser,
      PackageInfoX info) {// parse attr
    UsesSdkX sdk = new UsesSdkX();
    final int attCount = parser.getAttributeCount();
    for (int i = 0; i < attCount; i++) {
      String attName = parser.getAttributeName(i);
      String attValue = parser.getAttributeValue(i);
      if ("minSdkVersion".equals(attName)) {
        sdk.mMinSdkVersion = Integer.parseInt(attValue);
      } else if ("maxSdkVersion".equals(attName)) {
        sdk.mMaxSdkVersion = Integer.parseInt(attValue);
      } else if ("targetSdkVersion".equals(attName)) {
        sdk.mTargetSdkVersion = Integer.parseInt(attValue);
      } else {
        if (LOG_UN_HANDLED_ITEM) {
          Log.w(TAG, "un-handled att: " + attName + "=" + attValue);
        }
      }
    }
    
    info.mUsesSdk = sdk;
  }

  private static void parseApplication(XmlResourceParser parser,
      PackageInfoX info) throws XmlPullParserException, IOException {
    info.applicationInfo = new ApplicationInfoX();
    ApplicationInfoX app = (ApplicationInfoX) info.applicationInfo;
    // parse attr
    final int attCount = parser.getAttributeCount();
    for (int i = 0; i < attCount; i++) {
      String attName = parser.getAttributeName(i);
      String attValue = parser.getAttributeValue(i);
      if (ATTR_THEME.equals(attName)) {
        app.theme = Integer.parseInt(attValue.substring(1));
      } else if (ATTR_BACKUP_AGENT.equals(attName)) {
        app.backupAgentName = attValue;
      } else if (ATTR_ALLOW_TASK_REPARENTING.equals(attName)) {
        app.mAllowTaskReparenting = toBoolean(attValue);
      } else if (ATTR_DEBUGGABLE.equals(attName)) {
        app.mDebuggable = toBoolean(attValue);
      } else if (ATTR_PROCESS.equals(attName)) {
        app.processName = (attValue);
      } else {
        if (LOG_UN_HANDLED_ITEM) {
          Log.w(TAG, "un-handled att: " + attName + "=" + attValue);
        }
      }
    }
    parsePackageItem(parser, app);
    
    // parse sub-element
    int type;
    int outerDepth = parser.getDepth();
    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 (TAG_ACTIVITY.equals(tagName)) {
        parseActivity(parser, info);
      } else if (TAG_META_DATA.equals(tagName)) {
        if (info.applicationInfo == null){
          info.applicationInfo = new ApplicationInfoX();
        }
        if (info.applicationInfo.metaData == null) {
          info.applicationInfo.metaData = new Bundle();
        }
        parseMetaData(parser, info.applicationInfo.metaData);
      } if (TAG_SERVICE.equals(tagName)) {
        parseService(parser, info);
      }  else {
        if (LOG_UN_HANDLED_ITEM) {
          Log.w(TAG, "un-handled tag: " + tagName);
        }
      }
    }

  }
  
  /**
   * <href a="http://developer.android.com/reference/android/content/pm/ComponentInfo.html">aaa</href>
   */
  private static void parseComponentItem(XmlResourceParser parser, ComponentInfo info) {
    final int attCount = parser.getAttributeCount();
    for (int i = 0; i < attCount; i++) {
      String attName = parser.getAttributeName(i);
      String attValue = parser.getAttributeValue(i);
      if ("process".equals(attName)) {
        String cName = attValue;
        info.processName = cName;
      } else if ("exported".equals(attName)) {
        info.exported = Boolean.parseBoolean(attName);
      } else if ("enabled".equals(attName)) {
        info.enabled = Boolean.parseBoolean(attName);
      } else if ("description".equals(attName)) {
        info.descriptionRes = toResId(attValue);
      }  
    }
    
    parsePackageItem(parser, info);
  }

  private static void parsePackageItem(XmlResourceParser parser, PackageItemInfo info) {
    final int attCount = parser.getAttributeCount();
    for (int i = 0; i < attCount; i++) {
      String attName = parser.getAttributeName(i);
      String attValue = parser.getAttributeValue(i);
      if (ATTR_NAME.equals(attName)) {
        String cName = attValue;
        info.name = cName;
      } else if (ATTR_LABEL.equals(attName)) {
        if (attValue.startsWith("@")) {
          info.labelRes = Integer.parseInt(attValue.substring(1));
        } else {
          info.nonLocalizedLabel = attValue;
        }
      } else if (ATTR_ICON.equals(attName)) {
          info.icon = toResId(attValue);
      } else if (ATTR_LOGO.equals(attName)) {
          info.logo = toResId(attValue);
      } else if (ATTR_BANNER.equals(attName)) {
          info.logo = toResId(attValue);
      } else {
        if (LOG_UN_HANDLED_ITEM) {
          Log.w(TAG, "un-handled att: " + attName + "=" + attValue);
        }
      } 
    }
  }

  private static void parseMetaData(XmlResourceParser parser, Bundle metaData) {
    String key = null;
    String value = null;
    final int attCount = parser.getAttributeCount();
    for (int i = 0; i < attCount; i++) {
      String attName = parser.getAttributeName(i);
      String attValue = parser.getAttributeValue(i);
      if (ATTR_NAME.equals(attName)) {
        key = attValue;
      } else if (ATTR_VALUE.equals(attName)) {
        value = attValue;
      } else if (ATTR_RESOURCE.equals(attName)) {
        if (attValue.startsWith("@")) {
          value = attValue;
        }
      } else {
        if (LOG_UN_HANDLED_ITEM) {
          Log.w(TAG, "un-handled att: " + attName + "=" + attValue);
        }
      }
    }
    
    metaData.putString(key, value);    
  }

  private static void parseActivity(XmlResourceParser parser,
      PackageInfoX info) throws XmlPullParserException, IOException {
    ActivityInfoX component = new ActivityInfoX();
    component.applicationInfo = info.applicationInfo;
    // parse attr
    final int attCount = parser.getAttributeCount();
    boolean hasLabel = false;
    for (int i = 0; i < attCount; i++) {
      String attName = parser.getAttributeName(i);
      String attValue = parser.getAttributeValue(i);
      if (ATTR_THEME.equals(attName)) {
        component.theme = Integer.parseInt(attValue.substring(1));
      } else {
        if (LOG_UN_HANDLED_ITEM) {
          Log.w(TAG, "un-handled att: " + attName + "=" + attValue);
        }
      }
    }
    parseComponentItem(parser, component);    
    
    // parse sub-element
    int type;
    int outerDepth = parser.getDepth();
    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 (TAG_INTENT_FILTER.equals(tagName)) {
        parseIntentFilter(parser, info, component);
      } else if (TAG_META_DATA.equals(tagName)) {
        if (component.metaData == null) {
          component.metaData = new Bundle();
        }
        parseMetaData(parser, component.metaData);
      } else {
        if (LOG_UN_HANDLED_ITEM) {
          Log.w(TAG, "un-handled tag: " + tagName);
        }
      }
      
    }

    if (info.activities == null) {
      info.activities = new ActivityInfoX[1];

      info.activities[0] = component;
    } else {
      int len = info.activities.length;
      ActivityInfoX[] components = new ActivityInfoX[len + 1];
      System.arraycopy(info.activities, 0, components, 0, len);
      components[len] = component;

      info.activities = components;
    }
  }  
  
  private static void parseService(XmlResourceParser parser,
      PackageInfoX info) throws XmlPullParserException, IOException {
    ServiceInfoX component = new ServiceInfoX();
    component.applicationInfo = info.applicationInfo;
    // parse attr
    final int attCount = parser.getAttributeCount();
    boolean hasLabel = false;
    for (int i = 0; i < attCount; i++) {
      String attName = parser.getAttributeName(i);
      String attValue = parser.getAttributeValue(i);
      if (ATTR_THEME.equals(attName)) {
      } else {
        if (LOG_UN_HANDLED_ITEM) {
          Log.w(TAG, "un-handled att: " + attName + "=" + attValue);
        }
      }
    }
    parseComponentItem(parser, component);    
    
    // parse sub-element
    int type;
    int outerDepth = parser.getDepth();
    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 (TAG_INTENT_FILTER.equals(tagName)) {
//        parserIntentFilter(parser, info, component);
//      } else 
        if (TAG_META_DATA.equals(tagName)) {
        if (component.metaData == null) {
          component.metaData = new Bundle();
        }
        parseMetaData(parser, component.metaData);
      } else {
        if (LOG_UN_HANDLED_ITEM) {
          Log.w(TAG, "un-handled tag: " + tagName);
        }
      }
      
    }

    if (info.services == null) {
      info.services = new ServiceInfo[1];

      info.services[0] = component;
    } else {
      int len = info.services.length;
      ServiceInfo[] components = new ServiceInfo[len + 1];
      System.arraycopy(info.services, 0, components, 0, len);
      components[len] = component;

      info.services = components;
    }
  }

  private static void parseIntentFilter(XmlResourceParser parser,
      PackageInfoX info, ActivityInfoX a) throws XmlPullParserException,
      IOException {
    IntentInfoX intentInfo = new IntentInfoX();
    // parse attr

    // parse sub-element
    int type;
    int outerDepth = parser.getDepth();
    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 (TAG_ACTION.equals(tagName)) {
        parseAction(parser, info, intentInfo);
      } else if (TAG_CATEGORY.equals(tagName)) {
        parseCategory(parser, info, intentInfo);
      } else {
        if (LOG_UN_HANDLED_ITEM) {
          Log.w(TAG, "un-handled tag: " + tagName);
        }
      }
    }

    if (a.mIntents == null) {
      a.mIntents = new IntentInfoX[1];

      a.mIntents[0] = intentInfo;
    } else {
      int len = a.mIntents.length;
      IntentInfoX[] as = new IntentInfoX[len + 1];
      System.arraycopy(a.mIntents, 0, as, 0, len);
      as[len] = intentInfo;

      a.mIntents = as;
    }

  }

  private static void parseCategory(XmlResourceParser parser,
      PackageInfoX info, IntentInfoX intentInfo) {
    // parse attr
    final int attCount = parser.getAttributeCount();
    for (int i = 0; i < attCount; i++) {
      String attName = parser.getAttributeName(i);
      String attValue = parser.getAttributeValue(i);
      if (ATTR_NAME.equals(attName)) {
        String category = attValue;
        intentInfo.addCategory(category);
      } else {
        if (LOG_UN_HANDLED_ITEM) {
          Log.w(TAG, "un-handled att: " + attName + "=" + attValue);
        }
      }
    }
  }

  private static void parseAction(XmlResourceParser parser,
      PackageInfoX info, IntentInfoX intentInfo) {
    // parse attr
    final int attCount = parser.getAttributeCount();
    for (int i = 0; i < attCount; i++) {
      String attName = parser.getAttributeName(i);
      String attValue = parser.getAttributeValue(i);
      if (ATTR_NAME.equals(attName)) {
        String action = attValue;
        intentInfo.addAction(action);
      } else {
        if (LOG_UN_HANDLED_ITEM) {
          Log.w(TAG, "un-handled att: " + attName + "=" + attValue);
        }
      }
    }
  }

  private static void dumpParser(XmlResourceParser parser) {
    int depth = 0;
    int eventType;
    try {
      eventType = parser.getEventType();
      while (eventType != XmlPullParser.END_DOCUMENT) {
        if (eventType == XmlPullParser.START_DOCUMENT) {
          Log.d(TAG, makePrefix(depth) + "");
        } else if (eventType == XmlPullParser.START_TAG) {
          depth++;
          Log.d(TAG,
              makePrefix(depth) + "" + parser.getName());
        } else if (eventType == XmlPullParser.END_TAG) {
          Log.d(TAG,
              makePrefix(depth) + "" + parser.getName());
          depth--;
        } else if (eventType == XmlPullParser.TEXT) {
          Log.d(TAG, makePrefix(depth) + "" + parser.getText());
        }
        final int attCount = parser.getAttributeCount();
        for (int i = 0; i < attCount; i++) {
          String attName = parser.getAttributeName(i);
          String attValue = parser.getAttributeValue(i);
          Log.d(TAG, makePrefix(depth + 1) + "" + i + " " + attName
              + " : " + attValue);
        }
        eventType = parser.next();
      }
    } catch (XmlPullParserException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }

  static String makePrefix(int depth) {
    StringBuffer b = new StringBuffer();
    for (int i = 0; i < depth; i++) {
      b.append("  ");
    }
    return b.toString();
  }
}




Java Source Code List

org.bbs.apkparser.ApkManifestParser.java
org.bbs.apkparser.PackageInfoX.java
org.bbs.demo.apkparser.MainActivity.java