I had to make one application which should show the list of installed applications and their size occupied in internal memory, i struggled a lot to find the complete solution at one place. Here I ‘m sharing the full solution which i achieved.
We can’t get the cache size directly by using PackageManager. We need to use Java Reflection and AIDL to achieve this.
Steps to get get cache size, data size and apk size
1. Create AIDL package and add files.
2. Create Class AppDetails.java to get installed package list.
3. Create class by extending IPackageStatsObserver.Stub.
4. Use getPackageSizeInfo method to get data.
Android get app data size using AIDL
Create package android.content.pm inside src/main and add the below two files.
IPackageStatsObserver.aidl
package android.content.pm;
import android.content.pm.PackageStats;
/**
* API for package data change related callbacks from the Package Manager.
* Some usage scenarios include deletion of cache directory, generate
* statistics related to code, data, cache usage(TODO)
* {@hide}
*/
oneway interface IPackageStatsObserver {
void onGetStatsCompleted(in PackageStats pStats, boolean succeeded);
}
import android.content.pm.PackageStats;
/**
* API for package data change related callbacks from the Package Manager.
* Some usage scenarios include deletion of cache directory, generate
* statistics related to code, data, cache usage(TODO)
* {@hide}
*/
oneway interface IPackageStatsObserver {
void onGetStatsCompleted(in PackageStats pStats, boolean succeeded);
}
PackageStats.aidl
package android.content.pm;
parcelable PackageStats;
parcelable PackageStats;
Here is the snap for my project structure:
2. Create Class AppDetails.java to get installed package list.
AppDetails.java
AppDetails.java
import android.app.Activity;
import android.content.pm.PackageInfo;
import android.graphics.drawable.Drawable;
import android.widget.ListView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
/**
* Created by mukeshk on 6/17/2016.
*/
public class AppDetails {
Activity mActivity;
public ArrayList<PackageInfoStruct> res = new ArrayList<PackageInfoStruct>();
public ListView list;
public String app_labels[];
public AppDetails(Activity mActivity) {
this.mActivity = mActivity;
}
public ArrayList<PackageInfoStruct> getPackages() {
ArrayList<PackageInfoStruct> apps = getInstalledApps(false);
final int max = apps.size();
for (int i = 0; i < max; i++) {
apps.get(i);
}
return apps;
}
private ArrayList<PackageInfoStruct> getInstalledApps(boolean getSysPackages) {
List<PackageInfo> packs = mActivity.getPackageManager()
.getInstalledPackages(0);
try {
app_labels = new String[packs.size()];
} catch (Exception e) {
Toast.makeText(mActivity.getApplicationContext(), e.getMessage(),
Toast.LENGTH_SHORT).show();
}
for (int i = 0; i < packs.size(); i++) {
PackageInfo p = packs.get(i);
if ((!getSysPackages) && (p.versionName == null)) {
continue;
}
PackageInfoStruct newInfo = new PackageInfoStruct();
newInfo.appname = p.applicationInfo.loadLabel(
mActivity.getPackageManager()).toString();
newInfo.pname = p.packageName;
newInfo.datadir = p.applicationInfo.dataDir;
newInfo.versionName = p.versionName;
newInfo.versionCode = p.versionCode;
newInfo.icon = p.applicationInfo.loadIcon(mActivity
.getPackageManager());
res.add(newInfo);
app_labels[i] = newInfo.appname;
}
return res;
}
class PackageInfoStruct {
String appname = "";
String pname = "";
String versionName = "";
int versionCode = 0;
Drawable icon;
String datadir = "";
}
import android.content.pm.PackageInfo;
import android.graphics.drawable.Drawable;
import android.widget.ListView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
/**
* Created by mukeshk on 6/17/2016.
*/
public class AppDetails {
Activity mActivity;
public ArrayList<PackageInfoStruct> res = new ArrayList<PackageInfoStruct>();
public ListView list;
public String app_labels[];
public AppDetails(Activity mActivity) {
this.mActivity = mActivity;
}
public ArrayList<PackageInfoStruct> getPackages() {
ArrayList<PackageInfoStruct> apps = getInstalledApps(false);
final int max = apps.size();
for (int i = 0; i < max; i++) {
apps.get(i);
}
return apps;
}
private ArrayList<PackageInfoStruct> getInstalledApps(boolean getSysPackages) {
List<PackageInfo> packs = mActivity.getPackageManager()
.getInstalledPackages(0);
try {
app_labels = new String[packs.size()];
} catch (Exception e) {
Toast.makeText(mActivity.getApplicationContext(), e.getMessage(),
Toast.LENGTH_SHORT).show();
}
for (int i = 0; i < packs.size(); i++) {
PackageInfo p = packs.get(i);
if ((!getSysPackages) && (p.versionName == null)) {
continue;
}
PackageInfoStruct newInfo = new PackageInfoStruct();
newInfo.appname = p.applicationInfo.loadLabel(
mActivity.getPackageManager()).toString();
newInfo.pname = p.packageName;
newInfo.datadir = p.applicationInfo.dataDir;
newInfo.versionName = p.versionName;
newInfo.versionCode = p.versionCode;
newInfo.icon = p.applicationInfo.loadIcon(mActivity
.getPackageManager());
res.add(newInfo);
app_labels[i] = newInfo.appname;
}
return res;
}
class PackageInfoStruct {
String appname = "";
String pname = "";
String versionName = "";
int versionCode = 0;
Drawable icon;
String datadir = "";
}
3. Create class by extending IPackageStatsObserver.Stub.
I have created separate class StorageInformation which will have getpackageSize method to execute the code to calculate cache and another data. One inner class cachePackState have to create by extending IPackageStatsObserver.Stub. Here we have to onGetStatsCompleted method. Here is the complete code:
StorageInformation.java
import android.app.Activity;
import android.content.Context;
import android.content.pm.IPackageStatsObserver;
import android.content.pm.PackageManager;
import android.content.pm.PackageStats;
import android.os.RemoteException;
import android.util.Log;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
/**
* This class will perform data operation
*/
public class StorageInformation {
long packageSize = 0;
AppDetails cAppDetails;
public ArrayList<AppDetails.PackageInfoStruct> res;
Context context;
public StorageInformation(Context context){
this.context=context;
}
public void getpackageSize() {
cAppDetails = new AppDetails((Activity) context);
res = cAppDetails.getPackages();
if (res == null)
return;
for (int m = 0; m < res.size(); m++) {
// Create object to access Package Manager
PackageManager pm = context.getPackageManager();
Method getPackageSizeInfo;
try {
getPackageSizeInfo = pm.getClass().getMethod(
"getPackageSizeInfo", String.class,
IPackageStatsObserver.class);
getPackageSizeInfo.invoke(pm, res.get(m).pname,
new cachePackState()); //Call the inner class
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
/*
* Inner class which will get the data size for application
* */
private class cachePackState extends IPackageStatsObserver.Stub {
@Override
public void onGetStatsCompleted(PackageStats pStats, boolean succeeded)
throws RemoteException {
Log.w("Package Name", pStats.packageName + "");
Log.i("Cache Size", pStats.cacheSize + "");
Log.v("Data Size", pStats.dataSize + "");
packageSize = pStats.dataSize + pStats.cacheSize;
Log.v("Total Cache Size", " " + packageSize);
Log.v("APK Size",pStats.codeSize+"");
}
}
}
import android.content.Context;
import android.content.pm.IPackageStatsObserver;
import android.content.pm.PackageManager;
import android.content.pm.PackageStats;
import android.os.RemoteException;
import android.util.Log;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
/**
* This class will perform data operation
*/
public class StorageInformation {
long packageSize = 0;
AppDetails cAppDetails;
public ArrayList<AppDetails.PackageInfoStruct> res;
Context context;
public StorageInformation(Context context){
this.context=context;
}
public void getpackageSize() {
cAppDetails = new AppDetails((Activity) context);
res = cAppDetails.getPackages();
if (res == null)
return;
for (int m = 0; m < res.size(); m++) {
// Create object to access Package Manager
PackageManager pm = context.getPackageManager();
Method getPackageSizeInfo;
try {
getPackageSizeInfo = pm.getClass().getMethod(
"getPackageSizeInfo", String.class,
IPackageStatsObserver.class);
getPackageSizeInfo.invoke(pm, res.get(m).pname,
new cachePackState()); //Call the inner class
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
/*
* Inner class which will get the data size for application
* */
private class cachePackState extends IPackageStatsObserver.Stub {
@Override
public void onGetStatsCompleted(PackageStats pStats, boolean succeeded)
throws RemoteException {
Log.w("Package Name", pStats.packageName + "");
Log.i("Cache Size", pStats.cacheSize + "");
Log.v("Data Size", pStats.dataSize + "");
packageSize = pStats.dataSize + pStats.cacheSize;
Log.v("Total Cache Size", " " + packageSize);
Log.v("APK Size",pStats.codeSize+"");
}
}
}
Here I’m only logging the output data. You can display in list view with custom adapter.
Note: It may not work if in future the method name change or any thing changed in
IPackageStatsObserver.Stub.
4. Use getPackageSizeInfo method to get data.
I have just called the getPackageSize method from MainActivity class. You can call call this method according to your project.
MainActivity.java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Get the information of all the installed application data StorageInformation storageInformation =
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Get the information of all the installed application data StorageInformation storageInformation =
new StorageInformation(MainActivity.this);
storageInformation.getpackageSize();
storageInformation.getpackageSize();
}
}
Run the application. The output can be seen in log. Here is the snap of AndroidMonitor with all data size logged. All the data unit is in byte. Please convert in to KB or MB according to your requirement.
Please feel free to comment for any clarification or suggestion.
***
Hello Mukesh, this is great and very understandable, sorry i'm still searching on how i can get uninstalled apps residual files. do you any knowledge of doing that in android programatically?
ReplyDeleteThanks in advance!
DeleteBro you are life saver.
ReplyDeleteThanks
Love you.
man you just saved me alot of work and research really thanks, i don't just know why the real function for doing this was deprecated in api 16 an no alternative was given
ReplyDeleteI truly delighted in perusing your article. I discovered this as an instructive and fascinating post, so I think it is extremely helpful and learned. I might want to thank you for the exertion you have made in composing this article
ReplyDeleteplease check this link
i love reading this article so beautiful!!great job! cyberflix tv apk for pc
ReplyDeleteNice to be visiting your blog again, it has been months for me. Well this article that i’ve been waited for so long. I need this article to complete my assignment in the college, and it has same topic with your article. Thanks, great share. charlies-magazines.com
ReplyDeletehi
ReplyDeletethank you
i did all of these steps but didn't work for me.
is there source of project in GitHub?
because of some java files shown in your snap of project structure.
notwork
ReplyDeletejava.lang.reflect.InvocationTargetException
java.lang.UnsupportedOperationException: Shame on you for calling the hidden API getPackageSizeInfoAsUser(). Shame!
java.lang.UnsupportedOperationException: Shame on you for calling the hidden API getPackageSizeInfoAsUser(). Shame!
ReplyDeleteHello, I faced same problem. Did you understand that how to solve your problem ?
DeleteHello, I faced same problem. Did you understand that how to solve your problem ?
DeleteHi friend i have an error; IPackageStatsObserver.Stub returns error application couln't find "IPackageStatsObserver". Import IPackageStatsObserver returns error. Could you help me please?
ReplyDeleteimport android.content.pm.IPackageStatsObserver; // not working
A great degree energizing article thanks for sharing it to each one of us. Looking forward to more information and you have continually intrigued me.
ReplyDeleteBest Info
Thanks for according to critical information including all of us. It was surprisingly soft to work. I absolutely like your opinions. I personally relish your work. Your article is very practical and helpful for us.
ReplyDeleteclick Here
Your posts are really inspiring and useful. I think you deserve better attention on Google search rankings.
ReplyDeletevisit here Please