2011年07月29日

[Android] PorterDuffXfermodeについて

日本Androidの会に質問がきました。
半透明の色を重ねて描画すると、その部分の色が濃くなってしまうが、半透明のままにできないか、というものでした。
https://groups.google.com/group/android-group-japan/browse_thread/thread/b1b9a1298830f6d7?hl=ja#

以前、スクラッチゲーム風にタッチした部分が削れるような動作を実現するのに、Paint.setXfermode()を使って、「透明」を描画したのを思い出したので、回答をしたのですがそれではうまく行かなかったようです。
実際に自分の回答通りにコードを書いてみましたが、全然ダメでした。
人に教えるときは、もっとちゃんと理解していなきゃダメだな、と少し反省した次第です。

ただ、自分の回答は間違っていたものの、考え方まで間違っていたとは思えなかったので少し調べてみました。
自分の最初の回答では「DST」を指定すると言ったのですが、これは転送先の画像を使う指定ですね…。
逆でした…。「SRC」が転送元の画象を使う指定でした。
モードはこれで合っているはずです。

続いて「背景色と合成されて、ホントは上手くいってるんだけど、失敗しているように見えているんでは?」と思って、背景色と画像を分けてみることにしました。
背景色を真っ白にして、その上に目当ての画像だけを描くようにしてみました。
まぁ、正直に言って、最初のうちは実際に「ダメ」だったわけですけども、いろいろと調整していたらうまくいくようになりました。
やっぱり、自分の考え方は(そんなに)間違ってなかったー!

理解が曖昧なとこだったので良い機会でした。
簡単な動作確認用サンプルを置いておきますので、よろしければどうぞ。
XfermodeSample.zip
device-2011-07-29-021254.png
[参考]
Merlinの魔術: Porter-Duffのルール!
http://www.ibm.com/developerworks/jp/java/library/j-mer0918/
タグ:android
posted by t2low at 02:17| Android

2011年04月29日

[Android] SDカードを示すディレクトリ

先日、OreillyのLinuxハンドブックという本を読んでいて、printenvというコマンドを記憶しました。
その後、Androidアプリの開発を行っていて、「adb shell」でシェルを使うことがあったので、そのときたまたま覚えていたprintenvを使ってみました。
そんなに多くはないけれど、環境変数がずらずらっと表示されました。
その中にひとつ気になる環境変数が。
それが$EXTERNAL_STORAGEです。
初めてその環境変数に気づいたときは、Desireで実行していました。
パスは /mnt/sdcard/ を示していました。

以前、仕事でAndroidアプリの開発を行っていたとき、SMT-i9100(au の タブレット端末)のSDカードのディレクトリを取得するのに困ったことを思い出しました。
SMT-i9100は(というかSamsung製端末?)は、SDカードのパスがちょっと特殊なのです。
通常、SDカードのパスはEnvironment.getExternalStorageDirectory()で取得します。
Desireで実行すればもちろん「/mnt/sdcard/」を返してくれます。「/mnt/sdcard/」はSDカードのルートディレクトリ(っていうの?)を指します。

ところが、SMT-i9100で同じように実行すると、そうはいかないのです。
SMT-i9100のSDカードは「/mnt/sdcard/external_sd/」にあります。
ところが上記APIでパスを取得しようとすると、「/mnt/sdcard/」を返します。
これはSMT-i9100の内部メモリになります。
ファイルの読み書きは普通にできますので、アプリが単体で動く場合には問題ないのですが、物理的なSDカードにアクセスすることを前提としたアプリでは困ることがあります。

そこでこの環境変数です。
SMT-i9100でこの変数の中身が一体何を指しているか。
確認してみたところ、なんと「/mnt/sdcard/external_sd/」が設定されていました。
もし、これがどのAndroid端末も共通の仕様であれば、SDカードのパスを取得するのに困ることがなくなります。
すごい大発見だ、と思ったのですが、一人で確認するのはちょっと難しそうです。
一応、確認用のアプリを作ったので、もし確認いただける方がいらっしゃいましたら、ご協力ください。

・Environment.getExternalStorageDirectory()と$EXTERNAL_STORAGEの値を表示するアプリ
ExternalStorageSample.apk
(ソースはこちら→ExternalStorageSample.zip

現状、以下の端末は$EXTERNAL_STORAGEが正しくSDカードのパスを指すことが分かっています。
・HTC Desire
・SMT-i9100
・Galaxy S

MotorolaのXOOMに関してはSDカードがまだ使用できないせいか、どちらも「/mnt/sdcard/」を指していました。
こちらについてはアップデートを待ってもう一度確認してみたい(させてもらいたい)と思っています。
※6/24追記 コメントで情報いただきまして、アップデートしてAndroid3.1になったXOOM(SDカードが使える)でも「/mng/sdcard/」を指しているとのこと。
環境変数に正しいSDカードへのパスが格納されているんじゃないか、という推測は外れてしまいました。
きちんとしたSDカードへのパスを取得したい人はどうしたら良いのでしょうかね…。


ちなみにアプリから環境変数を取得するには以下のコードで取得できます。
System.getenv("EXTERNAL_STORAGE");
↑は$EXTERNAL_STORAGEを取得するときのコードですので、別の環境変数を取得する場合は適宜変数名を変えてください。

device.png
※こちらは同僚のGalaxy Sで試させてもらったときのスクリーンショット。
タグ:android
posted by t2low at 02:22| Android

2011年04月19日

[Android] AsyncTaskのバグ?

前回(http://blog.tappli.com/article/44407843.html)記事にしたAsyncTaskのバグについてですが、調べても調べても具体的な内容はネタ元と思われる以下のサイトしか出てきません…。

http://groups.google.com/group/android-developers/browse_thread/thread/07ea01892ee7a5f4/9f71428217c2cd44

あと、AsyncTaskの修正履歴を以下から確認してみたのですが、2010/09/10の修正ではThreadPoolExecuterのKeepAliveTimeを10から1に変更しただけで、その他の修正は行われていないっぽいのです。
http://android.git.kernel.org/?p=platform/frameworks/base.git;a=history;f=core/java/android/os/AsyncTask.java;h=5fb1d7c32879352170abbd6c56c1aa81f5fae175;hb=refs/heads/gingerbread
この修正で前回記事にした内容の不具合が直るとは思えないんだけれど…。

もしかしてネタ元が英語だったために、僕が読み間違えている可能性もあると思い、がんばって翻訳してみました。
英語は得意でないので、間違っているところとか、日本語としておかしいところは多々あるかと思いますが、それでも話の大筋としては、下記の翻訳で間違っちゃいないと思っています。
そうするとやっぱり不具合はあったということで、一体どういうことなのよ?という気分です。
onDestroy()でAsyncTaskのcancel()を実行しても、onPostExecute()が呼ばれるというのは本当に起こり得るのかしら?
Froyo以前にバグが残っているとしたら困るなぁ…。

--------------------------------
As far as I can tell, AsyncTask's cancel method doesn't work as advertised.
私が言える範囲では、AsyncTaskのcancel()メソッドは(公示通りに)きちんと動かない。

I can't tell whether this is a bug, or me not understanding AsyncTask's cancel() method.
私はこれがバグかどうかは言えない、AsyncTaskのcancel()メソッドについて理解していない。

I'm asking here instead of StackOverflow because I suspect it's a bug.
私はStackOverflowに代わってここで質問する。バグを疑っているから。


I understand from past discussions here that cancel() isn't meant to actually kill a thread
ここでの過去の議論から、cancel()が実際にスレッドを殺すわけではないことは分かっている。

(though the description of the mayInterruptIfRunning flag sure implies it is).
(mayInterruptIfRunningフラグの説明は、それを意味しているはずなのに)


But I'm also checking for isCancelled() (which is returning false),
私はisCancelled()も確認して(それはfalseを返す)、

and trying to use the onCancelled callback (which isn't getting called), to no avail.
onCancelled()コールバックを使おうとした(それは呼ばれなかった)が、無駄に終わった。

My situation is that I have a (short-running, one small network call) AsyncTask that begins in my Activity's onCreate.
状況しては、私は(1回小さな通信する短い処理の)AsyncTaskをActivityのonCreate()で開始する。

If the user backs out of the screen before it finishes though,
例えば、ユーザが画面を消して終了させるとき、

I need to either cancel the AsyncTask entirely,
完全にAsyncTaskをキャンセルするか、

or at least make sure its onPostExecute doesn't do any meaningful work.
少なくともonPostExecute()が意味のある(?)仕事をしないことを確認したい。

In my activity's onDestroy handler, I call cancel() on the task,
私のActivityのonDestroy()では、タスクのcancel()を呼んでいて、

and then inside the task I have an onCancelled handler that sets a boolean.
そして、そのときタスク内ではonCancelled()を受けてbooleanの値を設定している。

In my onPostExecute handler, I check isCancelled(),
onPostExecute()では、私はisCancelled()をチェックしていて、

and I also check to see whether the boolean has been set from onCancelled, and neither are.
そして、onCancelled()で設定されたはずの真偽値をもチェックしているのに、どちらもダメ。

I'm using the debugger, and the order of operations is:
私がデバッガを使っているときの操作手順は:

1) onDestroy(), calls task.cancel()
1) onDestroy()でAsyncTaskのcancel()を呼ぶ

2) task's onPostExecute runs, isCancelled() returns false,
2) タスクのonPostExecute()が実行され、isCancelled()はfalseを返すので、

so I have no conditional to stop the flow and that's it. onCancelled never runs.
私はタスクを停止させるための条件を得られない。onCancelled()は実行されない。


What am I doing wrong here?
私のやっていることは何か間違っていましたか?

I can't find any way to tell my task not to run its work in onPostExecute.
私はonPostExecute()でタスクが処理を行わないように命令する方法を見つけられない。
--------------------------------
タグ:android AsyncTask
posted by t2low at 09:03| Android

2011年04月18日

[Android] AsyncTask のバグ

AsyncTaskにバグがあると職場の同僚に聞いたのでググってみました。

http://d.hatena.ne.jp/kinneko/20100730/p9
http://amay077.posterous.com/asynctask-cancel-froyo22

症状としては、ActivityのonDestroy()でAsyncTaskのcancel()を呼ぶと、正しくonCancelled()が呼ばれずに、onPostExecute()が呼ばれてしまうということらしいです。
最初のバグ報告(?)はGoogle group(英語)に投稿されたものっぽいのですが、英語がろくに読めないこともあって、不具合の詳しい内容がわかりません…。
ちなみに、バグの修正は2.3でやるよ(やったよ?)ということのようです。

そうなると、2.2までのAsyncTaskを使ったアプリはそれを回避する方法を考慮した作りにしなければなりません。
が、やっぱり詳しい内容がよくわかっていません…。
発生条件はonDestroy()でcancel()を呼んだときだけなのか。onPause()で呼んだら本当に問題ないのか。
回避方法としては、それを考慮しておけばそれだけで大丈夫なのか。
探し方が悪いのかも知れませんが、バグをきちんと理解するだけの情報が得られませんでした。

そこでAsyncTaskをonCreate()で開始させ、onDestroy()でcancel()する簡単なプログラムを書いてみました。
イベントごとにLogを出力するようにしてあります。
試したのはDesire(2.2)です。

確認に使用したソース→AsyncTaskBug.zip

onDestroy()でキャンセルしたとき
04-18 00:30:28.970: VERBOSE/AsyncTaskBug(6820): Activity.onCreate:
04-18 00:30:28.970: VERBOSE/AsyncTaskBug(6820): onPreExecute:
04-18 00:30:29.990: VERBOSE/AsyncTaskBug(6820): onProgressUpdate:0
04-18 00:30:30.990: VERBOSE/AsyncTaskBug(6820): onProgressUpdate:1
04-18 00:30:31.990: VERBOSE/AsyncTaskBug(6820): onProgressUpdate:2
04-18 00:30:32.990: VERBOSE/AsyncTaskBug(6820): onProgressUpdate:3
04-18 00:30:33.990: VERBOSE/AsyncTaskBug(6820): onProgressUpdate:4
04-18 00:30:35.000: VERBOSE/AsyncTaskBug(6820): onProgressUpdate:5
04-18 00:30:35.590: VERBOSE/AsyncTaskBug(6820): Activity.onDestroy:
04-18 00:30:35.600: VERBOSE/AsyncTaskBug(6820): onCancelled
04-18 00:30:36.000: VERBOSE/AsyncTaskBug(6820): onProgressUpdate:6

…。
簡単にバグの確認ができるかと思ったのですが、きちんとキャンセルされてしまいました…。
きちんとといってもonCancelledのあとにonProgressUpdateが来ているのもおかしい気がしますが。
ついでなので、onPause()でcancel()を呼ぶよう修正して再度確認してみました。


onPause()でキャンセルしたとき
04-18 00:31:53.570: VERBOSE/AsyncTaskBug(6907): Activity.onCreate:
04-18 00:31:53.580: VERBOSE/AsyncTaskBug(6907): onPreExecute:
04-18 00:31:54.580: VERBOSE/AsyncTaskBug(6907): onProgressUpdate:0
04-18 00:31:55.580: VERBOSE/AsyncTaskBug(6907): onProgressUpdate:1
04-18 00:31:56.580: VERBOSE/AsyncTaskBug(6907): onProgressUpdate:2
04-18 00:31:57.591: VERBOSE/AsyncTaskBug(6907): onProgressUpdate:3
04-18 00:31:58.590: VERBOSE/AsyncTaskBug(6907): onProgressUpdate:4
04-18 00:31:59.590: VERBOSE/AsyncTaskBug(6907): onProgressUpdate:5
04-18 00:32:00.260: VERBOSE/AsyncTaskBug(6907): Activity.onPause:
04-18 00:32:00.290: VERBOSE/AsyncTaskBug(6907): onCancelled
04-18 00:32:00.600: VERBOSE/AsyncTaskBug(6907): onProgressUpdate:6
04-18 00:32:00.790: VERBOSE/AsyncTaskBug(6907): Activity.onDestroy:

…。
変わりません…。タイミングがちょっと早くなったくらいです…。


うーん、発生条件が違うのか…、それとも発生確率が低いのか…、はたまたDesireでは修正が適用されたものを使っているのか…。
よくわかりません。コードを書けばすぐに確認できると思っていただけに残念です。

というわけで、こんな記事にしておきながら、結局詳しいことはわかりませんでした。
この件についてどなたか教えていただけるととてもありがたいです。
バグの詳細が書かれているサイトがあればURLを教えていただけるだけでも大変助かります。
よろしくお願いします。
タグ:android AsyncTask
posted by t2low at 01:20| Android

2011年03月28日

[Android] 画像の等倍表示

数日間悩みました。解像度に関係なく、画像の1ドットを画面の1ドットとして表示させる方法がなかなかわからなくて。

インターネットを調べると、「res/drawable-nodpiの下に画像を入れれば良い」という情報は見つかったのですが、そのようにしても解像度に応じて自動的に拡大/縮小されてしまいます。
ApiDemoを動かして、drawable-nodpiの表示され方も確認しましたが、これでも拡大/縮小されているようなので、この方法は違うんだろな、と思って別の方法を探していました。

やりたかったのは、ドットをきれいに表示させたかっただけなのです。
まさかこんなに苦労するとは思いませんでした。

最初に思いついたのは、解像度ごとに同じ大きさの画像を用意することです。
drawable-hdpi/mdpi/ldpiのそれぞれに、まったく同じ画像を入れました。すごく無駄だとは思いながら。
結果は、変わりませんでした。
どういう仕組みになっているのか、hdpiの画像が正しく表示されません。

このときの表示方法がDrawableを継承したクラスで自前で描画していたので、それが影響しているのかとも考えました。
標準のImageViewに表示させてみましたが、こちらも変わりませんでした。
解像度別に画象を用意する方法と、ndpiに画象を入れる方法、どちらも試しましたが全然ダメでした。

前々から気にはしていたのですが、デフォルトの設定で大丈夫だろうと思っていた設定項目がありました。
それがマニフェストののanyDensity属性です。
このあたりが表示方法に影響してくることは知っていたのですが、デフォルトが正しいと何故か思い込んでいて、このあたりを変えようとは思っていませんでした。
が、やることもなくなったので、今朝試してみたところ…あっさり希望通りの表示になりました。
具体的にはres/drawable-ndpiの中にだけ画象を置いて、上記anyDensityをtrueにしただけです。
すごく時間を無駄にした気分です。

しかし、これでようやく先に進めます。
震災後、あまり趣味の開発にも時間をあてられていなかったので、少しずつ再開していこうかと思います。
タグ:android Drawable
posted by t2low at 08:53| Android

2011年02月25日

[Android] 縦横切り替えとインスタンスの再生成

以前から疑問だったことがありました。
縦向き画面のときと、横向き画面のときでレイアウトを変えたい場合どのようにしたら良いのだろう?と。

当時考えた方法は、とりあえず以下の4点でした。

◆configChangesを無指定にして、Activityが再生成されるようにする場合
1. layout-port、layout-land にxmlを置く。毎回Activityが破棄されるので、それでも問題ない作りにする。

◆configChangesに縦横切り替えをしていしてActivityが再生成されないようにする場合
2. 基本のレイアウトをlayout.xmlで記述する。差異のある部分だけプログラムから変更する。
3. layout-port、layout-land にxmlを置く。切り替え時点でsetContentViewを呼び、Viewのインスタンスだけ再生成させる。
4. 全部プログラムでViewを構築する。

1の場合、縦横を切り換えるだけで、onCreate()〜onDestroy()まで行われるため、もろもろのオブジェクトまで破棄〜再生成せねばならず、あまり良い方法には思えませんでした。
通信によって取得した場合も、どこかに保存するような処理を書かねば、縦横切り替えの度に通信が必要になってしまいます。

2の場合ですが、現状この方法で実装しているアプリがあります。
縦横切替のタイミングで呼ばれるメソッド(onConfigrationChanged())で、縦の場合、横の場合と分岐させてレイアウトを変えています。
ただ、setContentView()などを呼ぶとViewのインスタンスが再生成されてしまうので、それらは呼んでいません。
ViewGroupに対してaddView,removeViewなどして、せっせとレイアウトを変えています。
実際にやってみると(やらなくても?)わかるのですが、これはかなりイケていません。
レイアウトを定義している部分がxmlにもプログラムにもあり、どこを直したら良いのかわからなくなります。
もうこの案は二度と採用しないでしょう。

3の場合ですが、ちょっとこれは採用できませんでした。
今考えれば2よりはるかにマシかと思うのですが、2を採用したのは「改修」のタイミングですでに基盤があったのです。
データをViewそのものが持っているような構造になっていたため、Viewのインスタンスを再生成した場合に再描画するためのコードを書くのが恐ろしく面倒でした。

4の場合、これは面倒すぎてすぐに却下しました。


さて、今ならどれを採用するか。
ついこの間までは「やはり3かなぁ」と考えていましたが、最近見つけた以下の記事で考えを改めました。

http://developer.android.com/intl/ja/resources/articles/faster-screen-orientation-change.html

ここにはActivityが破棄されても、必要なインスタンスを持ち続ける方法が書かれていました。
Androidの正統派の作り方はこれなんじゃないかと思いました。
やっていることは簡単で、onRetainNonConfigurationInstance()をオーバーライドして、持ち続けたいインスタンうを返すだけです。
そのインスタンスを使うとき(onCreateだと思います)は、getLastNonConfigurationInstance()を呼ぶだけです。
これだけでわざわざインスタンスの再生成で悩んだり、Singletonオブジェクトを作ったりする必要が無くなると思いました。

詳しくは上の記事を読んでみてください。
他にも同様に役に立つ記事が多数あるようなので、読みたいと思います。

一応、自分でもサンプルコードを書いてみました。
よろしかったらご確認ください。
RotateTest.zip
タグ:android
posted by t2low at 12:05| Android

2011年02月15日

[Android] android_winusb.inf に追記する内容

新しいAndroid端末をWindowsにつなごうとすると、うまく認識しないことがあります。
そんなとき、android_winusb.inf になんだかよくわからない文字列を追記するだけで認識するようになることがあります。

; XXX XXXX
%SingleAdbInterface% = USB_Install, USB\VID_XXXX&PID_XXXX
%CompositeAdbInterface% = USB_Install, USB\VID_XXXX&PID_XXXX&MI_XX

こんな形式なやつです。
前々から不思議だったのです。
これに書く内容はどこで調べてくるんだろう、と。

で、今日ネットをいろいろ調べていたら、わかったのです。
(わかったと言っても人のブログを見ただけなんですけども)
ただ、完全に理解したわけでなくて、なんとなくそうっぽいという理解です。

それは「デバイスマネージャを見る!」でした。
デバイスマネージャからAndroid端末(ちゃんと認識してない「?」の状態でもだいじょぶ)を選んで、プロパティを開きます。
詳細タブを開いて、プロパティの欄をハードウェアIDに切り替えます。
すると、値の部分にそれっぽい文字列が!

property.png

USB\VID_0BB4&PID_0C87&REV_0226&MI_01
USB\VID_0BB4&PID_0C87&MI_01

これ↑を最初に書いた形式にするにはこれ↓をくっつければ良いのではないかと。

%SingleAdbInterface% = USB_Install,
%CompositeAdbInterface% = USB_Install,

一応、適当に連結したら認識するようになった端末もあるので、間違ってはないっぽい気もしますが、本当に合っているのかは自信がありません。
表示された値の順番は関係ないのかなぁ、とかVIDとかPIDとかREVとかMIとかってなんだろう、とか。
でも、昨日まではこの値がどこで調べられるのかも知らなかったわけで、一歩前進です。
また興味を持ったときに調べたいと思います。
タグ:android
posted by t2low at 01:58| Android

2010年11月26日

[Android] なんとなく使えるOAuth-Echo

記事タイトルに[Android]とつけましたが、たぶんAndroidに限った話ではないと思います。
が、Androidでしかやったことないので、とりあえず[Android]とつけています。

職場でTwitPicへの投稿機能を実装することになりました。
ざっとインターネットで調べてみた限りでは、そこまで難しくなさそうでした。
ただ、実際にやってみたら思っていた以上に時間がかかってしまいました。
そこで学習したことを忘れないようにメモっておきたいと思います。

TwitPicのリファレンスはこちら。
 http://dev.twitpic.com/docs/2/upload/

◆OAuth-Echoのざっくりとした使い方!(TwitPic編)

(1) http://api.twitter.com/version/account/verify_credentials.json のリクエスト(GET)を用意する。
  ※レスポンスのフォーマットはjsonじゃないとだめ(たぶん)。

(2) (1)にOAuth認証する。
  つまり、OAuthConsumer.sign()する。

(3) (2)からヘッダ(Authorization)を取り出す。
  たぶん↓こんなのが取れる。
   OAuth oauth_consumer_key="〜",
   oauth_signature_method="HMAC-SHA1",
   oauth_token="〜",
   oauth_timestamp="〜",
   oauth_nonce="〜",
   oauth_version="1.0",
   oauth_signature="〜"

(4) (3)に以下の文字列を連結する。
  , realm="http://api.twitter.com/"

  ※こんな↓感じになる。
   OAuth oauth_consumer_key="〜",
   oauth_signature_method="HMAC-SHA1",
   oauth_token="〜",
   oauth_timestamp="〜",
   oauth_nonce="〜",
   oauth_version="1.0",
   oauth_signature="〜",
   realm="http://api.twitter.com/"


(5) http://api.twitpic.com/2/upload.(xml or json) のリクエスト(POST)を用意する。
  こちらはxmlでもjsonでもだいじょーぶ。

(6) (5)に以下のヘッダを追加する。
  X-Auth-Service-Provider: https://api.twitter.com/1/account/verify_credentials.json
  ※このURLは(1)と一致していること!

(7) (6)にさらに以下のヘッダを追加する。
  X-Verify-Credentials-Authorization: (4)の内容

(8) (7)に以下のパラメータを指定する。MultipartFormDataで。
  key=(TwitPicでアプリ登録して取得しておく)
  message=(登録するメッセージ。空文字でもOKみたい)
  media=(投稿する写真データ)

  ※mediaはhttpmime4.0.3のFileBodyを使った。他はStringBody。
   InputStreamBodyでもいけると思ったけどRepeatableなんとかがどうのこうのでよくわからんかった…。

(9) (8)のリクエストを投げてレスポンスを受ける。
  成功すればURLを含むxml or jsonが返ってくるので適当にうまいことやる。
  以上!


僕は(6)の部分でひっかかっていました。
(1)の部分は結構前に作ってあって、それをそのまま使ったのですが、リクエストしたフォーマットがxmlだったのです。
よくよく考えればすぐ気づいても良かったと思うんですけど、OAuth-Echoが初めてだったというのもあって手探りでした。

TwitPicの動きを予想すると、(9)で受け取った(4)のヘッダーを使ってTwitterからユーザ情報を取ってきて、ちゃんとTwitterのユーザだったら、投稿を受け付けるということをしているんだと思います。
そのとき使うのが(5)のURLで認証されたものでないとだめなので、(1)と(5)は一致している必要があるわけです。きっと。たぶん。

今回はサンプルありません。
あと上の手順は記憶を頼りに書いたので、実際には別の手順も必要だったかもしれません。何か手順が抜けていたらご指摘ください。
これを読んでくれた人の参考になれば幸いです。
posted by t2low at 07:53| Android

2010年11月05日

[Android] 機内モードの切り替え

圏外のテストを行うときに厳密でなくても良い場合は機内モードが便利ですよね。
アプリ(できればサービス)から特定のコマンドを検知して機内モードのON/OFFを切り替えられたら良いな、と思って少し調べてみました。

機内モードの切り替えは↓こんな感じでできるようです。

private void setAirplaneMode(boolean enable) {
int value = enable ? 1 : 0;
Settings.System.putInt(getContentResolver(), Settings.System.AIRPLANE_MODE_ON, value);

Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
intent.putExtra("state", value);
sendBroadcast(intent);
}

ほぼネットに転がっていた情報をほとんどコピペしただけなので、いまいち理解はしていません。
空行で区切られている上か下の処理だけで切り替えられると思ったのですが、どうも両方必要なようです。
あとSettings.System.putInt()を使うには[android.permission.WRITE_SETTINGS]のパーミッションが必要です。

振ったらモードが切り替わるサービスを作ろうかと思ったのですが、今日は時間がなかったのであきらめました。
また時間があるときに気が向いたら作ろう。

↓いつものようにサンプルです。
AirplaneModeChanger.zip
posted by t2low at 02:55| Android

2010年10月29日

[Android] XMLを使ったビットマップ

AndroidはXMLで画像を作ることができます。
どんなものがあるのか調べるためにひと通り験してみることにしました。
ちなみにこのことが書かれているのは以下のページです。

http://developer.android.com/intl/ja/guide/topics/resources/drawable-resource.html

xml_bitmap.png

■Bitmap File
 画像を繰り返し並べたり、反転したりできるようです。
 小さな画像を用意して、「線」として使うときなどに使えるかな?

■Nine-Patch File
 XMLで指定する9パッチはよくわからなかったのでパス。

■Layer List
 複数枚の画像を重ねた画像を作成できるようです。
 画象をパーツで用意して、1つの画象を作るときに使いそうですね。

■State List
 いわゆるセレクタ(selector)というやつですね。
 状態に応じて画象を切替えるボタンなんかに使いますね。
 便利です。

■Level List
 使ったことがなかったのですが、JavaからsetLevel()というメソッドでレベルを指定したときに、そのレベルに応じて変化する画象を作ることができます。
 電池残量とかの画象はこれで作られてるのかなぁ?

■Transition Drawable
 ちゃんと理解してないですが、徐々に変化する画象を作れます。
 アニメーションとは違うのかな?よくらわかりません。

■Clip Drawable
 これまたsetLevel()でレベルを変えると、それに応じて変化する画象を作ります。
 Level Listでは画象自体が切り替わりましたが、これはレベルに応じて切り取られます。
 進捗を示すプログレスバーに使えそうです。

■Scale Drawable
 これはよくわかりませんでした。
 想像では元の画象から拡大・縮小された画象をつくることができる、と思ったのですが、いろいろ試してみたものの表示させることが出来ませんでした。
 ということで、これに関してはコメントアウトしてあります。
 おわかりになる方がいましたら教えてくださいまし。

 コメントをいただいて、ようやくわかりました。
 やはり拡大・縮小画像をつくるためのものでした。
 ただ、このDrawableもレベルでサイズが変化するもので、初期値がゼロだったため表示できなかったようです。
 (他にもレベルを使ったものがあるんだから気づけよ、自分、という気がしないでもないですが…)
 やっとむさん、ありがとうございました。

■Shape Drawable
 純粋にXMLで画象を書くことができるようです。SVGみたいにいろいろなことは出来なさそうですが。
 シンプルなアプリのパーツはこれだけでも結構かっこよく作れそうな予感がします。

■Animation Drawable
 上のURLの中には含まれてないのですが、AnimationDrawableというものもありました。
 start()で指定した画象のパラパラ漫画風に再生してくれます。


本当はScale Bitmapが表示できてから記事にしようと思っていたのですが、あまりにもわからなすぎてもういいやと載せてしまいました。
ひと通り試してみたサンプルを置いておきます。
BitmapSample.zip


コメントいただいたおかげで、XMLを使った画像については何とかひと通り試すことができました。
このXMLで作れる画像は、絵が描けないプログラマさんの味方なんじゃないかな、と感じています。
機会があれば積極的に使っていきたいと思います。
修正して完全版となったサンプルを置いておきます。
BitmapSample.2.zip
タグ:android
posted by t2low at 02:05| Android

2010年10月01日

[Android] Desireの「ネットワークオペレータの選択」

先日、GDD2010に参加した際、b-mobileで使っているDesireが不調になりました。
症状としては「ネットワークオペレータの選択」画面が頻繁に表示されるというものでした。
発症のきっかけはおそらく設定画面から「ネットワークオペレータの選択」を実行してしまったためだと思われます。
それまで表示されたことはありませんでしたので。

なぜそんなところを触ってしまったかと言いますと、会場が混んでいて通信状態が悪く、なんとかつながりやすくならないかなぁと試行錯誤してたためです。
ほんといらんことしなければ良かったと、後で思いました。

会場内にいるうちはまだ「混んでるせいかな?」と思っていた部分もあるので、それほど心配していなかったのですが、GDD2010が終わって会場の外に出ても、一向に直る気配がないのでだんだんと「このままなんじゃないだろうか」と不安になっていきました。
インターネットを調べてみても「よくわからん」というような情報しか見つかりません。
「ネットワークオペレータの選択」画面は表示されるものの、実は通信自体はできているので、我慢して使おうかとも思いました。
しかし、だんだんとひどくなり、BACKキーで画面を消しても10秒後くらいにはまた出るようになってきたので、これは何か解決策を見つけねばならんと考えた次第です。

ただ、出来ることはあまりない気がしていました。
b-mobileに電話しようにもUK版Desireは、動作確認端末には含まれていません。
b-mobile側も電話されても困るでしょう。なんらかの情報は持っているかも知れませんが。
で、やったことはといえば、APNの再設定です。
一回登録していたAPNを削除して、再度b-mobileの設定を作り直しました。
APN設定にネットワークオペレータの選択が紐付いているかどうかはわかりませんでしたが、まぁ、全く無関係ではないだろうと思ったので。

結果、「ネットワークオペレータの選択」画面は出なくなりました!
1日半くらい経過しましたが、1回も表示されていません(自分天才、と思いました)。
もうモバイルネットワークの設定周辺は極力さわらないようにしようと思いました。
同じような状況の方がいましたら、一度APNの作り直しをおすすめします。
posted by t2low at 00:42| Android

[Android] Google Developer Day 2010 に行ってきました。

9/28に開催されたGoogle Developer Day 2010に行ってきました。

◆基調講演
オープニングからかっこよかったです。
Web上でIMEが動いているのにはおどろきました。
HTML5もいろいろと遊べそうで、ちょっと勉強してみたいと思いました。
あと、初めて翻訳機というものを使いました。
慣れないと英語を聞いたり日本語を聞いたりよくわからなくなりますね。


◆ランチ
お弁当の配布場所が長蛇の列でした。
無料でもらえるとなれば、そうですよね。
僕はChromeのロゴを模した「Chrome丼」をいただきました。
量が足りなかったです…。普通のお弁当にしておけば良かったかも…。
IMAG0200.jpg

◆セッション「高性能なAndroidアプリを作るには」ティム ブレイ
基調講演に続き、翻訳機をつけてのセッションでした。
最初の1分くらい翻訳機が別のチャンネルになっててお隣のセッションを聞いていたのは内緒。
強調していたのは「UIスレッドで重い処理をさすな」ということでした。
あと「推定するな、測定しろ」と言っていました。
ということで、紹介していたのがtraceviewというツールです。
コードにandroid.os.Debug.startMethodTracing()というメソッドを埋め込むと、トレース情報を出力できるようです。
traceviewはそのトレース情報を見るためのツールだと思うのですが、どのメソッドにどれだけの時間がかかっているかを視覚的に確認することができました。
こんな便利なツールがあるなんて知りませんでした。
近いうちに調べて記事にしてみたいと思います。


◆セッション「ここちよいAndroid - 思いやりのUIデザイン」adamrocker 矢野りん
adamrockerさんが言われていたのは
「差異を見せるときは、距離|時間を近く」
「ユーザに時間的なゆとりを与える」
「自然な動作表現を心がける」
とのこと。
誰もが頭ではわかっていても、実装が面倒でほっとかれるような部分ですね。


◆セッション「クールなAndroidアプリを作るには」安生真 江川崇 山下盛史
IMoNiとFxCameraの制作者が登壇されていました。
端末のSMS通知は、何かどこかに書き込むだけとか言われていたので、これも試してみたいと思いました。
「個人開発者は無理せず続けることが大事」というようなことも言われていました。
僕も無理せず続けていこう、と思いました。


◆セッション「Androidでリアルタイムゲームを開発する方法:リベンジ」クリス プルエット
日本語でのセッションでした。
Android Marketに「ワンダのレプリカ島」というアプリがありますが、
あれはこのクリスさんが作られたものだったんですね。知りませんでした。
いろいろと端末のスペックを調べたり、いろいろな方法を試したりしながら、高速化を模索されているようでした。
楽しそうだなぁ、と感じました。

あと「アプリ内にWebServerを実装した」といって見せてくれたデモは衝撃でした。
3Dのオブジェクト(人とゾンビ?)の表面がPC上のパラメータを操作することで、リアルタイムに変わるのです。
OpenGL ES 2.0のシェーダーというものを使っているらしいです。
すごいことを考えるんだなぁ、と思いました。


この時点でセッションはおしまい。僕はこの時点で帰りました。
セッションを聞きに行っただけ、という感じになってしまいましたが、おもしろかったです。
また来年も行きたいな、と思いました。もちろん今度はSuper Hacker枠で!
posted by t2low at 00:40| Android

2010年09月24日

[Android] WebViewを高解像度で表示する

最近まで(今も?)よくわかっていなかったのですが、Androidアプリってどんな解像度の端末でもHVGA(320*480)の画面を想定して作れば良いのですね。
どうも端末側で自動的に拡大縮小して会わせてくれているようです。
ただ、このとき困るのがせっかくの高解像度なディスプレイを持った端末でも、HVGAの解像度でしか表示できなくなってしまうこと。
今回、高解像度で表示したいと考えていたのは、WebViewに表示する中身です。

WebViewのメソッドに何かないか、WebViewClientやWebChromeClient、WebSettingsに何か解像度に関するメソッドがあるんじゃないかと探しました。
あるんじゃないかとは思うのですが、それらしいものが見つかりません。
WebSettingsの中にsetDefaultZoom()というメソッドがあったのですが、これはAPI Level 7から…。
できれば、Android 1.6(API Level 4)から使えて欲しいのです。

そんな中、見つけたのがWebViewのリファレンスに書かれていた「Building web pages to support different screen densities」という部分の記述。
英語はほとんど読めないのですが、「density」とか「hdpi」とかあやしい単語が盛りだくさんです。
ざっくりと雰囲気を読んでみると、どうやらWebViewに設定するのではなく、HTMLやJavaScriptで解像度を変える方法が書かれているっぽいです。
いろいろ試してみたら、どうやらmetaタグを書くだけで解像度が変わるっぽいです。

◆タグを書かなかったときの表示
default_d.png

◆metaタグを書いたときの表示
<meta name="viewport" content="target-densitydpi=high-dpi" />
high_d.png

Android端末向けのWebページに使えそうですね。
ただ、ここまで調べて気づいたのですが、これも必要なAPI Levelが5から(Android 2.0以上)っぽいです…。
Android 1.6でWebViewの解像度を上げるにはどうしたら良いんでしょうね??

とりあえず、今回も確認に使ったサンプルを置いておきます。
HighDWebView.zip
posted by t2low at 01:07| Android

2010年09月21日

[Android] カメラアプリの起動と終了

カメラアプリを作るときに困ったことのメモです。
通常起動する分には、ネット上のサンプルを見れば何とかなったのですが、
連携起動する際の設定や実装方法が分からず、結構時間がかかってしまいました。
みなさん、こういうときは何処を読むようにしているのでしょう?
英語が読めれば、結構簡単に情報は見つかるのかな?

■起動時
余所のアプリから自分のカメラアプリを起動するために設定する<intent-filter>のアクションがわかりませんでした。
ネット上に転がっているサンプルが、外部のカメラアプリを起動するときに指定するアクションが「MediaStore.ACTION_IMAGE_CAPTURE」だったので、これを指定してみたのですがダメでした。
困ったときはGoogleさんの書いたコードですね。
↓こんな風に書かれていました。

<intent-filter>
<action android:name="android.media.action.IMAGE_CAPTURE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<action android:name="android.media.action.STILL_IMAGE_CAMERA" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>

とりあえず、このまま指定しました。
連携元のアプリとしては、Twitter(公式アプリ)と、twiccaを使いました。
写真撮影機能を呼びだすと、見事に自分の作成したアプリが選べるようになっていました!
連携起動だけなら、上のIMAGE_CAPTUREのアクションだけで大丈夫っぽいですね。


■終了時
上の記述で余所のアプリから起動してもらうことはできるようになったのですが、
今度は終了時に画像を返す方法がわかりませんでした。
カメラアプリを起動するアプリの処理として、Intentの中のgetExtars()のget("data")としているサンプルが
あったので、put("data", bmp)としてみましたが、Twitterもtwiccaも正しく画像を取得してくれません。
これもGoogleさんのサンプルコードを読むことにしました。

どうやら起動時のパラメータによって、返す方法が異なるようでした。
無指定の場合は、↑で書いたように指定すれば良いようですが、
起動時に「EXTRA_OUTPUT」が指定されていた場合は、ファイル書き出しを行う必要があるみたいです。
書き出し先はEXTRA_OUTPUTで指定されるUriでした。
ContentResolverのopenOutputStream()を使って、UriからOutputStreamを取得して書き出します。
これでうまくいきました。


これらを調べるのは結構面倒だったのですが、他の開発者の方々はどのようにして調べてるんでしょう?
やっぱり英語サイトなのでしょうか。
せめて読めるくらいには英語も勉強しようかなぁ、とちょっと思ったりしました。
posted by t2low at 06:08| Android

[Android] 2つのViewを両端に配置する方法

2つのViewを画面の両端に配置したいということはよくあると思います。
テキストビューとチェックボックスとか、イメージビューとテキストビューとか。

これまでこういったときはRelativeLayoutを使うもんだとばかり思っていましたが、Googleさんのソースを眺めていたら、別の方法を見つけました。
こんな風にしても書けるんだ、と感心してしまいました。

http://android.git.kernel.org/?p=platform/packages/apps/Email.git

ここで使われているレイアウトはRelativeLayoutではなく、LinearLayoutです。
LinearLayoutは左右のどちらかに詰めて配置するためのレイアウトだと思っていましたが、この方法を使うと画面の両端に配置することができます。
やり方は簡単で、両端に配置したい2つのビューの間にViewを配置するだけ。
実際に書くと↓な感じ。

<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
>
<ImageView
android:src="@drawable/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<View
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_weight="1"
/>
<TextView
android:text="Hello"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>

ss.png
一番のポイントは、Viewにlayout_weight="1"が設定されていることだと思います。
この設定のおかげで、2つのビューの間の詰め物みたいになるのでしょう。
こんな方法があるというのもスゴいと思ったのですが、Viewをそのままタグとして使えるということにもびっくりしました。
ほんとにAndroidはまだまだ知らないことでいっぱいです。

たぶん、プロジェクトを見なくても↑の説明だけで十分だと思いますが、一応サンプルも置いておきます。
↓どうぞお使いください。
LinearLayoutTest.zip
posted by t2low at 01:25| Android

2010年09月17日

[Android] IMEのサンプル

IMEを作り始めました。
「こんな入力方法があれば、快適なんじゃないだろうか」と思いつきまして。
とりあえず、思いついた入力方法は完成したときに披露するとして、まずは動くものを作ろうと。

Androidはサンプルが豊富にあるのが良いですね。
参考にさせてもらったのは↓こちら。
英語が読めれば本家のサイトでも良かったのですけど…。

http://www.techdoctranslator.com/resources/articles/articles-index/creating-input-method

あとはSDKにサンプルとして付属している「softkey」を参考にしています。


まず、IMEを実装するにはInputMethodServiceを継承したクラスが必要なようです。
もちろんManifest.xmlにserviceタグの記述が必要です。
serviceタグの中に必要な記述は以下のとおり。

<intent-filter>
<action android:name="android.view.InputMethod" />
</intent-filter>
<meta-data android:name="android.view.im" android:resource="@xml/method" />

まだ作り始めたばかりでよくわかっていませんが、intent-filterはIMEとして呼び出されるために必要なものでしょう。
meta-dataはどうも動きからすると、AndroidがIMEとして認識するために必要なようです。
参照している@xml/methodは、softkeyサンプルと同じ内容のxmlを作って参照しています。
xml/method.xmlの中身は↓こんな感じ。

<?xml version="1.0" encoding="utf-8"?>
<input-method xmlns:android="http://schemas.android.com/apk/res/android" />

このServiceでは以下のイベントが発生します。

1. void onCreate()
2. View onCreateInputView()
3. View onCreateCandidatesView()
4. void onStartInputView(EditorInfo info, boolean restarting)
5. void onFinishInput()
6. void onDestroy()

参考にさせてもらったページによると、IMEのライフサイクルになっているらしいです。
このうち、ソフトウェアキーボード部分を表示するためには、2と3が重要そうです。
2は「入力ビュー」を返します。
既存のIMEで言えばQWERTY配列のキーが表示される部分です。
3は「候補ビュー」を返します。
変換候補を表示する部分のようです。こちらはnullを返しても良いようです。

ということで、2でButtonを1つ返すようにしてみました。
ButtonのonClickListenerでは、押されたら「TEST」とキーイベントを発行するようにしてあります。
この状態で、Android端末にインストールしてみると…。

select_input.png my_ime.png

こんな感じでIMEとして認識されました!(Imeが僕が作ったIMEです)
IME開発の第一歩ですよ。
変換候補をどうやって拾ってきたら良いかなど、よくわからん部分がまだまだありますが、とりあえず、IMEは作り始めることができました。
がんばって新しいIMEを作りたいと思います。

↓に現時点のソースコードを置いておきます。
かなり最低限のことしかやっていないので、これからIME作成に取りかかる人にはわかりやすいかと思います。
(足りない部分がたくさんあると思いますがそこは知らね)
Ime.zip

以上です。
posted by t2low at 08:20| Android

2010年08月24日

[Android] assetsのファイルを使う

今日、職場で「へぇ」と思ったので忘れないうちにメモ。
WebViewでassetsフォルダに置いた画像を見る方法です。

WebView web = (WebView) findViewById(R.id.web);
String html = "<html><head><title>Test</title></head><body><img src='star.png' /></body></html>";
web.loadDataWithBaseURL("file:///android_asset/", html, "text/html", "utf-8", null);

こんな感じで「file:///android_asset/」をベースURLにしていしてやれば、画像を読むことができるらしい。
すごいねぇ。

100824_assets.png

注意点としては、
・ベースURLの末尾は「assets」ではなく「asset」。
・ベースURLの末尾のスラッシュ(/)は必須(htmlの記述内容次第??)。
・file:のあとのスラッシュ(/)は3つ。
といったところでしょうか。

まだまだ知らないことだらけですね。
というわけで、↓サンプルです。
AssetsTest.zip
posted by t2low at 02:32| Android

2010年06月23日

[Android] b-mobileSIM 購入

b-mobileSIMを購入しました。
もちろん、Desireに挿して使うためです。

とりあえず、実際に動作するかどうかを確認したかったので、まずは30日版を買うことにしました。
6カ月版と1年版はヨドバシやアマゾンでも買えるのですが、1カ月版は通販でしか買えないようです。
b-mobileのサイトから申し込みを行いました。
申し込みから到着までは3日くらいでした。

届いたのはSIMと簡単な説明書。
説明書を読むと、どうやら開通手続きをしなければならないようです。
開通手続きには携帯電話が必要でした。
説明書をに書かれていた電話番号に携帯電話からかけます。
自動応答ガイダンスの指示どおりに手続きをします。
具体的にやることはSIMの電話番号(説明書に書かれている)をプッシュするくらいです。
5分くらいで開通するらしいですが、僕は1時間くらい放置してたので、実際に何分でつながるようになるかは分かりません。

あとはDesireに差し込んで、アクセスポイントの設定をするだけです。
アクセスポイントの設定内容も説明書に書いてあります。
説明書に書かれている内容以外で設定したのは、設定の名前くらいで、他は全部空欄のままにしておきました。
ネットワークにはすぐ繋がりました(と思います…。ちゃんと覚えてません…)。
通信速度もWillcomのどこでもWi-fiを使っていた身としては快適です。

ただ、一度Wi-fiにつないだら、SIMでの通信ができなくなりました…。
Wi-fiをオフにしても繋がる気配がありません。端末を再起動したら再接続しました。
事前にネットで調べていた通りです…。
(http://sdlab-org.blogspot.com/2010/04/htc-desire-b.html)
いろいろと考えるのがめんどうなので通信速度が落ちることには目をつぶって、常にWi-fiはオフの状態で使うことにしました。

ちょっと気になる点としては、ステータスバーの電波強度のアイコンが常に×で表示されることでしょうか。
ロック画面では「制限付きサービス」と表示されます。
limited_service.png
まぁ、これは通話はできないけど、データ通信はできるよ、という意味の制限付きなんでしょう。
電波強度のアイコンも通話に関しての電波しか表示していないものと思われます。
実際、Real Signalをインストールしたらデータ通信の電波状況は確認できましたし。
real_signal.png

現時点では概ね満足です。
使用期限が1ヶ月しかないので、期限が切れたら更新しようかなぁ、と検討しています。
今度は6ヶ月版を購入しようかなぁ。
どこでもつながることで、Desireがより素敵な端末になってしまいました。

 
posted by t2low at 02:23| Android

2010年06月14日

[Android] イベントの確認

TabActivityを自作していて、困った部分が出てきたのでイベントを確認するサンプルを作ってみました。
イベントを確認すると言っても大したことはしてなくて、「on〜」から始まるメソッドでログを吐くようにしただけです。
なぜこんなことをしたかというと、自作したTabActivityでは「onResume」や「onPause」などのActivityが切り替わる際に呼ばれるべきイベントが呼ばれなかったからです。

しばらく原因がわからなかったのですが、少し前に判明しました。
一度LocalActivityManager.startActivity()でWindowを作成した後は、もうViewが取得済みだったので、それの表示・非表示しか切り替えていなかったのです。
Viewが取得出来ていても、毎回タブを切り替える度にstartActivity()を呼ばなければいけないのですね。
勉強になりました。

一応↓下にイベントを確認した際のサンプルコードを置いておきます。
CheckEvent.zip
posted by t2low at 02:40| Android

2010年06月10日

[Android] HTC Desire が届いた。

早い、早いですよ。
6/8の2:00頃に注文したのですが、6/9の17:00頃にはもう届いてしまいました。
国内でももっと時間がかかるところがあるというのになんて早さでしょう。

注文後、googleから発送したというメールが届きました。
google checkoutを使ったためか、連絡はgoogleが行うようですね。
荷物の追跡番号というものが発行されていたのですが、最初EMSで検索しても出てきませんでした。
違う配送会社が使われているのかとも考えたのですが、数時間してからまた試したところ、今度はきちんと表示出来るようになっていました。
追跡出来るようになるのに、しばらく時間がかかるということだったのでしょうか。

届いた荷物はこんな感じです。
EMSのビニール袋に入っています。
desire1.jpg

中身を取り出すと緩衝材でくるまれたDesireが出てきました。
緩衝材を2枚使ってぐるぐる巻きにしてありました。
この程度保護してくれてあれば、まぁ、十分かなぁ、という感じです。
desire2.jpg

緩衝材を取り払うとDesireの箱が出てきました。
数カ所カドがつぶれ気味でした。丸くなってました。
箱の中には全く影響はない程度ですが。
あと、どうも封が一度破られていたようで、封がしてあったと思われる箇所がセロハンテープで止められていました。
特に不足品などはなさそうですが、何か確認でもしたんでしょうかね。
desire3.jpg

箱に収められたDesireです。薄いプラスチックでくるまれていました。
本体の下にはバッテリーが入っていました。
その他の付属品は箱の底に収められていました。
desire4.jpg

箱の中身です。Desire本体に、バッテリー。
USB接続できる二股のプラグ、そしてその先に付ける変換プラグ(どちらも日本では使えそうにありません)。
あとは、USBケーブルと、イヤホン、取扱説明書などです。
簡素ですね。
desire5.jpg


Desireを取り出してみると、画面が指紋っぽいもので少し汚れていました。
封が開いていたことといい、動作確認を行ってから発送しているということなんでしょうか。
気を取り直して、バッテリーを接続、電源投入!
ちゃんと見ていなかったのですが、一瞬T-Mobleの文字が見えました。
T-Mobileってどこの国のキャリアでしたっけ?アメリカ?


さて、とりあえず、ロケールを日本にしようとSettingを開きました。
…が、日本語が選択できません。よく探しましたがありません。
ちょっと失敗したかなー、と思いつつもネットワークに繋いで、
マーケットやらブラウザやらメーラやらをいじっていました。
画面が広くて、レスポンスも良く、とても快適です。
ただ、ときどき光学式トラックポインタ?が暴走するようで、
動かしたつもりがなくても、上下左右に動くことがありました。
この辺は慣れでしょうかねぇ。


さて、やっぱり日本語になっていないと不便です。
インターネットで検索したところ、MoreLocale2というアプリをインストールすると日本語化できるようです。
早速インストールしました。本当に簡単に日本語化できてしまいました。
ただ、アプリでロケールを変更しているのか、設定画面からはやはり日本語は選べないままでした。
まぁ、それほど困る点ではないですけども。


さてさて、今日は楽しんだだけで終わってしまいましたが、
開発で使えるようにすこしずつ準備をしていこうかと思います。
これを機にいろいろとアプリを作れたら良いなぁ。


あ、最後にDesireを購入したのは、以下のサイトです。

http://1shopmobile.com/

Google Checkout さえ登録されていれば、簡単に購入出来ました。
また、海外端末が欲しくなったら、ここで買おうかと思います。

posted by t2low at 02:42| Android