ものがたり(旧)

atsushieno.hatenablog.com に続く

monodroid: Hello World

(これは http://monodroid.net/Tutorials/Hello_World の現時点での日本語訳をもとに書いたものです。)

御存知の通り、開発者として、開発フレームワークの第一印象は、"Hello World"がどれだけ簡単に書けるかということにかかっています。まあ、MonoDroidでは、これはとても簡単です。もしVisual StudioMonoDevelopIDEとして使用するなら、これは特に簡単なものになります(訳注 - MonoDevelop版はまだ公開されていない)。われわれは、プロジェクトの作成と維持を担い、あなたの開発サイクルを格段にスピードアップできるプラグインを提供しています。

このチュートリアルでは、あなたがVisual Studio 2010を使用することを想定しています。もしMonoDevelopを使用している場合でも、その使用法はほぼ同一ですので、ほとんどこれに従うだけでできます。

ここから先を始める前に、まずSDKをインストールしておく必要があります。もしまだ行っていなければ、monodroid:インストールを見て、インストールを終えてからここに戻ってきてください。

プラットフォームのインストール

Hello Worldアプリケーションを実行するには、最低でもひとつのAndroidプラットフォームをSDK環境にインストールする必要があります。もしこのステップをまだ終えていない場合、ここで行っておく必要があります。

プラットフォームをインストールするには、次のステップを実行します:

  1. Android SDKのAVD Managerの中で、左のパネルからAvailable Packagesを選択する
  2. repository siteチェックボックスをクリックして、インストールできるコンポーネントを表示する
  3. 最低でもひとつのプラットフォームをインストール対象として選択し、Install Selectedをクリックする。どのプラットフォームをインストールすればいいかわからない場合は、最新のバージョンを使います
AVDを作成する

このチュートリアルでは、あなたのアプリケーションをAndroidエミュレータ上で実行します。エミュレータを起動する前に、まずAndroid仮想デバイス(Android Virtual Device, AVD)を作成しなければなりません。AVDでは、エミュレータが使用するシステムイメージとデバイス設定を定義します。

AVDを作成するには、以下のステップを実行します:

  1. Visual Studio上で、ツール > Start Android Emulator Managerを選択します
  2. 左のパネルからVirtual devicesを選択します
  3. Newをクリックします
    1. Create New AVDのダイアログが出現します
  4. AVDの名前を "my_avd" のように入力します
  5. ターゲットを選択します。このターゲットは、あなたがエミュレータで実行したいプラットフォームです(つまり、Android SDKのバージョン、たとえば2.1などです)

    残りのフィールドはとりあえず無視できます。
  6. Create AVDをクリックします

AVDの使い方や、利用可能なオプションについては、Android Virtual Devicesのドキュメントを参照してください。

新しいAndroidプロジェクトを作成する

AVDを作成したら、次のステップはVisual Studioで新しいAndroidプロジェクトを開始することです。

  • Visual Studioファイル > 新規 > プロジェクト... を選択します。

    Visual Studio用MonoDroidプラグインが正しくインストールされていれば、このダイアログにVisual C# > MonoDroidカテゴリがあって、中に"MonoDroid Application"があるはずです。

  • "MonoDroid Application"を選択して、プロジェクト名を"HelloAndroid"にして、OKをクリックします。

(訳注 - これは初期beta版のスクリーンショットです。現在のbeta版にはこの他にライブラリのテンプレートなども存在します。)

  • ソリューション エクスプローラ中のプロジェクトを右クリックして、プロパティを選択します
  • Application Propertiesのセクションで、以下の値を設定します:
    • Application name: Hello, Android
    • Package name: com.example.helloandroid (あるいはあなたの好きなプライベート ネームスペース)

      以下、各プロパティについて説明します:

      Application Name
      これは、あなたのアプリケーション名の、人間用タイトルです。この名前が、Androidバイス上で表示されます。
      Package Name
      これはあなたのソースコードをこの名前のもとで格納させるパッケージ ネームスペースです(Javaプログラミング言語におけるパッケージと同一のルールです)。これが、スタブのActivityが生成される際のパッケージ名も設定します。

      パッケージ名は、Androidシステム上にインストールされているパッケージのすべてと、重複してはなりません。そのため、アプリケーションには、標準的なドメイン形式のパッケージ名を使用するのがポイントです。上記の例では、"com.example"というネームスペースを使用していますが、これはexampleのドキュメント用に予約されているネームスペースです -- あなたのアプリケーションを開発する際には、あなたの組織や実体に合わせたネームスペースを使用します。
      Minimum Android Version
      この値には、あなたのアプリケーションで要求する最低APIレベルを指定します。詳細については、Android API Levelsを参照してください。あなたのアプリケーションは、常に最新のMonoDroid APIを対象にビルドされますが、古いデバイス上で実行するためには、あなたは古いAPIバージョンの機能のみを選んで使用するかもしれませんし、実行時に条件付きで機能を有効にするかもしれません。

あなたのMonoDroidプロジェクトはこれで準備できました。右側のソリューション エクスプローラで表示されているはずです。デフォルトでは、ここにはActivity1.csに含まれる、MonoDroidのActivityクラスのサブクラスであるActivityがひとつ含まれます。Activityは、単純に、実行して作業を行うクラスです。必要であればUIを作成しますが、必要というわけではありません。Activityはほぼ常にそのアプリケーションの基盤として使用されます。

Activity1.csファイルを開いてください。これは以下のように見えるでしょう:

using System;

using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;

namespace HelloAndroid
{
    public class Activity1 : Activity
    {
        int count = 1;
        public Activity1 (IntPtr handle) : base (handle)
        {
        }

        protected override void OnCreate (Bundle bundle)
        {
            base.OnCreate (bundle);
            
            // Create your application here 

            var button = new Button (this) {
                Text = string.Format ("{0} clicks!", count)
            };
            button.Click += delegate {
                button.Text = string.Format ("{0} clicks!", ++count);
            };
            SetContentView (button);
        }
    }
}

このクラスがActivityクラスから派生していることに注意してください。Activityは、アクションを実行するために使用する、ひとつのアプリケーションの実体です。アプリケーションには、別々のactivityを数多く含むことができますが、その中でユーザーとインタラクトできるのは一度にひとつだけです。OnCreateメソッドは、あなたのActivityが開始された時に、Androidシステムによって呼び出されます -- ここが、すべての初期化とUIのセットアップを行うべきところです。activityにユーザーインターフェイスは必須ではありませんが、通常は使うでしょう。


ここまで出来たら、コードを少し変更してみましょう!

UIを構築する

以下のように修正したOnCreateメソッドの本体を見て、あなたのHelloAndroidクラスに同じ変更を加えてみてください。

protected override void OnCreate (Bundle bundle)
{
    base.OnCreate (bundle);
            
    var tv = new TextView (this) {
       Text = "Hello, World"
    };
    SetContentView (tv);
}

Androidユーザーインターフェースは、Viewと呼ばれるオブジェクトの階層構造になっています。Viewは、あなたのUIレイアウト中のひとつの要素として使われる描画オブジェクト(drawable object)で、たとえばボタンや画像や(この場合のように)テキストラベルがあります。これらのオブジェクトはそれぞれがViewクラスのサブクラスで、テキストを扱うサブクラスはTextViewです。

この変更によって、あなたは、このクラスの、AndroidTextプロパティを設定することで、テキスト内容を定義します。

最後に、このActivityのUIの内容として表示するために、このTextViewをSetContentView(View)に渡します。もしあなたのActivityでこのメソッドを呼び出さなかったら、UIは何も存在せず、システムはブランク スクリーンを表示するでしょう。

ともあれ、これがAndroidにおける "Hello, World" です! 次のステップでは、もちろん、これを実行してみましょう。

アプリケーションを実行する

Visual Studioプラグインが、アプリケーションの実行を簡単にさせてくれます。

  1. デバッグ > 実行を選択、またはCTRL-F5M
  2. 問い合わせが出現したら、先ほど作成したエミュレータバイス(AVD)を選択します。以下のようなダイアログが表示されます:

    もしデバイスが何も出現しなければ、"Launch emulator manager"をクリックします
  3. エミュレータ マネージャを起動するとこうなります:
  4. エミュレータ マネージャで "start" をクリックすると、"Select Device"ダイアログでデバイスが出現するまで "Refresh Devices" が押せるようになります。

環境によっては、Androidエミュレータが完全に起動するまでには何分もかかりますので、辛抱強く待ちます。エミュレータが起動したら、Visual Studioプラグインはあなたのアプリケーションをインストールし、デフォルトのActivityを起動します。以下のような状態になるはずです:

灰色のバーの上に見られる "Hello, Android" は、アプリケーションのタイトルです。Visual Studioプラグインは、これを自動生成します(この文字列はResources/values/strings.xmlファイルで定義されており、AndroidManifest.xmlファイルで参照されています)。タイトルの下にあるテキストは、あなたが実際にTextViewオブジェクトで作成したテキストです。

ここまでで基本的な"Hello World"のチュートリアルはおしまいですが、この先の、Androidアプリケーションの開発に有用な情報をもう少し読み続けることもできます。

UIをXMLレイアウトにアップグレードする

今しがた終えたばかりの"Hello World"の例では、プログラム主導のUIレイアウトを用いています。これはつまり、あなたはアプリケーションのUIを直接ソースコードで設計したということです。もしこれまでUIプログラミングをたくさんこなしていたら、時としてそのアプローチが不安定をもたらすものであることを経験的に知っていることでしょう: 小さなレイアウトの変更が大きなソースコードの変更という頭痛の種になりうるのです。また、ビューを適切につなぎあわせ忘れて、レイアウトのエラーや無駄なデバッグ作業につながることもあります。

AndroidがもうひとつのUI構築モデルである、XMLベースのレイアウトファイルを提供するのも、これが理由です。このコンセプトを説明するには、例をお見せするのが手っ取り早いでしょう。以下にプログラムで構築した例と同一の振る舞いとなるXMLレイアウトファイルを示します。

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@+id/textview"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  android:text="@string/hello"/>

Android XMLレイアウトファイルの一般的な構造は簡単です: 複数のXML要素のツリーで、各ノードはViewクラスの名前です(この例ではただ1つのViewしかありませんが)。XMLレイアウトの要素としては、Viewから派生するクラスの名前であれば、あなたが独自にコードで定義したカスタムViewクラスを含め、何を使ってもかまいません。この構造は、プログラムに基づくレイアウトを使用するより簡単な構造と文法によって、簡単にUIを構築させてくれます。このモデルは、アプリケーションの表示と、データの取得および適用のロジックを分離できる、Web開発モデルにインスパイアされたものです。

上記のXMLの例では、ただ1つのView要素しかありません。このTextView要素には、5つのXML属性があります。以下にそれらの意味を簡潔に記します。

属性意味
xmlns:androidXML名前空間宣言で、Androidツールに、Android名前空間で定義された共通属性を参照するということを伝えるものです。どのAndroidレイアウトファイルでも、最も外側にあるタグが、この属性をもつ必要があります。
android:idこの属性は、このTextView要素に一意識別子を与えます。このIDを使用することで、ソースコードや他のXMLリソース宣言でこのViewを参照できます。
android:layout_widthこの属性は、このViewが要求する、スクリーン上で利用可能な幅を定義します。この場合は唯一のViewとなるため、スクリーン全体を利用しようとしていて、それが "fill_parent" の意味するところです。
android:layout_heightこれはほぼandroid:layout_widthと同様で、高さを示します。
android:textこれはTextViewが表示すべきテキストを設定します。この例では、ハードコードされた文字列ではなく、文字列リソースを使用しています。このhello文字列はResource/values/strings.xmlで定義されています。これはアプリケーションに文字列を格納する際に推奨されるプラクティスです。そうすると、アプリケーションの他言語へのローカリゼーションを、レイアウトファイルに変更をハードコードすることなく行うことが出来るためです。詳細はResources and Internationalizationを見てください。

これらのXMLレイアウトファイルは、あなたのプロジェクトの Resources/layout/ ディレクトリ以下に存在し、"AndroidResource" ビルド アクションがあるはずです(訳注: たぶん原文がおかしくて、「プロジェクトには」が抜けている)。この Resources ディレクトリには、あなたのアプリケーションが必要とする非コード アセットが、便宜的に全て含まれています。レイアウトファイルの他に、リソースにはイメージ、サウンドローカリゼーション文字列などが含まれています。

水平レイアウト: 水平画面で別のデザインを使用したい場合は、/Resources/layout-land の下にレイアウトXMLファイルを置いてください。Androidは、レイアウトが変更されると自動的にここを見に行きます。ここで特別に定義された水平画面レイアウトがない場合は、Androidはデフォルトのレイアウトを伸縮させます。)

このVisual Studioプラグインでは、これらのレイアウトファイルをひとつ、main.xml として自動的に作成します。先ほど完成させた "Hello World" アプリケーションでは、このファイルは無視され、あなたはレイアウトをプログラム上で作成しました。これはむしろAndroidフレームワークについて教えるためだったのですが、ほぼ常にコードよりはXMLファイルでレイアウトを定義するようにするべきです。以下の手順で、既存のアプリケーションを、XMLを使うように変更できます。

1. Visual Studioソリューション エクスプローラーで、プロジェクトの Resources/layout フォルダを展開して、main.xmlを開きます。その内容を以下で置き換えます:

<?xml version="1.0" encoding=utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/textview"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:text="@string/hello"/>

ファイルを保存します

2. Resources/values/フォルダの中で、strings.xmlを開きます。ここに、あなたのユーザーインターフェースで使用する文字列のデフォルトテキストを保存しておくべきです。このファイルのデフォルト テンプレートは2つの文字列helloapp_nameから始まります。helloを何か他のものに修正してください。たとえば "Hello, Android! I am a string resource!" とか。ファイル全体はそうするとこんな感じになります:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="hello">Hello, Android! I am a string resource!</string>
    <string name="app_name">Hello, Android</string>
    </resources>

3. そうしたら、HelloAndroidクラスを開いてXMLレイアウトを使用するように修正します。以下のようにファイルを編集します:

public class Activity1 : Activity  
{   
    public Activity1 (IntPtr handle) : base (handle)  
    {  
    }  
   
    protected override void OnCreate (Bundle bundle)  
    {  
        base.OnCreate (bundle);
        SetContentView (R.layout.main);
    }
}

このように変更したら、コード補完機能をキー入力で試してみてください。"R.layout.main" と入力しようとすると、プラグインが候補を出してきます。これがさまざまなシチュエーションで助けとなることにいずれ気づくでしょう。

SetContentView()にViewオブジェクトを渡す代わりに、レイアウトリソースへの参照を渡します。このリソースは R.layout.main として識別されます。これは Resources/layout/main.xml で定義されたレイアウトをコンパイルしたオブジェクト表現です。このVisual Studioプラグインは、このプロジェクト中の R.cs のクラスの内部にこれを自動生成します。もしVisual Studioを使用しなければ、MSBuildでアプリケーションをビルドする時に、R.java のクラスが生成されます(Rクラスについてはすぐに説明します)。

さて、ではアプリケーションを再び実行しましょう。TextView文字列の変更以外では、このアプリケーションは全く同じように見えます。要するに、ここでの要点は、同一の結果に対する2つの異なるレイアウトのアプローチについてお見せすることだった、というわけです。

Tip: Ctrl+F5で、ソリューションのデフォルト起動プロジェクトを実行できます。

デバッグおよび他のIDEについての情報の紹介を見るには、続けて読んでください。もっと知りたい場合は、Androidアプリケーションを構成する要素の全てを紹介するApplication Fundamentalsを読んでください。また、開発ガイドのドキュメントの概要としては、Developer's Guideの紹介ページを参照してください。

Rクラス

Visual Studioで、R.csという名前のファイルを開いてみると、内容はこのようになっています:

namespace HelloAndroid 
{
    public static class R
    {
        public static class attr
        {
        }
        public static class drawable {
            public const int icon=0x7f020000;
        }
        public static class id
        {
            public const int textview=0x7f050000;
        }
        public static class layout
        {
            public const int main=0x7f030000;
        }
        public static class @string
        {
            public const int app_name=0x7f040001;
            public const int hello=0x7f040000;
        }
    }
}

プロジェクトのR.csファイルは、ファイル中に定義されたリソースへのインデックスです。このクラスを、プロジェクト中に含まれるリソースを参照する手短な方法として、ソースコード中で使用します。これは特にVisual StudioのようなIDEのコード補完機能を使用すると強力なもので、迅速かつインタラクティブに特定の参照を探し出すことができます。

これとはわずかに異なるものが生成されているかもしれません(たとえば16進数値が違うなど)。とりあえず今は、"layout"という名前の内部クラスがあって、"main"というメンバー フィールドがあることに気づいてください。このVisual Studioプラグインは、main.xmlという名前のXMLレイアウトファイルの存在に気づいて、ここにそのためのクラスを生成しているのです。あなたのプロジェクトにリソースを追加したら(たとえば Resources/values/strings.xml ファイル中の文字列や、 Resources/drawable ディレクトリ中の画像など)、R.csがその変更に追従しているのが分かることでしょう。

Visual Studioを使用しない場合は、このファイルは(MSBuildツールによって)ビルド時に生成されます。

このファイルは決して手作業で変更すべきではありません。

あなたのプロジェクトをデバッグする

MonoDroidのVisual Studioプラグインは、Visual Studioデバッガーとの優秀な統合も実現しています。これをデモンストレーションするために、あなたのコードにバグを仕込みましょう。OnCreateメソッドを以下のように変更します:

protected override void OnCreate (Bundle bundle)
{
    base.OnCreate (bundle);
       
    object o = null;
    o.ToString ();
    
    SetContentView (R.layout.main);
}

この変更はあなたのコードに単純にNullReferenceExceptionを引き起こしています。このアプリケーションを再度実行すると、以下のメッセージを見ることになるでしょう:

Press "Force Quit" to terminate the application and close the emulator window.

このエラーについてより詳しく見る場合は、ソースコード中のobject o = null;の行にブレークポイントを設定しましょう(ソースコードの該当行の横のマーカー バーをダブルクリックします)。そうしたら、デバッグモードに入るために、メニューからデバッグ > デバッグを選択します。あなたのアプリケーションはエミュレータを再起動しますが、ブレークポイントに到達したところで停止します。そうしたら、他の任意のアプリケーションと同様に、Visual Studioのデバッガー上でコードをステップスルーできます。

Portions of this page are modifications based on work created and shared by the Android Open Source Project and used according to terms described in the Creative Commons 2.5 Attribution License. This tutorial is based on the Android Hello World tutorial.