佐川 夫美雄

キミはNativeScriptを知っているか?Angular2でネイティブモバイルアプリが書けるぞ!

Web技術でアプリ開発2016特集・第4弾は、JavaScript(およびTypeScript)によるクロスプラットフォーム開発が可能ながらネイティブと同様の実行速度を得られる、Telerik社のNativeScriptを取り上げたいと思います。

NativeScriptは、Angular2とも組み合わせて使うことができる、現在注目のフレームワークです。本記事では、XMLによるUI定義を行う従来の開発手法だけではなく、Angular2(ただし、RC4という少し古いバージョン)と組み合わせてモバイルアプリを開発する方法まで網羅してご紹介します。

NativeScript_logo

NativeScriptの概要

NativeScript 2.0は、JavaScriptとCSSを使用し、ネイティブのiOSとAndroidのアプリを構築するためのフレームワークです。ネイティブで実行されるパフォーマンスとUXを提供し、その結果、ネイティブプラットフォームのレンダリングエンジンを使ってUIを構築します。WebViewsでのUIレンダリングはしていません。

NativeScriptにはtns-core-modulesというコアモジュールがあり、上記に述べたJavaScriptからネイティブへの変換を行っています。NativeScriptのgithubリポジトリを見ると「0.9.0」のリリースが「5 Mar 2015」なので、約1年とちょっとの歳月が経過していることになります。現時点での最新バージョンは「2.2.1」です。

NativeScriptでAngular2を利用する場合には、まず、Angular2のテンプレート(@Component.template)に、NativeScriptで提供しているディレクティブを記述します。そして、上記で説明したtns-core-modulesとnativescript-angularを利用してNativeScriptがビルドを行い、iOSやAndroidのネイティブコードを生成します。

nativescript-angular

「NativeScript with Angular2」の最初の「v0.3.0」がリリースされたのが今年8月初旬で、最新は「v0.3.1」です。

この記事では、macOS上での開発を前提に解説をしています。

インストール

インストール手順はquick-setupにも書かれている通り、あまり複雑なところはありません。しかし、もしAndroid SDKをはじめて利用する場合には少し戸惑うと思います(私もNativeScriptのあまりやさしいとはいえないエラーメッセージにちょっと苦しみました)ので、順を追って説明します。

  • ステップ1: Rubyのインストール
  • ステップ2: Node.jsのインストール
  • ステップ3: NativeScript CLIのインストール
  • ステップ4: iOSとAndroid開発に必要なもののインストール

ステップ1: Rubyのインストール

NativeScriptをビルドするとき、Rubyを利用します。Rubyのバージョンは2.2以降が必要ですが、macOSにデフォルトでインストールされているRubyは古いため、Homebrewを使って最新バージョンをインストールします。最新のRubyが入っている方は読み飛ばして下さい。

Homebrewのインストール

HomebrewはRubyを使いインストールし、インストール後環境変数を定義します。

rbenvとruby-buildのインストール

brewを使ってrbenvruby-buildをインストールします。rbenvを使ってRubyのバージョン管理を行います。ruby-buildはrbenvのプラグインで、異なるバージョンのRubyをコンパイルし、インストールするためのものです。

ステップ2: Node.jsのインストール

Node.jsはv4.0.0以降を利用する必要があります。rbenvと同様にバージョン管理システムをインストールします。Node.jsのバージョン管理システムにはnodebrew, nodist, nvm, nvm-windowsなどいくつかありますが、筆者はnodebrewを好んで利用しています。

nodebrew のインストール

curlを使ってインストールを行います。インストールが完了するとパスを追加するようにメッセージが表示されますので、.bash_profile に登録してください。

Node.jsのインストール

続いて、Node.jsをインストールします。nodebrew ls-remoteコマンドを使ってバージョンを確認し、nodebrew install-binaryコマンドを使ってNode.jsのインストールを行います。利用するバージョンを動かす場合にはnodebrew useコマンドを実行します。

今回、Node.jsのバージョンとしてはv5.12.0を利用しました。

ステップ3: NativeScript CLIのインストール

いよいよNativeScriptのインストールです。npmコマンドを使ってnativescriptをグローバルインストールします。nativescriptはスカッフォールディング(コード雛形の自動生成)を提供するモジュールで、tnsコマンドによって実行されます。

tnsコマンドを実行して、インストールが正しく行われているか確認しましょう。参考までにtnsコマンドで出力される内容はtns --helpと同じ内容です。tnsコマンドでは主に

  • テンプレートからプロジェクトの生成
  • プロジェクトへの生成プラットフォーム(iOS, Android)の追加
  • JavaScriptからネイティブへのビルド
  • エミュレータの実行

を行います

ステップ4: iOSとAndroid開発に必要なもののインストール

JDKのインストール

JDKはバージョンが8以降のものをインストールしてください。インストールが完了したら、.bash_profileに設定を登録してください。

Android開発環境のインストール

Android SDKをHomebrewからインストールし、変数ANDROID_HOMEを定義します.

Androidエミュレータのインストール

android-sdkのインストールが終わったら、実際に利用するエミュレータを定義します。android-sdkがインストールされているディレクトリへ移動し、andorid avdを実行することで設定を行います。android-sdk以下のディレクトリ構成は次の通りです。

Androidエミュレータを高速化するためのハードウェア支援環境「Intel Hardware Accelerated Execution Manager (Intel® HAXM) 」を事前にインストールします。次のスクリプトを実行してください。

完了したら、android avdを起動し、事前にエミュレータ定義を登録します。

android avd

この設定を忘れると「Cannot read property ‘targetNum’ of undefined」というエラーが出ます

参考までに、今回利用しているエミュレータは次のように定義しています。

スクリーンショット 2016-09-06 14.11.30

よくあるトラブルとしては、Dockerを起動しているようなら終了させておくのが無難です。Dockerが利用しているポートとエミュレータが利用するポートがぶつかり、実行できないことがあります。

iOS開発環境のインストール

macOSを利用されていれば、iOSのエミュレータを利用するのは容易だと思います。

Command Line Tools for Xcode

だいぶ長くなりましたが、これで開発環境の設定は完了です。尚、tnsコマンドにはtns doctorというコマンドがあります。環境設定などうまくできているかのチェックができますので、一通り終わった後に実行し、漏れがないかを確認します。

NativeScriptで作るHello World

ここではNativeScriptを使ってHello World的なアプリケーションを作成します。手順は

  1. プロジェクトの作成
  2. プラットフォームのインストール
  3. エミュレータの実行

です。NativeScriptでのアプリケーション作成にはtnsコマンドを使います。

今、プロジェクトをMyFirstNativeScriptAppとしますので、iOSとAndroidアプリケションの両方を作成する場合にはiOSとAndroidのプラットフォーム用ライブラリをインストールしエミュレートを起動します。

Androidエミュレータでの実行結果

MyFirstNativeScriptApp-Android

iOSエミュレータでの実行結果

MyFirstNativeScriptApp-iOS

tns create MyFirstNativeScriptAppで作成されたファイルを確認します。

このアプリケーションで特に重要なファイルがありますので、簡単に説明します。

  • app.js
  • main-page.xml
  • main-page.js
  • main-view-model.js

app.jsはアプリケーションが一番最初にロードするエントリーポイントで、このファイルからアプリケーションmain-page.jsの呼び出しを行っています。

main-page.xmlは画面をXMLで定義し、関連する処理をmain-view-model.jsに定義してます。

テンプレートを使って簡単なアプリケーションを作成する

NativeScriptには、テンプレートを使ってプロジェクトを生成する機能があります。

繰り返しになりますが、テンプレートを作成した後「プラットフォームのインストール」「エミュレータの実行」を行うとエミュレートで実行確認ができます。

このテンプレートはnpmに登録されています。が、まだあまり多くのテンプレートは定義されていないようです。その中から開発時に利用できそうなものを幾つかピックアップしました。具体的なコードは各テンプレートを使ってコードを生成し確認していただけると幸いです。

タブを使ったアプリケーション

タブ切り替えのテンプレート部分はTabViewタグを使い、各タブで表示する内容はTabViewItemで定義しています。

Androidエミュレータでの実行結果

MyNextGreatApp-Android

iOSエミュレータでの実行結果

MyNextGreatApp-iOS

一覧と詳細を表示するアプリケーション

一覧と明細はGridLayoutを使って表示する場所を定義し、一覧部分を表示するテンプレートはListViewを使っています。

明細部分はdetails-page.xmlでレイアウトを定義していて、具体的な内容の表示にはdetails-view.xmlを使っています。

Androidエミュレータでの実行結果

MyMasterDetailApp-Android

iOSエミュレータでの実行結果

MyMasterDetailApp-iOS

サイドメニュー付きアプリケーション

サイドメニュー付きアプリケーションを作成する場合には、サイドメニューdrawer-content.xmlを定義し、メニューをクリックしたときの画面をそれぞれ定義しています。

Androidエミュレータでの実行結果

MyDrawerApp-Android

iOSエミュレータでの実行結果

MyDrawerApp-iOS

NativeScriptとAngular2を組み合わせる

ここからが本記事の一番のポイント、「Angular2を使ったNativeScriptアプリケーション」に入ります。準備が長くて申し訳ありません!

npmにはいくつかのAngular2を利用したNativeScriptのテンプレートがありますが、今回はNativeScriptのチュートリアルを参考に、githubリポジトリーからテンプレートをcloneしたものを利用します。

NativeScript with Angular2で作るHello World

まずはリポジトリhttps://github.com/NativeScript/sample-Groceriesをcloneします。clone後、angular-startをcheckoutすると、NativeScript with Angular2で開発するための最も基本的な構成を得ることができます。

Androidエミュレータでの実行結果

HelloWorld-Android

iOSエミュレータでの実行結果

Helloworld-iOS

NativeScriptではBootstrapに特別なメソッドnativeScriptBootstrapを利用します。具体的にエントリーポイントmain.tsは次のように記述されます。

Angular2では、NativeScriptのXMLを@Component.templateにディレクティブとして定義します。ただ@Component.templateではXMLをそのまま利用できないので、少し書き換える必要があります。具体的には<foo />を<foo></foo>に書き換えるといった作業です。

具体的にこのサンプルの場合、XML定義では

ですが、Angular2ではコンポーネントとして定義します。

LabelはHTMLタグではなくNativeScriptで定義されたディレクティブです。NativeScriptでは幾つかのUIコンポーネントを定義していますので一覧にまとめます。

UIコンポーネントのマッピング

NativeScriptのUIコンポーネントは、iOSやAndroidのウィジェットにマッピングさせています。ビルドするとNativeScript with Angular2で定義したコンポーネントがマッピングされたiOSやAndroidのウィジェット変換されます。具体的な利用方法に関しては、Native Script UI Componentsを見ていただきたいと思います。

NativeScript with Angular2AndroidiOS
Buttonandroid.widget.ButtonUIButton
Labelandroid.widget.TextViewUILabel
TextFieldandroid.widget.EditTextUITextField
TextViewandroid.widget.EditTextUITextView
SearchBarandroid.widget.SearchViewUISearchBar
Switchandroid.widget.SwitchUISwitch
Sliderandroid.widget.SeekBarUISlider
Progressandroid.widget.ProgressBarUIProgressView
ActivityIndicatorandroid.widget.ProgressBarUIActivityIndicatorView
Imageandroid.widget.ImageViewUIImageView
ListViewandroid.widget.ListViewUITableView
HtmlViewandroid.widget.TextViewUILabel
WebViewandroid.webkit.WebViewUIWebView
TabViewandroid.support.v4.view.ViewPagerUITabBarController
SegmentedBarandroid.widget.TabHostUISegmentedControl
DatePickerandroid.widget.DatePickerUIDatePicker
TimePickerandroid.widget.TimePickerUIDatePicker
ListPickerandroid.widget.NumberPickerUIPickerView

NativeScript + Angular2でHello World

はじめに作成した「NativeScriptで作るHello World」のAngular2版のテンプレートがあります。アプリケーションの動きはまったく同じですがAngular2で書かれています。

テンプレート部分を見比べると、XMLで書かれていたテンプレートコードがAngular2スタイルで記載されていることが理解でき、結果見通しのよいコードになっています。

Todosアプリケーション

NativeScriptのサイトには、より多く機能が実装されたチュートリアルBuilding Apps with NativeScript and Angular 2を提供しています。完成したアプリケーションは先ほどと同じリポジトリhttps://github.com/NativeScript/sample-Groceriesにありますので、是非見て下さい。

Androidエミュレータでの実行結果

sample-Groceries-Android

iOSエミュレータでの実行結果

sample-Groceries-iOS

サンプルコードを読むと、NativeScriptで利用するnativeScriptBootstrapの使い方やNativeScript用のルーティング設定が記載されていたりとAngular2の特徴を活かした実装になっています。

今回は、環境設定からはじまり、NativeScriptを使ったもの、NativeScript wit Angular2へと進め、Hello World的なアプリケーションを動かすところまでをテンプレートを使いながら簡単に説明させていただきました。

最後に

NativeScriptの事例がないかと探してみましたがNativeScript Showcasesにいくつかありました。このアプリケーションがAngular2をベースにしたものかはわかりませんが、NativeScriptを使ったものです。

NativeScriptのXMLで定義したUIコンポーネントが、コンパイル時にiOS、Androidのウィジェットにそれぞれマッピングされネイティブアプリにコンパイルされます(ちょっと古いですがXSLTを思い出しました)。Angular2の@Component.templateを利用することでNativeScriptがUIコンポーネントの定義を解釈し、ネイティブコードの生成を行っています。

ただし、NativeScript with Angular2用に作成したコンポーネントとNativeScriptを使わない通常のAngular2のコンポーネントとの相互再利用性は低いです。ですが、慣れたAngular2の構造を利用しTypeScript(もしくはJavaScript)で書けるというのは非常に興味が湧くところです。

編集部よりお詫び
2016/9/9 18:30 編集部が付けた以前のタイトルは、一部の方を不快にさせる可能性があるとの判断のもと、記事タイトルを変更いたしました。 執筆者の佐川さん、及び以前のタイトルを不快に感じた多くの方々に、深くお詫び申し上げます。

Powered byNTT Communications

tag list

アクセシビリティ イベント エンタープライズ デザイン ハイブリッド パフォーマンス ブラウザ プログラミング マークアップ モバイル 海外 高速化 Angular2 AngularJS Chrome Cordova CSS de:code ECMAScript Edge Firefox Google Google I/O 2014 HTML5 Conference 2013 html5j IoT JavaScript Microsoft Node.js Polymer Progressive Web Apps React Safari SkyWay TypeScript UI UX W3C W3C仕様 Webアプリ Web Components WebGL WebRTC WebSocket WebVR