Преобразование AdaptiveIconDrawable в Bitmap в Android O preview

С новым предварительным выпуском вчера я начал обновлять свое приложение до этой версии. Часть моего приложения - список установленных приложений со связанными значками.

Drawable drawable = mPackageManager.getApplicationIcon(packageName);

Эта часть приложения все еще работает. Приложения, такие как часы, калькулятор или сообщения, уже поддерживают новую версию значков, поэтому они возвращают AdaptiveIconDrawable.

Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();

Эта часть больше не работает. Есть ли другой способ конвертировать AdaptiveIconDrawable в Bitmap? Заранее спасибо.

Ответ 1

Это гораздо более универсальное решение:

@NonNull
private Bitmap getBitmapFromDrawable(@NonNull Drawable drawable) {
    final Bitmap bmp = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
    final Canvas canvas = new Canvas(bmp);
    drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
    drawable.draw(canvas);
    return bmp;
}

Он также будет создавать фон в форме системы, если вы не хотите использовать собственный.

Вы можете использовать его на любом Drawable, а также для VectorDrawable. Он будет работать и на BitmapDrawable, только getBitmap() будет более эффективным с точки зрения памяти.

Ответ 2

Мы можем добиться следующим образом,

AppIconHelper.java

public class AppIconHelper {

    public static Bitmap getAppIcon(PackageManager mPackageManager, String packageName) {

        if (Build.VERSION.SDK_INT >= 26) {
            return AppIconHelperV26.getAppIcon(mPackageManager, packageName);
        }

        try {
            Drawable drawable = mPackageManager.getApplicationIcon(packageName);

            return ((BitmapDrawable) drawable).getBitmap();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }
}

Для устройства, поддерживающего Android O (> = 26), мы можем вызвать класс AppIconHelperV26 для получения AppIcon. В этом случае, если его drawable является AdaptiveIconDrawable, мы делаем следующие шаги: 1. Выделите Foreground и Background drawable и создайте как Layer Drawable 2. Используя Canvas, мы можем преобразовать Layer drawable в Bitmap

AppIconHelperV26.java

public class AppIconHelperV26 {

    @RequiresApi(api = Build.VERSION_CODES.O)
    public static Bitmap getAppIcon(PackageManager mPackageManager, String packageName) {

        try {
            Drawable drawable = mPackageManager.getApplicationIcon(packageName);

            if (drawable instanceof BitmapDrawable) {
                return ((BitmapDrawable) drawable).getBitmap();
            } else if (drawable instanceof AdaptiveIconDrawable) {
                Drawable backgroundDr = ((AdaptiveIconDrawable) drawable).getBackground();
                Drawable foregroundDr = ((AdaptiveIconDrawable) drawable).getForeground();

                Drawable[] drr = new Drawable[2];
                drr[0] = backgroundDr;
                drr[1] = foregroundDr;

                LayerDrawable layerDrawable = new LayerDrawable(drr);

                int width = layerDrawable.getIntrinsicWidth();
                int height = layerDrawable.getIntrinsicHeight();

                Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);

                Canvas canvas = new Canvas(bitmap);

                layerDrawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
                layerDrawable.draw(canvas);

                return bitmap;
            }
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }

        return null;
    }
}

Теперь вы можете вызвать AppIconHelper.getAppIcon, чтобы получить битмап,

AppListAdapter.java

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
    //... your code here
    Bitmap appIcon = AppIconHelper.getAppIcon(packageManager, packageName);
    imageView.setImageBitmap(appIcon);

}