2017年7月12日水曜日

Xamarinでアプリ開発して良かったこと悪かったこと

業務でXamarin.Formsを使い、iOSとAndroid向けに同じアプリを作るということをしました。

以前はiOSとAndroidの担当が数名ずつで2チームだったのですが、仕様や実装に関する知識が分断しやすく、結果的に実装の都合を互いに押しつけあうなど問題があったのでその解決をXamarinに求めたのです。(その後他にも色々対策はしましたが)

「どうだった」と聞かれがちなので、良かった点と悪かった点を書いておこうと思います。随時追記もするつもりです。

■どんな感じだったか
  • Xamarin.Formsをベースに、たとえばPageの切り替えアニメをiOSとAndroidで同様にするなど、独自のUIフレームワークを作りました。
  • UIが絡まなくてNative機能を使いまくるところはPCL+BindingLibraryな共通ライブラリを作り、UIからはあまりNativeを意識せず実装できるようにしました。
  • UI側でNative機能を使いたいときはDependencyServiceやRendererを使いました。
  • NuGetサーバやCI環境など色々必要になりました。

■良かった点
  • 仕様に関する知識が分断しづらくなりました。
    ある画面がiOSだとこういう仕様でAndroidだと違う仕様というのが激減しました。もちろんXamarin.Formsの中で実装が異なるので挙動が違うというのは良くありましたがたいていはRendererなどで回避・調整可能でした。
  • UIフレームワークやライブラリを使う「だけ」のNative分からない人も開発に参加できるようになりました。人の融通がしやすくなるという意味で良かったです。
  • GitやiOS、Macなど今まで「食わず嫌い」だったものが少し浸透しました。
    SubVersionで止まっている人にGitを使わせたり、AndroidやWindowsしか触ったことのない人に多少なりともiOSやMacを触らせることができました。
    GitはMergeコミットだらけになったり色々アレですが、そこは具体的な悪影響が出るまで我慢です。

■悪かった点
  • 開発環境を人数分揃えるのにかなりコストがかかりました(詳しくはココ)。
    XcodeやAndroid Studioだけなら無料なのに。
  • 実装に関する知識は分断したままでした。
    Nativeを分かる人が独自のUIフレームワークやライブラリを作る担当になり、画面を作る人は別となることが多かったです。結果iOS、Android、C#それぞれで担当部分しか触らないという人はそれなりに残りました。うまく分担できたという気もしますが、もう少し「誰でも触れる」状態が作れればと思います。ただMacやMSDN付きでないとやりづらくコストもより増えてしまうので敬遠されました。
  • 問題の原因を探る階層が増えました。
    例えばUI部品を思うように配置できなかったとき、Nativeならそれらの範囲を調べれば良いのですが、Xamarin.Formsの場合はそちらの挙動も見る必要があったりして手間を感じました。
  • なにかとiOSはズルいです。
    普通に作るとどうしてもiOSアプリの方が安定しています。処理中にホームボタンを押したりしたときもiOSはただサスペンドしている感じですが、Androidは動き続けてヌルポで死ぬとか。画像を読み込む速度もiOSの方が早いです。
    さらには独自ライブラリのほうで依存関係が増えたとしても、iOSの方は簡単に取り込めるのに、Androidはアプリ側でイチイチBinding Libraryを作成してjarを取り込まないとClassNotFoundExceptionになったり。Androidはやりづらさがありました。
  • Mac Agentがアテにならない
    Windows(Visual Studio)からMacへ接続してリモートビルドをかけるための仕組みですが、Visual Studioからのデバッグ実行などは頻繁に切れて失敗します。コマンド(msbuild)からなら割と安定しているのですが。
  • Xamarinの更新がドキドキ
    XcodeやAndroid Studioであれば更新しても問題にあうことはさほど頻繁ではなかったように思いますが、Xamarinは毎回心臓に悪いです。特に今回のXamarin.Android 7.3のようにGCやMonoが変わって実行時に原因不明でクラッシュするとかやめてほしいです。
  • 依存関係が難しい
    例えば今のプロジェクトはFormsの2.3.3.180を使っているのですが、2.3.4に上げるのは難しいかもしれません。
    というのもこれと合わせてXamarin.Android.Support.v4の23.3を使っていて、AndroidのBinding Libraryのほうも同じバージョンで、と揃えた状態で、これまたバージョンを上げるとどうなるか分からないというのがあります。ただモバイル開発は基本的にバージョン上げていかないとシンドイので、近いうちに、せーの、でやることになるのだと思います。

■その他

  • 計測していないのですが、コードを共通化できた部分はさほどないと思います。
    前述の通りBindingLibraryやRenderer、DependencyServiceなども結構書きましたし。

というわけで、Xamarinは(目的と手段とスキルと制限などとコストが折り合いつけば、わりと)いいぞ。

Visual Studio for MacのmsbuildでビルドするとDEBUG定数がなくなる

ちょっと不思議な現象です。

あるXamarin.iOS(+PCL)プロジェクトを、Visual Studio for MacのIDEでビルドするとDEBUG定数があるのに、同じMac上のmsbuildでビルドするとDEBUG定数がなくなるのです。

ソース内で
#if DEBUG
#pragma warning DEBUG is defined.
#else
#pragma warning DEBUG is not defined.
#endifと書き、またmsbuildに/v:diagを付けてログをみたところ、やはり"is not defined"と出力されましたし、DefineConstantsにTRACEしか付いていないみたいでした。

Ad-Hoc|iPhone構成にDEBUGを付けたのが悪かったのだろうか。

もうしばらく調べてみます。

MacでもWindowsと同じようにNuGetパッケージを作成しPushできる

以前、Xamarinを使った開発でNuGetのパッケージを作るならWindows側で行う方がよさそうというエントリを書きました。

その後Macの環境もVisual Studio for Macになり、何となく思いつきで「sudo nuget update -self」してみました。

すると2.xだったnugetが4.xになり、Windows(nugetは3.x)でpackしたNuGetパッケージと同じようなものが生成できるようになりました。
(ZIP展開して、中身がIDっぽい値以外ファイル構成や中身が同じでした。2.xの時はだいぶ違いました)

pushも問題なくできたので、そのまま使っています。

もともとこのMacはJenkinsのいちスレーブで、nuget pack/pushするためにWindowsスレーブも使っていたのですが、Macだけで済むようになりました。

めでたしめでたし。

2016年10月18日火曜日

Xamarinを使った開発でNuGetのパッケージを作るならWindows側で行う方がよさそう

Xamarinを使ったアプリ開発で「共通ライブラリ」的なものを作ることになりました。

複数のアプリで同じコードを使い回せるようにしたかったからです。

  • 自作のネイティブライブラリ(Binding Library)のDLL(iOS, Android)
  • Binding Libraryを使うXamarin.NativeのDLL(iOS, Android)
  • PCLのDLL
これらのファイルをnuspecに書いて、JenkinsからXamarin Studio(Mac)側のNuGetでpackしました。

そして出来たnupkgファイルをローカルにおいてVisual Studioで読み込ませてみようとしました。

・・・が、できません。表示されないのです。

Simple NuGet Severで構築したサーバにPushするとインストールはできるのですが、アンインストールや更新ができません。(metadataが読めない的なエラーが出る)

別に作った、Binding Libraryがないnupkgだと普通にアンインストールも更新もできます。

ちょっとワケが分からなかったのですが、色々試した結果、Windows側のNuGetでpackすると多少マシになりました。

「インストール済み」を見ようとするとエラーが表示されるのですが、とりあえずパッケージを選んでアンインストールしたり更新したりはできるようになりました。

Macで作成したnupkgとWindowsで作成したnupkgを展開してdiffしてみると、テキストファイルの改行コードが一部異なったりして(これはGitの影響かもしれないけど)、まぁ違うんだなーと。

あとNuGetのバージョンもMacのほうは2.12で、Windowsのほうは3.4と異なるので、とりあえずWindowsでpack, pushするようにしました(Jenkinsおじさんが)

なんというかMSDN付きで良かったと思う、今日この頃です。


2016年10月4日火曜日

ファーウェイの端末はFLAG_ONGOING_EVENTやsetOngoingしても通知が消せる

最近HUAWEIのhonor 8をメイン端末にしました。

そこで気づいたのですが、愛用しているアラームアプリが通知領域からすぐに消えてしまっています。

アプリを起動すると通知が表示されるのですが、フリックすると消えてしまうのです。

あれ?と思って実際に作って試してみたのですがNotificationにFLAG_ONGOING_EVENTをセットしても消せました。

それならとNotificationCompat.BuilderでsetOngoing(true)してみましたが同様です。

もしかしてAndroid 6.0あたりで変わったのか?とも思いましたが、Galaxyなどでは普通に消せません。

ここで気づいたのですが「すべて消去(ごみ箱ボタン)」では消えません。
通知すべてがsetOngoingしてある場合はごみ箱も表示されません。

というわけで、とりあえずの結論としては「ファーウェイの端末だと手動で通知が消せてしまう」ようです。

なお手元のHuawei MediaPad T1 7.0(4.4.2)で通知を消そうとすると『この通知を消去すると、送信中のアプリケーションで例外が発生します。消去しますか?』という警告ダイアログが表示されました。

honor 8だと表示されないので、例外も出ていないのでしょうか。

2016年9月9日金曜日

『実践としてのプログラミング講座』のレシピ8をちょっと改造

実践としてのプログラミング講座』という本を買いました。
Kindle向けではないですが、スマホで読んでいます。

月2回程度のボランティアとはいえ私もプログラミングを教えている身なので、Chapter 4の冒頭に書かれていたような「タブとインデントをおろそかにする」のはよく分かります。

さて、レシピ8に載っていた「爆弾回しゲーム」を次回の教材にしようとして微調整しました。

ちょっとずつ増築していこうと思っているネタを少し盛っただけですが、ここにあります。



改造したのはこのあたりです。
  • 「ばくはつ」の音の前に、ばくだんが大きくなるたびに「ポヨン」を鳴らす
  • 時々「少し小さくなる」ことで単調さを減らす
  • 爆発しっぱなしもナンなので、爆発してしばらくしたら「ゲームオーバー」で終わらせる
写経では何も学ばない風なので、おそらく次回も「小さなものからコツコツと足していく」パターンで進めようと思います。

  1. 先に爆発を作る(「ひとつだけでる」を入れて動きを見る)
  2. 爆弾の「ひとつだけでる」を消して、大きくなる爆弾を作る
  3. 爆発をクローンさせて、いったん完成。
  4. 微調整1:「ポヨン」を入れる
  5. 微調整2:確立で大きくなるようにする
  6. 微調整3:確立の「それ以外」で少し小さくなるようにする
  7. 爆発を4秒後に消してゲームオーバーとする
本当は赤い導線 or 青い導線みたいなゲームになると良いのだけど、それはさらに次の改造にしたいと思います。

ちなみに『「時間が進んだ」とき』というのは、初心者にはなじみのない概念なのかなと良く思います。頭の中で「あとで」「しばらくしたら」みたいなところまで分かっていても、このブロックにはたどり着かないことが多いです。

2016年9月8日木曜日

Xamarinを使うならMacはほぼ必須になるし、おそらくMSDN付きのVisual Studioを買うハメになる

Xamarinの入門記事を読むとたいていモヤモヤします。

これなんかも丁寧に書かれていて良いと思うのですが、『Macが必要なのはXamarin.iOSでiOSアプリを開発する場合だけ』とか言っちゃうあたりが引っかかるのです。

Androidアプリだけ開発したいなら素直にAndroid Studioを使う方がラクです。
IDEとしても優秀だし、Gradleも多機能で慣れれば快適です。

Xcodeは・・・嫌いですが無料だし、iOSアプリだけ開発したいならそれで良いのです。

そして、なんなら別々にAndroid版とiOS版のアプリを開発するほうがたいていラクです。
ググれば解決することが多いから。

今からXamarinを使う場合、普通はXamarin.Formsを使いたくなると思います。
これはかなりイバラの道です。

あまりノウハウもありませんし、そもそも部品が少ないのですぐにRendererやEffectの出番となります。
何しろフリックの検知すらできないのです。フリックするならそれぞれのNativeのViewにGestureDetector的なやつをセットしてイベント拾ってジェスチャー判定してそれをXamarin側に返す・・・というコードを書かなければなりません。

つまりiOSとAndroid両方の知識が必要になってくるのです。そのうえXamarin.FormsやC#の都合が出てくるのです。よほどの超人あるいは分業ができなければムリです。

それでもXamarinを使いたいのは、何かしらのロジック部分をC#で書いて共通化したいからだと思います。

前振りが長くなりましたが、Xamarinを使うケースはたいていAndroidとiOSのアプリを開発することになると思います。

つまり、Macは必須です。

さらに個人(正確には5人以内だっけ)でやっているのであれば無料のCommunity Editionを使えますが、そうでない組織ならVisual StudioのProfessional、しかもMSDN付が必要となります。

iOS向けのビルドをしないのであれば、MSDNは不要なので、分業してiOS担当の割合を下げれば全員がMSDN付きでなくても構いません。

こうして、私の職場でもン十万支払ってライセンスを何本か買いました。

MSDNがあれば開発用にWindowsマシンいっぱい作ったり、Azureでそこそこ何かできるな・・・と企んでいます。