Android 获取全部应用

休言女子非英物,夜夜龙泉壁上鸣。这篇文章主要讲述Android 获取全部应用相关的知识,希望能为你提供帮助。

 

private PackageManager mPackageManager;

 

//获取系统应用
mPackageManager = getActivity().getPackageManager();
List< Downloadinfo> packageInfos = getAllApps(getActivity());



/**
* 查询手机内非系统应用
*
* @param context
* @return
*/
public List< Downloadinfo> getAllApps(Context context) {
//获取手机内所有应用
Intent i = new Intent(Intent.ACTION_MAIN, null);
i.addCategory(Intent.CATEGORY_LAUNCHER);
List< ResolveInfo> rinfo = getActivity().getPackageManager().queryIntentActivities(i,
0);
List< Downloadinfo> appInfos = new ArrayList< Downloadinfo> (); // 保存过滤查到的AppInfo
// 根据条件来过滤
for (ResolveInfo app : rinfo) {
if ((app.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) < = 0) {// 第三方应用

Downloadinfo temp = getAppInfo(app);

if (temp.getPkgName().equals("com.lvshandian.menshen")) {

continue;
}
if (null != temp) {

appInfos.add(temp);
}
} else {// 系统应用
Downloadinfo temp = getAppInfo(app);
if (null != temp & & !TextUtils.isEmpty(temp.getPkgName())
& & !temp.getPkgName().equals("com.lvshandian.menshen")) {
}
}
}
return appInfos;
}

private Downloadinfo getAppInfo(ResolveInfo app) {

Downloadinfo appInfo = new Downloadinfo();


appInfo.setAppIcon(app.activityInfo.loadIcon(mPackageManager));
appInfo.setPkgName(app.activityInfo.packageName);
String appName = app.activityInfo.loadLabel(mPackageManager).toString();
appInfo.setAppName(appName);


return appInfo;

}
//获取包名的大小

http://www.xuebuyuan.com/901153.html



android中获取应用程序(包)的大小—–PackageManager的使用(二)

2013年09月22日? 综合 ? 共 20231字 ? 字号 小 中 大? 评论关闭

 

      通过第一部分< < Android中获取应用程序(包)的信息-----PackageManager的使用(一)> > 的介绍,对PackageManager以及
AndroidManife.xml定义的节点信息类XXXInfo类都有了一定的认识。
                    本部分的内容是如何获取安装包得大小,包括缓存大小(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)来获得每个安装包得信息。
具体方法如下:
 
              第一步、  通过放射机制调用getPackageSizeInfo()  方法原型为:                           
[java]
view plaincopyprint?
  1. /*@param  packageName  应用程序包名 
  2.           *@param  observer        当查询包得信息大小操作完成后,将回调给IPackageStatsObserver类中的onGetStatsCompleted()方法, 
  3.           *            ,并且我们需要的PackageStats对象也封装在其参数里. 
  4.           *  @hide  //隐藏函数的标记 
  5.           */   
  6.               public  abstract  void  getPackageSizeInfo(String  packageName,IPackageStatsObserver  observer); {   
  7.                     //    
  8.               }   
              内部调用流程如下,这个知识点较为复杂,知道即可,
                getPackageSizeInfo方法内部调用getPackageSizeInfoLI(packageName, pStats)方法来完成包状态获取。
getPackageSizeInfoLI方法内部调用Installer.getSizeInfo(String pkgName, String apkPath,String fwdLockApkPath,    PackageStats
pStats),继而将包状态信息返回给参数pStats。getSizeInfo这个方法内部是以本机Socket方式连接到Server,
然后向server发送一个文本字符串命令,格式:getsize apkPath fwdLockApkPath 给server。Server将结果返回,并解析到pStats
中。掌握这个调用知识链即可。
 
 
        第二步、  由于需要获得系统级的服务或类,我们必须加入Android系统形成的AIDL文件,共两个:
                        IPackageStatsObserver.aidl 和 PackageStats.aidl文件。并将其放置在android.pm.content包路径下。
    IPackageStatsObserver.aidl 文件
【Android 获取全部应用】 
 
[java]
view plaincopyprint?
  1. package  android.content.pm;    
  2.    
  3. import  android.content.pm.PackageStats;    
  4. /** 
  5.   *  API  for  package  data  change  related  callbacks  from  the  Package  Manager. 
  6.   *  Some  usage  scenarios  include  deletion  of  cache  directory,  generate 
  7.   *  statistics  related  to  code,  data,  cache  usage(TODO) 
  8.   *  {@hide} 
  9.   */   
  10. oneway  interface  IPackageStatsObserver  {   
  11.            
  12.         void  onGetStatsCompleted(in  PackageStats  pStats,  boolean  succeeded);    
  13. }   
PackageStats.aidl文件
 
[java]
view plaincopyprint?
  1. package  android.content.pm;    
  2.    
  3. parcelable  PackageStats;    
 
            第三步、  创建一个类继承至IPackageStatsObserver.Stub (桩,)它本质上实现了Binder机制。当我们把该类的一个实例通过getPackageSizeInfo()调用时,并该函数继而启动了启动中间流程去获取相关包得信息大小,当扫描完成后,最后将查询信息回调至该类的onGetStatsCompleted(in PackageStats pStats, boolean succeeded)方法,信息大小封装在此实例上。例如:
 
[java]
view plaincopyprint?
  1. //aidl文件形成的Bindler机制服务类    
  2.       public  class  PkgSizeObserver  extends  IPackageStatsObserver.Stub{   
  3.               /***  回调函数, 
  4.                 *  @param  pStatus  ,返回数据封装在PackageStats对象中 
  5.                 *  @param  succeeded    代表回调成功 
  6.                 */     
  7. @Override   
  8. public  void  onGetStatsCompleted(PackageStats  pStats,  boolean  succeeded)   
  9.                 throws  RemoteException  {   
  10.       //  TODO  Auto-generated  method  stub
       
  11.       cachesize  =  pStats.cacheSize    ;   //缓存大小
       
  12.                     datasize  =  pStats.codeSize    ;     //数据大小 
       
  13.                     codesize  =        pStats.codeSize    ;     //应用程序大小
       
  14.           }   
  15.     }   
             
            第四步、  最后我们可以获取 pStats的属性,获得它们的属性值,通过调用系统函数Formatter.formateFileSize(long size)转换
为对应的以kb/mb为计量单位的字符串。
 
        很重要的一点:为了能够通过反射获取应用程序大小,我们必须加入以下权限,否则,会出现警告并且得不到实际值。
             
[java]
view plaincopyprint?
  1. < uses-permission  android:name="android.permission.GET_PACKAGE_SIZE"> < /uses-permission>    
 
        流程图如下:
                     
Android 获取全部应用

文章图片

 
Demo说明:
                          在第一部分应用得基础上,我们添加了一个新功能,点击任何一个应用后后,弹出显示该应用的包信息大小的对话框。
              截图如下:
                              工程图:                                                                                                                                                                  程序效果图:
                           
Android 获取全部应用

文章图片
                     
Android 获取全部应用

文章图片

1、dialg_app_size.xml 文件
[html]
view plaincopyprint?
  1. < ?xml  version="1.0"  encoding="utf-8"?>    
  2. < LinearLayout  xmlns:android="http://schemas.android.com/apk/res/android"   
  3.         android:orientation="vertical"  android:layout_width="wrap_content"   
  4.         android:layout_height="wrap_content">    
  5.         < LinearLayout  android:layout_width="wrap_content"   
  6.                 android:layout_height="wrap_content"  android:orientation="horizontal">    
  7.                 < TextView  android:layout_width="100dip"   
  8.                         android:layout_height="wrap_content"  android:text="缓存大小:"> < /TextView>    
  9.                 < TextView  android:layout_width="100dip"  android:id="@+id/tvcachesize"   
  10.                         android:layout_height="wrap_content"> < /TextView>    
  11.         < /LinearLayout>    
  12.         < LinearLayout  android:layout_width="wrap_content"   
  13.                 android:layout_height="wrap_content"  android:orientation="horizontal">    
  14.                 < TextView  android:layout_width="100dip"   
  15.                         android:layout_height="wrap_content"  android:text="数据大小:"> < /TextView>    
  16.                 < TextView  android:layout_width="100dip"  android:id="@+id/tvdatasize"   
  17.                         android:layout_height="wrap_content"> < /TextView>    
  18.         < /LinearLayout>    
  19.         < LinearLayout  android:layout_width="wrap_content"   
  20.                 android:layout_height="wrap_content"  android:orientation="horizontal">    
  21.                 < TextView  android:layout_width="100dip"   
  22.                         android:layout_height="wrap_content"  android:text="应用程序大小:"> < /TextView>    
  23.                 < TextView  android:layout_width="100dip"  android:id="@+id/tvcodesize"   
  24.                         android:layout_height="wrap_content"> < /TextView>    
  25.         < /LinearLayout>    
  26.         < LinearLayout  android:layout_width="wrap_content"   
  27.                 android:layout_height="wrap_content"  android:orientation="horizontal">    
  28.                 < TextView  android:layout_width="100dip"   
  29.                         android:layout_height="wrap_content"  android:text="总大小:"> < /TextView>    
  30.                 < TextView  android:layout_width="100dip"  android:id="@+id/tvtotalsize"   
  31.                         android:layout_height="wrap_content"> < /TextView>    
  32.         < /LinearLayout>    
  33. < /LinearLayout>    
  2、另外的资源文件或自定义适配器复用了第一部分,请知悉。
  3、添加AIDL文件,如上。
  4、主文件MainActivity.java如下:
 
[java]
view plaincopyprint?
  1. package  com.qin.appsize;    
  2.    
  3.    
  4. import  java.lang.reflect.Method;    
  5. import  java.util.ArrayList;    
  6. import  java.util.Collections;    
  7. import  java.util.List;    
  8.    
  9. import  com.qin.appsize.AppInfo;    
  10.    
  11. import  android.app.Activity;    
  12. import  android.app.AlertDialog;    
  13. import  android.content.ComponentName;    
  14. import  android.content.Context;    
  15. import  android.content.DialogInterface;    
  16. import  android.content.Intent;    
  17. import  android.content.pm.IPackageStatsObserver;    
  18. import  android.content.pm.PackageManager;    
  19. import  android.content.pm.PackageStats;    
  20. import  android.content.pm.ResolveInfo;    
  21. import  android.graphics.drawable.Drawable;    
  22. import  android.os.Bundle;    
  23. import  android.os.RemoteException;    
  24. import  android.text.format.Formatter;    
  25. import  android.util.Log;    
  26. import  android.view.LayoutInflater;    
  27. import  android.view.View;    
  28. import  android.widget.AdapterView;    
  29. import  android.widget.ListView;    
  30. import  android.widget.TextView;    
  31. import  android.widget.AdapterView.OnItemClickListener;    
  32.    
  33. public  class  MainActivity  extends  Activity  implements  OnItemClickListener{   
  34.         private  static  String  TAG  =  "APP_SIZE";    
  35.    
  36.         private  ListView  listview  =  null;    
  37.         private  List< AppInfo>   mlistAppInfo  =  null;    
  38.         LayoutInflater  infater  =  null  ;      
  39.         //全局变量,保存当前查询包得信息    
  40.         private  long  cachesize  ;   //缓存大小
       
  41.         private  long  datasize    ;     //数据大小 
       
  42.         private  long  codesize    ;     //应用程序大小
       
  43.         private  long  totalsize  ;   //总大小
       
  44.         @Override   
  45.         public  void  onCreate(Bundle  savedInstanceState)  {   
  46.                 super.onCreate(savedInstanceState);    
  47.                 setContentView(R.layout.browse_app_list);    
  48.                 listview  =  (ListView)  findViewById(R.id.listviewApp);    
  49.                 mlistAppInfo  =  new  ArrayList< AppInfo> ();    
  50.                 queryAppInfo();   //  查询所有应用程序信息
       
  51.                 BrowseApplicationInfoAdapter  browseAppAdapter  =  new  BrowseApplicationInfoAdapter(   
  52.                                 this,  mlistAppInfo);    
  53.                 listview.setAdapter(browseAppAdapter);    
  54.                 listview.setOnItemClickListener(this);    
  55.         }   
  56.           //  点击弹出对话框,显示该包得大小    
  57.         public  void  onItemClick(AdapterView< ?>   arg0,  View  view,  int  position,long  arg3)  {   
  58.                 //更新显示当前包得大小信息    
  59.                 queryPacakgeSize(mlistAppInfo.get(position).getPkgName());      
  60.                    
  61.                 infater  =  (LayoutInflater)  MainActivity.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);    
  62.                 View  dialog  =  infater.inflate(R.layout.dialog_app_size,  null)  ;    
  63.                 TextView  tvcachesize  =(TextView)  dialog.findViewById(R.id.tvcachesize)  ;   //缓存大小
       
  64.                 TextView  tvdatasize  =  (TextView)  dialog.findViewById(R.id.tvdatasize)    ;   //数据大小
       
  65.                 TextView  tvcodesize  =  (TextView)  dialog.findViewById(R.id.tvcodesize)  ;   //  应用程序大小
       
  66.                 TextView  tvtotalsize  =  (TextView)  dialog.findViewById(R.id.tvtotalsize)  ;   //总大小
       
  67.                 //类型转换并赋值    
  68.                 tvcachesize.setText(formateFileSize(cachesize));    
  69.                 tvdatasize.setText(formateFileSize(datasize))  ;    
  70.                 tvcodesize.setText(formateFileSize(codesize))  ;    
  71.                 tvtotalsize.setText(formateFileSize(totalsize))  ;    
  72.                 //显示自定义对话框    
  73.                 AlertDialog.Builder  builder  =new  AlertDialog.Builder(MainActivity.this)  ;    
  74.                 builder.setView(dialog)  ;    
  75.                 builder.setTitle(mlistAppInfo.get(position).getAppLabel()+"的大小信息为:")  ;    
  76.                 builder.setPositiveButton("确定",  new  DialogInterface.OnClickListener()  {   
  77.    
  78.                         @Override   
  79.                         public  void  onClick(DialogInterface  dialog,  int  which)  {   
  80.                                 //  TODO  Auto-generated  method  stub
       
  81.                                 dialog.cancel()  ;     //  取消显示对话框
       
  82.                         }   
  83.                            
  84.                 });    
  85.                 builder.create().show()  ;    
  86.         }   
  87.         public  void    queryPacakgeSize(String  pkgName)  throws  Exception{   
  88.                 if  (  pkgName  !=  null){   
  89.                         //使用放射机制得到PackageManager类的隐藏函数getPackageSizeInfo
       
  90.                         PackageManager  pm  =  getPackageManager();     //得到pm对象
       
  91.                         try  {   
  92.                                 //通过反射机制获得该隐藏函数    
  93.                                 Method  getPackageSizeInfo  =  pm.getClass().getDeclaredMethod("getPackageSizeInfo",  String.class,IPackageStatsObserver.class);    
  94.                                 //调用该函数,并且给其分配参数  ,待调用流程完成后会回调PkgSizeObserver类的函数
       
  95.                                 getPackageSizeInfo.invoke(pm,  pkgName,new  PkgSizeObserver());    
  96.                         }     
  97.                         catch(Exception  ex){   
  98.                                 Log.e(TAG,  "NoSuchMethodException")  ;    
  99.                                 ex.printStackTrace()  ;    
  100.                                 throw  ex  ;     //  抛出异常
       
  101.                         }     
  102.                 }   
  103.         }   
  104.          
  105.         //aidl文件形成的Bindler机制服务类
       
  106.         public  class  PkgSizeObserver  extends  IPackageStatsObserver.Stub{   
  107.                 /***  回调函数, 
  108.                   *  @param  pStatus  ,返回数据封装在PackageStats对象中 
  109.                   *  @param  succeeded    代表回调成功 
  110.                   */     
  111.                 @Override   
  112.                 public  void  onGetStatsCompleted(PackageStats  pStats,  boolean  succeeded)   
  113.                                 throws  RemoteException  {   
  114.                         //  TODO  Auto-generated  method  stub
       
  115.                       cachesize  =  pStats.cacheSize    ;   //缓存大小
       
  116.                         datasize  =  pStats.dataSize    ;     //数据大小 
       
  117.                         codesize  =  pStats.codeSize    ;     //应用程序大小
       
  118.                         totalsize  =  cachesize  +  datasize  +  codesize  ;    
  119.                         Log.i(TAG,  "cachesize---> "+cachesize+"  datasize----> "+datasize+  "  codeSize----> "+codesize)    ;    
  120.                 }   
  121.         }   
  122.         //系统函数,字符串转换  long  -String  (kb)
       
  123.         private  String  formateFileSize(long  size){   
  124.                 return  Formatter.formatFileSize(MainActivity.this,  size);      
  125.         }   
  126.       //  获得所有启动Activity的信息,类似于Launch界面
       
  127.         public  void  queryAppInfo()  {   
  128.                 PackageManager  pm  =  this.getPackageManager();   //  获得PackageManager对象
       
  129.                 Intent  mainIntent  =  new  Intent(Intent.ACTION_MAIN,  null);    
  130.                 mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);    
  131.                 //  通过查询,获得所有ResolveInfo对象.
       
  132.                 List< ResolveInfo>   resolveInfos  =  pm.queryIntentActivities(mainIntent,  0);    
  133.                 //  调用系统排序  ,  根据name排序
       
  134.                 //  该排序很重要,否则只能显示系统应用,而不能列出第三方应用程序
       
  135.                 Collections.sort(resolveInfos,new  ResolveInfo.DisplayNameComparator(pm));    
  136.                 if  (mlistAppInfo  !=  null)  {   
  137.                         mlistAppInfo.clear();    
  138.                         for  (ResolveInfo  reInfo  :  resolveInfos)  {   
  139.                                 String  activityName  =  reInfo.activityInfo.name;   //  获得该应用程序的启动Activity的name
       
  140.                                 String  pkgName  =  reInfo.activityInfo.packageName;   //  获得应用程序的包名
       
  141.                                 String  appLabel  =  (String)  reInfo.loadLabel(pm);   //  获得应用程序的Label
       
  142.                                 Drawable  icon  =  reInfo.loadIcon(pm);   //  获得应用程序图标
       
  143.                                 //  为应用程序的启动Activity  准备Intent
       
  144.                                 Intent  launchIntent  =  new  Intent();    
  145.                                 launchIntent.setComponent(new  ComponentName(pkgName,activityName));    
  146.                                 //  创建一个AppInfo对象,并赋值
       
  147.                                 AppInfo  appInfo  =  new  AppInfo();    
  148.                                 appInfo.setAppLabel(appLabel);    
  149.                                 appInfo.setPkgName(pkgName);    
  150.                                 appInfo.setAppIcon(icon);    
  151.                                 appInfo.setIntent(launchIntent);    
  152.                                 mlistAppInfo.add(appInfo);   //  添加至列表中
       
  153.                         }   
  154.                 }   
  155.         }   
  156. }   
          获取应用程序信息大小就是这么来的,整个过程相对而言还是挺简单的,比较难理解的是AIDL文件的使用和回调函数的处理。
仔细研究后,才有所理解。


























































































































    推荐阅读