Android获取安装的应用程序的信息


在Android系统中,使用PackageManager类获取手机安装的应用信息,如:应用程序的图标、名称、包名等。将这些应用的程序的信息显示到界面的ListView上,形成一个应用列表。如图:

app_info.png

AppInfo类

AppInfo类用于封装获取到的每一个应用程序的信息。appName表示应用程序的名称,packageName表示应用程序的包名,appIcon表示应用程序的图标。代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.example.application_info;

import android.graphics.drawable.Drawable;

public class AppInfo {
private String appName; // 应用名称
private String packageName; // 包名
private Drawable appIcon; // 图标

public AppInfo(String appName, String packageName, Drawable appIcon) {
this.appName = appName;
this.packageName = packageName;
this.appIcon = appIcon;
}

public String getAppName() {
return appName;
}

public String getPackageName() {
return packageName;
}

public Drawable getAppIcon() {
return appIcon;
}
}

ListView子项的自定义布局

在layout目录下新建app_info_item.xml。代码如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <ImageView 
        android:id="@+id/app_icon"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <RelativeLayout 
        android:layout_width="wrap_content"
        android:layout_height="match_parent" >
        <TextView 
            android:id="@+id/app_name_label"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="名称: "
            android:layout_marginLeft="10dip"/>
        <TextView 
            android:id="@+id/app_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_toRightOf="@id/app_name_label" />
        <TextView 
            android:id="@+id/app_package_name_label"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/app_name_label"
            android:text="包名: "
            android:layout_marginLeft="10dip"/>
        <TextView 
            android:id="@+id/app_package_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/app_name"
            android:layout_toRightOf="@id/app_package_name_label" />  

    </RelativeLayout>
</LinearLayout>

在这个布局中,定义了一个用于显示应用图标的ImageView(id为app_icon),以及对应的应用名称(id为app_name)和包名的TextView(id为app_package_name)。

AppInfoAdapter类

创建一个自定义个的AppInfoAdapter类,并将泛型指定为AppInfo类。代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package com.example.application_info;

import java.util.List;

import com.example.application_info.AppInfo;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;


public class AppInfoAdapter extends ArrayAdapter<AppInfo> {
private int resourceId;

public AppInfoAdapter(Context context, int resource,
List<AppInfo> objects) {
super(context, resource, objects);
resourceId = resource;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
AppInfo appInfo = getItem(position);
View view;
ViewHolder viewHolder;
if(convertView == null) {
view = LayoutInflater.from(getContext()).inflate(resourceId, null);
viewHolder = new ViewHolder();
viewHolder.imageView = (ImageView)view.findViewById(R.id.app_icon);
viewHolder.appNameTextView = (TextView)view.findViewById(R.id.app_name);
viewHolder.packageNameTextView = (TextView)view.findViewById(R.id.app_package_name);

view.setTag(viewHolder); // 将ViewHolder存储在View中
} else {
view = convertView;
viewHolder = (ViewHolder) view.getTag(); // 重新获取ViewHolder
}

viewHolder.imageView.setImageDrawable(appInfo.getAppIcon());
viewHolder.appNameTextView.setText(appInfo.getAppName());
viewHolder.packageNameTextView.setText(appInfo.getPackageName());
return view;
}

class ViewHolder {
ImageView imageView;
TextView appNameTextView;
TextView packageNameTextView;
}
}

AppInfoAdapter类重写了父类的一组构造函数,用于将上下文、ListView子项布局的id和数据都传递进来。另外又重写了getView()方法,这个方法在每个子项被滚动到屏幕内的时候被调用。

ListView的优化:

  • getView()方法中,首先通过getItem()方法得到当前项的AppInfo实例,如果convertView为空,则使用LayoutInflater去加载布局。如果不为空直接对convertView进行重用。

  • 内部类ViewHolder用于对控件的实例进行缓存。当convertView为空的时候,创建一个ViewHolder对象,调用ViewfindViewById()方法分别获取到应用图标的ImageView、应用名称和包名的TextView 的实例,并将控件的实例都存放在ViewHolder里,然后调用View的setTag()方法,将ViewHolder对象存储在View中。当convertView不为空的时候则调用
    View的getTag()方法,把ViewHolder重新取出。这样所有控件的实例都缓存在了ViewHolder
    里,就没有必要每次都通过findViewById()方法来获取控件实例了。最后分别调用ImageView的setImageResource()和TextView的setText()方法来设置显示的图片和文字。

activity_main.xml

在布局中加入ListView控件,指定一个id为app_info_list_view。代码如下:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.application_info.MainActivity" >

    <ListView 
        android:id="@+id/app_info_list_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >   
    </ListView>

</RelativeLayout>

MainActivity类

onCreate()方法中调用PackageManager来获得手机上安装的所有应用程序的信息。对于每一个应用获取它的名称、包名、图标。并显示到相应的ListView控件中。代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package com.example.application_info;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;

public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

PackageManager pm = getPackageManager();
List<ApplicationInfo> applicationInfos = pm.getInstalledApplications(pm.GET_UNINSTALLED_PACKAGES);
List<AppInfo> appInfoList = new ArrayList<AppInfo>();

for(ApplicationInfo applicationInfo : applicationInfos) {
String appName = applicationInfo.loadLabel(getPackageManager()).toString(); //应用名称
String packageName = applicationInfo.packageName; //应用包名
Drawable appIcon = applicationInfo.loadIcon(pm); // 应用的图标

appInfoList.add(new AppInfo(appName, packageName, appIcon));
}

ArrayAdapter<AppInfo> adpater = new AppInfoAdapter(MainActivity.this, R.layout.app_info_item, appInfoList);
ListView lisView = (ListView)findViewById(R.id.app_info_list_view);
lisView.setAdapter(adpater);
}
}