android 获取应用程序(包)的信息和缓存大小 PackageManager的使用

PackageManger 类
说明: 获得已安装的应用程序信息 。可以通过 getPackageManager()方法获得。
常用方法:
    public abstract PackageManager  getPackageManager()  
     功能:获得一个PackageManger对象
    public abstrac  tDrawable    getApplicationIcon(StringpackageName)
      参数: packageName 包名
      功能:返回给定包名的图标,否则返回null

    public abstract ApplicationInfo   getApplicationInfo(String packageName, int flags)

      参数:packagename 包名
                           flags 该ApplicationInfo是此flags标记,通常可以直接赋予常数0即可
      功能:返回该ApplicationInfo对象

     public abstract List<ApplicationInfo>  getInstalledApplications(int flags)
      参数:flag为一般为GET_UNINSTALLED_PACKAGES,那么此时会返回所有ApplicationInfo。我们可以对ApplicationInfo的flags过滤,得到我们需要的。
      功能:返回给定条件的所有PackageInfo

     public abstract List<PackageInfo>  getInstalledPackages(int flags)
      参数如上
      功能:返回给定条件的所有PackageInfo

     public abstractResolveInfo  resolveActivity(Intent intent, int flags)
       参数:  intent 查寻条件,Activity所配置的action和category
       flags: MATCH_DEFAULT_ONLY    :Category必须带有CATEGORY_DEFAULT的Activity,才匹配
       GET_INTENT_FILTERS         :匹配Intent条件即可
       GET_RESOLVED_FILTER    :匹配Intent条件即可
       功能 :返回给定条件的ResolveInfo对象(本质上是Activity)

       public abstract  List<ResolveInfo>  queryIntentActivities(Intent intent, int flags)
       参数同上
       功能 :返回给定条件的所有ResolveInfo对象(本质上是Activity),集合对象

       public abstract ResolveInfo  resolveService(Intent intent, int flags)
           参数同上
           功能 :返回给定条件的ResolveInfo对象(本质上是Service)

     public abstract List<ResolveInfo> queryIntentServices(Intent intent, int flags)
          参数同上
          功能 :返回给定条件的所有ResolveInfo对象(本质上是Service),集合对象

案例讲解

通过queryIntentActivities()方法,查询Android系统的所有具备ACTION_MAIN和CATEGORY_LAUNCHER的Intent的应用程序,点击后,能启动该应用,说白了就是做一个类似Home程序的简易Launcher 。

android 获取应用程序(包)的信息和缓存大小 PackageManager的使用_第1张图片

布局文件
<?xml version="1.0" encoding="utf-8"?>  
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:orientation="vertical" android:layout_width="fill_parent"  
    android:layout_height="fill_parent">>  
    <ListView android:id="@+id/listviewApp" android:layout_width="fill_parent"  
        android:layout_height="fill_parent" ></ListView>  
</LinearLayout>  


<?xml version="1.0" encoding="utf-8"?>  
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:layout_width="fill_parent" android:layout_height="50dip">  
  
    <ImageView android:id="@+id/imgApp" android:layout_width="wrap_content"  
        android:layout_height="fill_parent" ></ImageView>  
    <RelativeLayout android:layout_width="fill_parent"  android:layout_marginLeft="10dip"  
        android:layout_height="40dip">  
        <TextView android:id="@+id/tvLabel" android:layout_width="wrap_content"  
            android:layout_height="wrap_content" android:text="AppLable : "></TextView>  
        <TextView android:id="@+id/tvAppLabel" android:layout_width="wrap_content"  
            android:layout_toRightOf="@id/tvLabel" android:layout_height="wrap_content"  
            android:layout_marginLeft="3dip" android:text="Label" android:textColor="#FFD700"></TextView>  
        <TextView android:id="@+id/tvName" android:layout_width="wrap_content"  
            android:layout_height="wrap_content" android:layout_below="@id/tvLabel"   
            android:text="包名:"></TextView>  
        <TextView android:id="@+id/tvPkgName" android:layout_width="wrap_content"  
            android:layout_height="wrap_content" android:layout_below="@id/tvAppLabel"  
            android:layout_alignLeft="@id/tvAppLabel" android:textColor="#FFD700"></TextView>  
    </RelativeLayout>  
</LinearLayout> 


自定义适配器类
//自定义适配器类,提供给listView的自定义view
public class BrowseApplicationInfoAdapter extends BaseAdapter {
	
	private List<AppInfo> mlistAppInfo = null;
	
	LayoutInflater infater = null;
    
	public BrowseApplicationInfoAdapter(Context context,  List<AppInfo> apps) {
		infater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		mlistAppInfo = apps ;
	}
	@Override
	public int getCount() {
		// TODO Auto-generated method stub
		System.out.println("size" + mlistAppInfo.size());
		return mlistAppInfo.size();
	}
	@Override
	public Object getItem(int position) {
		// TODO Auto-generated method stub
		return mlistAppInfo.get(position);
	}
	@Override
	public long getItemId(int position) {
		// TODO Auto-generated method stub
		return 0;
	}
	@Override
	public View getView(int position, View convertview, ViewGroup arg2) {
		System.out.println("getView at " + position);
		View view = null;
		ViewHolder holder = null;
		if (convertview == null || convertview.getTag() == null) {
			view = infater.inflate(R.layout.browse_app_item, null);
			holder = new ViewHolder(view);
			view.setTag(holder);
		} 
		else{
			view = convertview ;
			holder = (ViewHolder) convertview.getTag() ;
		}
		AppInfo appInfo = (AppInfo) getItem(position);
		holder.appIcon.setImageDrawable(appInfo.getAppIcon());
		holder.tvAppLabel.setText(appInfo.getAppLabel());
		holder.tvPkgName.setText(appInfo.getPkgName());
		return view;
	}

	class ViewHolder {
		ImageView appIcon;
		TextView tvAppLabel;
		TextView tvPkgName;

		public ViewHolder(View view) {
			this.appIcon = (ImageView) view.findViewById(R.id.imgApp);
			this.tvAppLabel = (TextView) view.findViewById(R.id.tvAppLabel);
			this.tvPkgName = (TextView) view.findViewById(R.id.tvPkgName);
		}
	}
}


MainActivity.java 主工程逻辑
请仔细体会queryIntentActivities()方法,并且注意到排序,它很重要。
public class MainActivity extends Activity implements OnItemClickListener {  
  
    private ListView listview = null;  
  
    private List<AppInfo> mlistAppInfo = null;  
  
    @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) {  
        // TODO Auto-generated method stub  
        Intent intent = mlistAppInfo.get(position).getIntent();  
        startActivity(intent);  
    }  
    // 获得所有启动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, PackageManager.MATCH_DEFAULT_ONLY);  
        // 调用系统排序 , 根据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); // 添加至列表中  
                System.out.println(appLabel + " activityName---" + activityName  
                        + " pkgName---" + pkgName);  
            }  
        }  
    }  
}


转自: http://blog.csdn.net/qinjuning/article/details/6867806


下面部分的内容是 如何获取安装包得大小,包括缓存大小(cachesize)、数据大小(datasize)、应用程序大小(codesize)。
本部分的知识点涉及到AIDL、Java反射机制。理解起来也不是很难。
  
      关于安装包得大小信息封装在PackageStats类中,该类很简单,只有几个字段:
      PackageStats类:
          常用字段:
               public long cachesize      缓存大小
               public long codesize       应用程序大小
               public long datasize       数据大小
               public String packageName  包名

        PS:应用程序的总大小 = cachesize  + codesize  + datasize
        也就是说只要获得了 安装包所对应的PackageStats对象,就可以获得信息了。但是在AndroidSDK中并没有显示提供方法来
获得该对象,是不是很苦恼呢?但是, 我们可以通过放射机制来调用系统中隐藏的函数(@hide)来获得每个安装包得信息。

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) {
        //更新显示当前包得大小信息
		queryPacakgeSize(mlistAppInfo.get(position).getPkgName()); 
        
		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); // 添加至列表中
			}
		}
	}
}


转自: http://blog.csdn.net/qinjuning/article/details/6892054














你可能感兴趣的:(android 获取应用程序(包)的信息和缓存大小 PackageManager的使用)