从PackageManager中检索xhdpi应用程序图标?

6

我在我的应用程序中有一个活动,其中生成了所有已安装应用程序的ListView。除了应用程序名称外,还显示应用程序图标。我创建了一个包含有关应用程序的所有信息(包括图标)的对象数组,并使用以下方式检索图标:

drawableAppIcon = mPackageManager.getApplicationIcon(apps.applicationInfo);

application是一个<PackageInfo>对象时,存在一个问题。尽管我可以轻松访问所有可绘制的图像,但各种应用程序似乎提供各种质量的可绘制图像;一个应用程序图标可能非常高分辨率,而另一个则是低分辨率版本。我本以为上面这行代码会考虑屏幕大小并找到适当的图标,但事实并非如此。是否有一种替代方法来考虑屏幕大小?或者更好的是,是否有一种方法可以提取最高分辨率的图标,然后根据屏幕大小进行缩放,从而基本保证它们都看起来很清晰?

编辑:我已经找到了一个解决方案,但它只适用于Android 4.0及以上版本。

try {
    Context otherAppCtxt = context.createPackageContext(apps.applicationInfo.packageName, Context.CONTEXT_IGNORE_SECURITY);
    info.drawableAppIcon = otherAppCtxt.getResources().getDrawableForDensity(apps.applicationInfo.icon, DisplayMetrics.DENSITY_XHIGH);
} catch (PackageManager.NameNotFoundException e) {
    e.printStackTrace();
}

供他人参考,这个方法可行。如果有人有针对旧版本安卓的解决方案,那将非常有帮助。


应用程序图标在Android的其他地方看起来还好吗?您是否在您的应用程序中调整它们的大小?我会建议先确保您使用它们的固有宽度/高度来绘制它们。 - Dane White
3个回答

8
ApplicationInfo applicationInfo = 
        packagemanager.getApplicationInfo(packageName(), PackageManager.GET_META_DATA);
Resources res = packagemanager.getResourcesForApplication(applicationInfo);
Drawable appIcon = res.getDrawableForDensity(applicationInfo.icon, 
                                             DisplayMetrics.DENSITY_XXXHIGH, 
                                             null);

谢谢你,巫师! - ORY
使用以下代码替换原有代码:'Drawable appIcon = res.getDrawableForDensity(applicationInfo.icon, DisplayMetrics.DENSITY_XXXHIGH);',不需要传入null参数。 - ORY

7

我怀疑图标出现问题的原因可能是你在应用内进行了缩放等操作。但如果你需要对任意 Android 版本进行操作,可以按以下步骤进行:

// Get the application's resources
Resources res = mPackageManager.getResourcesForApplication(appInfo);

// Get a copy of the configuration, and set it to the desired resolution
Configuration config = res.getConfiguration();
Configuration originalConfig = new Configuration(config);
config.densityDpi = DisplayMetrics.DENSITY_XHIGH;

// Update the configuration with the desired resolution
DisplayMetrics dm = res.getDisplayMetrics();
res.updateConfiguration(config, dm);

// Grab the app icon
Drawable appIcon = res.getDrawable(appInfo.icon);

// Set our configuration back to what it was
res.updateConfiguration(originalConfig, dm);

1
config.densityDpi是API17字段,因此该解决方案无法用于任何Android版本。 - Vlad Kuts
谢谢Vlad,这是我犯下的一个重大疏忽。我将尝试设置DisplayMetrics.densityDpi而不是(API 4)。 - Dane White
如果你有结果,请分享给我们。如果可能的话,当然可以。 - Vlad Kuts
@DaneWhite:你尝试设置DisplayMetrics.densityDpi有什么反馈吗?它有效吗? - Lisitso

0

这是对一个旧问题的新答案,只是为了把所有东西放在一起。您需要获取设备的默认密度,并调整图像大小以确保您具有适当的符合尺寸,因为仅请求图标并不总是返回正确的大小。

考虑这两种方法,一种是获取设备大小,另一种是调整可绘制对象的大小:

private int getDeviceDpi(){
        DisplayMetrics dm = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(dm);
        return dm.densityDpi;
}

private Drawable getSizedAppIcon(Context context, String packageName, int Density) throws PackageManager.NameNotFoundException {
    //for @param Density you can use a static from DisplayMetrics.<something>

        PackageManager pm = Objects.requireNonNull(context).getPackageManager();
        ApplicationInfo appInfo = this.getPackageManager().getApplicationInfo(packageName, 0);
        Drawable icon = pm.getApplicationIcon(appInfo);
        Bitmap bitmap = ((BitmapDrawable) icon).getBitmap();
        switch (Density){
            case DisplayMetrics.DENSITY_LOW: //120
                return new BitmapDrawable(getResources(), Bitmap.createScaledBitmap(bitmap,
                        32, 32, true));
            case DisplayMetrics.DENSITY_MEDIUM: //160
                return new BitmapDrawable(getResources(), Bitmap.createScaledBitmap(bitmap,
                        48, 48, true));
            case DisplayMetrics.DENSITY_HIGH: //240
                return new BitmapDrawable(getResources(), Bitmap.createScaledBitmap(bitmap,
                        72, 72, true));
            case DisplayMetrics.DENSITY_XHIGH: //320
                return new BitmapDrawable(getResources(), Bitmap.createScaledBitmap(bitmap,
                        96, 96, true));
            case DisplayMetrics.DENSITY_XXHIGH: //480
                return new BitmapDrawable(getResources(), Bitmap.createScaledBitmap(bitmap,
                        144, 144, true));
            case DisplayMetrics.DENSITY_XXXHIGH: //640
                return new BitmapDrawable(getResources(), Bitmap.createScaledBitmap(bitmap,
                        192, 192, true));
            default:
                return icon;
        }

}

然后像这个例子一样调用它们:

try{
    getSizedAppIcon(this, "com.example.app",getDeviceDpi());
}catch (Exception ignore) {}

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