ページ

2015年3月17日火曜日

[C#] Xamarin 始めました(始めてます)

始めましたと言っても最初に始めたのは「[勉強会] 第2回 Japan Xamarin User Group Conference 西日本編に参加しました」この記事を書いたちょっと前のことなので、すでに3ヶ月以上が経過しているんですけど。
個人的には Xamarin かなり気に入ってます。まぁ、Visual Studio が使えて C# で書けるって時点で気に入らないわけがないんですが(笑)

ところで、たまに「Xamarin を使うと C# で作ったものが iPhone でも Android でも動くようになるらしい」と誤解している人がいますので一応書いておくと、、、
Xamarin は『プログラミング言語として C# が使えるようになるだけ』です。
たとえば、iOS の加速度センサーからデータを取得するコードを Objective-C で書くとこんな感じです。

// iOS(Objective-C)でのコード
CMMotionManager *manager = [[CMMotionManager alloc] init];
if (manager.accelerometerAvailable) {
    manager.accelerometerUpdateInterval = 0.1;
    [manager startAccelerometerUpdatesToQueue:[NSOperationQueue currentQueue] withHandler:^(CMAccelerometerData *data, NSError *error) {
        // data.acceleration に加速度の値が入っている
    }];
}

これを Xamarin を使って C# で書くとこうなります。

// iOS(C#)でのコード
var manager = new CMMotionManager();
if (manager.DeviceMotionAvailable)
{
    manager.DeviceMotionUpdateInterval = 0.1;
    manager.StartDeviceMotionUpdates(NSOperationQueue.CurrentQueue, (data, error) =>
    {
        // data.Acceleration に加速度の値が入っている
    });
}

見比べればわかるように使っている言語が Objective-C から C# に変わっただけで、使っている API とかはほぼ同じです。
今度は Android で同じく加速度センサーからデータを取得するコードを Java で書くとこんな感じになります。

// Android(Java)でのコード
private SensorManager sensorManager;

@Override
protected void onCreate(Bundle savedInstanceState) {
    sensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
    List<sensor> sensors = sensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER);
    sensorManager.registerListener(this, sensors.get(0), SensorManager.SENSOR_DELAY_UI);
}

@Override
public void onSensorChanged(SensorEvent event) {
    // event.values に加速度の値が入っている
}

これを Xamarin を使って C# で書くとこうなります。

// Android(C#)でのコード
private SensorManager sensorManager;

protected override void OnCreate(Bundle savedInstanceState) {
    this.sensorManager = (SensorManager)ApplicationContext.GetSystemService(Context.SensorService);
    var sensors = this.sensorManager.GetSensorList(Android.Hardware.SensorType.Accelerometer);
    this.sensorManager.RegisterListener(this, sensors[0], SensorDelay.Ui);
}

public void OnSensorChanged(SensorEvent event) {
    // event.values に加速度の値が入っている
}

こちらも見比べればわかるように使っている言語が Java から C# に変わっただけで、使っている API とかはほぼ同じです。

こんな風に、Xamarin は抽象化レイヤーを持ってるわけでもなくでも無く、プラットフォームが持つ固有の機能をほぼそのままラップして C# で使えるようにしている、と思えばいいんじゃないかと思います。API 自体は iOS や Android のものをそのままクラスライブラリにしてあるだけという感じです。(メソッドの一文字目が大文字になっているとか、CMMotionManager.StartDeviceMotionUpdates メソッドのように引数の型によって判断がつく場合はオーバーロードで済ませるようになっているとか、C# で使って不自然にならないように変更されている部分はあります)
また、Xamarin.iOS と Xamarin.Android はクラスライブラリも含めて基本的に別物です。CMMotionManager クラスは Xamarin.iOS にしかありませんし、SensorManager クラスは Xamarin.Android にしかありません。ですから CMMotionManager クラスを使ったコードは Android では動かないどころかそもそも Xamarin.Android でコンパイルすることができません。こういったプラットフォームによって異なる部分はそもそもソースコードを兼用したりといったことはできないわけですね。もちろん、ラットフォームに依存しない部分、たとえばデータを処理する部分とかは共通化できます。Portable Class Library(PCL)や Shared Project といったそれを支援する機能もあります。MVC や MVVM などでビューとコントローラー、ビューとビューモデルをデータバインディングやメッセージングを使ってきちんと疎結合にしてあげればプラットフォームに依存するビュー部分は iOS や Android ごとに作り、依存しない部分は PCL で共通に、といった感じにできるわけです。(WPF や Windows ストアーアプリと共通化するってことだってできます)

※ Xamarin.Forms というビュー部分を抽象化して iOS、Android、Windows Phone の各プラットフォームのビューを「一度書けばすべてで動く」ようにしてくれる機能もあります。Xamarin.Forms はまだまだ進化の途中という感じですが、これはこれでちょっとしたものを作るときには便利なので応援してます。

今やっているプロジェクトでは iOS、Android の両方に対応する必要があるんですが、ビュー部分だけプラットフォームごとに作ってそれ以外は PCL でまとめています(MVVMCross を使っています)。さらにスマホに閉じたアプリではなくサーバーと通信しあうタイプのアプリなんですが、サーバー側は ASP.NET Web API や SignalR なんかを使ってます。もちろん C# です。さらにサーバーにあるデータを表示したりする Windows アプリも必要なんですがこれは WPF + C# です。とすべて C# で統一できてとても楽になりました。もしこれがスマホが Objective-C と Java で、サーバーが PHP で、Windows アプリが WPF C# で、なんてことになっていたら開発効率的に大変なことになっていたと思います。あと、このアプリはデータを処理・解析する必要があって、それがスマホやサーバー、Windows クライアントのいずれでも動かす必要があるんですが、これももちろん PCL でまとめてあります。なので、同じデータ処理 DLL が iOS、Android、ASP.NET、WPF の中で動いています。最初の頃は mono を使って CentOS 上でも動いてました(諸事情で今は CentOS は使ってませんが)。もしこれがプラットフォームごとに別々に実装しなくてはいけなくなったりしたら気が遠くなります。C/C++ なんかを使えばある程度共用はできると思いますが今ほど簡単にはいかないでしょうし。

と、こんなプロジェクトをやっているんですが正直ちょっと(いや、だいぶ)人手不足です。そのためリアルに求人してるんですが、興味があるっていう人どっかにいないかなぁ(Xamarin 知らなくても C# 好きなら OK)

0 件のコメント:

コメントを投稿