Android Support LibraryのソースコードをGrepCodeを使って確認する

Android Support LibraryのソースコードはAndroid Studioで確認することができません 例えば、android.support.v7.app.ActionBarActivityのソースコードを確認したいとしましょう。その場合、調べたいクラスをCmd+クリックすることで、対象のクラスのソースコードに自動的にジャンプできます。 しかし、サポートライブラリについてはソースコードまでは見つかりません。 ちなみにAndroid SDKのクラスであれば、SDKマネージャーでソースコードまでダウンロードしていれば確認することができます。例えばBundleクラスのソースコードは以下のように確認できます。 サポートライブラリのソースコードを確認するのは、Gitを使ってGoogleのリポジトリから拾ってくる方法もありますが、今回はWebサービスのGrepCodeを利用してみます。 GrepCodeにアクセスして、検索したいクラスを入力します。(今回の場合はandroid.support.v7.app.ActionBarActivity) すると検索結果が表示されるので、調べたいクラスのバージョンを選択します。 他のバージョンとの差異をDiffで確認できるので、バージョンアップでどこが変更されたのかを調べるのにはちょうどいいかもしれません。

AndroidのOSバージョンとコードネームとAPIの一覧表

私は未だにAndroidのOSバージョンとAPIの数字とコードネームが結びついていません。最新の5.0がAPI21で、Lolipopだというのは分かるんですけどね。 ソースコードを読んでいて、JBとかICSとか出てきて「それバージョンで言うとどこ?」と混乱したのでまとめておくことにしました。 バージョン コードネーム api 5.0.1 Lolipop 21 4.4w Android L Preview 20 4.4 KitKat 19 4.3 Jelly Bean 18 4.2.x 17 4.1.x 16 4.0.3〜4.0.4 Ice Cream Sandwich 15 4.0〜4.0.2 14 3.2 Honeycomb 13 3.1 12 3.0 11 2.3.3〜2.3.7 Gingerbread 10 2.3〜2.3.2 9 2.2 Froyo 8 2.1 Eclair 7 2,0.1 6 2.0 5 1.6 Donut 4 1.5 Capcake 3 1.1 2 1.0 1 Android Studioのデフォルトでは、API10〜21をサポートするようにプロジェクトが作成されます。2.3.3までサポートするということですね。 ちなみにOSバージョンごとのシェアはAndroid DevelopersのDashbordsで公開されています。(2.2以降のバージョンのみですが) コードネームの頭文字がAから順番につけられているので、それを押さえていれば大体どのあたりのバージョンなのか検討がつくかもしれません。

ファイル名の付け方の罠 不用意にハイフンを使わない

レイアウトXMLのファイル名、drawableに用意する画像のファイル名、自分で作ったカスタムスタイルの名前などなど。これらの名前の中にハイフンを使うとビルドが通らないことがあります。 ハイフンを使ってもビルドをかけるまでエラーと表示されなかったり、名前にハイフンが入っているせいでレイアウトプレビューがうまく表示されなかったりすることがあります。この原因がファイル名等にハイフンを使っているせいだとはなかなか気づけません。 命名規則には、例えばレイアウトXMLのファイル名に大文字が使えないというのもありますが、これはAndroid Studioがちゃんと指摘してくれるので分かりやすいです。ファイル名なら指摘してくれるのでわかりますが、例えば独自のスタイル名については指摘してくれません。 私は普段ファイル名の区切りにハイフンをよく使うので、エラーだと直接指定されないとついついハイフンを惰性で使ってしまいます。レイアウトのレンダリングプレビューがちゃんと表示されないな、なんでだろう・・・とすごい悩んでいたのですが、原因は使用しているスタイルの名前にハイフンを使っているせいでした。 Android開発で名前をつけるのには、ファイル名にかぎらずスタイル名などでもハイフンは使わないよう気をつけましょう。

ProGuardによる難読化って具体的にはどうなってるのだろう

確認方法 手順としては、ProGuardを適用していないapkファイルと、適用したapkファイルの2つを用意しました。そしてリバースエンジニアリングを行い、apkファイルからソースコードの抽出を行い確認を行いました。 ProGuard適用前 こちらがProGuard適用前のソースコードです。ほぼ自分で作ったソースコードのままで、Android Studioで作り上げたソースコードと大差ありません。 ProGuard適用後 こちらはProGuardを適用した後のソースコードです。一部の変数名やクラス名、メソッドなどがa,bといった意味のない文字列に置き換えられています。 全てが書き換わっているわけではなく、forやifなどの命令文はそのままですし、解読しようとしてできないレベルではありません。 ProGuardのお仕事 私は難読化というからには、もっと複雑な変換が行われているのだとばかり思っていましたが、意外にシンプルな難読化でした。確かに読みづらくはなっていますが、解析しようと思えばやってできないレベルではありません。 変数名やメソッド名等は、一部意味のない文字列に置き換えられているものの、処理の流れなどはそのままであるため、アルゴリズムの解析は比較的しやすそうです。 よく考えてみれば、解析不可能なほどに難読化が行われると、今度はプログラムとして動作しなくなるので本末転倒になってしまうのでしょう。そのためProGuardによる難読化は、変換をしてもプログラムの動作に影響のない範囲で難読化が行われているようです。 注意点 まずはProGuardによる難読化はあくまで気休めレベルであるということを認識しなければなりません。私も実際にこうやって中身を確認するまでは、ProGuardを適用していればソースコードの盗用などは防げるものだとばかり思っていました。 またソースコードの書き換えが行われるため、以下の様なことに注意が必要です。 別途動作確認が必要 ProGuardはメソッド名やクラス名を書き換えてしまうため、プログラムによってはProGuardを適用することにより誤動作を起こす可能性があります。 私はまだそのようなプログラムを作ったことはありませんが、クラス名やメソッド名を文字列等を使って参照するようなプログラムは動作しなくなるでしょう。そのため、ProGuardを適用したapkファイルを用いた動作確認を別途行う必要があります。これはちょっと面倒臭いですね・・・。 文字列リテラルの中身は変換されない ProGuardは文字列リテラルの中身の変換は行いません。ここを変換すると、プログラム実行時に表示される内容や動作に影響が出てしまうからです。ここは逆に変換されないということに注意が必要です。 これは、例えばソースコード中にパスワードを記述してしまうと、そのまま見えてしまうということです。まぁ、そもそもソースコード中にパスワードを平文で書くこと自体が悪手ですけれども。 難読化以外の効果 ここまで難読化について書いてきましたが、ProGuardは難読化と一緒にソースコードの最適化も行っています。 例えばapkファイルの軽量化です。これは変数名等を短い文字列に変換することも寄与しているでしょう。今回使ったapkファイルであれば、ProGuardを適用することにより、適用していないapkファイルと比較して、ファイルサイズが600kb削減されていました。 その他にも処理の最適化を行ったりするようで、基本的にはProGuardを適用した方がいいのだと思います。ただ、難読化のために適用するという観点では「適用したほうがマシだ」というレベルであって、完全なものではないということを念頭に置いたほうがいいでしょう。 むしろ余計なデバッグの手間をかけるくらいなら、最初からProGuardを使わないという選択肢もありなのかもしれません。

@Overrideってなに?

Androidアプリを作成していてよく目にする「@Override」ですが、私はこれがなんなのかよく分かりませんでした。メソッドによってついていたりついていなかったりで、いまいち基準が分からなくて気持ち悪かったですが、あまり深く考えずにサンプルコードをコピペしていました。 結論から言うと、この@Overrideはアノテーションの一種です。別に書かなくてもプログラムは動きます。 ではなぜ書いているのかというと、IDEやビルドツールに対して、「このメソッドはオーバーライドしたメソッドだぞ」と伝えるために書いているのです。 例えばAndroidでよく出てくるonStart()というメソッドをオーバーライドする際に、間違えてonStrat()と打ち間違えていたとします。仮に@Overrideのアノテーションをつけていなかったら、打ち間違えたメソッドでもエラーなくビルドできてしまいます。そしてアプリを実行すると・・・「想定通りに動かない。なんでだ!」となってしまいます。 プログラムを書いている本人は、メソッドをオーバーライドしているつもりで書いていても、それはIDEやビルドツールには分かりません。本人はonStart()をオーバーライドしているつもりでも、ビルドツールは独自のonStrat()メソッドだと解釈して処理してしまいます。@Overrideはそんなプログラマーの気持ちを彼らに伝え、しょうもないミスで時間を浪費しないようにするためのものなのです。 ちなみにアノテーションには、@Override以外にもいろんな種類があります。Java標準のアノテーションからはじまり、ライブラリ特有で利用するものもあります(Junit4で使う@Testなど)。ソースコードを簡略化するために使われたりもしています。