读取未安装的APK图标等
有两种方式:
一种为反射方式,代码上比较麻烦,但操作上方便。
另一种方式使用系统隐藏API实现,代码上比较简单,但操作上会麻烦一些。
无论哪一种,请注意传入的文件名参数时,千万注意文件名后面不要带有'/'字符,否则会出错。
strpath="/mnt/sdcard/uc.apk/" 错误方式
strpath="/mnt/sdcard/uc.apk" 正确方式
第一种代码如下:
private void showUninstallAPKIcon(String apkPath) { String PATH_PackageParser = "android.content.pm.PackageParser"; String PATH_AssetManager = "android.content.res.AssetManager"; try { Class pkgParserCls = Class.forName(PATH_PackageParser); Class[] typeArgs = new Class[1]; typeArgs[0] = String.class; Constructor pkgParserCt = pkgParserCls.getConstructor(typeArgs); Object[] valueArgs = new Object[1]; valueArgs[0] = apkPath; Object pkgParser = pkgParserCt.newInstance(valueArgs); DisplayMetrics metrics = new DisplayMetrics(); metrics.setToDefaults(); typeArgs = new Class<?>[]{File.class,String.class, DisplayMetrics.class,int.class}; Method pkgParser_parsePackageMtd = pkgParserCls.getDeclaredMethod("parsePackage", typeArgs); valueArgs=new Object[]{new File(apkPath),apkPath,metrics,0}; Object pkgParserPkg = pkgParser_parsePackageMtd.invoke(pkgParser, valueArgs); Field appInfoFld = pkgParserPkg.getClass().getDeclaredField("applicationInfo"); ApplicationInfo info = (ApplicationInfo) appInfoFld.get(pkgParserPkg); Class assetMagCls = Class.forName(PATH_AssetManager); Object assetMag = assetMagCls.newInstance(); typeArgs = new Class[1]; typeArgs[0] = String.class; Method assetMag_addAssetPathMtd = assetMagCls.getDeclaredMethod("addAssetPath", typeArgs); valueArgs = new Object[1]; valueArgs[0] = apkPath; assetMag_addAssetPathMtd.invoke(assetMag, valueArgs); Resources res = getResources(); typeArgs = new Class[3]; typeArgs[0] = assetMag.getClass(); typeArgs[1] = res.getDisplayMetrics().getClass(); typeArgs[2] = res.getConfiguration().getClass(); Constructor resCt = Resources.class.getConstructor(typeArgs); valueArgs = new Object[3]; valueArgs[0] = assetMag; valueArgs[1] = res.getDisplayMetrics(); valueArgs[2] = res.getConfiguration(); res = (Resources) resCt.newInstance(valueArgs); if (info.icon != 0) { Drawable icon = res.getDrawable(info.icon); ImageView image = (ImageView) findViewById(R.id.imageView1); image.setVisibility(View.VISIBLE); image.setImageDrawable(icon); } } catch (Exception e) { String strExce=e.getLocalizedMessage(); e.printStackTrace(); Toast.makeText(this, e.getMessage(), Toast.LENGTH_SHORT).show(); } }
第二种方式:
要使用编译SDK源码中的classes.jar包。实现步骤如下:
首先要把SDK源码进行编译(这里不做解释),然后在目录.\out\target\common\obj\JAVA_LIBRARIES\framework_intermediates\中找到classes.jar,copy到你认为合适的地方。
其次,对eclipse进行配置,打开工程的properties(在eclipse中右键单击工程目录,最后一项就是),打开java build path选项,在右边框中删除系统原有的包文件约为android *.*.*,然后Add Library->User Library->User Libraries->New,中间该点next或者接钮什么的,自己对应。在New窗口中输入一个自己认为合适的库名字,选中下面的复选框(System library...)->OK->Add JARs,同时选中classes.jar和android.jar(在SDK中对应的平台文件夹中有),调整一下顺序,把classes.jar放到上面。后面就一路OK,别忘记把你建的库在Add Library窗口中选中。
代码如下:
public Drawable getIconFromPackage(String archiveFilePath) { PackageParser packageParser = new PackageParser(archiveFilePath); File sourceFile = new File(archiveFilePath); DisplayMetrics metrics = new DisplayMetrics(); metrics.setToDefaults(); PackageParser.Package pkg = packageParser.parsePackage(sourceFile, archiveFilePath, metrics, 0); if (pkg == null) return this.getResources().getDrawable(R.drawable.ic_launcher); ApplicationInfo info = pkg.applicationInfo; Resources pRes = this.getResources(); AssetManager assmgr = new AssetManager(); assmgr.addAssetPath(archiveFilePath); Resources res = new Resources(assmgr, pRes.getDisplayMetrics(), pRes.getConfiguration()); if (info.icon != 0){ Drawable icon = res.getDrawable(info.icon); return icon; } else { return this.getResources().getDrawable(R.drawable.ic_launcher); } }