在Android中获取应用程序图标

19

我在检索安装的Android应用程序图标方面遇到了一些麻烦。以下代码返回所有应用程序的图标,但是有些应用程序的图标很小(可能来自drawable-ldpi文件夹),而有些应用程序的图标很大。

List<PackageInfo> package = getPackageManager().getInstalledPackages(0);

for(PackageInfo p : package){
    iApp.icon = p.applicationInfo.loadIcon(getPackageManager()); 
}

我该如何获取大小都相同的图标,就像Android应用管理部分一样?

4个回答

22

我想在之前的答案中添加一些内容,适用于Android 3.0及更高版本。

你可以注意到以标准方式(即applicationInfo.loadIcon和其他典型方法)检索的图标比您在启动器应用程序中看到的图标要小。放大只会使图标变得模糊。如果你想要大图标,你可以使用下面的代码(我从启动器源代码中取出,你可以在这里找到并进行了一些更改)。请注意activityManager.getLauncherLargeIconDensity方法。

public Drawable getFullResDefaultActivityIcon() {
    return getFullResIcon(Resources.getSystem(), android.R.mipmap.sym_def_app_icon);
}

public Drawable getFullResIcon(Resources resources, int iconId) {
    Drawable d;
    try {
        ActivityManager activityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
        int iconDpi = activityManager.getLauncherLargeIconDensity();
        d = resources.getDrawableForDensity(iconId, iconDpi);
    } catch (Resources.NotFoundException e) {
        d = null;
    }

    return (d != null) ? d : getFullResDefaultActivityIcon();
}

public Drawable getFullResIcon(String packageName, int iconId) {
    Resources resources;
    try {
        resources = mContext.getPackageManager().getResourcesForApplication(packageName);
    } catch (PackageManager.NameNotFoundException e) {
        resources = null;
    }
    if (resources != null) {
        if (iconId != 0) {
            return getFullResIcon(resources, iconId);
        }
    }
    return getFullResDefaultActivityIcon();
}

public Drawable getFullResIcon(ResolveInfo info) {
    return getFullResIcon(info.activityInfo);
}

public Drawable getFullResIcon(ActivityInfo info) {
    Resources resources;
    try {
        resources = mContext.getPackageManager().getResourcesForApplication(info.applicationInfo);
    } catch (PackageManager.NameNotFoundException e) {
        resources = null;
    }
    if (resources != null) {
        int iconId = info.getIconResource();
        if (iconId != 0) {
            return getFullResIcon(resources, iconId);
        }
    }
    return getFullResDefaultActivityIcon();
}

private Drawable getAppIcon(ResolveInfo info) {
    return getFullResIcon(info.activityInfo);
}

希望对某人有所帮助。


getFullResIcon(Resources....) 正是我所需要的!!这个答案更加精确..我可以获取最大的图标,然后根据我的需求进行缩放。+1 @Andrei - IronBlossom
2
getDrawableForDensity(int id, int density) 在api level 15中添加...低于该级别呢? - Braj

21

不同的应用程序可能具有不同大小的图标。Android Settings应用程序和你一样加载图标。在显示图标时,它会进行缩放。

这是来自packages/apps/Settings/res/layout/manage_applications_item.xml的代码片段:

<ImageView android:id="@+id/app_icon"
    android:layout_width="@android:dimen/app_icon_size"
    android:layout_height="@android:dimen/app_icon_size"
    android:layout_marginRight="11dip"
    android:layout_gravity="center_vertical"
    android:scaleType="fitCenter"/>

你能详细说明一下吗?我遇到了同样的问题。 - Nikunj Patel
3
然而,在应用程序的标准启动器列表中(不是在设置中的“管理应用程序”显示中的应用程序列表),您会看到美丽的大图标(在平板电脑上),而不是您所描述的被缩放后模糊的图标。一定有其他的方法:-( - Andrei Buneyeu

11

虽然这个问题很久以前就已经被回答了,但是这里提供完整的函数。希望对其他人有所帮助。

要获取图标,您应该查询不同dpi的图标。

尝试这个:

public static Drawable getIconFromPackageName(String packageName, Context context)
    {
        PackageManager pm = context.getPackageManager();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)
        {
            try
            {
                PackageInfo pi = pm.getPackageInfo(packageName, 0);
                Context otherAppCtx = context.createPackageContext(packageName, Context.CONTEXT_IGNORE_SECURITY);

                int displayMetrics[] = {DisplayMetrics.DENSITY_XHIGH, DisplayMetrics.DENSITY_HIGH, DisplayMetrics.DENSITY_TV};

                for (int displayMetric : displayMetrics)
                {
                    try
                    {
                        Drawable d = otherAppCtx.getResources().getDrawableForDensity(pi.applicationInfo.icon, displayMetric);
                        if (d != null)
                        {
                            return d;
                        }
                    }
                    catch (Resources.NotFoundException e)
                    {
//                      Log.d(TAG, "NameNotFound for" + packageName + " @ density: " + displayMetric);
                        continue;
                    }
                }

            }
            catch (Exception e)
            {
                // Handle Error here
            }
        }

        ApplicationInfo appInfo = null;
        try
        {
            appInfo = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA);
        }
        catch (PackageManager.NameNotFoundException e)
        {
            return null;
        }

        return appInfo.loadIcon(pm);
    }

getDrawableForDensity(int id, int density) 在 API 级别 15 中添加... 低于此级别怎么办? - Braj
有助于获取原始的未主题化图标。 - lambda

1

你必须在 App 类中进行定义;

private Drawable appIcon; 

public Drawable getappIcon(){
        return this.appIcon;
    }

如果您使用 RecyclerViewAdapter;
   List<App> list_app;

    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
    holder.appIcon.setImageDrawable(list_app.get(position).getappIcon());

    }

在MainActivity中;
private List<App> appList;

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

        final PackageManager pm = getPackageManager();
        List<ApplicationInfo> packages = pm.getInstalledApplications(PackageManager.GET_META_DATA);

        appList = new ArrayList<App>();

        for (ApplicationInfo packageInfo : packages) {
          Drawable drawableIcon =packageInfo.loadIcon(getPackageManager());
          appList.add(new App (drawableIcon));

        }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接