2011年12月31日
Android で大画像ファイルを扱う+Xperia標準ギャラリーでサムネイルが表示されない場合の対策
Androidでプログラムを作ると機種依存になかされます。
特に!!標準ギャラリーの呼び出し
Galaxy,Nexus,Htcではokだけど、Xperiaではサムネイルが表示されない
Galaxy,ではokだけど、HTCでは落ちるとか
で、先人は考えた!!
// ギャラリー表示
Intent intent = null;
try
{
// for Hanycomb
intent = new Intent();
intent.setClassName("com.android.gallery3d", "com.android.gallery3d.app.Gallery");
startActivity(intent);
return;
}
catch(Exception e)
{
try
{
// for Recent device
intent = new Intent();
intent.setClassName("com.cooliris.media", "com.cooliris.media.Gallery");
startActivity(intent);
}
catch(ActivityNotFoundException e1)
{
try
{
// for Other device except HTC
intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("content://media/external/images/media"));
startActivity(intent);
}
catch (ActivityNotFoundException e2)
{
// for HTC
intent = new Intent();
intent.setClassName("com.htc.album", "com.htc.album.AlbumTabSwitchActivity");
startActivity(intent);
}
}
}
これだと、
Galaxy,Nexus,XperiaはいけるがHTC Desireが落ちる
さらに機種依存が強くて全世界の機種に対応できない
以下の方法であれば、Android2.2以上に限ってではあるが、完璧に標準ギャラリーを起動させ
サムネイルも表示し、ピックした画像のアドレス(uri)が返ってくる。
int REQUEST_PICK_CONTACT=1;//任意の数字
Intent intent = new Intent();
intent.setAction(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("image/*");
String choose_info=(String)getText(R.string.astro_caution);
Intent chooser = Intent.createChooser(intent,choose_info);
//これを入れないとXperiaではサムネイルが表示されない
intent = new Intent(Intent.ACTION_PICK);
//以下はデコ美対策のため。デコ美で標準使用にチェックを入れると二度とギャラリーが使えなくなるための対策
Intent chooser2 = Intent.createChooser(intent,choose_info);
intent.setData(Uri.parse("content://media/external/images/media"));
startActivityForResult(chooser2,REQUEST_PICK_CONTACT);
次に大画像を扱う場合out of memoryに泣かされる
上記の方法で画像の居場所が返ってきて
camb=BitmapFactory.decodeFile(direct_path, bm_opt)を実行したとたん落ちる(泣
で、どうするかだが、以下の方法で完璧に読込が出来る。(ただし、機種によって上限サイズが違うため機種判別で上限サイズを制限する必要あり)
direct_path=file_path;
int Width = 0;
int Height = 0;
Matrix matrix = new Matrix();
float rate =0;
if (direct_path != null)
{
try {
Bitmap temp_bitmap=null;
//これがないとOutOfMemoryErrorが出てきてどうしようもなかった
if(camb!=null)
{
camb.recycle();
camb=null;
}
if(bmp!=null)
{
bmp.recycle();
bmp=null;
}
bm_opt = new BitmapFactory.Options();
//ビットマップには実際には転送されないためサイズを得ることができる
bm_opt.inJustDecodeBounds = true;
bm_opt.inPurgeable=true;
BitmapFactory.decodeFile(direct_path, bm_opt);
camb_Width = (float)bm_opt.outWidth;
camb_Height = (float)bm_opt.outHeight;
int srcSize = Math.max(bm_opt.outWidth,bm_opt.outHeight);
long base_rate=0;
//機種によって1200以上だとメモリー不足で落ちるため1/2の画質にしちゃう
double base_size=1200;
if(srcSize>1200)
{
base_rate=Math.round((double)srcSize/base_size);
//これを入れないと、Galaxy以外の全機種は即死します。
//特に日本メーカは/撃沈必須
//Galaxyは標準以上なので優れてます。日本メーカーは見習ってね!!
bm_opt.inSampleSize=(int)base_rate;//2;//inSampleSizeが2なら1/2になる
}
else if(srcSize<=1200)
{
bm_opt.inSampleSize=1;
base_rate=1;
}
bm_opt.inJustDecodeBounds = false;//実際に読み込む
bm_opt.inPurgeable=true;
if(srcSize>1200)
{
long base_rate2=base_rate%2;
if(base_rate2!=0)
//inSampleSizeは偶数倍で処理されるため奇数は偶数に直す base_rate=base_rate-1;
//機種判別自作関数呼び出しで上限サイズから縮小率の計算
rate=calc_rate(ver)*(float)base_rate;//縮小比率を元に戻す。
}
else
rate=calc_rate(ver);//通常の縮小比率を計算する。
if(camb!=null)
{
camb.recycle();
camb=null;
}
if(bmp!=null){
bmp.recycle();
bmp=null;
}
matrix.postScale(rate, rate);
camb=BitmapFactory.decodeFile(direct_path, bm_opt);
//縮小したサイズを取得する
Width = camb.getWidth();
Height = camb.getHeight();
camb = Bitmap.createBitmap(camb, 0,0, Width, Height, matrix, true);
bmp=BitmapFactory.decodeFile(direct_path, bm_opt);
bmp= Bitmap.createBitmap(bmp, 0,0, Width, Height, matrix, true);
ブログ一覧 | 日記
Posted at
2011/12/31 00:13:22
今、あなたにおすすめ