rksoftware

Visual Studio とか C# とかが好きです

Android アプリを Xamarin.Android に移植する (1)

Android アプリを Xamarin.Android に書き換えるシリーズ(1) です。
※Android サンプルアプリ MediaRecorder ( https://github.com/googlesamples/android-MediaRecorder )

■ プロジェクトの新規作成

Xamarin.Android のアプリを作るので最初はプロジェクト(ソリューション)の新規作成からです。

Mac の場合

・Visual Studio for Mac を起動します。
・メニューの ファイル > 新しいソリューション を選択します。
・[新しいプロジェクト用のテンプレートを選択する] で Android > アプリ > (全般) の Android アプリ (C#) を選択し、[次へ] をクリックします。
・[アプリ名] に適当な名前を入力し、[次へ] をクリックします。
・[プロジェクト名] [ソリューション名] は特に変える必要はありません。[場所] は好みの場所があれば変更してください。
・[作成] をクリックします。

Windows の場合

・Visual Studio (2017) を起動します。
・メニューの ファイル > 新規作成 > プロジェクト を選択します。
・[新しいプロジェクト] で Visual C# > Android > からのアプリ(Android) を選択します。
・[名前] に適当なアプリケーション名を入力します。[場所] は好みの場所があれば変更してください。
・[OK] をクリックします。

■ UI の移植

Xamarin はネイティブの UI 定義が使えることが特徴です。
ネイティブの UI 定義が使えるとは、Android で言えば、Android(Java) のプロジェクトで res フォルダー内にある .axml や .xml、画像ファイル などをそのまま使うということです。

Mac の場合

res フォルダーは Xamrin では Resources フォルダになります。
・Android(Java) プロジェクトの res フォルダーの中身(フォルダー、ファイル)を、Xamarin プロジェクトの Resources フォルダーにコピーします。
・Visual Studio for Mac の [ソリューション] の Resources を右クリック(二本指タップ)します。
追加 > フォルダーからファイルを追加 を選択します。
Resources フォルダーを選択し、[開く] をクリックします。
・[Resources から追加するファイルを選ぶ] で [すべて含める] をクリックします。
・全てチェック ON になっていることを確認し、[OK] をクリックします。

Windows の場合

res フォルダーは Xamrin では Resources フォルダーになります。
・Android(Java) プロジェクトの res フォルダーの中身(フォルダー、ファイル)を、Xamarin プロジェクトの Resources フォルダーにコピーします。
・(Win+e などで)エクスプローラーを開き、Resources フォルダー内のフォルダーをすべて選択しドラッグ、Visual Studio のソリューションエクスプローラー上の Resources フォルダーにドロップします。
・タイトル「ファイルを新しい場所に移動しますか?」メッセージ「1つ以上のファイルを "XXXXXXX\Resources" に移動します。この操作は長時間かかることがあります。」のダイアログで [OK] をクリックします。

共通

・「ファイルが見つかりません」というエラーが出て、Resources\layout\Main.axml 無いとされる場合、ソリューションエクスプローラーから Main.axml ファイルを削除します。

■ UI の適用

Xamarin はネイティブの UI 定義が使えることが特徴です。
axml などのファイルを使えるばかりでなく、Activity も Activity クラスで定義します。
また、先程コピーしたリソースファイルも、自動生成される Resource クラスに定数として定義されます。
(Android(Java) では R でしたが Xamarin では Resource になります)
また、Activity クラスのメソッドなども基本、Java と同じものが定義されており、同じ使い方になります。
ただし、メソッド名などは C# の流儀に変わっているので少し名前が変更されています。
例えば Java では onCreate メソッドでしたが、C# では OnCreate メソッドになっています。

Activity の書き換え

・ソリューションエクスプローラー上で、MainActivisy.cs をバブルクリックして開きます。
・7 行目あたりに

[Activity(Label = "XamMediaRecorder", MainLauncher = true, ...

という記述があります。
これが Activity に対する設定になります。Android では AndroidManifest.xml 内に記述していましたが、Xamarin では Activity クラスの属性として設定します。
属性とは、Java で言うところのアノテーションに当たる機能です。
この属性を先程追加したリソースを参照するよう、次のように変更します。

[Activity(Label = "@string/app_name", MainLauncher = true, ScreenOrientation = ScreenOrientation.Landscape)]

・ここでビルドを行うと「ScreenOrientation が見つからない」という様なエラーになります。
ScreenOrientation クラスの存在する名前空間(Java のパッケージに当たる機能)を using (Java でいう import に当たる機能) で宣言します。
ファイルの先頭の using の塊に次を追加します。

using Android.Content.PM;

この追加はエラーの発生している View にカーソルを合わせて、Mac の場合は alt+enter > クイック修正、Windows の場合は ctrl+. から自動で追加することもできます。
・また、Export 属性を使用する場合、dll の参照を追加する必要があります。
Mac の場合は、ソリューション上の [参照] を右クリック(二本指タップ) > [参照の編集] で開くダイアログで。
Windows の場合は、[参照] を右クリック > [参照の追加] で開くダイアログで [アセンブリ] を選択し。
Mono.Android.Export にチェックをつけて [OK] をクリックします。
・画面レイアウトの定義も、先程追加したリソースを参照するよう、次のように変更します。
変更箇所は15〜17行目あたりにあります。
変更前

SetContentView(Resource.Layout.Main);

変更後

SetContentView(Resource.Layout.sample_main);

・Mac の場合、OnCreate メソッド内に次のようなコードが書かれています。

Button button = FindViewById<Button(Resource.Id.button_capture);

button.Click += delegate {button.Text = $"{count++} clicks!";

このコードは、不要なので削除します。

イベントハンドラメソッドの作成

サンプルの画面定義にはボタンクリックのイベントが設定されています。
このイベントのハンドラとなるメソッドを MainActivity に作成します。
・MainActivity クラスに次のメソッド定義を追加します。
Java.Interop.Export 属性で定義に設定されているメソッド名を設定することがポイントです。

[Java.Interop.Export("onCaptureClick")]
public void OnCaptureClick(View view)
{
}

・ここでビルドを行うと「View が見つからない」という様なエラーになります。
View クラスの存在する名前空間(Java のパッケージに当たる機能)を using (Java でいう import に当たる機能) で宣言します。
ファイルの先頭の using の塊に次を追加します。

using Android.Views;

この追加はエラーの発生している View にカーソルを合わせて、Mac の場合は alt+enter > クイック修正、Windows の場合は ctrl+. から自動で追加することもできます。
・また、Export 属性を使用する場合、dll の参照を追加する必要があります。
Mac の場合は、ソリューション上の [参照] を右クリック(二本指タップ) > [参照の編集] で開くダイアログで。
Windows の場合は、[参照] を右クリック > [参照の追加] で開くダイアログで [アセンブリ] を選択し。
Mono.Android.Export にチェックをつけて [OK] をクリックします。

ここまでで、MainActivity.cs は次の様になります。

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

namespace XamMediaRecorder
{
    [Activity(Label = "@string/app_name", MainLauncher = true, ScreenOrientation = ScreenOrientation.Landscape)]
    public class MainActivity : Activity
    {
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);

            SetContentView(Resource.Layout.sample_main);
        }

        [Java.Interop.Export("onCaptureClick")]
        public void OnCaptureClick(View view)
        {
        }
    }
}

■ UI の確認

これだけで、UI の移植が完了しました。
F5 キーで実行し画面を確認しましょう。
次の様な画面が表示されていれば成功です。

■ 次回予定

ここまでで UI の移植は完了しました。
次回以降でロジックの移植を行って行きます。