39

I am using PackageStats and on printing the PackageStats's codeSize, cacheSize, dataSize, some data is coming as negative.

A few questions:

  • How is this possible?
  • What are the scenarios when codeSize could be negative considering the apk size is around 50MB?
  • Any other ways which can be reliably used to extract above information?

Also, for Android N it gives me "NoSuchMethodException".So,

  • Is it removed for Android N or is there some way to use it?
  • Any alternatives that could help me calculate the above sizes?

Code:

PackageManager packageManager = context.getPackageManager();
Method myUserId = UserHandle.class.getDeclaredMethod("myUserId");
int userID = (Integer) myUserId.invoke(packageManager);

Method getPackageSizeInfo = packageManager.getClass().getDeclaredMethod("getPackageSizeInfo", String.class, int.class,
IPackageStatsObserver.class);
getPackageSizeInfo.invoke(packageManager, context.getPackageName(), userID, new IPackageStatsObserver.Stub() {

    @Override
    public void onGetStatsCompleted(PackageStats pStats, boolean succeeded) throws RemoteException {
        long codeSize = pStats.codeSize / MB; //long MB = 1024*1024;
        long cacheSize = pStats.cacheSize / MB;
        long dataSize = pStats.dataSize / MB;
        long appSize = codeSize + cacheSize + dataSize;
    };
}
thepace
  • 2,221
  • 1
  • 13
  • 21
  • Could you add a code example including how you are displaying / checking the value as well as any calculations being performed on that value? – Zachary Sep 18 '16 at 12:12
  • Ok sure. I am not performing any calculations except 1 wherein I divide the values by 1024*1024 to get the value in MB. – thepace Sep 18 '16 at 12:32

1 Answers1

1

just tried on API 23/24 and can just instance it.

these external* properties might refer to the SD card.

    PackageStats stats = new PackageStats(context.getPackageName());
    long codeSize  = stats.codeSize + stats.externalCodeSize;
    long dataSize  = stats.dataSize + stats.externalDataSize;
    long cacheSize = stats.cacheSize + stats.externalCacheSize;
    long appSize   = codeSize + dataSize + cacheSize;
Martin Zeitler
  • 1
  • 19
  • 155
  • 216
  • I agree with you. One other way is if it exceeds long which is possible. What do you mean by just instance it? – thepace Sep 21 '16 at 09:21
  • @thepace with "just instance it" I mean the `new` keyword - without `invoke()` and the `onGetStatsCompleted()`. negative values are basically only possible with signed integer, so the maximum might not be 4294967295, but 2147483647 (while -2147483647 might simply indicate an error or an absent value)... while it indeed matters which user runs the code, since there is application, user-private and user-shared storage - and the user-private area might vary in size. – Martin Zeitler Sep 21 '16 at 09:46
  • could you share the exact command to get the size (as you suggested with onGetStatsCompleted not required) – thepace Sep 21 '16 at 11:07
  • It gives zero every time. I doubt it works because if it were that simple everyone would be using it. http://stackoverflow.com/questions/1806286/getting-installed-app-size – thepace Sep 22 '16 at 06:23
  • Only instantiating will never give you the size of the application. Have a look at line number 16562 of PackageManagerService class where you can find how the Package sized is initialized. The actual calculation for size is done in Installer class – Anirudha Agashe Sep 23 '16 at 06:06
  • @thepace I don't think it's plausible that a stat exceeds a Long. There's not enough memory on today's devices to do that. – M. Prokhorov Dec 28 '17 at 07:56