I'm successfully getting a recent app's icon using this code:
//app is an ActivityManager.RunningTaskInfo
//image is an ImageView
ApplicationInfo appInfo = packageManager.getApplicationInfo(app.topActivity.getPackageName(), 0);
Drawable d = packageManager.getApplicationIcon(appInfo);
image.setImageDrawable(d);
However the image displayed is only 48x48px. I'm guessing this is because my device is mdpi, however it's making the icons very blurry. Is there a way to always get the xhdpi icon, regardless of the devices display density? Thanks for any help.
I don't think you can get any other density icons out of packageManager.getApplicationIcon(appInfo); without some hacking. Either you would hack the device's reported screen DPI or somehow convince PackageManager that you have a xhdpi screen size (you can specify a Bitmap's density, but I don't know how you could pass that to PackageManager).
However there might be an easier way to get the xhdpi icon (and other DP icons as well). If you can get the application's apk to your computer and unzip it, you should find the res/drawable* folder(s) inside where you could get the icon from.
Though if you need xhdpi icons during your app runtime and for any app on the device, this sadly is not the solution to your problem. If the latter is the case, note also that not every app has xhdpi resources/icons.
Related
I was researching a little bit on mipmap to learn more about it. However, I just ended up confusing myself even more.
In this post: Mipmaps vs. drawable folders
The reason they use a different density is that some launchers
actually display the icons larger than they were intended. Because of
this, they use the next size up.
Hence, I got the idea that with larger icons mipmap will use a higher density(scaling up).
But then in this post: Mipmap drawables for icons
However some launchers (shipped with some devices, or available on the
Play Store) use larger icon sizes than the standard 48dp. Launchers
use getDrawableForDensity and scale down if needed, rather than up, so
the icons are high quality. For example on an hdpi tablet the launcher
might load the xhdpi icon.
I concluded that for larger icons, mipmap will scale down the icons to provide higher quality.
And finally in this post:Mipmap drawables for icons by #Sergej:
What Android will do is, it will try to pick up the image from a
higher density bucket instead of scaling it up. This will increase
sharpness (quality) of the image.
Mipmap will use a higher density instead of scaling up for larger icons.
What is really going on? Thanks.
Update:
Also, in the second post Mipmap drawables for icons by #Kazuaki, I don't understand this
Different home screen launcher apps on different devices show app
launcher icons at various resolutions. When app resource optimization
techniques remove resources for unused screen densities, launcher
icons can wind up looking fuzzy because the launcher app has to
upscale a lower-resolution icon for display. To avoid these display
issues, apps should use the mipmap/ resource folders for launcher
icons. The Android system preserves these resources regardless of
density stripping, and ensures that launcher apps can pick icons with
the best resolution for display.
Even if unused screen densities are stripped, why would the launcher app have to switch to a lower resolution? The current resolution(whatever resolution it's using), isn't unused, meaning, it wouldn't be stripped and the launcher icon wouldn't have to switch resolutions.
How does this work? Thanks.
I think your confusion about #Kazuaki quote is the now deleted documentation, replaced by: https://developer.android.com/training/multiscreen/screendensities#mipmap
Like all other bitmap assets, you need to provide density-specific versions of you app icon. However, some app launchers display your app icon as much as 25% larger than what's called for by the device's density bucket.
For example, if a device's density bucket is xxhdpi and the largest app icon you provide is in drawable-xxhdpi, the launcher app scales up this icon, and that makes it appear less crisp. So you should provide an even higher density launcher icon in the mipmap-xxxhdpi directory. Now the launcher can use the xxxhdpi asset instead.
The mipmap directories provide that "do not remove when trying to make a smaller APK".
In my understanding, mipmaping is principally for scaling-down.
In OpenGL, you can set texture filtering modes. One for scaling-down (minification), another for scaling-up (magnification) (cf. An Introduction to Texture Filtering).
Scaling-down (GL_TEXTURE_MIN_FILTER):
GL_NEAREST
GL_LINEAR
GL_NEAREST_MIPMAP_NEAREST
GL_NEAREST_MIPMAP_LINEAR
GL_LINEAR_MIPMAP_NEAREST
GL_LINEAR_MIPMAP_LINEAR
Scaling-up (GL_TEXTURE_MAG_FILTER):
GL_NEAREST
GL_LINEAR
You notice that there are no options of mipmap for scaling-up, but those are for scaling-down.
So, in my understanding, if scaling-up/down is needed, the nearest higher density texture is chosen to scale-down. Only when the current magnification is higher than the highest density texture, scaling-up is done based on the highest one.
I am using the onCreateOptionsMenu method to create a toolbar with icons in the MainActivity of my app. I am testing on different screen sizes and pixel densities with Android Studio's emulator. The documentation states, "Based on the density of the current screen, the system uses any density-specific resources from your app. If resources are not available in the correct density, the system loads the default resources and scales them up or down as needed." I've tried putting all of my vector icons the default drawable directory, but the system does not scale them for different screen sizes or densities at all. Nor does onCreateOptionsMenu scale the height of the toolbar or the title text. Is it supposed to? Because of this, I have also tried using different density buckets to address that problem. However, I'm running into an issue with greatly varying screen sizes sharing the same density bucket.
As an example, I'm testing on Pixel 3 (5.5" phone) and Pixel C (10" tablet). They are using the same density bucket (xhdpi) so if I use a 24dp x 24dp icon for the phone, then it looks way too small on the tablet. How do I work around this?
You can string together multiple qualifiers and create a custom bucket. So in addition to the drawable-xhdpi bucket I added a drawable-sw720dp-xhdpi bucket with larger icons for the 10" tablet. Now tablet displays the slightly larger icons while the phone still uses the standard bucket. The solution can be found in the comments of the selected answer in this post by #Theo. Unfortunately the documentation does not state that multiple qualifiers are supported.
I have an app that has buttons with background images that I specify in the layout. For mdpi and up it works fine and you can see the images. But I recently started tested on a small device and saw the backgrounds only show black. I then checked the screen size (small) which I cater for and also checked the density, which I saw in this case is ldpi. So I rescaled the mdpi images to 36x36 and created a mipmap-ldpi folder. Android studio sees it in design time but for some reason it is not picked up at runtime. So I Googled around and saw that I might have to add them manually via Android Studio. So I created a New Resource Directory where I specified the density as ldpi as below :
I then for each Icon added a new file with the same name and selected the ldpi folder as below :
And select ldpi directory :
I then entered the same name as it is with all the other densities for each icon / image.
After all this I still get black background so I thought let me try and assign the background programmatically. That then works. Can anyone help me with why it will not work when specifying it in the layout file. I have a layout file specifically for small screens. Must I specify density as well ?
Apologies for the images. I see I cannot embed yet because my reputation is too low.
Update 1 :
Moved all the icons to Drawables as recommended and it was still doing it.
Read other articles where LDPI is not really supported anymore and then answered the question as to make the problem go away by not supporting devices with LDPI density.
But the next day then picked the same problem up on a old S2 with HPDI density. So it is possibly not a LDPI problem anymore until proven otherwise. Hopefully we will find the problem and get it fixed.
The mipmap directories are used to store the launcher icons. They are not used inside the app, but at the home screen and the app listing.
The reason is, when a resource from drawable-directory is requested, a bitmap is chosen from the folder that matches the current density. But, when you use the mipmap drawable, the launcher may choose an icon from a different folder (usually a size-up). That's why you're not seeing the ldpi icon.
Some launchers actually display the icons larger than they were intended. Therefore, using the mipmap for launchers helps in this.
Also check this link out.
SUMMARY: use drawables for icons used inside the app and mipmap for the launcher icon of the app.
Apologies. I asked my question incorrectly. I assumed it was the icons but I neglected to mention I call the icons from Layer-List drawables. Turns out Layer-List draws black on some devices that runs Android 4.0 and 4.1 if you do not explicitly mention transparent as a color. I can now see all icons from ldpi up.
Thanks for your assistance. Reference link : Android xml layer-list not displayed correctly on some devices
So im creating a new app and I was wondering if i could only make one icon(technically two but one is 512*512 for the play store). So ill just make a max size icon for xxhdpi will lower res phones scale correctly, or would i actually have to make one for each dpi level. If that is the case, are there any tools that creates the different sizes for me?
You have to make one for each screen density. There are tools available to assist you in this: http://romannurik.github.io/AndroidAssetStudio/index.html
You really have to have an icon for each density value, otherwise you will have a 512*512 icon being used in a ldpi phone, which is very inefficient, as for ldpi phones you should use a 32x32 icon instead. Just use an image editor and resize your original icon or use on-line tools to resize it for you. ynnadkrap has a good example of a tool you can use to get your icons.
I am working on an app which is able to add shortcuts icons to the homescreen.
What is the correct icon size for Android tablets? (Or better said, how to get it at runtime?) It seems to differ from what is written on this page.
I have switch on DisplayMetrics.densityDpi and change the icon size accordingly. But it does not work for all devices..Gnex seems to be ok, but my Galaxy Tab while beeing DisplayMetrics.DENSITY_MEDIUM device displays only 48x48px icon (as it is in guidelines), but usual launcher icons are 72x72 pixels and not 48x48 - it differs from guidelines? Is it possible that it is related to TouchWiz UI and thus it differs from pure Android? Or where is the problem? Also good to note, that apps itself displays correct launcher icon (it takes the icon from hdpi folder), but at runtime it looks like it is mdpi device:/
Thanks
Android tablets looks one bucket up, when looking for launcher icon..That means mdpi device will actually look into hdpi folder..
This code returns correct size for launcher icons
ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
int iconSize = am.getLauncherLargeIconSize();
Answer is based on this g+ post by Nick Butcher
best thing you use the android assets studio tool for this task .
it will automatically create the correct sizes and put them in the correct folders .