Getting installed app size

You can do it simplier by gettting path to apk file, and checking its lenght:

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

Unfortunately there is currently no official way to do that. However, you can call the PackageManager's hidden getPackageSize method if you import the PackageStats and IPackageStatsObserver AIDLs into our project and generate the stubs. You can then use reflection to invoke 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);
        }
    });

That's obviously a big hack and should not be used for public applications.

  • Android Package Size
  • Using AIDL with Eclipse and ADT
  • APK Piracy: Using private code & resources in Android

Remember the needed permission, I solved these issues by adding the following permission to the manifest:

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

Or this wrong: not use getDeclaredMethod(),should be use getMethod().

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


Here is additional answer @Josef Pfleger 's, for comment

“I found that some device doesn't have getPackageSizeInfo() then you get this java.lang.NoSuchMethodException: getPackageSizeInfo()” @ ATom Nov 29 '11 at 15:56.

After api 16( Build.VERSION.SDK_INT >16),the method

 PackageManager.getPackageSizeInfo(String packageName, IPackageStatsObserver observer);

changed into:

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

And the explain for the new added param userHandle is :The user whose size information should be retrieved.

So we should do it like this:

 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;} 

The class needed to callback like:

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);
    }
}

And use this method to parse long2string,then you can see xx MB instead of long like 2342334 :)

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

Tags:

Android