[Android]教你如何获取未安装应用的ResolveInfo

原理:

查看了下安卓源码,明白了解析过程,只是自己的话就要移植安卓的源码,有人解析成功了,但是我觉得太麻烦。

大概说下安卓的解析过程吧。

    public PackageInfo getPackageArchiveInfo(String archiveFilePath, int flags) {
        PackageParser packageParser = new PackageParser(archiveFilePath);
        DisplayMetrics metrics = new DisplayMetrics();
        metrics.setToDefaults();
        final File sourceFile = new File(archiveFilePath);
        PackageParser.Package pkg = packageParser.parsePackage(
                sourceFile, archiveFilePath, metrics, 0);
        if (pkg == null) {
            return null;
        }
        if ((flags & GET_SIGNATURES) != 0) {
            packageParser.collectCertificates(pkg, 0);
        }
        return PackageParser.generatePackageInfo(pkg, null, flags, 0, 0);
    }

这里是源码,首先通过PackageParser解析,然后通过PackageParser.generatePackageInfo返回PackageInfo,但是PackageInfo里却把intent-filter给去掉了,不知道为啥,不过既然知道了这段代码那么就好好办了。那就是通过反射把PackageParser.Package得到,然后再封装成intentfilter。

解决方案:

直接上代码把。因为完全就是通过反射又重写了一次代码。

  try {
   // 先得到解析类PackageParser并实例化
   Class packageParserClass = Class.forName("android.content.pm.PackageParser");
   Object packageParser = packageParserClass.getConstructor(String.class).newInstance(dexPath);

   // 构建参数
   DisplayMetrics metrics = new DisplayMetrics();
   metrics.setToDefaults();
   File sourceFile = new File(dexPath);

   // 调用PackageParser的parsePackage解析数据
   Method method = packageParserClass.getDeclaredMethod("parsePackage", File.class, String.class, DisplayMetrics.class, int.class);
   method.setAccessible(true);
   Object Package = method.invoke(packageParser, sourceFile, dexPath, metrics, 0);

   // 反射得到结果
   Field activities = Package.getClass().getDeclaredField("activities");
   activities.setAccessible(true);
   ArrayList filters = (ArrayList) activities.get(Package);
   for (int i = 0; i < filters.size(); i++) {
    Object activity = filters.get(i);
    Field intentsField = activity.getClass().getField("intents");
    intentsField.setAccessible(true);
    ArrayList<IntentFilter> intents = (ArrayList<IntentFilter>) intentsField.get(activity);
    for (int j = 0; j < intents.size(); j++) {
     if (intents.iterator().hasNext()) {
      String actionString = intents.get(0).getAction(0);
      String categoryString = intents.get(0).getCategory(0);
      System.out.println(actionString + " " + categoryString);
     }
    }
   }
  } catch (Exception e) {

  }

dexPath就是你要解析的APK的路径。intentfilter里有action和category。这样就实现了得到一个activity的ResolveInfo,至于为什么要类型转来转去,那就具体看安卓源码吧。

时间: 2024-08-08 06:48:43

[Android]教你如何获取未安装应用的ResolveInfo的相关文章

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

原理: 原理不多说,看下安卓源码就知道了. 首先得到AssetManager,然后用AssetManager的openXmlResourceParser方法获取XmlResourceParser,通过XmlResourceParser开始解析APK内的AndroidManifest.xml文件 解决方案: 直接上代码吧,很简单. package com.example.linetest; import java.lang.reflect.Method; import java.util.Hash

Android菜鸟笔记- 获取未安装的APK图标、版本、包名、名称、是否安装、安装、打开

周末闲来无事,把Android的基础知识拿出来复习复习,今天主题是<获取未安装的APK图标.版本.包名.名称.是否安装.跳转安装.打开> 一.获取APK图标 通常读取APK的图标可以用,PackageManager里面的getApplicationIcon(ApplicationInfo)来得到一个drawable.但实际使用的时候经常只能得到一个默认的图标,根本不是APK的图标. 参考小米开源文件管理器,结合实践,代码如下: /* * 采用了新的办法获取APK图标,之前的失败是因为andro

Android菜鸟笔记- 获取未安装的APK图标、版本号、包名、名称、是否安装、安装、打开

周末闲来无事,把Android的基础知识拿出来复习复习,今天主题是<获取未安装的APK图标.版本号.包名.名称.是否安装.跳转安装.打开> 一.获取APK图标 通常读取APK的图标能够用,PackageManager里面的getApplicationIcon(ApplicationInfo)来得到一个drawable.但实际使用的时候常常仅仅能得到一个默认的图标.根本不是APK的图标. 參考小米开源文件管理器,结合实践,代码例如以下: /* * 採用了新的办法获取APK图标.之前的失败是由于a

Android插件化开发---运行未安装apk中的Service

如果你还不知道什么叫插件化开发,那么你应该先读一读之前写的这篇博客:Android插件化开发,初入殿堂 上一篇博客主要从整体角度分析了一下Android插件化开发的几个难点与动态加载没有被安装的apk中的Activity和资源的方法.其实一般的插件开发主要也就是加载个Activity,读取一些资源图片之类的.但是总有遇到特殊情况的时候,比如加载Service. 要动态加载Service,有两种思路:一是通过NDK的形式,将Service通过C++运行起来(这种方法我没有尝试,只听群里的朋友说实现

获取未安装的APK图标

/* * 采用了新的办法获取APK图标,之前的失败是因为android中存在的一个BUG,通过 * appInfo.publicSourceDir = apkPath;来修正这个问题,详情参见: * http://code.google.com/p/android/issues/detail?id=9151 */ public static Drawable getApkIcon(Context context, String apkPath) { PackageManager pm = con

android 教你怎么获取AndroidManifest.xml文件中的meta-data数据

直接上代码,不用解释 <span style="font-size:18px;">ApplicationInfo appInfo = null; try { appInfo = getPackageManager().getApplicationInfo(getPackageName(), PackageManager.GET_META_DATA); } catch (NameNotFoundException e) { e.printStackTrace(); } if

获取apk签名信息(已经安装和未安装的)

import java.io.File; import java.io.UnsupportedEncodingException; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Iterator; import ja

android动态加载已安装和未安装的apk资源

在android开发中动态加载已安装和未安装的apk资源,是很有用的,可以用来实现换肤功能等等.今天我们来学习. 首先新建一个工程plugpicinstall,我们需要往该工程的asset目录和drawable目录下拷贝一些呆会需要加载的图片.运行该工程,即安装. 我们先看看如何实现加载已经安装的apk中的资源: 我们需要先写两个方法,用来获取对应的已安装的apk的context对象和resource对应的id,如下: /** * 该方法用来获取已经安装的apk对应的context对象 * @r

android得到已安装和未安装apk的信息

在获取apk资源时候最重要的一个类就是PackageManager,我们可以通过这个类得到各种想要的东西,首先是得到已经安装的apk的基本信息,包括label,和图标等资源: PackageManager pm = getPackageManager(); List<PackageInfo> apkInfos = pm.getInstalledPackages(0); ArrayList<String> infos_name = new ArrayList<String>