Cordovaで始めるハイブリッドモバイルアプリ（for Windows）

※本ドキュメントは、2015年10月に開催するハンズオンワークショップ向けのドキュメントです。
※本内容は、ドキュメント作成時において有効なAPIやライブラリを利用しています。

#完成イメージ
##画面
![023.png](https://qiita-image-store.s3.amazonaws.com/0/81226/bf3a3761-0659-93b6-affe-0d86062d2099.png)
![024.png](https://qiita-image-store.s3.amazonaws.com/0/81226/cc88b847-04d9-7317-40a4-31bcaf5000c3.png)

##概要
為替レートを取得するAPIから現時点のレートを取得し、変換前の通貨から変換後の通貨への計算を行うアプリケーションです。

##ありがとうございます
今回利用するAPIは下記になります。
[クジラ 外国 為替 確認 API ( 為替 RSS )](http://api.aoikujira.com/kawase/)

くじらはんど様には勉強会にて当該APIを利用する旨をお伝えし、快諾頂いて居ります。
※Swiftサンプルでも同じAPIを利用させて頂いて居ります。

#開発環境の準備
##開発環境仕様
今回は、Windows7 / 32bitでの開発になります。
JDK、ant、node.jsのインストールは既にされている事を前提とします。
##Cordova
Cordovaをインストールします。
これが、スマートフォン向けハイブリッドアプリケーション開発の為のフレームワークになります。

コマンドプロンプトから、下記の通りコマンドを実行します。
`$npm install -g cordova`
![001.png](https://qiita-image-store.s3.amazonaws.com/0/81226/6f6f6331-2261-1a23-0464-872957ffe330.png)
～途中省略
![002.png](https://qiita-image-store.s3.amazonaws.com/0/81226/3b5dbc1e-1565-b43f-b296-50059b571b0a.png)
特にエラーが無ければ、上記のように終了します。

下記の通り、コマンドを実行し、バージョンが表示されればインストール成功です。
`$cordova -v`
![003.png](https://qiita-image-store.s3.amazonaws.com/0/81226/98489343-2964-21e5-bd78-e59921a692f7.png)

##plugman
plugmanをインストールします。（今回は必須では無いです）
これは、モバイルデバイス固有機能へのアクセスを提供するCorodva Pluginのひな形を作ってくれる、コマンドラインツールになります。

コマンドプロンプトから、下記の通りコマンドを実行します。
`$npm install -g plugman`
![004.png](https://qiita-image-store.s3.amazonaws.com/0/81226/e3558364-52c2-506b-83e1-847836806222.png)
～途中省略
![005.png](https://qiita-image-store.s3.amazonaws.com/0/81226/a0ba6082-c812-c2b3-fc9e-8fd81e2b1bc3.png)
特にエラーが無ければ、上記のように終了します。

下記の通り、コマンドを実行し、バージョンが表示されればインストール成功です。
`$plugman -v`
![006.png](https://qiita-image-store.s3.amazonaws.com/0/81226/bc8d4012-fd4e-7de3-c709-cd09366daedd.png)

##Android SDK for Windows
今回、Androidのエミュレーターで動作確認を行おうと思うので、AndroidのSDKをインストールします。
Javaがインストールされている事が前提なので、未インストールの場合は事前にJAVAをインストールして下さい。

インストーラーは、下記リンクからダウンロードできます。
http://developer.android.com/sdk/installing/index.html

「STAND-ALONE SDK TOOLS」をクリック。
![007.png](https://qiita-image-store.s3.amazonaws.com/0/81226/730094cd-e0b0-8805-ec49-1ec40cf5c28f.png)

「download the SDK now」をクリック。
![008.png](https://qiita-image-store.s3.amazonaws.com/0/81226/52a47696-30e9-30ce-ecf3-33d4e1462308.png)

「installer_r24.3.4-windows.exe (Recommended)」をクリック。（※記事執筆時点での最新）
![009.png](https://qiita-image-store.s3.amazonaws.com/0/81226/62179560-7012-873f-1a83-76fc09bc3f16.png)

「規約同意のチェックボックス」にチェックを入れ「DOWNLOAD INSTALLER_R24.3.4-WINDOWS.EXE」をクリックでダウンロードが開始します。
![010.png](https://qiita-image-store.s3.amazonaws.com/0/81226/c06f3809-0dbd-9828-0f48-cb8eecb2e24d.png)

ダウンロードしたインストーラーを実行します。Nextをクリック。
![011.png](https://qiita-image-store.s3.amazonaws.com/0/81226/ce8651ca-e644-519b-e8d6-e73240484f66.png)

Javaがインストールされていないとここでエラーになります。インストールされていれば下記の用に、Javaが見つけられた旨を表すメッセージが表示されます。問題なければNextをクリック。
![012.png](https://qiita-image-store.s3.amazonaws.com/0/81226/a7344646-ab82-fae1-0105-e01801bb30f6.png)

「Install just for me」にチェックを入れNextをクリック。
![013.png](https://qiita-image-store.s3.amazonaws.com/0/81226/5cc83aee-d878-35fc-9da5-081c5cef4a0f.png)

インストール先のパスを指定し（任意の場所）Nextをクリック。
![014.png](https://qiita-image-store.s3.amazonaws.com/0/81226/e14b7e3f-5557-dfbb-ef21-a5a638617d4e.png)

スタートメニューへ登録する際の名前を指定し（必要であればディレクトリも作成可）Installをクリック。
不要で有れば「Do not create shortcuts」にチェックを入れて下さい。
![015.png](https://qiita-image-store.s3.amazonaws.com/0/81226/9da56a6a-b222-51d9-199f-57407c2cc4e2.png)

インストールが完了しました。
![016.png](https://qiita-image-store.s3.amazonaws.com/0/81226/67968b74-3159-741f-d3ca-22f20c774546.png)
![017.png](https://qiita-image-store.s3.amazonaws.com/0/81226/a00e4a74-9c11-6275-2823-ac5f66e9990a.png)

SDKマネージャーを起動します。
![025.png](https://qiita-image-store.s3.amazonaws.com/0/81226/029d2452-aa33-5157-e597-c0c0e4de04a0.png)

今回はAndroid5.1.1(API22)をビルドターゲットとします。
下記のプログラムをインストールしていきます。
- Android SDK Tools
　アプリケーション、他のユーティリティツールの、開発、デバッグ及びテスト用ツールを含みます。
- Android SDK Platform-tools
　最新プラットフォーム向けの、開発及びデバッグに必要なツールを含みます。
- Android SDK Build-tools
　SDK22から追加されたビルド用モジュールです。
- SDK Platform
　Android搭載デバイスに準拠したAndroidライブラリ、システム画像、サンプルコード、エミュレータスキン、そして各バージョン特有のツールを含みます。
- ARM EABI v7a System Imagemage
　エミュレーターに利用するCPUを含んだシステムイメージです。

※ターゲットOSはどれでも構いませんが、それに適応したプログラムをインストールして下さい。
![026.png](https://qiita-image-store.s3.amazonaws.com/0/81226/1f20b1a9-163b-718b-3018-0b21366388a2.png)

Android SDKのインストールが完了したら、下記二つのパスを通す為に、環境変数へ追加して下さい。
`インストール先\android-sdk\platform-tools`
`インストール先\Android\android-sdk\tools`

AVDマネージャーを起動します。
![027.png](https://qiita-image-store.s3.amazonaws.com/0/81226/a8f053fb-f268-084e-80e0-d52cc41f0298.png)

Createボタンを押します。
![028.png](https://qiita-image-store.s3.amazonaws.com/0/81226/ac553a57-e396-317b-f576-c11cda9baec4.png)

下記の通り設定します。
AVD Name：　AVD_Android22
Device：　5.1" WVGA(480x800: mdpi)
Target：　Android 5.1.1 - API Level 22
CPU/ABI：　ARM(armeabi-v7a)
Keyboard Hardware keyboard present チェックボックス：　ON
Skin：　Skin with dynamic hardware controls
Front Camera：　None
Back Camera：　None
その他はデフォルトのままで、OKボタンを押します。
![029.png](https://qiita-image-store.s3.amazonaws.com/0/81226/e3ac63c6-acef-4d3e-712c-85881a398d16.png)

作成されたAVDを選択し、Startボタンをクリックします。
![030.png](https://qiita-image-store.s3.amazonaws.com/0/81226/64b6de92-e121-e5dc-a69f-a02611c170fa.png)

そのままLaunchボタンをクリックします。
![031.png](https://qiita-image-store.s3.amazonaws.com/0/81226/580f4b2e-decf-8800-23af-3b001a785156.png)

しばらく時間がかかりますが、Androidのエミュレータが起動しOSのロックスクリーンが表示されます。
![032.png](https://qiita-image-store.s3.amazonaws.com/0/81226/1a5032ad-019a-8366-f1a2-d8997cdc2053.png)
![033.png](https://qiita-image-store.s3.amazonaws.com/0/81226/b46732b0-9732-7a64-6ed4-e3e851db2bec.png)

これで準備はOKです！

#プロジェクトの作成
プロジェクトを補完するディレクトリを作成します。
どこに作成しても良いですが、ここでは説明の為下記で統一します。
`C:\Users\ユーザー名\Documents\cordova`

コマンドプロンプトから下記のコマンドを実行します。
`$cordova create kawaseapp jp.mki.cordovahandson SampleHybridApp -d`
プロジェクトが作成されます。
![034.png](https://qiita-image-store.s3.amazonaws.com/0/81226/4d4c4d1d-1d8a-62ab-94cc-c5689f936c8b.png)

treeコマンドで、ディレクトリ構成が生成されているのが確認出来ます。
`$tree /f`
![036.png](https://qiita-image-store.s3.amazonaws.com/0/81226/72815340-b398-cc5b-3579-c77441f2b86f.png)

作成されたプロジェクトディレクトリへ移動します。
`$cd kawaseapp`

Nativeアプリ依存のファイル生成を行います。Android向けに、下記のコマンドを実行します。
`$cordova platform add android`
問題がなければ下記のように正常に終了します。
![037.png](https://qiita-image-store.s3.amazonaws.com/0/81226/17687dd8-4650-bcef-e78e-c09f8da56eaa.png)

treeコマンドで、追加されたファイルを確認出来ます。
`$tree /f`

```lang:コマンドプロンプト
C:.
│  config.xml
│
├─hooks
│      README.md
│
├─platforms
│  │  platforms.json
│  │
│  └─android
│      │  .gitignore
│      │  AndroidManifest.xml
│      │  build.gradle
│      │  project.properties
│      │  settings.gradle
│      │
│      ├─assets
│      │  └─www
│      │      │  cordova.js
│      │      │  cordova_plugins.js
│      │      │  index.html
│      │      │
│      │      ├─cordova-js-src
│      │      │  │  exec.js
│      │      │  │  platform.js
│      │      │  │
│      │      │  ├─android
│      │      │  │      nativeapiprovider.js
│      │      │  │      promptbasednativeapi.js
│      │      │  │
│      │      │  └─plugin
│      │      │      └─android
│      │      │              app.js
│      │      │
│      │      ├─css
│      │      │      index.css
│      │      │
│      │      ├─img
│      │      │      logo.png
│      │      │
│      │      ├─js
│      │      │      index.js
│      │      │
│      │      └─plugins
│      │          └─cordova-plugin-whitelist
│      │                  whitelist.js
│      │
│      ├─cordova
│      │  │  android_sdk_version
│      │  │  build
│      │  │  build.bat
│      │  │  check_reqs
│      │  │  check_reqs.bat
│      │  │  clean
│      │  │  clean.bat
│      │  │  defaults.xml
│      │  │  log
│      │  │  log.bat
│      │  │  run
│      │  │  run.bat
│      │  │  version
│      │  │  version.bat
│      │  │
│      │  ├─lib
│      │  │      android_sdk_version.js
│      │  │      appinfo.js
│      │  │      build.js
│      │  │      check_reqs.js
│      │  │      device.js
│      │  │      emulator.js
│      │  │      exec.js
│      │  │      install-device
│      │  │      install-device.bat
│      │  │      install-emulator
│      │  │      install-emulator.bat
│      │  │      list-devices
│      │  │      list-devices.bat
│      │  │      list-emulator-images
│      │  │      list-emulator-images.bat
│      │  │      list-started-emulators
│      │  │      list-started-emulators.bat
│      │  │      log.js
│      │  │      plugin-build.gradle
│      │  │      retry.js
│      │  │      run.js
│      │  │      spawn.js
│      │  │      start-emulator
│      │  │      start-emulator.bat
│      │  │
│      │  └─node_modules
│      │      ├─nopt
│      │      │  │  LICENSE
│      │      │  │  package.json
│      │      │  │
│      │      │  ├─lib
│      │      │  │      nopt.js
│      │      │  │
│      │      │  └─node_modules
│      │      │      └─abbrev
│      │      │              abbrev.js
│      │      │              LICENSE
│      │      │              package.json
│      │      │
│      │      ├─q
│      │      │  │  CONTRIBUTING.md
│      │      │  │  LICENSE
│      │      │  │  package.json
│      │      │  │  q.js
│      │      │  │  queue.js
│      │      │  │  README.md
│      │      │  │
│      │      │  └─benchmark
│      │      │          compare-with-callbacks.js
│      │      │          scenarios.js
│      │      │
│      │      ├─shelljs
│      │      │  │  .documentup.json
│      │      │  │  .jshintrc
│      │      │  │  .npmignore
│      │      │  │  .travis.yml
│      │      │  │  global.js
│      │      │  │  LICENSE
│      │      │  │  make.js
│      │      │  │  package.json
│      │      │  │  README.md
│      │      │  │  shell.js
│      │      │  │
│      │      │  ├─bin
│      │      │  │      shjs
│      │      │  │
│      │      │  ├─scripts
│      │      │  │      generate-docs.js
│      │      │  │      run-tests.js
│      │      │  │
│      │      │  └─src
│      │      │          cat.js
│      │      │          cd.js
│      │      │          chmod.js
│      │      │          common.js
│      │      │          cp.js
│      │      │          dirs.js
│      │      │          echo.js
│      │      │          error.js
│      │      │          exec.js
│      │      │          find.js
│      │      │          grep.js
│      │      │          ls.js
│      │      │          mkdir.js
│      │      │          mv.js
│      │      │          popd.js
│      │      │          pushd.js
│      │      │          pwd.js
│      │      │          rm.js
│      │      │          sed.js
│      │      │          tempdir.js
│      │      │          test.js
│      │      │          to.js
│      │      │          toEnd.js
│      │      │          which.js
│      │      │
│      │      └─which
│      │          │  LICENSE
│      │          │  package.json
│      │          │  README.md
│      │          │  which.js
│      │          │
│      │          └─bin
│      │                  which
│      │
│      ├─CordovaLib
│      │  │  AndroidManifest.xml
│      │  │  build.gradle
│      │  │  cordova.gradle
│      │  │  project.properties
│      │  │
│      │  └─src
│      │      └─org
│      │          └─apache
│      │              └─cordova
│      │                  │  AuthenticationToken.java
│      │                  │  CallbackContext.java
│      │                  │  Config.java
│      │                  │  ConfigXmlParser.java
│      │                  │  CordovaActivity.java
│      │                  │  CordovaArgs.java
│      │                  │  CordovaBridge.java
│      │                  │  CordovaClientCertRequest.java
│      │                  │  CordovaDialogsHelper.java
│      │                  │  CordovaHttpAuthHandler.java
│      │                  │  CordovaInterface.java
│      │                  │  CordovaInterfaceImpl.java
│      │                  │  CordovaPlugin.java
│      │                  │  CordovaPreferences.java
│      │                  │  CordovaResourceApi.java
│      │                  │  CordovaWebView.java
│      │                  │  CordovaWebViewEngine.java
│      │                  │  CordovaWebViewImpl.java
│      │                  │  CoreAndroid.java
│      │                  │  ExposedJsApi.java
│      │                  │  ICordovaClientCertRequest.java
│      │                  │  ICordovaCookieManager.java
│      │                  │  ICordovaHttpAuthHandler.java
│      │                  │  LOG.java
│      │                  │  NativeToJsMessageQueue.java
│      │                  │  PluginEntry.java
│      │                  │  PluginManager.java
│      │                  │  PluginResult.java
│      │                  │  Whitelist.java
│      │                  │
│      │                  └─engine
│      │                          SystemCookieManager.java
│      │                          SystemExposedJsApi.java
│      │                          SystemWebChromeClient.java
│      │                          SystemWebView.java
│      │                          SystemWebViewClient.java
│      │                          SystemWebViewEngine.java
│      │
│      ├─libs
│      ├─platform_www
│      │  │  cordova.js
│      │  │
│      │  └─cordova-js-src
│      │      │  exec.js
│      │      │  platform.js
│      │      │
│      │      ├─android
│      │      │      nativeapiprovider.js
│      │      │      promptbasednativeapi.js
│      │      │
│      │      └─plugin
│      │          └─android
│      │                  app.js
│      │
│      ├─res
│      │  ├─drawable-hdpi
│      │  │      icon.png
│      │  │
│      │  ├─drawable-land-hdpi
│      │  │      screen.png
│      │  │
│      │  ├─drawable-land-ldpi
│      │  │      screen.png
│      │  │
│      │  ├─drawable-land-mdpi
│      │  │      screen.png
│      │  │
│      │  ├─drawable-land-xhdpi
│      │  │      screen.png
│      │  │
│      │  ├─drawable-ldpi
│      │  │      icon.png
│      │  │
│      │  ├─drawable-mdpi
│      │  │      icon.png
│      │  │
│      │  ├─drawable-port-hdpi
│      │  │      screen.png
│      │  │
│      │  ├─drawable-port-ldpi
│      │  │      screen.png
│      │  │
│      │  ├─drawable-port-mdpi
│      │  │      screen.png
│      │  │
│      │  ├─drawable-port-xhdpi
│      │  │      screen.png
│      │  │
│      │  ├─drawable-xhdpi
│      │  │      icon.png
│      │  │
│      │  ├─values
│      │  │      strings.xml
│      │  │
│      │  └─xml
│      │          config.xml
│      │
│      └─src
│          ├─jp
│          │  └─mki
│          │      └─cordovahandson
│          │              MainActivity.java
│          │
│          └─org
│              └─apache
│                  └─cordova
│                      └─whitelist
│                              WhitelistPlugin.java
│
├─plugins
│  │  android.json
│  │  fetch.json
│  │
│  └─cordova-plugin-whitelist
│      │  CONTRIBUTING.md
│      │  LICENSE
│      │  NOTICE
│      │  package.json
│      │  plugin.xml
│      │  README.md
│      │  RELEASENOTES.md
│      │  whitelist.js
│      │
│      └─src
│          ├─android
│          │      WhitelistPlugin.java
│          │
│          └─ios
│                  CDVNavigationWhitelistPlugin.h
│                  CDVNavigationWhitelistPlugin.m
│
└─www
    │  index.html
    │
    ├─css
    │      index.css
    │
    ├─img
    │      logo.png
    │
    └─js
            index.js
```

もし、iOS向けも生成したければ、下記のコマンドを実行します。（macのみ）
※別途iOS SDKが必要です。macにしかインストールできないので今回は使いません。
`$cordova platform add ios`

#HTML部分の実装
##index.html
今回はjavascriptは特に外へ出しておらずHTMLファイル内に記述しています。お好みで外部ファイル化して下さい。
尚、HTMLはutf-8で書いて下さい。

```lang:index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Sample Hybrid App</title>
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.css" />
<script src="http://code.jquery.com/jquery-2.1.4.min.js"></script>
<script src="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script>
<script>

var b_unit = "";	// 変換前の通貨単位
var a_unit = "";	// 変換後の通貨単位
var b_amount = 0;	// 変換前の通貨額
var e_late = 0;		// APIから取得する為替レート

$(document).ready( function() {
	$("#button_1").click(function(){

		// 変換前の通貨種別を取得
		b_unit =  document.getElementById("b_unit").value;
		// 変換後の通貨種別を取得 
		a_unit =  document.getElementById("a_unit").value; 

		// 為替レート取得APIを呼出し
		$.getJSON("http://api.aoikujira.com/kawase/json/"+b_unit, getFunc);

	});

	// API呼出のコールバック関数
	function getFunc(myData){

		// 為替レートを取得
		if(a_unit=="USD"){
			// JPYからUSD
			e_late = myData.USD;
		}else if(a_unit=="JPY"){
			// USDからJPY
			e_late = myData.JPY;
		}else{
			// 今後対象通貨を増やす場合は適宜追加
		}

		// 計算の為にFloat型へパース
		b_amount = parseFloat(document.getElementById("b_amount").value);
		e_late = parseFloat(e_late);

		// 変換前の値×取得した為替レート
		var resaultval = e_late*b_amount;

		// 結果表示
		alert(b_amount+(b_unit.toUpperCase())+"は"+resaultval+a_unit);
	};

});
</script>
</head>
<body>
<!-- ヘッダー部 -->
<div data-role="header" data-theme="b">
	<h1>為替両替シミュレーター</h1>
</div>

<!-- コンテンツ部 -->
<div role="main" class="ui-content">
	<form name="exchange_form">
		<!-- 変換前の通貨単位を選択 -->
		<div class="ui-field-contain">
			<label for="b_unit">変換前の通貨：</label><br>
			<select id="b_unit" name="b_unit">
			<option value="jpy">日本円</option>
			<option value="usd">アメリカドル</option>
			</select>
		</div>
		<!-- 変換前の金額を入力 -->
		<div class="ui-field-contain">
			<label for="b_amount">金額：</label><br>
			<input id="b_amount" name="b_amount" type="number" />
		</div>
		<!-- 変換後の通貨単位を選択 -->
		<div class="ui-field-contain">
			<label for="a_unit">変換後の通貨：</label><br>
			<select id="a_unit" name="a_unit">
			<option value="JPY">日本円</option>
			<option value="USD">アメリカドル</option>
			</select>
		</div>
	</form>

	<input id="button_1" type="button" value="両　替" />
</div>

<!-- フッター部 -->
<div data-role="footer">
	<h3>Copyright 2015, Taiji HAGINO</h3>
</div>
</body>
</html>
```

#ビルド・動作確認
##まずはビルドします
コマンドラインからビルドコマンドを実行します。
`$cordova build`

問題がなければこんな感じでビルドが成功します。
非推奨のAPI?とりあえず気にせず行きましょう！
![038.png](https://qiita-image-store.s3.amazonaws.com/0/81226/abe8100c-afb0-9447-11a2-51e048934a33.png)

では、エミュレータを起動します。
`cordova run android`

先ほど登録したAVDが起動し、アプリケーションが起動されれば成功です。
![image](https://qiita-image-store.s3.amazonaws.com/0/81226/09b89d9d-79d6-4468-9bb8-2e80900d0093.png)

##動かしてみよう
アメリカの洋服屋にでも居るとします。
180ドルのものを手に取り、これって日本円でいくらかしら？とお店でアプリを取りだします。
変換前の通貨種別に米ドルを選択、金額を入力し、変換後通貨種別には日本円を指定。
両替ボタンをタップ。
![040.png](https://qiita-image-store.s3.amazonaws.com/0/81226/25ae2bd2-cd3b-f94c-b66c-d6d35736b083.png)

ちょっと見づらいですが、現在のレートだと約21,685円で有る事が分かりました。
高いよ。。。
![041.png](https://qiita-image-store.s3.amazonaws.com/0/81226/bd2a0f13-9c30-49c2-56c7-b8a53b6368f6.png)

#今回使用したソースコード一式
こちらから取得できます。
https://github.com/taijihagino/kawaseapp


-- 以上