Androidのdrawabaleに組み込んだ画像リソースから、検索してよく出てくる方法よりも素早くデータのバイト列を取得する方法です。
私がXamarin使いなのでXamarinのc#コードで例示しますが、XamarinのAPIは基本ラッパなので、JavaでAndroid開発されている方にも基本伝わるかと思います。
drawableの画像リソースをバイト列で取得する方法を検索していて、よく出てくる方法は以下のようなものです。
drawableリソース取得法1
var res_id = context.Resources.GetIdentifier ("res_name", "drawable", context.PackageName);
if (res_id == 0) {
throw new Java.IO.FileNotFoundException("Resource Not Found");
}
var bitmap = BitmapFactory.DecodeResource(context.Resources, res_id);
byte[] data;
using (var stream = new MemoryStream())
{
bitmap.Compress(Bitmap.CompressFormat.Png, 0, stream);
data = stream.ToArray();
}
return data;
ですが、これ、クソ重いです。
小さなアイコン画像とかだと気にならないのかもしれませんが、全画面サイズくらいのレベルの画像を取得しようと思うと、本当に一息つくというレベルでデータ取得までに時間がかかります。
考えてみれば当たり前で、元々pngでresourceに登録されているデータを、Bitmapに戻してから、またpngに圧縮してバイト化してるので、無駄な解凍/圧縮処理の分負荷と時間がかかってしまいます。
解決方法を探していて、以下のやり方を見つけました。
drawableリソース取得法2
var res_id = context.Resources.GetIdentifier ("res_name", "drawable", context.PackageName);
if (res_id == 0) {
throw new Java.IO.FileNotFoundException("Resource Not Found");
}
var ins = context.Resources.OpenRawResource(res_id);
var baos = new ByteArrayOutputStream();
var buff = new byte[10240];
var i = int.MaxValue;
while ((i = ins.Read(buff, 0, buff.Length)) > 0)
{
baos.Write(buff, 0, i);
}
return baos.ToByteArray();
この方法だと、resourceから直接InputStreamを取得しているので、無駄な解凍/圧縮をしなくてよい分、一瞬でデータ取得できます。