4

I'm trying to get the size occupied by my application package. Every application has one location in the internal/external storage.

I want to calculate the size of the following directory, how can I do that? I know I can use StorageStateManager on and above Oreo (API 26) devices, but how can I achieve this before oreo devices.

Application Directory : /Android/data/myapplicationpackage

I'm trying to use PackageStats but It's giving me always zero. What's the actual way to use this code?

I used the following code and it gives me all zero.

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;
sam_k
  • 5,983
  • 14
  • 76
  • 110

1 Answers1

11

PackageStats stats = new PackageStats(context.getPackageName());

It will only creates the packagestats object. As from the source, the constructor will do initializing the fields,

 public PackageStats(String pkgName) {
        packageName = pkgName;
        userHandle = UserHandle.myUserId();
    }

for api<26,

You need to use IPackageStatsObserver.aidl and have to invoke getPackageSizeInfo method by reflection.

PackageManager pm = getPackageManager();

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

getPackageSizeInfo.invoke(pm, "com.yourpackage",
    new IPackageStatsObserver.Stub() {

        @Override
        public void onGetStatsCompleted(PackageStats pStats, boolean succeeded)
            throws RemoteException {

            //here the pStats has all the details of the package
        }
    });

Here is the complete solution for it. It works great.

from api 26,

The getPackageSizeInfo method is deprecated.

You can use this code,

 @SuppressLint("WrongConstant")
            final StorageStatsManager storageStatsManager = (StorageStatsManager) context.getSystemService(Context.STORAGE_STATS_SERVICE);
            final StorageManager storageManager = (StorageManager)  context.getSystemService(Context.STORAGE_SERVICE);
            try {
                        ApplicationInfo ai = context.getPackageManager().getApplicationInfo(packagename, 0);
                        StorageStats storageStats = storageStatsManager.queryStatsForUid(ai.storageUuid, info.uid);
                        cacheSize =storageStats.getCacheBytes();
                        dataSize =storageStats.getDataBytes();
                        apkSize =storageStats.getAppBytes();
                        size+=info.cacheSize;
                } catch (Exception e) {}

But to use this code, You need USAGE ACCESS PERMISSION .

Jyoti JK
  • 2,141
  • 1
  • 17
  • 40
  • Thanks for the answer, but I am looking for the answer without reflection, you can't rely on the reflection for the production code. Thanks for clarifying the concept of `PackageStats`, I believe android document is not good for this class. – sam_k Apr 02 '18 at 06:59
  • When I was trying to get package size , I searched a lot. I didn't get any official solution for it. – Jyoti JK Apr 02 '18 at 07:12
  • 1
    @JyotiJK thanks for your code, but where the `storageManager` variable used and how can we get an `info.uid`? Thanks. – Acuna Dec 01 '18 at 01:26
  • @Acuna sorry I just pasted my project code. Here info.uid is your application uid. **getApplicationInfo().uid** – Jyoti JK Dec 03 '18 at 04:03
  • And yes, what is the `USAGE ACCESS PERMISSION`? Is it `android.permission.PACKAGE_USAGE_STATS`? – Acuna Dec 03 '18 at 23:56
  • yup, You can refer [this](https://stackoverflow.com/a/42153556/8867002) – Jyoti JK Dec 04 '18 at 03:51