Getting installed app size
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
You can do it simplier by gettting path to apk file, and checking its lenght:
final PackageManager pm = context.getPackageManager();
ApplicationInfo applicationInfo = pm.getApplicationInfo(appInfo.getPackage(), 0);
File file = new File(applicationInfo.publicSourceDir);
int size = file.length();
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);
}
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);