確認方法 手順としては、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を使わないという選択肢もありなのかもしれません。
ださいデザインからの脱却 1分間タイマーは、最初のバージョンでは文字とボタンだけが表示されている、非常にダサいアプリでした。それに比べると現在の見た目はだいぶましになったように思います。あくまで最初の頃よりはましになったなというだけで、カッコイイ見た目にするにはどうすればいいのかよく分かりません。
ただ、見た目をかっこ良くするという観点からのアプローチは難しくとも、使いやすくするという観点からのアプローチであれば、少し突破口が見えるような気がします。私がSmashing Android UI レスポンシブUIとデザインパターンという本を読んで、1分間タイマーに加えた変更を例にしてみましょう。
Smashing Android UI レスポンシブUIとデザインパターン 開始ボタンを押しやすくする 1分間タイマーを自分で使っていてとても不便だったのが、タイマーの開始ボタンが押しづらいことでした。
1分間タイマーの当初のバージョンでは、デフォルトのButtonを開始ボタンとして利用していました。私はタイマーを開始させたらすぐに紙に向かって文字を書き出していきたいため、アプリの開始ボタンは横目で見ながら押すような感じで使っていました。しかし以前のバージョンの四角い小さなボタンでは、開始させたつもりが押せていないということがよくあってテンポが悪かったのです。
ボタンを大きくすれば使い勝手はかなり向上します。
残り時間の表示方法 ボタンの巨大化にともなって、残り秒数の表現方法も変えることにしました。開始ボタンを円形にしたので、その周りにバーのような感じで残り秒数が分かればスマートかなと考えました。
以前は単に文字で残り秒数を表示していました。しかし自分で使っていて、あと何秒残っているかを文字で読み取ることはいままで一度もありませんでした。そもそも音声による通知もあるので、残り秒数を文字で把握する必要性はありません。
円形のバーであれば視覚的に横目であとどれくらい残っているかが分かるので、文字で表示されるよりもマシだと思います。
ただ、このバーの動きがカクカクしているのが残念なところです。スムーズに動くように見せることができれば、見た目もよくなるのですが、実装方法が分かりませんでした。いずれやり方を調べて実装できたらいいなぁと思っています。
アプリ終了時の確認ダイアログをなくした 以前のバージョンでは、バックボタンを押した時に「終了しますか?」という確認ダイアログを表示していました。この終了するかどうか確認をとるアプリは、世の中にまだまだ多く存在しています。
みなさんは、アプリを使っていて終了時に確認ダイアログが出ることについてどう考えていますか?
「そんな確認はいらないんでさっさと終了しろよ」派でしょうか、「わざわざ確認してくれて親切やね、ありがとう」派でしょうか。
Smashing Android UI レスポンシブUIとデザインパターンでは、この終了時に確認ダイアログを出すのは、多くの場合開発者の都合によってつけられているものであると断じていました。
確認ダイアログは悪である 終了時に限らず、何らかの操作を行う際に確認ダイアログを表示するのは、取り返しの付かないことを実行する場合にユーザーに責任を転嫁させるため、開発者の都合で使われている悪しきものだとバッサリでした。
確認ダイアログを出したところでユーザーがちゃんと確認するかどうかは分かりません。操作ミスを恐れて確認ダイアログを表示させるという考え方もあるかもしれませんが、そのダイアログのボタンを操作ミスしないとは言い切れないはずです。
そこで確認ダイアログを使うくらいなら、操作を実行した後にそれを取り消すための手段をユーザーに提供することこそが、真のユーザーフレンドリーであるとこの本には書いてありました。ごもっともだと思いました。
終了時の確認で言えば、一度終了してしまうと起動するのに膨大な時間がかかってしまうため、操作ミスによる終了を防止する意味で出すというのはありかもしれません。起動するのに1分かかるゲームアプリで、やっと起動したと思った時に手が滑ってバックボタンを押してしまった。そういう場合であれば、確認ダイアログを表示する方が親切かもしれません。
ですが、その確認ダイアログは必要なのかと自問することが大切です。終了前の操作状態を復元することで対処できないか、いつ終了されてもデータが保存されるように作ればすむ話ではないか。そう考えることで使い勝手が向上していくのです。
アプリのデザインは難しい デザインといえば見た目の話だけだと思っていましたが、使い勝手に関わるすべてのものがデザインです。アプリの開発と一口に言っても、プログラムのことだけではなく、使い勝手のことについても考えなければなりません。実際にやってみると奥が深いなぁとつくづく思います。
今まで「デザイン」というと見た目をカッコよくすることだと思っていましたが、考えることはそれだけではないのだということが分かりました。見た目をカッコよくするのは難しくても、使いやすくすることであれば考えれば何とかなりそうです。
そんな見た目がおしゃれなデザインの話より、使い勝手を重視したデザインの話がいっぱいなSmashing Android UI レスポンシブUIとデザインパターン。読んでいるといろんな発見があると思います。
Smashing Android UI レスポンシブUIとデザインパターン
Android Studio 0.8.10がCanary Channelでリリースされています。このアップデートにはバグフィクス以外に、新しい機能の実装が含まれています。
Memory Monitor Memory Monitorが新たに実装されました。アプリのメモリ使用量をグラフでリアルタイムに確認することができます。なかなか便利です。
とりあえず使ってみましたが、カジュアルにメモリ使用量の確認ができるのは便利なのではないでしょうか。
ただ現状ではMemory Monitorのウィンドウサイズの変更がうまくできずに非常に邪魔臭い感じです。実用できるようになるのはもうちょっと先かなぁという感じです。
Inspect Code Analyze > Inspect Codeを実行することにより、コードチェックを行ってくれます。
String Bufferではなく、String Builder使えと指摘されました。その他にも詳しく教えてくれるみたいで、勉強のためのヒントがいっぱいですね。ありがたやありがたや。
外部ツールで変更を行った場合にダイアログで表示 Lintの変更を確認するのに、Android Studio 0.5.9で同じプロジェクトを開いたら、こんなウィンドウが出てきました。
こんな感じで、「なんかしらんけどファイル書き換わってんで? 再読込する?」と聞いてくれるようになったようです。(0.5.9で開いた後に「やっちまった」と思いましたが、この機能のおかげで助かりました)
その他いろいろアップデートあり その他にも、Lintがパワーアップしていたり、ビルドエラーをハイパーリンクで修正できるようになったケースが追加されたり、バグ修正があったりと、いろんな機能が追加されたようです。
Lintについては、私はその存在を無視していたこともあって、以前と比較してどう変わっているのかよく分かりませんでした。ただ、今回改めて見てみると、いろいろと賢くなっているような気がします(黄色いメッセージがやたらと出てこなくなっている気がしましたが気のせいかもしれません)。
今回のアップデートはCanary Channelのみのようなので、先んじて試したい方はUpdate Channelを変更してみてください。
詳しくはリリースノートを参照してください。
アプリでデータベースを利用する場合、動作確認のためにその中身を確認したい時があります。
データベースへの書き込みを行ってみたものの、ちゃんと保存されているのか確認したい・・・よくあると思います。そんな場合に、adb shellを利用します。
adb shell Androidアプリを開発するなら簡単なadbコマンドは知っておいたほうがいいと思います。ちなみにadb shellで端末やエミュレータにアクセスする手順は必ずしも以下のとおりでなくてもいいです。
まずはAndroid Studioからエミュレータを起動します。起動したらAndroid StudioのTerminalツールウィンドウを開きます。
adb shellと入力すると、端末にログインできます。
データベースは特別な指定をしていない限り、/data/data/パッケージ名/databases/データベースファイル名に作成されています。
この例の場合は/data/data/jp.gcreate.sample.sampledatabase.app/databases/Sample.dbとなっています。
これがSQLiteのデータベースファイルになるので、ローカルにコピーしてツールを使って確認するなりしましょう。今回は中身を確認するだけなので、そのままターミナルからsqlite3コマンドを使ってみます。
sqlite3コマンド sqlite3 データベースファイル名でSQLiteコマンドが実行されます。
このモードではSQLを使っていろいろできます。私が最初戸惑ったのはこんなかんじです。
基本的に全てSQL文であると判断される エンターでコマンドが実行されるわけではない SQL文は最後に`;`つけない限り改行だと判断される SQLiteのシステムコマンドを使いたい場合は最初にドットをつける とりあえず以下のコマンドを知っていればなんとかなると思います。
`.help`コマンドでヘルプが見れます。 `.exit`コマンドで脱出できます。 `.schema`コマンドで、データベースファイル内のテーブル構造なんかが確認できます。 `.tables`コマンドで、データベースファイル内にどんなテーブルがあるか確認できます。 `SELECT * from テーブル名;`で、テーブル内のデータを確認できます。` 実際に実行してみると以下の様な感じで確認できます。
SQLite version 3.7.11 2012-03-20 11:35:50 Enter ".help" for instructions Enter SQL statements terminated with a ";" sqlite> .schema CREATE TABLE Sample(_id integer primary key autoincrement , InputText text not null , InputDate text not null ); CREATE TABLE android_metadata (locale TEXT); sqlite> .tables Sample android_metadata sqlite> SELECT * from Sample; 1|abc|2014/09/10 12:42:22 2|welcome to JAPAN!|2014/09/10 12:42:40 3|this is test|2014/09/10 12:42:50 4|aaa|2014/09/10 12:43:04 sqlite> 私はドットインストールでSQLiteを勉強しました。AndroidのSQLiteは簡易版なので、使えないプロパティとかもあったりしますが、基本的なところはこれでなんとかなると思います。
実機の場合はうまくいかない ちなみにこの方法は、実機では使えない手段です。データのパーミッションの関係でファイルを取得することもできず、そもそもsqlite3コマンドが利用できない場合があるからです。
実機をルート化しているとか、デバッグ用のアプリ(AndroidManifest.xmlのdebuggableがtrueになっている)であるとかなら何とかなりますが、基本的にこの方法はエミュレータを前提とした話です。
Androidアプリを作成していてよく目にする「@Override」ですが、私はこれがなんなのかよく分かりませんでした。メソッドによってついていたりついていなかったりで、いまいち基準が分からなくて気持ち悪かったですが、あまり深く考えずにサンプルコードをコピペしていました。
結論から言うと、この@Overrideはアノテーションの一種です。別に書かなくてもプログラムは動きます。
ではなぜ書いているのかというと、IDEやビルドツールに対して、「このメソッドはオーバーライドしたメソッドだぞ」と伝えるために書いているのです。
例えばAndroidでよく出てくるonStart()というメソッドをオーバーライドする際に、間違えてonStrat()と打ち間違えていたとします。仮に@Overrideのアノテーションをつけていなかったら、打ち間違えたメソッドでもエラーなくビルドできてしまいます。そしてアプリを実行すると・・・「想定通りに動かない。なんでだ!」となってしまいます。
プログラムを書いている本人は、メソッドをオーバーライドしているつもりで書いていても、それはIDEやビルドツールには分かりません。本人はonStart()をオーバーライドしているつもりでも、ビルドツールは独自のonStrat()メソッドだと解釈して処理してしまいます。@Overrideはそんなプログラマーの気持ちを彼らに伝え、しょうもないミスで時間を浪費しないようにするためのものなのです。
ちなみにアノテーションには、@Override以外にもいろんな種類があります。Java標準のアノテーションからはじまり、ライブラリ特有で利用するものもあります(Junit4で使う@Testなど)。ソースコードを簡略化するために使われたりもしています。
Android Studioを使い始めた頃、ものすごく困ったことがありました。(今も少し困ることはありますが・・・)
それは、書籍やWebでの情報はその多くがEclipse(ADT)の使用を前提にしているということです。特にAndroidアプリ開発を初めて間もない頃は、これが致命的なほどに効いてきます。
アプリをどうやって作っていくのかも分からない最初の頃は、どんなファイルをどういう手順で作っていくのかサッパリ分かりません。どこにどんなファイルがあって、アプリを動かすには何が必要なのか。書籍などに書いてある手順通りにやらないと、上手く動かなかった時に何が原因なのか自分で判断できません。
Android StudioとEclipseに大きな差異がなければ、本に書いてあることをそのまま読みかえれば済む話ですが、残念なことに両者はプロジェクトのディレクトリ構成が違います。使われている用語が同じ意味でないこともあります(プロジェクトとかモジュールの意味するところが違う)。対応している機能も異なります。知識が乏しいうちは、どこをどう読み替えればいいのかすら分かりません。
「この本に書いてあるこの手順は、Android Studioだとどうやればいいんだろう」とわからないことばかりでした。そのやり方をネットで調べようとしても、情報が少ないので解決策に辿り着けることは稀でした(最近は情報増えてきたのでそうでもないですが)。
手探りで似たような作業をしていると、最初は動いていたアプリが動かなくなったりしてよく困ったものです。アプリがなんかおかしくなったら、プロジェクトを1度削除して1から作りなおしたりしていました。
プログラミングしている時間より、明らかにAndroid Studioと格闘している時間が長く、勉強がさっぱり捗りませんでした。素直にEclipseを使うしかないのかと迷ったこともありましたが、Android Studioの便利な部分が捨てきれず、そのまま使い続けて今に至ります。
アプリ内で利用する文字列は、直接文字列を書き込む方法と、リソースファイルを参照する方法と2種類あります。基本的にはリソースファイルを参照する方法が推奨されます。
それはなぜかというと、主に多言語対応を簡単に行うためです。そのためにわざわざstrings.xmlへ文字列を書き出します。
Android Studio 0.8.8からTranslation Editorが追加され、この多言語対応が比較的簡単に行えるようになりました。といっても、まだ開発中の機能のため、操作性に難があります(執筆時利用バージョン0.8.9)。エクセルみたいな感じで編集できると便利なんだけどなぁ・・・と使っていて思いました。
具体的にはどうやっているか ディレクトリ例
└app ├res ├values ←デフォルトで利用されるリソース ├values-ja ←日本語環境で利用されるリソース ├values-en ←英語環境で利用されるリソース : こんな感じでディレクトリを作成してそれぞれのリソースファイルを用意します。
日本語環境で利用していれば、values-jaに用意されているstrings.xmlの中身が使用されます。英語環境ならvalues-enのもの、それ以外の環境ならvaluesのものが適用されます。
多言語に対応できるのは何もstrings.xmlだけに限りません。文字を書き込んだ画像の多言語対応のために、drawableを同じように用意してやることもできます。
ソースコードから出力する文字列はどうするのか ここは私の疑問なんですよね・・・。
とりあえずプログラムで端末のデフォルトロケールを取得して振り分ける処理をしてごまかしました。
if(Locale.getDefault().equals(Locale.JAPAN)){ //日本語の場合の文字列 }else{ //それ以外の場合の文字列 } 後から修正が大変になる駄目なパターンだと思いつつ、間に合わせで処理しました。
私がこうやって処理した部分は年月を表示する部分でした。例えば2014年9月と出力する部分です。日本語以外の環境で日本語が出てくるのはおかしいので振り分けてみました。
そもそもソースコードから直接文字列を出力するような実装が間違っているのかもしれません。一番いいのは2014と年と9と月とそれぞれ分割してViewで表示するようにしてやるのがいいのかもしれませんね。
ただそれだけでは対応できないところもあると思うので、ベストプラクティスが何なのか知りたいところです。
Android StudioでGitを利用したバージョン管理ができます。Git以外にもGitHubやSubversionなども使えるのですが、私はGitを使っているのでGitで説明します。
ちなみに私のGit力はGUIでしか管理できないレベルなので、コマンドで管理するのはどうするのかは聞かないでください・・・。これまでずっとSourceTreeでしかGit触ったことがないのです。
リポジトリの作成の仕方 まずはAndroid StudioでGitのリポジトリを作成する方法です。今回はSampleGitというプロジェクトを例に説明します。
メニューのVCS > Inport into Version Control > Create Git Repositoryを選択します。
そうすると、リポジトリを作成する場所を聞いてくるのでプロジェクトルートを選択します。
これでGitリポジトリが作成されます。
Gitリポジトリが作成されると、Android Studioの下部にChangesという項目が新たに増えます。このタブでコミットしたり、Gitのログを確認したりといった作業を行えます。
また、リポジトリを作成したことによりプロジェクトウィンドウ等に表示されるファイル名の色が変わります。色の意味はこんな感じです。
赤色:Gitで管理されていないファイル 緑色:新規に作成されたファイル(まだコミットされていないファイル) 青色:コミット後に変更があったファイル 白色:コミットされたファイル(もしくは.gitignoreによってGit管理下から除外されているファイル) リポジトリ作成直後はほとんどのファイル名が赤色になっていると思うので、まずはGit管理下においてやる必要があります。
ファイルをGit管理下に追加する 下部にあるChangesツールウィンドウを開くと、Unversioning Filesという部分に、赤色で表示されているファイルの一覧がずらっと並んでいます。
これらのファイルを右クリック→Add to VCS(もしくはcmd+option+a)でGit管理下においてやります。そうするとファイル名が赤から緑色に変わります。
1つ1つファイルを選ばずとも、Unversioning Filesという部分を右クリックしてAdd to VCSとすれば一気に全部変更できます。
(余談)リポジトリ作成後に新規ファイルを作成した場合 ちなみに、リポジトリを作成した後にファイルを追加すると、Git管理下におくかどうかきいてくるので、Yesを押せばわざわざこんな面倒臭いことをしなくてすみます。
コミットの仕方 ファイルをGit管理下に加えた後はコミットするだけです。以下のいずれかの方法でコミットを行うためのダイアログが表示されます。
メニューの`VCS > Commit Changes` ChangesツールウィンドウのVCSの文字の下に上矢印のついたアイコンをクリック キーボードショートカット`cmd+k` 後はコミットするファイルにチェックをつけて、コミットメッセージを入力して、Commitボタンを押せばOKです。
ちなみにコミットする際にCode Analysisが働いて確認ダイアログが表示されることがあります。
コミットする前にコードをチェックしてくれる機能で、「こういう風にした方がいいんじゃね?」という提案ではありますが、正直細かすぎる指摘もあるので、Warning程度であれば無視してもいいと思います。
Reviewを押せばWarning等の内容が表示されるので、無視してコミットする場合はCommitのボタンを押せばコミットできます。
Changesツールウィンドウを使ってコミットする際の注意点 Changesツールウィンドウを使ってコミットをする際は、リストに表示されている1つのファイルを選択した状態でVCSアイコンを押さないように気をつけましょう。
その場合、選択されているファイルしかコミット対象にならないことがあります。私はよく1ファイルだけコミットされてないという状況に陥りました。
そんなときは再度コミットするファイルを選び直し、Ammend commitにチェックをつけてコミットすると、直前のコミットを修正することができます。
コミット後のファイルの変更 コミット後にファイルに変更を加えると、ファイル名が青くなります。
またファイル名だけでなく、ソースコードの変更した部分のウィンドウの端にも色がつくようになります。この部分の色も、新規追加が緑、変更が青という規則にそっています。覚えておくと何かと便利かもしれません。
Android Studioは、Gradleが便利だとよく言われています。
私がAndroid Studioを使い始めた頃は「Gradle便利っていうけど、どう便利なんだろう」とさっぱり分かりませんでした。むしろGradleが何をやっているか、何者なのかさっぱり分からず、逆によく分からない存在でした。(でしたというか、現在進行形でよく分かっていませんが・・・)
実際にGradleが便利というのが実感できたのは、外部ライブラリを簡単に取り込めることが分かってからです。
外部ライブラリの取り込み Androidではアプリ開発に便利なライブラリが多数公開されています。
自分で1から作るより、すでにある便利なライブラリのお世話になった方が、アプリ開発スピードも早くなりますしクオリティも高くなります。
Android Studioではそういったライブラリを、build.gradleに1行記述するという簡単な方法で自分のプロジェクトに取り込むことができます。
デフォルトではbuild.gradleは2つあるのですが、いじるのはプロジェクト直下にあるものではなく、appディレクトリにあるbuild.gradleです。
例えばcroutonというToastをカスタマイズして使える便利ライブラリを取り込む場合は、app/build.gradleのdependanciesにcompile 'de.keyboardsurfer.android.widget:crouton:1.8.4'と記述をするだけで取り込めます。
app/build.gradle
dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.android.support:appcompat-v7:19.+' compile 'de.keyboardsurfer.android.widget:crouton:1.8.4' } Sync Project with Gradle Filesを実行すると、External Librariesに目的のライブラリが取り込まれます。
あらゆるライブラリがこの方法で使えるとは限りませんが、非常に便利です。
アプリ開発の始めの頃は外部ライブラリを利用するなんて発想がなかったものですから、Gradleが便利だぞと言われてもなんのこっちゃとさっぱり理解できませんでした。しかし、実際にこうやってライブラリが簡単に取り込めるのを確認すると、「なるほど、こりゃ便利だわ」とAndroid Studioを使うのが楽しくなってきました。
Android Studio 0.8.9がリリースされています。canary channelで配信されていますが、数日中にはbeta channelにも流れるようです。
内容は0.8.8からのバグ修正のみということです。
詳細は0.8.9リリースノートを参照してください。