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沉浸式狀態(tài)欄設(shè)計的實例代碼
本篇文章主要介紹了Android沉浸式狀態(tài)欄設(shè)計的實例代碼,整理了詳細(xì)的代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-07-07
Android徹底清除APP數(shù)據(jù)的兩種方案總結(jié)
大家在用Android手機的時候肯定都遇到過內(nèi)存剩余空間越來越小的情況,所以下面這篇文章主要給大家介紹了關(guān)于Android徹底清除APP數(shù)據(jù)的兩種方案,需要的朋友可以參考下2021-11-11
Android編程之SQLite數(shù)據(jù)庫操作方法詳解
這篇文章主要介紹了Android編程之SQLite數(shù)據(jù)庫操作方法,簡單介紹了SQLite數(shù)據(jù)庫及Android操作SQLite數(shù)據(jù)庫的步驟與相關(guān)實現(xiàn)技巧,需要的朋友可以參考下2017-08-08
android中用xml文件實現(xiàn)帶邊框背景效果的方法
這篇文章主要給大家介紹了在android中xml文件實現(xiàn)帶邊框背景效果的方法,其實實現(xiàn)的功能不是很難,僅作記錄,幫助需要的朋友們做個參考,需要的朋友們下面來一起看看吧。2017-06-06
Android Studio 利用Splash制作APP啟動界面的方法
這篇文章主要介紹了Android Studio 利用Splash制作APP啟動界面,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-05-05
Android開發(fā)實現(xiàn)布局幀布局霓虹燈效果示例
這篇文章主要介紹了Android開發(fā)實現(xiàn)布局幀布局霓虹燈效果,涉及Android界面布局、資源文件操作及屬性設(shè)置等相關(guān)技巧,需要的朋友可以參考下2019-04-04
Android利用Andserver搭建服務(wù)器的詳細(xì)教程
這篇文章主要介紹了Android利用Andserver搭建服務(wù)器的教程,本文通過圖文實例代碼相結(jié)合給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-06-06

