Androidアプリを作ろう!と思って適当にEclipseを入れて、AndroidSDKを入れて、手持ちのNexus10をUSBデバッグ有効にして接続。
準備を整えたうえで Hello World してみたんだけど、Eclipse起動してから1行も書かずにHello Worldが終わってしまった話。
とりあえずHelloWorldを新規作成する。
1.プロジェクトの新規作成
ツールバーの新規作成っぽいやつから、「Androidアプリケーションプロジェクト」を選ぶと作れるみたい。
アプリケーション名: Hello World
を入力したら他のも勝手に入ります。
パッケージ名は、デフォだと com.example.helloworld
名前空間みたいなもんだと思う。
URLをさかさまにしたような感じなので、うちの場合は jp.ahox.helloworld にしてみた。
あとはSDKのバージョンを選ぶ。
おいらのNexus10は4.2なんで、とりあえずAndroid4.0の開発でいいやーということで画面のような感じに。
プロジェクトの構成では、アイコンも一緒に作りますか?最初に表示される画面(アクティビティ)も作っときますか?みたいなことを聞かれる。
とりあえず、デフォルトのままでOK。
アイコン作るよーっての選んだので、アイコンを選べる画面になる。
面倒なのでそのままでOKにした。
アクティビティーを選んで作る。
いろいろあるけど、シンプルにHello Worldするだけなので、BlankActivityにしてる。
アクティビティの設定とか。名前も別にそのままでいいと思ってデフォルトのまま完了。
アプリケーション名をHello Worldにしたので、なんかもう画面にHello Worldって書いてある。
とりあえず実行してみる。
端末を選ぶ画面にちゃんとNexus10が出ていた。
ので、選んでOKしてみた。
おぉ。起動した。
まだ、1行もプログラム書いてないんだけど。
何も理解していないがプログラムは動く。
が、ひとまずAndroid端末から実行時の情報を引っ張ってこれると思しき、DDMSなる画面があるので、これを見てみるとしよう。
DDMSの画面を見る。
こんなところにDDMS。とりあえず開く。
左の窓に今実行してる端末とアプリが見えます。
その窓のツールバーを見てみると、いろいろ書いてありますが。
まぁ、実行した時点で「プロセスのデバッグ」が有効になってますね。
あとはヒープメモリビューア的なのとか、スレッドビューア的なのがあるみたい。
最初は有効になってないけど、ツールバーのボタンを押せば端末から情報を取ってきてくれます。
他にもネットワーク使用量とか、ファイルエクスプローラがあるみたいですよ。
下のコンソールにはなにやらいろいろメッセージが流れていますし。
次はソースを見てみる。
ソースコードを見てみる&少しいじる。
/res/layout/activity_main.xml
自動生成されたアクティビティのレイアウトファイル
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:text="@string/hello_world" /> </RelativeLayout>
リラティブレイアウトの中に、テキストビューが入っている模様。
RelativeLayoutとは… 子要素を相対的な位置関係でもって場所指定して配置するレイアウトのよう。
なので、場所を変えようと思えば、子要素のTextViewをこうすると…
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="false" android:layout_centerVertical="false" android:layout_marginLeft="20dp" android:layout_marginTop="50dp" android:text="@string/hello_world" />
こうなる。
さらに右寄り、下寄り、にしたいときはこうするとできるみたい。
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:layout_centerHorizontal="false" android:layout_centerVertical="false" android:layout_marginRight="20dp" android:layout_marginBottom="50dp" android:text="@string/hello_world" />
RelativeLayoutはこんな感じで使えるようです。
次は、子要素のTextViewのほうを見てみる。
レイアウトの指定以外に指定されているパラメータは、
android:text=”@string/hello_world”
これで文字列を指定していると思われる。 @stringってなんだろう。
調べてみた。
文字列はリソースとして外部に保存されているらしい。
場所は、/res/values/strings.xml
ここに作ったリソースを @string/リソース名 で指定すればいいようだ。
ついでに他のリソースについても見てみることにした。
先ほどレイアウトのために指定した、20dpと50dp。
これをリソース化してみる。
まずはリソースを追加するのだが、文字列リソースってのは適切じゃなさそうなので、リソースのXMLを新規作成してみる。
まずはresを右クリックして新規作成からAndroid XML ファイル。
リソースタイプはvaluesですね。んで、ファイル名を書く。
ファイル名は寸法という意味のdimension。
次に格納できる値に制限を賭けられるようだ。
今回は無指定。
ファイルができたので、リソースを追加していく。
種類に Dimension を選択。
すると、リソースができるので名前と値を入れていく。
これでリソースができた。
ソースへ戻ってこれを参照してみよう。
res/layout/activity_main.xmlを開く。
当該個所にて、”@dimen/margin_20″と入力
これで寸法についてもリソース化することができた模様。
実行結果は変わらなかったので、問題なし。
XMLのほうはこんなもんにしておいて、次は java のほうを見ようと思う。
/src/jp/ahox/helloworld/MainActivity.java
package jp.ahox.helloworld; import android.os.Bundle; import android.app.Activity; import android.view.Menu; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.activity_main, menu); return true; } }
1行目: package ~;
パッケージ名を指定している。これは普通に java だ。
オライリーの詳解Javaプログラミング(p.177)によれば、”パッケージとは関連するクラスとインターフェースの集まりにつけられた名前です。”とのこと。そこから何やらいろいろくわしく書いてあるが、
packageはprivateなclassを外から見えなくする。publicなもののみ外部から見えるようになる。
外部から参照するときには import 文を使えば完全修飾名を入れなくとも参照できるようになる。
とのこと。
3~5行目: import ~;
外のpackageをimportしている。
android.os.Bundle は、android.osパッケージのBundleクラス。(Bundle | Android Developers)
onCreateの引数として(Bundle savedInstanceState)で使っているもの。
インスタンスのデータを保存しておいて、画面の回転とかでインスタンスが一時的に破棄されて再作成されるようなときのデータの受け渡しに使うらしい。
使用例を探してみたら簡潔でわかりやすいのがあったのでリンクしておきます。
→Y.A.M の 雑記帳: Android Bundle で状態を保存
android.app.Activityとandroid.view.Menuは名前の通りでわかりやすいが、アクティビティとメニュー関連のクラスのよう。
7行目: アクティビティのクラス定義
android.app.Activityを継承してMainActivityが作られている。
9,15行目: @Override
親クラスのメソッドを子クラスで再定義することをオーバーライドと言うが、次のメソッドはオーバーライドなんですよ!ということを明示して、もしもスペルミスなんかで正しくオーバーライドされていなかったらコンパイラに警告させるもの。
クラスの継承関係のややこしいことがまとめられているところがあった。
→いまさらですが、職業Javaプログラマーなら理解しておいてほしい「継承」の意味について – 達人プログラマーを目指して
10~13行目: onCreate(Bundle savedInstanceState)
onCreateはアクティビティが生成される時に呼び出されるメソッド。
アクティビティのライフサイクルについては、Android プログラミングバイブルという本に図解してあったのが見やすかった。
ちなみにDevelopersのサイトにも英語だけど図解されてた。
起動→onCreate→onStart→onResume→実行中→onPause→onStop→onDestroy→終了
の中で、一番最初にくる部分だ。
画面遷移がある場合は、onResumeとかも使うことになるが、Hello WorldだとonCreateだけでおkということ。
引数の savedInstanceStateは上で説明したように、インスタンスのデータを保存しておくもの。
Helloworldでは何も保存すべきものがないので使っていない。
super.onCreateでは、継承元クラスのonCreateが呼び出される。
setContentViewでは、画面に表示すべきビューを設定している。
ここで R クラスなるものが使われているよう。
R クラスは自動的にリソースから作られるクラスで、/gen フォルダにある。
ここでは R.layout.activity_main で res/layout/activity_main.xml と関連付けられている。
16~20行目:onCreateOptionsMenu
なんか。しらないうちにオプションメニューも追加されているようです。
onCreateOptionsMenuはオプションメニューが最初に表示されるときに呼び出される模様。
メニューが呼び出されたんで、表示に必要な処理を書いてね的なものなんだけど。
中に書いてあるのは、
getMenuInflater().inflate(R.menu.activity_main, menu);
という謎のもの。
これを読むには Inflater なるものを見ないといけないよう。
MenuInflater | Android Developers
このクラスは、メニューオブジェクトにメニューXMLファイルをインスタンス化するために使用されます。
メニューをXMLから生成するよ。とのこと。
その時参照するXMLが引数の、R.menu.activity_mainとのこと。
メインの画面と同じようでわかりにくいが、こちらはmenu用のactivityのようで。
開いてみるとこうなっていた。
ここでメニューを定義できるらしい。
んで。現状はメニューを表示するところまでは自動生成されるが、メニューを押しても何も実行されるコードがない模様。
折角なんで書いてみよう。
package jp.ahox.helloworld; import android.os.Bundle; import android.app.Activity; import android.view.Menu; import android.view.MenuItem; import android.app.AlertDialog; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.activity_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch(item.getItemId()){ case R.id.menu_settings: AlertDialog.Builder alertd = new AlertDialog.Builder(this); alertd.setTitle(R.string.hello_world); alertd.setMessage(R.string.hello_world); alertd.setPositiveButton("OK", null); alertd.show(); break; default: break; } return true; } }
メニューを押したらダイアログが出るようになりました。
onOptionsItemSelected(MenuItem item)なるメソッドをOverrideして、その中で押されたボタンの判定とその後の処理を書いてあげればできました。
ここまでちょいちょいいじってみて、ようやく少々HelloWorldって感じですね。
そろそろ説明書くのが飽きてきたので終わりにしようと思います。
次は、CSVファイルくらい読み込んで、グリッド状に表示してみようと思う。
2件のコメント
ahox · 2013-05-28 02:20
よーし、作っちゃおうかー!
いつになるかわからんけど★
たこたこ · 2013-05-27 12:36
ゲーム作ってゲーム!