Android獲取應(yīng)用程序大小的方法
今天碰到個問題,想獲取某個已安裝的包的大小,沒找到合適的方法。搜索了一下,發(fā)現(xiàn)PackageManager里面有個getPackageSizeInfo方法,可惜是hide的,而且它執(zhí)行之后,會將結(jié)果回調(diào)給IPackageStatsObserver的onGetStatsCompleted方法。后來想直接計算/data/app和/system/app里面的apk大小,可是有時候會碰到權(quán)限問題,需要root才可以獲取大小。 再后來,我想起系統(tǒng)的設(shè)置里面有一個應(yīng)用程序管理,它里面列出了所有程序的占用空間大小、數(shù)據(jù)大小和緩存大小。恩,這個就是突破口。
以前寫過一篇獲取其他包的Context ,這個東西是真有用,這個結(jié)合反射,可以做很多神奇的事情,比如今天的這個。
上代碼:
Java代碼
package chroya.demo;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.concurrent.CountDownLatch;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageStats;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
public class Main extends Activity {
private PackageStats ps;
public void getPackageStats(String packageName) {
try {
//獲取setting包的的Context
Context mmsCtx = createPackageContext("com.android.settings",
Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
//使用setting的classloader加載com.android.settings.ManageApplications類
Class<?> maClass = Class.forName("com.android.settings.ManageApplications", true, mmsCtx.getClassLoader());
//創(chuàng)建它的一個對象
Object maObject = maClass.newInstance();
/*
* 將私有域mPm賦值。因為mPm在SizeObserver的invokeGetSize中用到了,
* 卻因為沒有執(zhí)行onCreate而沒有初始化,所以要在此處初始化。
*/
Field f_mPm = maClass.getDeclaredField("mPm");
f_mPm.setAccessible(true);
f_mPm.set(maObject, mmsCtx.getPackageManager());
/*
* 給mHandler賦值為重新定義的Handler,以便接收SizeObserver的
* onGetStatsCompleted回調(diào)方法中dispatch的消息,從中取PackageStats對象。
* */
Field f_mHandler = maClass.getDeclaredField("mHandler");
f_mHandler.setAccessible(true);
f_mHandler.set(maObject, new Handler() {
public void handleMessage(Message msg) {
if(msg.what == 1) {
//此處獲取到PackageStats對象
ps = (PackageStats) msg.getData().getParcelable("ApplicationPackageStats");
Log.d("", ""+ps.codeSize);
}
}
});
//加載內(nèi)部類SizeObserver
Class<?> sizeObserverClass = Class.forName("com.android.settings.ManageApplications$SizeObserver", true, mmsCtx.getClassLoader());
Constructor sizeObserverConstructor = sizeObserverClass.getDeclaredConstructors()[0];
sizeObserverConstructor.setAccessible(true);
/*
* 創(chuàng)建SizeObserver對象,兩個參數(shù),第一個是外部類的對象,
* 也就是ManageApplications對象,第二個是msgId,也就是
* 分發(fā)消息的id,跟Handler接收的msgId一樣。
* */
Object soObject = sizeObserverConstructor.newInstance(maObject, 1);
//執(zhí)行invokeGetSize方法
sizeObserverClass.getMethod("invokeGetSize", String.class,
CountDownLatch.class).invoke(soObject, packageName, new CountDownLatch(1));
} catch (NameNotFoundException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getPackageStats("chroya.demo");
}
}
注釋都在代碼里面了,稍微理解一下應(yīng)該都能懂的。
獲取到PackageStats對象,就可以從中獲取到應(yīng)用程序的占用空間大小、數(shù)據(jù)大小和緩存大小。
另,這畢竟只是hack code,不可能通用。這段代碼的局限性是,只有1.5能用,而且如果別人把setting包去掉了,也沒法使用。要寫出各版本SDK通用的代碼,就必須查看每個版本的setting包,看代碼有何變化,然后根據(jù)上面給出的思路為每個版本寫一個方法,就ok了。
想要獲得成功,首先要自己相信自己,再者要贏得周圍朋友的信任!
相關(guān)文章
Android實現(xiàn)將View保存成Bitmap的方法
這篇文章主要介紹了Android實現(xiàn)將View保存成Bitmap的方法,涉及Android畫布Canvas、位圖bitmap及View的相關(guān)使用技巧,需要的朋友可以參考下2016-06-06edittext + listview 實現(xiàn)搜索listview中的內(nèi)容方法(推薦)
下面小編就為大家?guī)硪黄猠dittext + listview 實現(xiàn)搜索listview中的內(nèi)容方法(推薦)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-03-03Android編程根據(jù)系列圖片繪制動畫實例總結(jié)
這篇文章主要介紹了Android編程根據(jù)系列圖片繪制動畫的方法,以實例形式總結(jié)了Android根據(jù)圖片繪制動畫的常見情況與具體實現(xiàn)技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-11-11Android 使用registerReceiver注冊BroadcastReceiver案例詳解
這篇文章主要介紹了Android 使用registerReceiver注冊BroadcastReceiver案例詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-08-08獲取Android手機(jī)中所有短信的實現(xiàn)代碼
這篇文章主要介紹了獲取Android手機(jī)中所有短信的實現(xiàn)代碼,需要的朋友可以參考下2014-08-08Android自定義view實現(xiàn)太極效果實例代碼
這篇文章主要介紹了Android自定義view實現(xiàn)太極效果實例代碼的相關(guān)資料,需要的朋友可以參考下2017-05-05