2010年11月29日月曜日

BitmapFactoryのdecodeStreamでoutofMemory

そろそろ画像修正ツールが出来上がってきたので、学生のエクスペリア(2.1)を使ってテストテストーー。

すると、ガツガツ落ちる。 いやいや。 落ちること落ちること。

原因はタイトル通りBitmapFactoryのdecodeStreamでoutofMemory
うぇー。 IS01だと起きないのになぁ。 あれか。カメラの解像度が高すぎるからか。

てことで、調べたら、エクスペリアの最大の解像度は8Mピクセル!! サイズにすると3264×2448 !!!?

なんとまぁ。 それをARGB_8888で取ったらー。 大体容量32M。そりゃ落ちるわ。

対応としては、BitmapFactory.Optionsを上手く指定すればいいらしい。
家帰ったらやってみよう。

2010年11月26日金曜日

IS01

僕が持っているAndroid端末はIS01だけなんだけども。

まぁ、OSがアップデートされないのはよしとしよう。 実機チェックとしてはVerは高いより低いほうがなにかと便利だしね。

ただ、プロセスの暴走だけはなんとかしてくれんかなー。

最近のアップデートから、uimdっちゅープロセスも気付くと暴走していることが多い。

熱中して開発してたらPCからのUSB充電じゃ間に合わなくて、電源落ちたりするし。 やめとくれ。

電子書籍が最近話題だけども

最近、近くの技術書の揃いがグンバツの本屋さんが潰れちゃって途方に暮れてたんだけど、電子書籍なんか流行ろうもんなら本屋はますます潰れるよね。

しかしながら、いまいち電子書籍のウリがわかんねぃ。

エコですか。 紙使わないからエコですか。 んじゃぁ、エコポイントとかくれればいいのに。
そもそも紙使わないから安く売れるとか?
広告がズバズバカットインするから無料とか?
まぁ、値段で勝負ですよね。普通に考えれば。

あと「検索」か。

夜中とかに
「あれ、この台詞なんだっけ!!? どの漫画の誰の台詞だっけ!!!?」
って眠れぬ夜にはいいかもしれない。(最近では『犬みたいに同じところでぐるぐる回ってろ』みたいな台詞がどこ出展だったか思い出せなくて苦労した。 BLACK LAGOONだった。あふん。)

しかし。
冒頭にもどるけど、本屋が生き残る道はあるんだろうか。

ちょっと考えるとーーー。
本屋のウリって、「実物感」であったり、店員さんの趣味丸出しの「品揃え」だったり、技術書や小説で言うと「立ち読み」だったりだと思う。
すると、それをそのまま電子書籍に当てはめると、本屋はwifiのフリースポットみたいな状態になって、本を揃える(試し読みをする権利を買う)。
ユーザーは本屋に行くと、電子書籍が試し読み出来る。
んで、そこで購入すると、本屋にマージンが入る。 ・・・・とか?

駄目だ。本屋で立ち読み(試し読み)して、家帰ってから購入されちゃったらアウトだ。
ってーいうか、それって正に今の「本屋で立ち読みして、良さそうだったらAmazonで注文」の状況だし。

難しいね。

個人的には本屋さんには頑張っていただきたい。

華氏451度みたいになってもらっても困る。

2010年11月25日木曜日

ProgressDialogを上手く使う

昨日、「あの保存とかするときにくるくる回ってる砂時計替わりみたいなの出したい」的な事を書いたんですが、ProgressDialogなんですね。 ふむん。

で。
これの使い道っていうと、重い処理を別スレッドで動かして、その間に表示。
処理が終了したら閉じる。 ってなる。

なので、重い処理の開始前にshow()して、処理が終わったらdismiss()を呼ぶ。

でも、その「重い処理」ってーのは、別スレッドなので、別スレッドからshow()すると、RuntimeExceptionだしてくれるんだよね。コイツ。(Toastでも同じ現象発生)

んで、Handlerを使えとかなんとか言われるわけなんだけど。
なんとかクラスでまとめられないかなーと思って、作ってみました。

package mosaic.dividebyzero.net;
import android.app.ProgressDialog;
import android.content.Context;
import android.os.Handler;

class MyProgressDialog implements Runnable {
 private String title, message;
 private static ProgressDialog progressDialog;
 private static Handler handle = new Handler();

 public static void init(Context context) {
  if (progressDialog == null) progressDialog = new ProgressDialog(context);
 }

 public static void createDialog(String title, String message) {
  if (progressDialog == null)
   throw new RuntimeException("MyProgressDialog is not initialize\nplease call init Method.");
  handle.post(new MyProgressDialog(title, message));
 }

 public static void close() {
  if (progressDialog != null) progressDialog.dismiss();
 }

 public MyProgressDialog(String title, String message) {
  this.title = title;
  this.message = message;
 }

 @Override
 public void run() {
  // TODO 自動生成されたメソッド・スタブ
  progressDialog.setTitle(title);
  progressDialog.setMessage(message);
  progressDialog.setIndeterminate(false);
  progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
  progressDialog.setCancelable(true);
  progressDialog.show();
 }
}

肝は、createDialogより前にinitを呼ぶということ。
さらに言えば、initはviewのスレッドから呼ぶ必要があるっぽいです(てか、無きゃinitとcreateに分ける必要が無い)

正直、ここらへんは行き当たりばったりというか、やってみたら出来た。というか。
理論に基づいた作りじゃないのでなにか間違ってるかもですが。とりあえず、今のところ問題無しです。

SDに保存した画像がすぐに認識しない件

SDカードに画像を保存した直後は、何故かギャラリー系のアプリから見ることが出来ないんですよね。
一回PCへマウントして、アンマウントしたり、OS自体を再起動したりすれば見れるんですけども。 なんでしょうか。これは。

でも、touch2pixelとかはちゃんと保存した後もすぐ見れるんですよね。これがまた。
なにか特別な保存方法があるんだろうかー。

って、調べてみたら。
ContentResolverってので登録しなきゃいけないんですね。 サムネイル絡みかと思ってたら、こんなのがあるとは・・・。

一応コード
// 保存先を取得
  String status = Environment.getExternalStorageState();
  File fout = null;
  if (!status.equals(Environment.MEDIA_MOUNTED)) {
   // SDカードがマウントされてないので、システムの使える場所に保存
   fout = getContext().getFilesDir();
  } else {
   // SDカードがマウントされているので、勝手にフォルダ作成
   fout = new File("/sdcard/ciasom/");
   fout.mkdirs();
  }
  File fname = new File(fout ,"/ciasom" + getDate() + ".png");
  FileOutputStream fos = new FileOutputStream(fname);
  bitmap.compress(CompressFormat.PNG, 100, fos);
  fos.flush();
  fos.close();
  //メディアに登録作業が必要らしい。
  ContentValues values = new ContentValues();
  ContentResolver contentResolver = getContext().getContentResolver();
  values.put(Images.Media.MIME_TYPE, "image/png");
  values.put(Images.Media.DATE_MODIFIED,System.currentTimeMillis()/1000);
  values.put(Images.Media.SIZE, fname.length());
  values.put(Images.Media.TITLE, fname.getName());
  values.put(Images.Media.DATA, fname.getPath());
  contentResolver.insert(Media.EXTERNAL_CONTENT_URI, values);
これは今作っている可逆モザイクアプリのソースそのままぶっこぬいてきました。

これまたはまったのが、Images.Media.DATE_MODIFIED には更新時間を入れるんだけど、ちょっとぐぐると
「System.currentTimeMillis()」が平気で指定されてるところ。

でも、これで保存すると、2037年とかになっちゃうんですよな。

ここで指定するのは1970年1月1日からの~ってとこまでは一緒なんだけど、「秒数」を入れるらしい。
んで、System.currentTimeMillis()は1970年起点の「ミリ秒」なので、時間が狂う。と。

ちゅーわけで、/1000が要るわけです。 ふむん。

完成が近づいてきたぜー

2010年11月24日水曜日

カメラをintentで外部起動して、指定した場所に保存してもらう

最近はゲームはさておき、自分がほしいな。 っていうツールを作るのでいっぱいいっぱいです。 kszです。

今は可逆モザイクアプリを作ろうと思っているんだけども、当然元の画像はギャラリーから持ってきたり、カメラから取得しなきゃなので、調べつつつくっていたんですが、ハマりまくりました。

まず、カメラから戻ってきた(onActivityResultの引数の)Intent の data には縮小した画像が入ってしまうということ。
これはIntentに受け渡せるデータ量の上限が決まっているかららしい。 まずこれで1ハマリ。

ではでは、EXTRA_OUTPUT で、urlを指定して、指定した場所に保存をしてもらおう。と。
具体的には
putExtra(MediaStore.EXTRA_OUTPUT, [ここに保存してほしい場所をurlで]);
ふむ。

逆を言えば、何か外部からグローバルのintent呼び出しを自分のアプリがうけた場合は、このEXTRA_OUTPUTが入っていた場合はそこに保存するようにしなきゃって事ですよな。

それはさておき。
では、それでonActivityResultで受け取ろうーって思ったんだけど、
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
 String url = data.getStringExtra(MediaStore.EXTRA_OUTPUT);
//↑で受け取ったurlから画像ファイル読み込み処理をここから下に
}

ってやったら、ヌルポが飛ぶ。 何が!? って調べると、そもそもIntent data のdataがnull。
EXTRA_OUTPUTを指定しちゃうと、戻りのIntentがnullになる・・・。 んですか・・・?

腑に落ちねぇ・・・。

2010年11月17日水曜日

eclipseショートカット覚書

Ctrl + Shitf + B
でブレークポイント設置/解除

うーん。 F9がみに染み付いていて困る。 VisualStudioショートカットに全部変えてしまいたい・・・。