了解问题想看异常
```java
I/MainActivity: 我被诶点击了com.google.android.calendar
W/example.applis: Accessing hidden method Landroid/content/pm/IPackageStatsObserver$Stub;-><init>()V (light greylist, linking)
W/System.err: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Native Method)
W/System.err: at com.example.applist.MainActivity.queryPacakgeSize(MainActivity.java:176)
at com.example.applist.MainActivity$1.run(MainActivity.java:119)
at java.lang.Thread.run(Thread.java:764)
Caused by: java.lang.UnsupportedOperationException: Shame on you for calling the hidden API getPackageSizeInfoAsUser(). Shame!
at android.app.ApplicationPackageManager.getPackageSizeInfoAsUser(ApplicationPackageManager.java:2220)
W/System.err: at android.content.pm.PackageManager.getPackageSizeInfo(PackageManager.java:5269)
... 4 more
D/EGL_emulation: eglMakeCurrent: 0xee1c3320: ver 3 1 (tinfo 0xee1c5f80)
D/EGL_emulation: eglMakeCurrent: 0xee1c3320: ver 3 1 (tinfo 0xee1c5f80)
D/EGL_emulation: eglMakeCurrent: 0xee1c3320: ver 3 1 (tinfo 0xee1c5f80)
I/chatty: uid=10088(com.example.applist) RenderThread identical 21 lines
D/EGL_emulation: eglMakeCurrent: 0xee1c3320: ver 3 1 (tinfo 0xee1c5f80)
D/EGL_emulation: eglMakeCurrent: 0xee1c3320: ver 3 1 (tinfo 0xee1c5f80)
下边是代码详情
```java
public class MainActivity extends Activity implements AdapterView.OnItemClickListener {
private static String TAG = "APP_SIZE";
private PackageManager pm;
private ListView listview = null;
private List<AppInfo> mlistAppInfo = null;
LayoutInflater infater = null ;
//全局变量,保存当前查询包得信息
private long cachesize ; //缓存大小
private long datasize ; //数据大小
private long codesize ; //应用程序大小
private long totalsize ; //总大小
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
int permisstion = checkSelfPermission(Manifest.permission.GET_PACKAGE_SIZE);
if(permisstion == PackageManager.PERMISSION_DENIED){
requestPermissions(new String[]{Manifest.permission.GET_PACKAGE_SIZE},0);
}
//requestAppUsagePermission(this);
listview = (ListView) findViewById(R.id.listviewApp);
mlistAppInfo = new ArrayList<AppInfo>();
queryAppInfo(); // 查询所有应用程序信息
BrowseApplicationInfoAdapter browseAppAdapter = new BrowseApplicationInfoAdapter(
this, mlistAppInfo);
listview.setAdapter(browseAppAdapter);
listview.setOnItemClickListener(this);
}
public static void requestAppUsagePermission(Context context) {
Intent intent = new Intent(android.provider.Settings.ACTION_USAGE_ACCESS_SETTINGS);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
context.startActivity(intent);
} catch (ActivityNotFoundException e) {
e.printStackTrace();
}
}
// 获得所有启动Activity的信息,类似于Launch界面
public void queryAppInfo() {
PackageManager pm = this.getPackageManager(); // 获得PackageManager对象
Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
// 通过查询,获得所有ResolveInfo对象.
List<ResolveInfo> resolveInfos = pm.queryIntentActivities(mainIntent, 0);
// 调用系统排序 , 根据name排序
// 该排序很重要,否则只能显示系统应用,而不能列出第三方应用程序
Collections.sort(resolveInfos,new ResolveInfo.DisplayNameComparator(pm));
if (mlistAppInfo != null) {
mlistAppInfo.clear();
for (ResolveInfo reInfo : resolveInfos) {
String activityName = reInfo.activityInfo.name; // 获得该应用程序的启动Activity的name
String pkgName = reInfo.activityInfo.packageName; // 获得应用程序的包名
String appLabel = (String) reInfo.loadLabel(pm); // 获得应用程序的Label
Drawable icon = reInfo.loadIcon(pm); // 获得应用程序图标
// 为应用程序的启动Activity 准备Intent
Intent launchIntent = new Intent();
launchIntent.setComponent(new ComponentName(pkgName,activityName));
// 创建一个AppInfo对象,并赋值
AppInfo appInfo = new AppInfo();
appInfo.setAppLabel(appLabel);
appInfo.setPkgName(pkgName);
appInfo.setAppIcon(icon);
appInfo.setIntent(launchIntent);
mlistAppInfo.add(appInfo); // 添加至列表中
}
}
}
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
//更新显示当前包得大小信息
String pkgname = mlistAppInfo.get(i).getPkgName();
Log.i("MainActivity","我被诶点击了"+pkgname);
PhoneAppInfo phoneAppInfo = new PhoneAppInfo();
new Thread(new Runnable() {
@Override
public void run() {
//getPkgSize(getApplicationContext(),pkgname,phoneAppInfo);
try {
queryPacakgeSize(pkgname);
} catch (Exception e) {
e.printStackTrace();
}
runOnUiThread(new Runnable() {
@Override
public void run() {
infater = (LayoutInflater) MainActivity.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View dialog = infater.inflate(R.layout.dialog_app_size, null) ;
TextView tvcachesize =(TextView) dialog.findViewById(R.id.tvcachesize) ; //缓存大小
TextView tvdatasize = (TextView) dialog.findViewById(R.id.tvdatasize) ; //数据大小
TextView tvcodesize = (TextView) dialog.findViewById(R.id.tvcodesize) ; // 应用程序大小
TextView tvtotalsize = (TextView) dialog.findViewById(R.id.tvtotalsize) ; //总大小
// //类型转换并赋值
cachesize = phoneAppInfo.getCatchSize();
datasize = phoneAppInfo.getDataSize();
codesize = phoneAppInfo.getCodeSize();
totalsize = phoneAppInfo.getAppSize();
tvcachesize.setText(formateFileSize(cachesize));
tvdatasize.setText(formateFileSize(datasize)) ;
tvcodesize.setText(formateFileSize(codesize)) ;
tvtotalsize.setText(formateFileSize(totalsize)) ;
// //显示自定义对话框
AlertDialog.Builder builder =new AlertDialog.Builder(MainActivity.this) ;
builder.setView(dialog) ;
builder.setTitle(mlistAppInfo.get(i).getAppLabel()+"的大小信息为:") ;
builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
dialog.cancel() ; // 取消显示对话框
}
});
builder.create().show() ;
}
});
}
}).start();
}
//系统函数,字符串转换 long -String (kb)
private String formateFileSize(long size){
return Formatter.formatFileSize(MainActivity.this, size);
}
public void queryPacakgeSize(String pkgName) throws Exception{
pm = getPackageManager();
Method getPackageSizeInfoMethod = null;
if ( pkgName != null){
Method[] methods = PackageManager.class.getMethods();
for(Method method : methods){
if("getPackageSizeInfo".equals(method.getName())){
getPackageSizeInfoMethod = method;
}
}
getPackageSizeInfoMethod.invoke(pm,pkgName,new PkgSizeObserver());
//使用放射机制得到PackageManager类的隐藏函数getPackageSizeInfo
// PackageManager packageManager = getPackageManager(); //得到pm对象
// try {
// //通过反射机制获得该隐藏函数
// // Method getPackageSizeInfo = packageManager.getClass().getDeclaredMethod("getPackageSizeInfo", String.class, IPackageStatsObserver.class);
// Method getPackageSizeInfo = packageManager.getClass().getMethod("queryPacakgeSize", String.class,
// IPackageStatsObserver.class);
// //调用该函数,并且给其分配参数 ,待调用流程完成后会回调PkgSizeObserver类的函数
// //getPackageSizeInfo.invoke(packageManager, pkgName,new PkgSizeObserver());
// getPackageSizeInfo.invoke( pkgName,new PkgSizeObserver());
// }
// catch(Exception ex){
// Log.e(TAG, "NoSuchMethodException") ;
// ex.printStackTrace() ;
// throw ex ; // 抛出异常
}
}
//aidl文件形成的Bindler机制服务类
class PkgSizeObserver extends IPackageStatsObserver.Stub{
/*** 回调函数,
* @param pStats ,返回数据封装在PackageStats对象中
* @param succeeded 代表回调成功
*/
@Override
public void onGetStatsCompleted(PackageStats pStats, boolean succeeded)
throws RemoteException {
// TODO Auto-generated method stub
cachesize = pStats.cacheSize ; //缓存大小
datasize = pStats.dataSize ; //数据大小
codesize = pStats.codeSize ; //应用程序大小
totalsize = cachesize + datasize + codesize ;
Log.i(TAG, "cachesize--->"+cachesize+" datasize---->"+datasize+ " codeSize---->"+codesize) ;
}
}
/**
* 作用:-----获取包的大小-----
* @param context 上下文
* @param pkgName app的包名
* @param appInfo 实体类,用于存放App的某些信息
*/
public static void getPkgSize(final Context context, String pkgName, final PhoneAppInfo appInfo) {
// getPackageSizeInfo是PackageManager中的一个private方法,所以需要通过反射的机制来调用
Method method;
try {
method = PackageManager.class.getMethod("getPackageSizeInfo",
new Class[]{String.class, IPackageStatsObserver.class});
// 调用 getPackageSizeInfo 方法,需要两个参数:1、需要检测的应用包名;2、回调
method.invoke(context.getPackageManager(), pkgName,
new IPackageStatsObserver.Stub() {
@Override
public void onGetStatsCompleted(PackageStats pStats, boolean succeeded) throws RemoteException {
if (succeeded && pStats != null) {
synchronized (PhoneAppInfo.class) {
appInfo.setCatchSize(pStats.cacheSize);//缓存大小
appInfo.setDataSize(pStats.dataSize); //数据大小
appInfo.setCodeSize(pStats.codeSize); //应用大小
appInfo.setAppSize(pStats.cacheSize + pStats.codeSize + pStats.dataSize);//应用的总大小
Log.d("asdasdxx",appInfo.getAppSize()+"");
}
}
}
});
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
e.printStackTrace();
}
}
}
appInfo.setCatchSize(pStats.cacheSize);//缓存大小
appInfo.setDataSize(pStats.dataSize); //数据大小
appInfo.setCodeSize(pStats.codeSize); //应用大小
权限在Manifest.xml文件已经申请了,就是无法获得得到数据大小。