KLab若手エンジニアの これなぁに?

KLab株式会社の若手エンジニアによる技術ブログです。phpやRubyなどの汎用LLやJavaScript/actionScript等のクライアントサイドの内容、MySQL等のデータベース、その他フレームワークまで幅広く面白い情報を発信します。

2011年05月

Android 2.3 Only Hacks 書評 #2

このblogには久々の登場となります、nakazawa-k(@muo_jp)です。 最近はAndroid方面で変な電波を飛ばしたりしてます。ちなみに1日の自ツイート数が100を超えた日に「なんかもう帰れないとこまで来たのかな」と思った程度の真人間()です。 さて、今回はレビュー(※1)を行ったご縁で献本を頂きました「Android 2.3 Only Hacks」の書評をかいてみます。といっても内容についてはきっと他の方が書いてくださる(maruyama-rさんも書いてくれてる)ので、私は「どういう人が、どういう風にこの本を読んで、読んだその次はこうしていくといいんじゃないかなー」という、なかなか押し付けがましいエントリを書いてみます。あんまり書評じゃない気がしますね、気にしないようにしましょう。 その前にこの本が他の本から飛び抜けているポイントをひとつ挙げてみます。 ・表紙がいい。ジンジャーブレッドマンの癒しっぷりはとても良い。 通常Android本といえばカバーが緑色でなんとなくドロイド君な感じのするものが多かったりします。これはAndroidのバージョンアップ頻度を考えると結構理にかなっていて、バージョン依存のものを紙媒体で出すとすぐに風化して賞味期限が大変短くなってしまう、という問題への対処と考えられます。けどこの本は「2.3で何が変わったか、何が出来るか」を解説するものなので、そんなこと気にせずアグレッシブにやった感がすがすがしくてとても好感を持てます(他の本をdisってるわけでなく、ただただ仕方ないということです)。 さて。 どういう人のための本か 冒頭にも書かれているように、この本は「Android自体に関する知識や開発経験は既にある程度持っているけれど最近のSDKを追いかけてはいない。何が出来るのか気になっているけどまとまって勉強する時間を取るのは大変だし日本語ドキュメントはあちこちに散逸してるしあばばばば」な方向けかな、と思います。記載されている情報の多くは既に(著者の方々も含め)いくつかのblogにて日本語情報として発信されているものでありますし、それこそ本書でターゲットとしているSDK(2.3系)の初期リリースからは半年近くの時間が経っています。それでも書籍としてまとまって出版されることには参照性と学習の面で多くの意味があるのだと、私は思います。「最近Androidから離れてたけど、なんか面白い機能追加されてるみたいだしこの機に勉強してみよう」なんてのも素敵ですね! この本の読み方 1. ざっと技術の流れを概観する。 OS/プラットフォームとして完成度が高まってきているAndroidにおいて、なぜこれらのAPIがサポートされたか、ということを考えながらアップデート全体を俯瞰してみるのは有用だと感じました。APIは無駄に追加されているわけでなく、何かしらデベロッパによる要求やGoogle(またはその他OHA参加者)が「こういう風に使って欲しい」という希望を持って追加されているものです。それをどのように解釈してアプリケーションに盛り込むか、というのはもちろんデベロッパそれぞれだと思いますが、ある時期にまとめて投入された新機能(とりわけ未完成なのになぜか先行投入されたOBBなど)を見て「これらのAPIを使える端末が普通に溢れてる未来(または現在)で、これらを活かしてどんなアプリやサービスを書くとユーザはもっと便利になり、嬉しくなるんだろう」と考えてみるだけでもなかなかワクワクします。 2. 機能を実際に利用する上でのヒントを本文から見つけ出す。 本書の各章を書かれた方々は、新SDKがリリースされてワクワクしながらドキュメントを読み、サンプルを読んだり動かしたりし、そして時にはうまく動かないその理由をAndroidのソースコードまで降りて調べてきて本書の執筆に至っています。速報的にその一部始終をtwitterやblogで発信されている方も多く居られますが、それらが書籍の中の1章として再構成されたことで「このAPIを使ってハマるところ」といった情報も全体にうまく織り込まれているように感じました。実際にAPIを使ってアプリを書いてみてなぜかうまくいかずハマる、という際に本書を開いてみるとヒントになるところがあるのではないかなぁ、と思うのですが今のところ実体験はしていないのであくまで推測ですはい。 3. ソースにアクセスして動かしてみたり読んだりする。 本書の価値の1/3ぐらいは、サポートサイトにて公開されるソースコード群にあるかな、と感じました。例えばBluetoothの項でInsecure通信(事前のペアリング無しに非暗号化通信を行うことが出来る)がサポートされたこととそのAPIに関する記載は行われていますが、書かれてるのは「従来のAPIのここを変えればInsecure通信出来るよ」ということだけなので、ぶっちゃけ「俺は以前にAndroidでBluetooth通信やってみたことあるぜ」という方以外にはスパルタンな記述です。けれど、サポートサイトにある実際のソースコードを読んで動かしてみることで、そこで使われているプログラミング手法を参考にしたり、関連するAPIの名前を手がかりとして更にドキュメントの山をひっくり返したり、と「実践してみて更に興味を持つ...」という好循環が生まれるのだと思います。なので、是非サポートサイトにアクセスしてソースをダウンロードしてみましょう。 ・この本を読んだ次は…! →デ部関連のイベントやメーリングリストに参加しましょう ご覧の通り、OSバージョンが上がると多くの新機能がサポートされます。そして、当然これからも同じくOSバージョンは上がっていきます。デベロッパ負担を減らすためにメジャーバージョンアップ間隔を広げる方向にはありますが、結果的にマイナーバージョン(2.3.2→2.3.3)ですらAPIレベル(Androidとして利用出来るAPIセットを定めた群)が変わるという状況になっていますし、タブレット向けのAndroid 3.xとそれ以外向けの2.xという2系統が当面は継続開発されており、基本的に3.xの新バージョンでの機能が2.xにバックポートされるという形を取るにしても既に状況は相当カオスです。 ということでデ部への参加をオススメします。新機能に敏感な方々が活発に情報交換を行っている、いいコミュニケーションの場と機能していると思います。関連イベントの開催地は多くが東京で、それ以外の地方のかたがちょくちょくリアル参加するのは難しいかと思いますが、大体Ustreamなどのライブ配信が行われるので、遠隔地からもだいぶ参加し易いと思います。 以上、書評といっていいのかよく分からない文章となりましたが参考頂けると幸いです。想定読者にマッチする方は買って損無いと思いますが、いくら本読んでもやっぱりAndroid系はアプリ(仕事でもプライベートでも)でアウトプットしてなんぼですよね(と自戒で締めくくる)。 ---- このblogエントリは、レビュー時の副産物としてEvernote内になぜか発生していた「全体的に非常によく調査した上で、更に執筆者自らがサンプル実装を行い動作を確認したコード、手法が掲載されており、旧バージョンのAndroidでの開発を行なってきた開発者が最新SDKを利用することでどのような利便性を得られるか、新たな機能を利用出来るか、という点がよく網羅されている。また、Gingerbread/Honeycombにて不完全ながらも提供されているAPI群を知ることで、Android自体が今後どのような進化の方向性を持っているか、という大枠での技術動向を掴むことも出来る。 惜しい点としては、著者が複数人であるためバージョン対応にばらつきが見られるところである。例えば、APIレベル11での追加サポート内容について具体的に言及している章とそうでないものが混在しており、本書が全体としてどのバージョンについてカバーしているか、という点が不明瞭となっている。これはいみじくもまえがきに記載されているように、本書執筆中にも複数のSDKがバージョンアップが行われたためであり、全ての品質を揃えることを優先するといつまで経っても出版出来ない、という事情を鑑みるとやむを得ないことと言える(特に想定読者は必ずしも最新SDKを追いかけてはいない開発者となっているため、完全な最新版対応へのコミットが大きく読者の利益につながるわけでもない)。 デ部関連イベントでの発表内容を追いかけることでその後の最新事情へ追随することは可能であるため、最新SDK動向への興味を強く持たれた読者においてはメーリングリストやイベントへの参加、著者blogの購読などで情報を継続的にアップデートされたい。」というメモをもとに書かれました。かための文章がお好みの方はこちらをどうぞ。 ※1: 押しかけレビューアで、最終確認用の版を頂いてそこに結構な量のtypo指摘を投げつけるという暴挙を行いました。多分編集さんは泣いてたと思います(面識ありませんが)

Android2.3で何が変わったんだろう?

はじめまして。若手ブログ初投稿のmaruyama-rです(twitter:@h13i32maru) 「Android2.3 - Gingerbreadをさくさく使うためのサンプルとテクニック - 」を本書レビュワーのnakazawa-kさんに貸していただいたので、僕が気になったところをピックアップして感想なんかを書いてみます。 まずこの本はAndroid2.3で追加/改善された機能の話なので今からAndroidを勉強しようとしている人向けというよりはある程度開発してきてAndroid2.3でどう変わったのかなーと気になってる人向けです。 各章は「機能の概要」と「実際のコード」で構成されています。なのでどんな機能が追加されたのかをさっと知りたい人は概要だけを、詳しく読んでみたい方はコードも合わせて読んでみるというのが良いと思います。 (僕は機能の概要だけをさらっと読んだ感じです) それでは僕が気になったところを書いていきます。

NFC

Android2.3でNFCに対応しました。NFCとはNear Field Communicationの略で近距離無線通信の規格だそうです(僕はこの本を読むまでぜんぜん知りませんでした)Android2.3ではこのNFCの規格に対応しており、NFCに対応した非接触ICカードから情報を受信したり送信したりできます。 NFCではNDEF(NFC Data Exchange Format)というNFCで使用するデータフォーマットが定義されています。このNDEFにはテキストを保持するのやURI保持するものなどいろいろあるようですが、それを解析するためのクラスは用意されていないようです。。ただAndroidSDK付属のNFCDemoにはそのサンプル実装があるので参考にすることができます。 注意としてはFeliCaはこのNDEFを使っていないので独自の実装が必要になるようです。 このNFCの章にのってるサンプルコードを理解するにはNFCの仕様をある程度しってないと難しいのかなという印象です(´・ω・`)でもNFC楽しそうですね!端末をさっとかざすだけでプロフィール交換やゲームのアイテム交換とかできそうですね!Suicaから乗車履歴をとってソーシャルゲーム等の進行に影響させたりもできるかも。

DownloadManager

大きなファイルをHTTP経由でダウンロードする場合に2.3から追加されたDownloadManagerを使うとすごく便利そうです。2.2以前なら自前でDefaultHttpClientなどを使って実装が必要だったことがDownloadManagerにお任せでできるようです。 ただ、中断やレジュームなどの処理方法が書かれていないのが残念です。developer.android.comのDownloadManagerを見ても中断やレジュームについては書かれていないようなので、まだ実装されていないのかも知れないです。。

Strict Mode

Strict Modeを使うとANR(Application Not Responding)の発生を開発者が検知しやすくなります。ANRとはユーザの入力に対し、アプリが何の応答もしないまま一定時間すぎてしまった状態をします。Androidでは「ユーザからの入力イベントの応答に5秒以上かかった場合」などに発生します。 Strict Modeを有効にするとANRが発生しそうな処理を実行するとエラーのダイアログやログを出力してアプリケーションを終了させることができます。これによりどこでANRが発生しそうなのかを開発者が知ることができます。 Strict ModeにはANRの検知対象を設定するためいくつかのポリシーがあります。ディスクの読み書きやネットワークアクセスなど開発者が自由にポリシーを設定することができます。 Strict Modeを有効にする方法は任意のActivityで以下のようなコードを実行します。このコード以降でStrict Modeが有効になるのでなるべく早い段階で有効にするほうが良いようです。

public void onCreate(Bundle savedInstanceState) {
  StricMode.enableDefaults();
super.onCreate(savedInstanceState);
}
それと注釈にあった「Honeycombからはメインスレッドでのネットワーク処理の実装はFatalとなり、コンパイル時に検知できるようになる予定です。」というのが凄く驚きです!思い切ったことをやるんだなと思いつつ、どうやってメインスレッドからの実行なのか判定してるのかも興味があるところです。 ユーザへ良いレスポンスを返すことにプログラム的に支援をしたり制限を加えることでAndroidアプリ全体の質を向上させることができると思うので、このStrict Modeは是非つかっていきたいですね。前述のDownloadManager、Service、AsyncTask、Thread/HandlerなどUIスレッド以外での処理方法がいくつも提供されているのでこれらを使えばそんなに難しくなくできると思います。

その他

  • OBB(Opaque Binary Blob)による暗号化ディスクイメージ
  • Native ActivityによるC/C++だけでのAndroidアプリ開発
  • Dalvik RuntimeのJIT改善とJRE6対応
  • Media Provider / Speech Recognitionによる音声のテキスト化
など面白い話がたくさん載っているのでAndroid2.3はどんな風に変わったのか気になっている方は是非読んでみることをお勧めします これを読むと2.3な端末がほしくなりますね(・∀・) おわり

CSSトラブルシューティング:追加したルールが適用されない

季節の変わり目に弱いosuga-hです。 お急ぎの方はクイズをすっ飛ばして、続きからお読みください。

突然ですがクイズです。

以下のHTMLとCSSで指定されているdivはマウスオーバで何色になるでしょう? ※答えは緑か赤かのどちらかです。

Q1. まずはジャブから

<style type="text/css">
.sample:hover .s1 div { background-color:#0F0}
.sample:hover .s1 div { background-color:#F00}
</style>
<div class="sample">
    <div class="s1">
        <div>このdiv</div>
    </div>
</div>
このdiv

Q2. idを付けてみる

<style type="text/css">
.sample:hover .s2 div#sample2 { background-color:#0F0}
.sample:hover .s2 div { background-color:#F00}
</style>
<div class="sample">
    <div class="s2">
        <div id="sample2">このdiv</div>
    </div>
</div>
このdiv

Q3. idとクラス

<style type="text/css">
.sample:hover .s3 div#sample3 { background-color:#0F0}
.sample:hover .s3 div.sample3 { background-color:#F00}
</style>
<div class="sample">
    <div class="s3">
        <div id="sample3" class="sample3">このdiv</div>
    </div>
</div>
このdiv

Q4. 親を持たせてみる

<style type="text/css">
.sample:hover .s4 #outer4 div.sample4 { background-color:#0F0}
.sample:hover .s4 div     #sample4    { background-color:#F00}
</style>
<div class="sample">
    <div class="s4">
        <div id="outer4">
            <div id="sample4" class="sample4">このdiv</div>
        </div>
    </div>
</div>
このdiv

Q5. 最後の問題

<style type="text/css">
.sample:hover .s5 #outer5 div.sample5 { background-color:#0F0}
.sample:hover .s5 div#sample5.sample5 { background-color:#F00}
</style>
<div class="sample">
    <div class="s5">
        <div id="outer5">
            <div id="sample5" class="sample5">このdiv</div>
        </div>
    </div>
</div>
このdiv
どうですか?全部わかりましたか? ここからが本題になります。

CSSルールの優先順位 詳細度(specificity)とは

CSSを書いていて、「あれ?追加したCSSが適用されないんだけど?」ということありませんか? そんな時は、十中八九、「詳細度」が既存のルールに負けています。※ブラウザのバグってこともあるけど・・・ ここからは詳細度とは何か?どうやって決まるのかを解説します。 詳細度に関してはの詳しい説明はW3Cのサイトでも確認できます。 Selectors Level 3 - 9. Calculating a selector's specificity

詳細度の求め方

 CSSルールの優先順位は単純にあとから定義してあれば有効というわけではなく、セレクタを定められたアルゴリズムで評価しそのスコアが高いものが優先されます。 このスコアの事を「詳細度(specificity)」と言います。ある要素に2つ以上のCSSセレクタがヒットしている時、詳細度が比較されるわけです。  詳細度の比較にはセレクタに含まれるid、クラス、html要素の数が使われ、それ以外のセレクタ(*など)は考慮されません。 簡単に詳細度の比較の様子を示します。
  1. セレクタに指定されているid、クラス、html要素の数をそれぞれ数える
  2. 指定されているidの数が多い方が強い
    ↓引き分けたら
  3. 指定されているクラスの数が多い方が強い
    ↓引き分けたら
  4. 指定されている要素数の多い方が強い
    ↓引き分けたら
  5. 後から定義された方が勝つ

style属性と!important

詳細度以外に優先順位に関わる要素としてhtml要素のstyle属性に記述されているスタイルと、!important指定されているスタイルがあります。 これらも含めての優先順位は以下のように決定されます。
  1. !important
  2. style属性
  3. 詳細度が一番高いCSSルール

実験してみよう!

詳細度の理解を深めるために色々実験してみましょう。

id x1個 vs クラス x10個

idの数が優先的に比較されるならどんなにクラスが大量に指定してあってもidで指定してあるルールが勝つはず。
<style type="text/css">
.sample:hover .t0 #test0 { background-color:#0F0}
.sample:hover .t0 .t00 .t01 .t02 .t03 .t04 .t05 .t06 .t07 .t08 .t09 { background-color:#F00}
</style>
<div class="sample">
    <div class="t0">
        <div class="t00">
            <div class="t01">
                <div class="t02">
                    <div class="t03">
                        <div class="t04">
                            <div class="t05">
                                <div class="t06">
                                    <div class="t07">
                                        <div class="t08">
                                            <div id="test0" class="t09">このdiv</div>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
このdiv

style属性に!importantが書いてあったら誰も勝てない

style属性よりCSSルールで!important指定してある方が強いわけですが、style属性で定義されているスタイルに!importantを指定したらいかなる方法でも上書き出来ないはず。
<style type="text/css">
.sample:hover .t1 #test1 { background-color:#0F0;}
.sample:hover .t1 .t10 .t11 { background-color:#F00 !important}
</style>
<div class="sample">
    <div class="t1">
        <div class="t10">
            <div id="test1" class="t11" style="background-color:#00F !important">このdiv</div>
        </div>
    </div>
</div>
このdiv
マウスオーバしても色を変えられない。

詳細度を上げたかったら

詳細度の関係でセレクタを増やさなければいけないとき、いろんな方法で詳細度を上げる方法がありますが、私はだいたい以下のようなルールでセレクタを調整しています。
  • #target
    ↓とりあえず要素名を追加
  • div#target
    ↓親があれば
  • div div#target
    ↓idの付いている親がすでに存在するなら
  • #parent #target
    ↓どうにもならない場合の最終手段
  • #target { width : 100px !important }
!importantを使わなければいけないようなケースではすでにCSSに無理が来ている可能性が高いのでリファクタリングを考えた方がいいでしょう。

まとめ

要素にルールを適用するときセレクタに出現するid、クラス、要素数を用いて詳細度が比較され、一番高い詳細度のルールが適用されます。 CSSを書いていて、ルールが思うように適用されないときは、その要素に適用されているルールを調べ、それらより高い詳細度になるようにセレクタを調整しましょう。
 KLab若手エンジニアブログのフッター