Transparent adaptive icon background
Easiest Solution ever:
Assuming you have a PNG file with a transparent background (preferably, square ratio), let's call it "app_icon.png", put it in your drawable folder P.S: It doesn't matter how large it is, what matters is the square ratio.
Go to AndroidManifest.xml, in your main application tag, check for the
android:icon="@mipmap/app_icon"
and change it to
android:icon="@drawable/app_icon"
- Delete all your "mipmap" folders now since you don't need them.
Why does this work: This tells android to use a drawable DIRECTLY from the folder as an icon, without going through the hurdle of mipmap XML files.
Congratulations, now you will have a logo with a transparent background.
TL;DR Adaptive Icons cannot have transparent Background
Transparent background will be opaque black.
According to the source code of Android 8.0 framework, the <background>
layer is inherently opaque; the framework fills the background with opaque black, as mentioned in the question.
The framework has a class AdaptiveIconDrawable
, which draws adaptive launcher icons.
https://developer.android.com/reference/android/graphics/drawable/AdaptiveIconDrawable.html
The element <adaptive-icon>
creates an instance of it:
This class can also be created via XML inflation using
<adaptive-icon>
tag in addition to dynamic creation.
The source code of method draw
in AdaptiveIconDrawable.java
is:
@Override
public void draw(Canvas canvas) {
if (mLayersBitmap == null) {
return;
}
if (mLayersShader == null) {
mCanvas.setBitmap(mLayersBitmap);
mCanvas.drawColor(Color.BLACK);
for (int i = 0; i < mLayerState.N_CHILDREN; i++) {
if (mLayerState.mChildren[i] == null) {
continue;
}
final Drawable dr = mLayerState.mChildren[i].mDrawable;
if (dr != null) {
dr.draw(mCanvas);
}
}
mLayersShader = new BitmapShader(mLayersBitmap, TileMode.CLAMP, TileMode.CLAMP);
mPaint.setShader(mLayersShader);
}
if (mMaskBitmap != null) {
Rect bounds = getBounds();
canvas.drawBitmap(mMaskBitmap, bounds.left, bounds.top, mPaint);
}
}
In short, a Canvas instance receives a bitmap to draw into, and initially it fills the bitmap with black color. Then the foreground drawable and the background drawable do the job:
mCanvas.setBitmap(mLayersBitmap); // reset
mCanvas.drawColor(Color.BLACK); // fill
for (int i = 0; i < mLayerState.N_CHILDREN; i++) { // two layers
...
final Drawable dr = mLayerState.mChildren[i].mDrawable;
...
dr.draw(mCanvas); // draw
...
}
The Color.BLACK is opaque:
0xff000000
The method drawColor fills the bitmap with it, using SRC_OVER mode:
Fill the entire canvas' bitmap (restricted to the current clip) with the specified color, using srcover porterduff mode.
So, the background will be always opaque, even if you set transparent color to the background, as in the screenshot below (from my answer to a similar question).