获取已安装的应用程序

我想弄清楚如何获得已安装的应用程序的大小。
什么已经失败了:
new File('/data/app/some.apk') – 报告不正确的大小
PackageManager.getPackageSizeInfo(String packageName, IPackageStatsObserver observer) – 是@hide并依赖于一些隐藏的IPackageStatsObserver的结果,所以我不能通过reflection来调用它。

不幸的是,目前没有官方的方式来做到这一点。 但是,如果将PackageStatsIPackageStatsObserver AIDL导入到项目中并生成存根,则可以调用PackageManager的隐藏getPackageSize方法。 然后你可以使用reflection来调用getPackageSize

 PackageManager pm = getPackageManager(); Method getPackageSizeInfo = pm.getClass().getMethod( "getPackageSizeInfo", String.class, IPackageStatsObserver.class); getPackageSizeInfo.invoke(pm, "com.android.mms", new IPackageStatsObserver.Stub() { @Override public void onGetStatsCompleted(PackageStats pStats, boolean succeeded) throws RemoteException { Log.i(TAG, "codeSize: " + pStats.codeSize); } }); 

这显然是一个大黑客 , 不应该用于公共应用程序。

  • Android程序包大小
  • 在Eclipse和ADT中使用AIDL
  • APK盗版:在Android中使用私人代码和资源

你可以通过获取apk文件的path来简单地完成它,并检查它的长度:

 final PackageManager pm = context.getPackageManager(); ApplicationInfo applicationInfo = pm.getApplicationInfo(appInfo.getPackage(), 0); File file = new File(applicationInfo.publicSourceDir); int size = file.length(); 

这里有更多的答案@Josef Pfleger的评论

“我发现一些设备没有getPackageSizeInfo()那么你得到这个java.lang.NoSuchMethodException:getPackageSizeInfo()”@ ATom 11年11月29日在15:56。

之后的API 16(Build.VERSION.SDK_INT> 16),方法

  PackageManager.getPackageSizeInfo(String packageName, IPackageStatsObserver observer); 

改成:

 PackageManager.getPackageSizeInfo(String packageName, int userHandle, IPackageStatsObserver observer); 

而新添加的参数userHandle的解释是:应检索大小信息的用户。

所以我们应该这样做:

  int sysVersion= Build.VERSION.SDK_INT; if (pkgName != null) {// packageName PackageManager pm = getPackageManager(); try { Class<?> clz = pm.getClass(); if (sysVersion>16) { Method myUserId=UserHandle.class.getDeclaredMethod("myUserId");//ignore check this when u set ur min SDK < 17 int userID = (Integer) myUserId.invoke(pm); Method getPackageSizeInfo = clz.getDeclaredMethod( "getPackageSizeInfo", String.class,int.class, IPackageStatsObserver.class);//remember add int.class into the params getPackageSizeInfo.invoke(pm,pkgName, userID, new PkgSizeObserver()); } else {//for old API Method getPackageSizeInfo = clz.getDeclaredMethod( "getPackageSizeInfo", String.class, IPackageStatsObserver.class); getPackageSizeInfo.invoke(pm, pkgName, new PkgSizeObserver()); } } catch (Exception ex) { Log.e(TAG, "NoSuchMethodException"); ex.printStackTrace(); throw ex;} 

该类需要callback,如:

 private class PkgSizeObserver extends IPackageStatsObserver.Stub { /*** * @param pStatus * @param succeeded */ @Override public void onGetStatsCompleted(PackageStats pStats, boolean succeeded) throws RemoteException { cachesize = pStats.cacheSize;//remember to declare these fields datasize = pStats.dataSize; codesize = pStats.codeSize; totalsize = cachesize + datasize + codesize; Log.i("123","cachesize--->" + cachesize + " datasize---->" + datasize + " codeSize---->" + codesize); } } 

并使用此方法来parsinglong2string,那么你可以看到xx MB而不是像2342334 🙂 long

 private String formateFileSize(long size) { return Formatter.formatFileSize(MainActivity.this, size); } 

记住所需的权限,我通过向清单添加以下权限来解决这些问题:

 < uses-permission android:name="android.permission.GET_PACKAGE_SIZE" /> 

或者这个错误:不使用getDeclaredMethod() ,应该使用getMethod()

Method getPackageSizeInfo = mPackageManager.getClass().getMethod("getPackageSizeInfo", String.class, IPackageStatsObserver.class);

 package inc.xiomi.apkextrator.entity; import android.annotation.SuppressLint; import android.content.ComponentName; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageStats; import android.content.pm.ResolveInfo; import android.content.res.AssetManager; import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.drawable.Drawable; import android.os.RemoteException; import android.util.DisplayMetrics; import android.util.Log; import java.lang.reflect.Method; import java.util.Locale; import java.util.concurrent.Semaphore; public class AppInfo implements Comparable<Object> { private Context ctx; private ResolveInfo ri; private ComponentName componentName = null; private PackageInfo pi = null; private Drawable icon = null; String size = null; String name = null; // Code size will be here long codeSize = 0; PackageManager packageManager; // Semaphore to handle concurrency Semaphore codeSizeSemaphore = new Semaphore(1, true); public AppInfo(Context ctx, ResolveInfo ri) { this.ctx = ctx; this.ri = ri; packageManager = ctx.getPackageManager(); this.componentName = new ComponentName(ri.activityInfo.applicationInfo.packageName, ri.activityInfo.name); try { pi = ctx.getPackageManager().getPackageInfo(getPackageName(), 0); } catch (NameNotFoundException e) { } } public String getName() { if (name != null) { return name; } else { try { return getNameFromResolveInfo(ri); } catch (NameNotFoundException e) { return getPackageName(); } } } public String getSize() { if (size != null) { return size; } else { try { return getSizeFromResolveInfo(ri); } catch (Exception e) { return getPackageName(); } } } public String getActivityName() { return ri.activityInfo.name; } public String getPackageName() { return ri.activityInfo.packageName; } public ComponentName getComponentName() { return componentName; } public String getComponentInfo() { if (getComponentName() != null) { return getComponentName().toString(); } else { return ""; } } public ResolveInfo getResolveInfo() { return ri; } public PackageInfo getPackageInfo() { return pi; } public String getVersionName() { PackageInfo pi = getPackageInfo(); if (pi != null) { return pi.versionName; } else { return ""; } } public int getVersionCode() { PackageInfo pi = getPackageInfo(); if (pi != null) { return pi.versionCode; } else { return 0; } } public Drawable getIcon() { if (icon == null) { icon = getResolveInfo().loadIcon(ctx.getPackageManager()); /* Drawable dr = getResolveInfo().loadIcon(ctx.getPackageManager()); Bitmap bitmap = ((BitmapDrawable) dr).getBitmap(); icon = new BitmapDrawable(ctx.getResources(), AppHelper.getResizedBitmap(bitmap, 144, 144)); */ } return icon; } @SuppressLint("NewApi") public long getFirstInstallTime() { PackageInfo pi = getPackageInfo(); if (pi != null && android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.GINGERBREAD) { return pi.firstInstallTime; } else { return 0; } } @SuppressLint("NewApi") public long getLastUpdateTime() { PackageInfo pi = getPackageInfo(); if (pi != null && android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.GINGERBREAD) { return pi.lastUpdateTime; } else { return 0; } } @Override public int compareTo(Object o) { AppInfo f = (AppInfo) o; return getName().compareTo(f.getName()); } @Override public String toString() { return getName(); } /** * Helper method to get an applications name! * * @param ri * @return * @throws android.content.pm.PackageManager.NameNotFoundException */ public String getNameFromResolveInfo(ResolveInfo ri) throws NameNotFoundException { String name = ri.resolvePackageName; if (ri.activityInfo != null) { Resources res = ctx.getPackageManager().getResourcesForApplication(ri.activityInfo.applicationInfo); Resources engRes = getEnglishRessources(res); if (ri.activityInfo.labelRes != 0) { name = engRes.getString(ri.activityInfo.labelRes); if (name == null || name.equals("")) { name = res.getString(ri.activityInfo.labelRes); } } else { name = ri.activityInfo.applicationInfo.loadLabel(ctx.getPackageManager()).toString(); } } return name; } public String getSizeFromResolveInfo(ResolveInfo ri) throws Exception { try { codeSizeSemaphore.acquire(); } catch (InterruptedException e) { e.printStackTrace(System.err); } // Collect some other statistics // Collect code size try { Method getPackageSizeInfo = packageManager.getClass().getMethod("getPackageSizeInfo", String.class, android.content.pm.IPackageStatsObserver.class); getPackageSizeInfo.invoke(packageManager, ri.activityInfo.packageName, new android.content.pm.IPackageStatsObserver.Stub() { // Examples in the Internet usually have this method as @Override. // I got an error with @Override. Perfectly works without it. public void onGetStatsCompleted(PackageStats pStats, boolean succeedded) throws RemoteException { codeSize = pStats.codeSize; Log.e("codeSize", codeSize + ""); codeSizeSemaphore.release(); } }); } catch (Exception e) { e.printStackTrace(System.err); } return String.valueOf(codeSize); } public Resources getEnglishRessources(Resources standardResources) { AssetManager assets = standardResources.getAssets(); DisplayMetrics metrics = standardResources.getDisplayMetrics(); Configuration config = new Configuration(standardResources.getConfiguration()); config.locale = Locale.US; return new Resources(assets, metrics, config); } }