使用放射機制得到PackageManager類的隱藏函數getPackageSizeInfo,從而得到包的大小

     <uses-permission android:name="android.permission.GET_PACKAGE_SIZE"></uses-permission>

 

IPackageStatsObserver.aidl

/*
**
** Copyright 2007, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
**     http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/

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);
}

 

 

 

PackageStats.aidl

/* //device/java/android/android/view/WindowManager.aidl
**
** Copyright 2007, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
**     http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/

package  android.content.pm;

parcelable PackageStats;

 

 

 

MainActivity.java

 

package com.qin.appsize;


import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import com.qin.appsize.AppInfo;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.IPackageStatsObserver;
import android.content.pm.PackageManager;
import android.content.pm.PackageStats;
import android.content.pm.ResolveInfo;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.RemoteException;
import android.text.format.Formatter;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;

public class MainActivity extends Activity implements OnItemClickListener{
    private static String TAG = "APP_SIZE";

 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
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.browse_app_list);
        listview = (ListView) findViewById(R.id.listviewApp);
  mlistAppInfo = new ArrayList<AppInfo>();
  queryAppInfo(); // 查詢所有應用程序信息
  BrowseApplicationInfoAdapter browseAppAdapter = new BrowseApplicationInfoAdapter(
    this, mlistAppInfo);
  listview.setAdapter(browseAppAdapter);
  listview.setOnItemClickListener(this);
    }
     // 點擊彈出對話框,顯示該包得大小
 public void onItemClick(AdapterView<?> arg0, View view, int position,long arg3) {
     
  //更新顯示當前包得大小信息
  try {
   queryPacakgeSize(mlistAppInfo.get(position).getPkgName());
  } catch (Exception e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
       
  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) ; //總大小
  //類型轉換並賦值
  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(position).getAppLabel()+"的大小信息爲:") ;
  builder.setPositiveButton("確定", new DialogInterface.OnClickListener() {

   @Override
   public void onClick(DialogInterface dialog, int which) {
    // TODO Auto-generated method stub
    dialog.cancel() ;  // 取消顯示對話框
   }
   
  });
  builder.create().show() ;
 }
    public void  queryPacakgeSize(String pkgName) throws Exception{
     if ( pkgName != null){
      //使用放射機制得到PackageManager類的隱藏函數getPackageSizeInfo
      PackageManager pm = getPackageManager();  //得到pm對象
      try {
       //通過反射機制獲得該隱藏函數
    Method getPackageSizeInfo = pm.getClass().getDeclaredMethod("getPackageSizeInfo", String.class,IPackageStatsObserver.class);
       //調用該函數,並且給其分配參數 ,待調用流程完成後會回調PkgSizeObserver類的函數
       getPackageSizeInfo.invoke(pm, pkgName,new PkgSizeObserver());
   }
         catch(Exception ex){
          Log.e(TAG, "NoSuchMethodException") ;
          ex.printStackTrace() ;
          throw ex ;  // 拋出異常
         }
     }
    }
  
    //aidl文件形成的Bindler機制服務類
    public class PkgSizeObserver extends IPackageStatsObserver.Stub{
        /*** 回調函數,
         * @param pStatus ,返回數據封裝在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)  ;
  }
    }
    //系統函數,字符串轉換 long -String (kb)
    private String formateFileSize(long size){
     return Formatter.formatFileSize(MainActivity.this, size);
    }
   // 獲得所有啓動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); // 添加至列表中
   }
  }
 }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章