特集:.NETでもAndroid開発はできるのか?

初めてのMono for Android開発

WINGSプロジェクト かるあ(監修:山田 祥寛)
2011/08/05
Page1 Page2 Page3 Page4

画面レイアウトの作成

 まずは検索画面のレイアウトを作成していこう。

 今回作成する書籍検索の画面を、図11に示す。

図11 今回作成する書籍検索の画面

 Androidの画面レイアウトは、[ソリューション エクスプローラー]上のResourcesフォルダのLayoutフォルダ以下に、「AXML」(拡張子は「.axml」)というXML形式のファイルで定義を行う。ちょうどSilverlightのXAMLと同じ位置付けと思ってもらえばいいだろう。Androidの.axmlファイルをリスト1に示す。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="vertical"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent">

  <!-- 検索テキストボックスと検索ボタンを横に並べて配置する -->
  <LinearLayout android:orientation="horizontal"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content">
  <EditText android:id="@+id/txtKeyword"
        android:layout_width="200px"
        android:layout_height="wrap_content" />
  <Button android:id="@+id/btnFind"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="@string/btnFindText" />
  </LinearLayout>

  <!-- 検索結果件数と、検索結果の一覧を表示するビュー -->
  <TextView android:id="@+id/lblResult"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content" />
  <ListView android:id="@+id/bookList"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content" />

</LinearLayout>
リスト1 Androidの書籍検索画面の定義(Main.axml)

 Androidの画面サイズは端末によってさまざまに異なるため、幅や高さを明示的には指定せず、成り行きに任せて描画されるように画面を設計することが多い。今回は、水平/垂直方向にコントロールなどを並べられるLinearLayoutクラスを利用し、その中に配置する各コントロール・クラスのandroid:layout_width/android:layout_height属性には「wrap_content」を指定することで、実行するデバイスに応じてコントロールのサイズが変化するようにデザインした。また、プログラム・コードから各コントロール要素にアクセスするため、android:id属性にコントロールのIDを設定している。

 TextViewコントロールなどに表示するテキストは、「@string」プリフィクスを付けることで(例えばTextViewコントロールのandroid:text属性に「@string/MainTitle」のような値を指定することで)、プロジェクトのResources\Values\Strings.xmlファイルに定義したリソースから取得することが可能だ。Resources\Values\Strings.xmlファイルの定義内容を、リスト2に示す。

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <string name="ApplicationName">ほんだな</string>
  <string name="MainTitle">ほんだなあぷり</string>
  <string name="btnFindText">検索</string>
</resources>
リスト2 Resources\Values\Strings.xmlファイルの定義内容

 android:id属性に指定した値は、アプリのコンパイル時にMono for Androidによって自動生成されたResourceクラス内のIdクラスでプログラムから参照することが可能だ。例えば、検索ボタンのID値を取得したい場合は、「Resource.Id.btnFind」と指定すればよい。

【コラム】GUIデザイナ・ツールについて

 Mono for Androidには、Androidの画面レイアウトを定義するためのGUIデザイナ・ツールは付属していない。従って、Androidの画面レイアウトを定義するためには、レイアウト定義用のAXMLコードを直接記述する必要がある。AXMLコードを効率的に記述する際には、Visual StudioのIntelliSenseが便利なので問題ないのだが、DroidDrawという無料のGUIツールを別途インストールして利用することも可能だ。

画面制御コードの作成

 続いて画面で入力されたテキスト情報を基に、Amazonに対して書籍を検索するサービスを呼び出す部分を見ていこう。

 リスト3はリスト1(Main.axmlファイル)で定義された画面要素をコントロールするためのアクティビティ・クラスの実装例だ。Androidの開発では、「アクティビティ」がフォーム(アプリ画面)に相当する。

using System;
using System.Linq;

using Android.App;
using Android.OS;
using Android.Runtime;
using Android.Widget;
using MonoBookMgr.Service;

namespace MonoBookMgr.Activities
{
  [Activity(Label = "ほんだなあぷり", MainLauncher=true)]
  public class MainActivity : Activity
  {
    // コントロールの参照
    private Button btnFind { get; set;}
    private TextView lblResult  { get; set;}
    private ListView bookList { get; set;}
    private EditText txtKeyword { get; set;}

    protected override void OnCreate(Bundle bundle)
    {
      base.OnCreate(bundle);

      // ビューの決定
      SetContentView(Resource.Layout.Main);  
     
      // コントロールの取得
      btnFind = FindViewById<Button>(Resource.Id.btnFind);
      txtKeyword = FindViewById<EditText>(Resource.Id.txtKeyword);
      lblResult = FindViewById<TextView>(Resource.Id.lblResult);
      bookList = FindViewById<ListView>(Resource.Id.bookList);

      // イベントの割り当て
      btnFind.Click += btnFind_Click;
    }

    // ボタン・クリック時のイベント・ハンドラ
    void btnFind_Click(object sender, EventArgs e)
    {
      // 画面要素に書き込みを行うためのハンドラ・クラスの定義
      var handler = new Handler();
      // ビジネス・ロジック・クラスの作成
      var service = new Service.AmazonService();
      // リクエスト終了時のイベント登録
      service.RequestCompleted += (object _s, AmazonService.AmazonRequestCompletedEventArgs _e) => handler.Post(() =>
      {
        if (_e.Error != null)
        {
          var errMessage = _e.Error.ToString();
          lblResult.Text = string.Format("取得失敗:{0}", errMessage);
          return;
        }

        // ビジネス・ロジックからの値を、画面要素に設定
        var message = string.Format("検索成功:{0}件", _e.Result.TotalResults);
        lblResult.Text = message;

        var dataSource = new JavaList<string>(_e.Result.Items.Select(r => r.ToString()).ToList());

        // リストの表示方法を定義したMain.axmlに関連付ける
        bookList.Adapter = new ArrayAdapter<string>(this, Resource.Layout.BookListColumns, dataSource);
      });

      // 書籍検索の実行
      service.FindAsync(txtKeyword.Text);
    }
  }
}
リスト3 Androidの画面制御ロジック(Activity1.cs)

 「画面定義」(=.axmlファイル)と「画面の制御ロジック」(=Activetyクラスを継承したクラス)の関係はどこにも定義されていないため、アクティビティの初期化のタイミング(OnCreateメソッド)で、ビューの決定や、コントロールの取得、イベントの割り当てなどの関連付けを行う。

 ビューの決定では、SetContentViewメソッドを利用してページ本体(=Main.axmlファイル)とビューの関連付けを行う。

 コントロールの取得では、FindViewById<T>メソッドでページに含まれる各画面要素を検索して取得する。リスト3では、検索した画面要素はアクティビティ・クラスのプロパティとして保存している。

 イベントの割り当てでは、ボタンのイベント・ハンドラを登録している。イベントの割り当てや、イベント・ハンドラの実装自体は、通常のC#のアプリ開発とほぼ変わりないが、別スレッドからGUIスレッドに値を書き込むために、Handlerクラスを利用している点に注意してほしい。

 今回のサンプルを実行し、テキストボックスに書籍の検索キーワードを入力して[検索]ボタンをクリックした結果の画面を、図12に示す。

図12 今回作成したサンプルの実行結果

Windows Phoneとのコード共有

 Windows Phoneでアプリを作成したことがあれば、Mono for Androidの開発も大差ないことが分かるだろう。例えば、XAMLとほぼ同じようなXML形式のコードで画面定義が行われていたり、コードビハインドとほぼ同じような役割のアクティビティ・クラスが実装されたりしている。

 リスト1のサンプル・コード(Main.axml)で利用しているAndroidの画面要素とWindows Phoneで利用できるコントロールのマッピングを表2に示す。それぞれ細かい違いはあるが、各プラットフォームで、同じようなレイアウトを作成する道具はそろっている。

Android Windows Phone 意味
LinearLayout StackPanel 水平または垂直に伸縮するパネル
TextView TextBlock テキストの表示
EditText TextBox 入力可能なテキストボックス
ListView ListBox リストの表示
表2 リスト1とリスト2で利用している画面要素(=コントロール)のマッピング

 本稿のサンプル(monosample.zip)に添付したサンプル・プロジェクトでは、Androidで作成した画面と同じ構成で、ビジネス・ロジックをAndroidと共有するWindows Phoneプロジェクトを含めている。このようにMono for Androidを利用すると、画面の操作などが必要ないコードはもとより、画面を制御するクラスも、ほぼ同じコードで実装できる。

【コラム】Windows Phone

 「開発者のためのWindows Phone概説」でも取り上げたが、複数のスマートフォン・プラットフォームで同じような機能を実装したい場合に、それぞれの環境でどのAPIを利用すればよいかを確認するには、マイクロソフトが公開しているサイト「Windows Phone 7 Interoperability(英語)」を参照されたい。例えばWindows PhoneとAndroidのマッピングを確認したい場合は、そのサイト内にある「API Mapping tool - Android(英語)」を参照すると、AndroidのAPIがWindows PhoneのどのAPIに相当するかを確認できる。

 サンプル・プロジェクトを確認すると、アプリの“キモ”となる、書籍検索用のAmazonServiceクラスは、Android、Windows Phoneで同じコードを共有して利用しているが、何も変更せずにAmazonの書籍検索が行われている点を確認できるだろう。1つのコードを複数のプラットフォームで共有することを考えた場合、「プラットフォーム固有(今回の場合は画面の操作)」と「共通で利用できる部分」の設計をあらかじめ行い、コードの再利用性を高めることが重要になる。

 今回は触れないが、MonoTouchを利用すると、iPhone向けのアプリでも同じような手法でC#のコードの共有が可能だ。次のブログ・エントリでは、Mono for Android、MonoTouch、Windows Phoneでコードの共有を行うサンプルが紹介されている。

 最後に、Android端末に搭載される各センサーを扱う方法を紹介しよう。


 INDEX
  特集:.NETでもAndroid開発はできるのか?
  初めてのMono for Android開発
    1.Mono for Androidとは/開発環境の構築
    2.書籍検索アプリを作ってみよう(プロジェクト構成の概要)
  3.書籍検索アプリを作ってみよう(画面の作成/Windows Phoneとのコード共有)
    4.センサーに触ってみよう


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間