在获取apk资源时候最重要的一个类就是PackageManager,我们可以通过这个类得到各种想要的东西,首先是得到已经安装的apk的基本信息,包括label,和图标等资源:

PackageManager pm = getPackageManager();List<PackageInfo> apkInfos = pm.getInstalledPackages(0);ArrayList<String> infos_name =  new ArrayList<String>() ;//用来存放labelArrayList<Drawable> infos_icon = newArrayList<Drawable>();//用来存储apk启动图标资源String name = "";   Drawable icon;   PackageInfo apk;   for (int i = 0; i < apkInfos.size(); )   {      apk = apkInfos.get(i);      i++;      name = (String) pm.getApplicationLabel(apk.applicationInfo);      icon = pm.getApplicationIcon(apk.applicationInfo);      infos_icon.add(icon);      infos_name.add(name);   }
接下来我们利用PackageManager获得已安装apk中的activity,和service等

List<PackageInfo>packagesInfo =  pm.getInstalledPackages(0);for (PackageInfo packageInfo : packagesInfo) {Log.d("TAG","packageInfo NAME IS :"+packageInfo.packageName);}PackageManager pm = getPackageManager();try {   //获得com.example.pertest包中的activity,service和broadcastreceiverPackageInfo packageInfo = pm.getPackageInfo("com.example.pertest",PackageManager.GET_PERMISSIONS| PackageManager.GET_SERVICES| PackageManager.GET_RECEIVERS);ActivityInfo[] activities = packageInfo.activities;if (activities != null) {for (ActivityInfo activityInfo : activities) {Log.d("TAG", "the activity " + activityInfo.toString()+ "==" + packageInfo.versionCode + "==="+ packageInfo.versionName);}} else {Log.d("TAG", "the activity is null");}ServiceInfo[] serviceInfos = packageInfo.services;for (ServiceInfo serviceInfo : serviceInfos) {Log.d("TAG", "service name is :" + serviceInfo.name);}activities = packageInfo.receivers;for (ActivityInfo activity : activities) {Log.d("TAG", "receiver is :" + activity.name);}} catch (NameNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();}

上面就是获取已经安装的apk的基本信息,接下来看看如何获取未安装的apk文件的基本信息,这对于android动态加载时很有用的,我们来看:

得到未安装apk的图标:

public static Drawable getAppIcon(Context context, String apkFilepath) {        PackageManager pm = context.getPackageManager();        PackageInfo pkgInfo = getPackageInfo(context, apkFilepath);        if (pkgInfo == null) {            return null;        }        ApplicationInfo appInfo = pkgInfo.applicationInfo;        if (Build.VERSION.SDK_INT >= 8) {            appInfo.sourceDir = apkFilepath;            appInfo.publicSourceDir = apkFilepath;        }        return pm.getApplicationIcon(appInfo);    }
得到未安装apk的名称:

public static CharSequence getAppLabel(Context context, String apkFilepath) {        PackageManager pm = context.getPackageManager();        PackageInfo pkgInfo = getPackageInfo(context, apkFilepath);        if (pkgInfo == null) {            return null;        }        ApplicationInfo appInfo = pkgInfo.applicationInfo;        if (Build.VERSION.SDK_INT >= 8) {            appInfo.sourceDir = apkFilepath;            appInfo.publicSourceDir = apkFilepath;        }        return pm.getApplicationLabel(appInfo); }
如果还觉得不够的话,我们可以得到:PackageInfo对象,通过该对象,我们就可以获得该未安装apk的activity,service,broadcastreceiver等,方法同"获得已安装apk中的activity,和service" ,代码如下:

//得到PackageInfo对象,其中包含了该apk包含的activity和servicepublic static PackageInfo getPackageInfo(Context context, String apkFilepath) {        PackageManager pm = context.getPackageManager();        PackageInfo pkgInfo = null;        try {            pkgInfo = pm.getPackageArchiveInfo(apkFilepath, PackageManager.GET_ACTIVITIES | PackageManager.GET_SERVICES);        } catch (Exception e) {            // should be something wrong with parse            e.printStackTrace();        }        return pkgInfo;    }

在android动态加载的时候,是通过DexClassLoader来实现的,通过这种方式来获取未安装程序的DexClassLoader对象:

String mNativeLibDir = mContext.getDir("pluginlib", Context.MODE_PRIVATE).getAbsolutePath(); private DexClassLoader createDexClassLoader(String dexPath) {        File dexOutputDir = mContext.getDir("dex", Context.MODE_PRIVATE);        dexOutputPath = dexOutputDir.getAbsolutePath();        DexClassLoader loader = new DexClassLoader(dexPath, dexOutputPath, mNativeLibDir, mContext.getClassLoader());        return loader; }
第一个参数dexPath就是我们apk的存放路径。

第二个参数dexOutPath就是该apk文件对应的dex文件的存放路径,不可以为null。

第三个参数是目标类中使用的C/C++库的列表,每个目录用File.pathSeparator间隔开; 可以为null。

第四个参数是该类装载器的父装载器,一般用当前执行类的装载器。

在获得了该DexClassLoader对象以后,我们就可以实现动态加载该apk中的方法了,详细的方法,请看我的另一篇文章:android动态加载

对于加载未安装的apk中的资源,由于使用的是不同的context,所以,这里先这样做:

 private AssetManager createAssetManager(String dexPath) {        try {            AssetManager assetManager = AssetManager.class.newInstance();            Method addAssetPath = assetManager.getClass().getMethod("addAssetPath", String.class);            addAssetPath.invoke(assetManager, dexPath);            return assetManager;        } catch (Exception e) {            e.printStackTrace();            return null;        }    }private Resources createResources(AssetManager assetManager) {        Resources superRes = mContext.getResources();        Resources resources = new Resources(assetManager, superRes.getDisplayMetrics(), superRes.getConfiguration());        return resources;}
此时的assetManager和resources就可以和平时一样来用了。







更多相关文章

  1. Android(安卓)实现ListView异步加载图片
  2. Android应用升级构想和要点总结
  3. Android(安卓)N调用系统安装APK方法报错原因整理及解决方案
  4. Windows 7安装Android(安卓)Studio
  5. Android的冷启动优化
  6. android 中 intent 重点
  7. greenDao框架使用心得
  8. Touchpad上通过vnc体验ubuntu 11.10
  9. [置顶] [Android基础]Android中如何使用Intent传递对象

随机推荐

  1. Linux常用命令的超全整理(附Linux学习笔记
  2. MySql基本查询-基本函数
  3. Elasticsearch的基础语法
  4. 用 Python 制作一个迷宫游戏
  5. python实现Hangman游戏
  6. 微信API接口监控
  7. web前端中涉及的回流和重绘详解!
  8. SumSwap节点预售开启,新的DEX挑战者即将
  9. vite 中文网
  10. Unity 3D网页游戏与flash网页游戏的较量