转载请注明出处:http://blog.csdn.net/l1028386804/article/details/47114331
前几篇有关Android的博文中,向大家介绍了几个项目中常用的实用功能,那么在这篇博文中,我将向大家介绍如何获取Android手机中已经安装的手机应用程序,实用过金山手机卫士或者360手机卫士的童鞋都知道,这些软件都可以获取到当前手机中安装的应用程序。那么,这些功能是如何实现的呢?就让我们一起来看看这些功能具体是如何实现的吧。
一、原理
原理很简单,我们通过Android中提供的PackageManager类,来获取手机中安装的应用程序信息,将这些信息封装成一个对象,这个对象包含应用程序的图标、名称、版本号、包名、是否是用户应用程序等信息,然后将这些对象封装成一个对象集合,再将这个集合显示到界面的listView上,形成一个应用程序列表。呈现给用户的便是一个手机中安装的应用程序列表了。
原理是不是很简单呢?下面,就让我们一起来实现这些功能吧。
二、实现
1、创建应用程序的实体类AppInfo
为了更加面向对象化和体现面向对象的封装性,我将获取到的每一个应用程序信息封装成了一个java对象,这个对象包含应用程序的图标、名称、版本号、包名、是否是用户应用程序等信息。
具体实现代码如下:
package cn.lyz.mobilesafe.domain; import android.graphics.drawable.Drawable; /** * 获取的应用基本信息实体类 * @author liuyazhuang * */ public class AppInfo { //图标 private Drawable app_icon; //应用名称 private String app_name; //应用版本号 private String app_version; //应用包名 private String packagename; //是否是用户app private boolean isUserApp; public AppInfo() { super(); // TODO Auto-generated constructor stub } public AppInfo(Drawable app_icon, String app_name, String app_version, String packagename) { super(); this.app_icon = app_icon; this.app_name = app_name; this.app_version = app_version; this.packagename = packagename; } public AppInfo(Drawable app_icon, String app_name, String app_version, String packagename, boolean isUserApp) { super(); this.app_icon = app_icon; this.app_name = app_name; this.app_version = app_version; this.packagename = packagename; this.isUserApp = isUserApp; } public Drawable getApp_icon() { return app_icon; } public void setApp_icon(Drawable app_icon) { this.app_icon = app_icon; } public String getApp_name() { return app_name; } public void setApp_name(String app_name) { this.app_name = app_name; } public String getApp_version() { return app_version; } public void setApp_version(String app_version) { this.app_version = app_version; } public String getPackagename() { return packagename; } public void setPackagename(String packagename) { this.packagename = packagename; } public boolean isUserApp() { return isUserApp; } public void setUserApp(boolean isUserApp) { this.isUserApp = isUserApp; } @Override public String toString() { return "AppInfo [app_icon=" + app_icon + ", app_name=" + app_name + ", app_version=" + app_version + ", packagename=" + packagename + ", isUserApp=" + isUserApp + "]"; } }
2、获取手机应用程序的业务类AppInfoService
这个类主要实现获取手机中安装的应用程序的主要业务功能,封装了如何获取手机安装的应用程序的方法。
具体实现代码如下:
package cn.lyz.mobilesafe.engine; import java.util.ArrayList; import java.util.List; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.graphics.drawable.Drawable; import cn.lyz.mobilesafe.domain.AppInfo; /** * 获取手机应用程序 * @author liuyazhuang * */ public class AppInfoService { private Context context; private PackageManager pm; public AppInfoService(Context context) { // TODO Auto-generated constructor stub this.context = context; pm = context.getPackageManager(); } /** * 得到手机中所有的应用程序信息 * @return */ public List<AppInfo> getAppInfos(){ //创建要返回的集合对象 List<AppInfo> appInfos = new ArrayList<AppInfo>(); //获取手机中所有安装的应用集合 List<ApplicationInfo> applicationInfos = pm.getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES); //遍历所有的应用集合 for(ApplicationInfo info : applicationInfos){ AppInfo appInfo = new AppInfo(); //获取应用程序的图标 Drawable app_icon = info.loadIcon(pm); appInfo.setApp_icon(app_icon); //获取应用的名称 String app_name = info.loadLabel(pm).toString(); appInfo.setApp_name(app_name); //获取应用的包名 String packageName = info.packageName; appInfo.setPackagename(packageName); try { //获取应用的版本号 PackageInfo packageInfo = pm.getPackageInfo(packageName, 0); String app_version = packageInfo.versionName; appInfo.setApp_version(app_version); } catch (NameNotFoundException e) { e.printStackTrace(); } //判断应用程序是否是用户程序 boolean isUserApp = filterApp(info); appInfo.setUserApp(isUserApp); appInfos.add(appInfo); } return appInfos; } //判断应用程序是否是用户程序 public boolean filterApp(ApplicationInfo info) { //原来是系统应用,用户手动升级 if ((info.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) { return true; //用户自己安装的应用程序 } else if ((info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) { return true; } return false; } }
3、样式文件styles.xml
在res/values目录下新建styles.xml文件来定义应用程序的样式信息,我在这个文件中主要定义个两个样式。
具体代码如下:
<style name="view_divide_line_style"> <item name="android:layout_width">fill_parent</item> <item name="android:layout_height">1dip</item> <item name="android:layout_marginTop">5dip</item> <item name="android:background">@drawable/devide_line</item> </style>
<style name="text_title_style"> <item name="android:layout_width">fill_parent</item> <item name="android:layout_height">wrap_content</item> <item name="android:gravity">center</item> <item name="android:textColor">#42E700</item> <item name="android:textSize">25sp</item> </style>
4、主布局文件applationinstall.xml
具体实现代码如下:
<?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="fill_parent" android:orientation="vertical" > <TextView android:id="@+id/tv_title" style="@style/text_title_style" android:text="所 有 程 序" /> <View style="@style/view_divide_line_style" /> <FrameLayout android:layout_width="fill_parent" android:layout_height="fill_parent" > <!-- android:cacheColorHint="#00000000" 缓存的颜色 默认是黄色 android:divider="#00ffffff" 分割线 android:dividerHeight="3.0dip" 分割线的宽度 --> <ListView android:id="@+id/lv_appmanage" android:layout_width="fill_parent" android:layout_height="fill_parent" android:cacheColorHint="#00000000" android:divider="#fff" android:fastScrollEnabled="true" android:dividerHeight="1.0dip" android:paddingLeft="3.0dip" android:paddingRight="3.0dip" /> <RelativeLayout android:id="@+id/rl_loading" android:layout_width="fill_parent" android:layout_height="fill_parent" > <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" android:layout_centerInParent="true"> <ProgressBar android:id="@+id/pb" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="10dip" android:text="正在加载应用程序。。" android:textColor="#fff" android:textSize="22sp" /> </LinearLayout> </RelativeLayout> </FrameLayout> </LinearLayout>
5、ListView中每一项条目布局applationinstall_item.xml
具体实现代码如下
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:paddingBottom="8.0dip" android:paddingLeft="6.0dip" android:paddingRight="5.0dip" android:paddingTop="8.0dip" > <ImageView android:id="@+id/iv_appicon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:src="@drawable/ic_launcher" /> <TextView android:id="@+id/tv_appname" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_marginLeft="4.0dip" android:layout_toRightOf="@id/iv_appicon" android:textColor="#fff" android:text="我最摇摆" android:textSize="16.0dip" /> <TextView android:id="@+id/tv_appversion" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:layout_marginLeft="4.0dip" android:textColor="#fff" android:layout_marginRight="10dp" android:text="1.0" android:textSize="16.0dip" /> </RelativeLayout>
6、自定义ListView适配器AppManagerAdapter
这个类继承自BaseAdapter主要作为List显示数据的适配器,在这个类中通过布局加载器LayoutInflater来加载条目布局,找到布局上的控件来设置相应的信息。
具体实现代码如下:
package cn.lyz.mobilesafe.adapter; import java.util.List; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.TextView; import cn.lyz.mobilesafe.R; import cn.lyz.mobilesafe.domain.AppInfo; /** * App管理的Adapter类 * @author liuyazhuang * */ public class AppManagerAdapter extends BaseAdapter { private Context context; //布局加载器 private LayoutInflater mInflater; private List<AppInfo> appInfos; //动态改变appInfos public void setAppInfos(List<AppInfo> appInfos) { this.appInfos = appInfos; } public AppManagerAdapter(Context context,List<AppInfo> appInfos) { this.context = context; this.appInfos = appInfos; mInflater = LayoutInflater.from(context); } public int getCount() { return appInfos.size(); } public Object getItem(int position) { return appInfos.get(position); } public long getItemId(int position) { return position; } public View getView(int position, View convertView, ViewGroup parent) { //1 得到控件 //2 得到数据 //3 绑定数据 View view = null; if(convertView != null){ view = convertView; }else{ view = mInflater.inflate(R.layout.applationinstall_item, null); } //获取布局控件 ImageView iv_appicon = (ImageView) view.findViewById(R.id.iv_appicon); TextView tv_appname = (TextView) view.findViewById(R.id.tv_appname); TextView tv_appversion = (TextView) view.findViewById(R.id.tv_appversion); //获取position位置上的AppInfo对象 AppInfo appInfo = appInfos.get(position); iv_appicon.setImageDrawable(appInfo.getApp_icon()); tv_appname.setText(appInfo.getApp_name()); tv_appversion.setText(appInfo.getApp_version()); return view; } }
7、程序显示界面AppManagerActivity
这个类实现的功能很简单,调用其他类的方法,将获取的信息显示到ListView上。具体的实现是在onCreate方法中找到布局上的控件,并在一个线程程序中调用AppInfoService中的方法获取手机中安装的应用程序,并将获取的结果通过Handler与Message机制传递到主线程,主线程将这些数据显示到UI视图上。
具体实现代码如下:
package cn.lyz.mobilesafe.activity; import java.util.ArrayList; import java.util.List; import android.app.Activity; import android.content.pm.PackageManager; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.View; import android.widget.ListView; import android.widget.PopupWindow; import android.widget.RelativeLayout; import android.widget.TextView; import cn.lyz.mobilesafe.R; import cn.lyz.mobilesafe.adapter.AppManagerAdapter; import cn.lyz.mobilesafe.domain.AppInfo; import cn.lyz.mobilesafe.engine.AppInfoService; /** * APP管理的Manager类 * @author liuyazhuang * */ public class AppManagerActivity extends Activity{ protected static final int SUCCESS_GET_APPLICAITON = 0; //布局中的各个控件 private RelativeLayout rl_loading; private ListView lv_appmanage; private TextView tv_title; //包管理器 private PackageManager pm; //获取手机应用信息的业务类 private AppInfoService appInfoService; //手机应用app信息集合 private List<AppInfo> appInfos; //用户应用程序信息集合 private List<AppInfo> userAppInfos; //是否是所有的app程序,默认为true private boolean isAllApp = true; //AppManagerAdapter适配器对象 private AppManagerAdapter mAdapter; private PopupWindow mPopupWindow; //mHandler方法 private Handler mHandler = new Handler(){ public void handleMessage(android.os.Message msg) { switch (msg.what) { case SUCCESS_GET_APPLICAITON: //给listview去绑定数据,隐藏加载的控件 mAdapter = new AppManagerAdapter(getApplicationContext(), appInfos); //设置数据 lv_appmanage.setAdapter(mAdapter); //隐藏RelativeLayout rl_loading.setVisibility(View.GONE); //View.VISIBLE (控件显示)View.INVISIBLE(控件隐藏 但占据空间) View.GONE(控件隐藏 不占据空间) break; default: break; } }; }; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.applationinstall); //获取布局中的控件 rl_loading = (RelativeLayout) findViewById(R.id.rl_loading); lv_appmanage = (ListView) findViewById(R.id.lv_appmanage); tv_title = (TextView) findViewById(R.id.tv_title); //实例化AppInfoService对象 appInfoService = new AppInfoService(this); //包管理器 pm = getPackageManager(); //在子线程中获取手机安装的应用程序信息 new Thread(){ public void run() { appInfos = appInfoService.getAppInfos(); userAppInfos = new ArrayList<AppInfo>(); for(AppInfo appInfo:appInfos){ if(appInfo.isUserApp()){ userAppInfos.add(appInfo); } } Message msg = new Message(); msg.what = SUCCESS_GET_APPLICAITON; mHandler.sendMessage(msg); }; }.start(); } }
三、运行效果
正在加载应用程序
获取到手机中安装的应用程序
四、温馨提示
本实例中,为了方面,我把一些文字直接写在了布局文件中和相关的类中,大家在真实的项目中要把这些文字写在strings.xml文件中,在外部引用这些资源,切记,这是作为一个Android程序员最基本的开发常识和规范,我在这里只是为了方便直接写在了类和布局文件中。
版权声明:本文为博主原创文章,未经博主允许不得转载。