Monacaを使ってCordovaでのデバイスセンサー操作を覚える


※本ドキュメントは、2016年8月に開催するハンズオンワークショップ向けのドキュメントです。
※本内容は、ドキュメント作成時において有効なAPIやライブラリを利用しています。
#1.はじめに
**Monacaとは**
Monacaは、アシアル社が提供する、スマートフォン向けアプリの開発環境の呼称です。アプリの開発は、MonacaクラウドIDE(Web経由)を使用して行います。
開発環境の提供だけではなく、だれでも簡単にスマートフォン向けのアプリ開発ができるように、その仕組みとサポートを提供してくれています。

![057.png](https://qiita-image-store.s3.amazonaws.com/0/81226/0541bf6d-d36e-1b99-923c-1586bae5cbdd.png)



**OnsenUIとは**
OnsenUIは同じくアシアル社が提供する、フロントエンド開発用のツールです。OnsenUIが提供するUIを使用すると、PhoneGap/Cordovaアプリを非常に簡単に綺麗で見映えの良い、使いやすいUIを実現できます。JQuery-MobileやSencha-Touchなんかと似たようなものと思ってもらえれば良いです。
ハイブリッドアプリにおいても、ネイティブ並みの外観と操作性を、すべてのプラットフォーム上で実現できます。Monacaと共に使用すれば、バックエンドとデバイスのサポート機能を追加でき、公開可能なアプリを簡単に作成できます。Monacaが提供するテンプレートには標準でOnsenUIが使用されています。

**詳しくは**
[Monaca Docs](http://docs.monaca.mobi/cur/ja/)をご覧ください。

#2.開発準備
**Monacaにアカウントを作成**
Monacaのサイトへアクセスします。
https://ja.monaca.io/

「今すぐ試す（無料）」をクリックします。
![image](https://qiita-image-store.s3.amazonaws.com/0/81226/a00d994c-72bf-7783-e8a3-a0f1b7c71c4e.png)

メールアドレス、パスワードを入力し、利用規約同意のチェックボックスをONにし、「今すぐ登録（無料）」をクリック。
![051.png](https://qiita-image-store.s3.amazonaws.com/0/81226/1585acb5-b04a-7919-1862-5d58c4a03358.png)

確認メールを送信した旨を告げる画面が表示されます。
もし、メールが届かないようなら、「確認メールを再送する」ボタンをクリックし、再度メール受信を試みてください。
![053.png](https://qiita-image-store.s3.amazonaws.com/0/81226/b067926e-3e0a-74ce-d9fe-2ed57895f073.png)

メールを確認し、リンクをクリックします。
![054.png](https://qiita-image-store.s3.amazonaws.com/0/81226/9793b598-d162-8dbc-eb79-c5d8ca268d1d.png)

アカウントの登録が完了しました。
![image](https://qiita-image-store.s3.amazonaws.com/0/81226/a2f58a48-2435-ec0b-751a-6619da4c9717.png)

自動的にダッシュボードへ遷移します。
![image](https://qiita-image-store.s3.amazonaws.com/0/81226/55f0a0ac-1d2d-87cd-df91-f985dcfd0b37.png)

**IDEを使ってみる**
ダッシュボード画面の左側に、作成したプロジェクトがリスト表示されます。デフォルトで「Hello Worldアプリ」が作成されています。
新規に開発をスタートする場合は、同じペインの右上「開発をスタート」をクリックします。
![055.png](https://qiita-image-store.s3.amazonaws.com/0/81226/872d5ada-9a46-0dc3-b001-e8432e75ee68.png)

開発をスタートすると、プランが選べます。
今回は無料プラン(monaca.io)を選択します。
無料プランは、プロジェクトを最大3つまでしかストックできないので、注意してください。
![056.png](https://qiita-image-store.s3.amazonaws.com/0/81226/ebdf254e-a8be-ce00-5869-16d5a163342a.png)

monacaは用途に応じた沢山のテンプレートを用意してくれています。
ポップアップウィンドウ上部にある帯から「Onsen UI」を選択し、その下のリストから「Onsen UI V2 JS Minimum」を選択します。
![ss01.jpg](https://qiita-image-store.s3.amazonaws.com/0/81226/420791c1-d3a7-57af-5353-1e91d6aec95c.jpeg)


プロジェクト名は任意の名称でOKです。ここでは「sensorapp_monaca」とします。
プロジェクトを作成するボタンをクリック。
![ss02.jpg](https://qiita-image-store.s3.amazonaws.com/0/81226/007581f4-332b-18fa-1527-aff302675211.jpeg)


左ペインの最上部に新しく「sensorapp_monaca」が追加されたことが確認できます。
開くボタンをクリック。
![ss03.jpg](https://qiita-image-store.s3.amazonaws.com/0/81226/1ecb1c09-7ca3-611d-50f3-d921caae27fe.jpeg)


IDEが開き、READMEが表示されます。READMEは閉じてOKです。
デフォルトではindex.htmlのみの単一ページの作りになっています。

index.html
![ss04.jpg](https://qiita-image-store.s3.amazonaws.com/0/81226/b08e3b70-8c45-4149-09dd-badfcd6f44c7.jpeg)


既にお気づきの通り、IDEの右ペインにはデフォルトで画面のプレビューが表示されます。
このまま表示させておいても良いですし、邪魔でしたら消してもOKです。
再表示させたい場合はツールバー上の「プレビュー」をクリックします。
![ss05.jpg](https://qiita-image-store.s3.amazonaws.com/0/81226/18b546ba-b25a-11c3-138c-4cfceb67ddaf.jpeg)


#3.実装
**実際にアプリを作成する**
最初にネタばらしをしてしまうと、この実装に関しては既にMonaca上にテンプレートとして提供されているものを元に、必要最小限な内容だけを抽出したものになります。
出来上がりだけを求める場合は、そちらのテンプレートを選択すれば最初から出来上がったものが提供されます。今回は、敢えてそれをトレースする形で、実際の作りを勉強していきます。

ではまず、今回のアプリの主要なファイル構成を説明します。ライブラリの読み込みなどを除外すると、基本的に下記３ファイルで完結します。

ページ表示：index.html
処理記述：main.js　※新たに作成
レイアウト：style.css　※ファイル自体はデフォルトで存在するが中身は空なので新たに記述

JavaScriptファイルから作成します。
ファイルの置き場所はどこでも良いですが、今回はルート（www）直下に「js」というフォルダを作成し、その配下に「main.js」を作成します。

wwwを右クリックし、新規フォルダーを選択します。
![ss07.jpg](https://qiita-image-store.s3.amazonaws.com/0/81226/684e30bf-ba00-1e7b-08f9-74e354377a70.jpeg)

フォルダー名を「js」にしてOKをクリックします。
![ss08.jpg](https://qiita-image-store.s3.amazonaws.com/0/81226/8b9a8746-9f58-24fc-f952-1193961fe4f5.jpeg)

jsフォルダーを右クリックし、新規ファイルを選択します。
![ss09.jpg](https://qiita-image-store.s3.amazonaws.com/0/81226/49a87aec-b6d8-f6fa-eabf-3c7ad655b3d9.jpeg)

ファイル名を「main.js」にしてOKをクリックします。
![ss10.jpg](https://qiita-image-store.s3.amazonaws.com/0/81226/e109ef77-b295-cf7c-6adf-d77a75977562.jpeg)

これで、JavaScriptファイルの準備はOKです。
後ほど、中身の実装を行います。

実装の最初はindex.htmlからです。
まずは不要なコードを削除します。
![ss06.jpg](https://qiita-image-store.s3.amazonaws.com/0/81226/8ac6900b-ede5-f21f-18a5-b128b687c685.jpeg)


次に、index.htmlを編集します。
下記の通りコーディングしてください。下記コードで上書きして頂いてもOKですが、編集した部分がどんな意味、理由を持っているかを理解しましょう。

```lang:index.html
<!DOCTYPE HTML>
<html>
<head>
    <title>Sensors</title>
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    <meta charset="utf-8">
    <meta http-equiv="Content-Security-Policy" content="default-src * data:; style-src * 'unsafe-inline'; script-src * 'unsafe-inline' 'unsafe-eval'">
    <script src="components/loader.js"></script>
    <script src="lib/onsenui/js/onsenui.min.js"></script>
    <script src="js/main.js"></script>
    <link rel="stylesheet" type="text/css" href="components/loader.css">
    <link rel="stylesheet" type="text/css" href="css/style.css">
    <script>
        ons.ready(function() {
            console.log("Onsen UIが使えるようになりました！");
        });
    </script>
    <script type="text/javascript">
        document.addEventListener("deviceready", onDeviceReady, false);
        function onDeviceReady(){
            console.log("センサーが使えるようになりました！");
        }
    </script>
</head>
  <body onload="init();" id="stage" class="theme">

    <h1>Control Device</h1>
    <h2>いろいろなデバイス操作を行います</h2>
    <div id="info">
        <h4>Platform: <span id="platform"> &nbsp;</span>,   Version: <span id="version">&nbsp;</span></h4>
        <h4>UUID: <span id="uuid"> &nbsp;</span>,   Name: <span id="name">&nbsp;</span></h4>
        <h4>Width: <span id="width"> &nbsp;</span>,   Height: <span id="height">&nbsp;
                   </span>, Color Depth: <span id="colorDepth"></span></h4>
     </div>
    <dl id="accel-data">
      <dt>X:</dt><dd id="x">&nbsp;</dd>
      <dt>Y:</dt><dd id="y">&nbsp;</dd>
      <dt>Z:</dt><dd id="z">&nbsp;</dd>
    </dl>
    <a href="#" class="btn" onclick="toggleAccel();">加速度</a>
    <a href="#" class="btn" onclick="getLocation();">位置（緯度経度）</a>
    <a href="tel:117" class="btn">117へ電話</a>
    <a href="#" class="btn" onclick="vibrate();">バイブレーター</a>
    <a href="#" class="btn" onclick="check_network();return false;">ネットワーク</a>
    <a href="#" class="btn" onclick="snapPicture();">カメラ</a>
    <img id="picture" src="" width="150" height="80">
  </body>
</html>
```

次に、main.jsの編集です。
下記の通りコーディングしてください。こちらも下記コードで上書きして頂いてOKですが、先ほど同様、編集した部分がどんな意味、理由を持っているかを理解しましょう。

```lang:main.js
// This is a JavaScript file

// デバイスの情報を取得
var deviceInfo = function() {
    document.getElementById("platform").innerHTML = device.platform;
    document.getElementById("version").innerHTML = device.version;
    document.getElementById("uuid").innerHTML = device.uuid;
    document.getElementById("name").innerHTML = device.name;
    document.getElementById("width").innerHTML = screen.width;
    document.getElementById("height").innerHTML = screen.height;
    document.getElementById("colorDepth").innerHTML = screen.colorDepth;
};

// 位置（緯度経度）を取得
var getLocation = function() {
    var suc = function(p) {
        alert(p.coords.latitude + " " + p.coords.longitude);
    };
    var locFail = function() {
    };
    navigator.geolocation.getCurrentPosition(suc, locFail);
};

// バイブレーターを起動
var vibrate = function() {
    navigator.notification.vibrate(500);
};

// 加速度用の値を３桁に丸める
function roundNumber(num) {
    var dec = 3;
    var result = Math.round(num * Math.pow(10, dec)) / Math.pow(10, dec);
    return result;
}

// 加速度取得時に使う変数
var accelerationWatch = null;

// 加速度を取得
function updateAcceleration(a) {
    document.getElementById('x').innerHTML = roundNumber(a.x);
    document.getElementById('y').innerHTML = roundNumber(a.y);
    document.getElementById('z').innerHTML = roundNumber(a.z);
}

// 加速度を取得し値を都度更新
var toggleAccel = function() {
    if (accelerationWatch !== null) {
        navigator.accelerometer.clearWatch(accelerationWatch);
        updateAcceleration({
            x : "",
            y : "",
            z : ""
        });
        accelerationWatch = null;
    } else {
        var options = {};
        options.frequency = 1000;
        accelerationWatch = navigator.accelerometer.watchAcceleration(
                updateAcceleration, function(ex) {
                    alert("accel fail (" + ex.name + ": " + ex.message + ")");
                }, options);
    }
};

// カメラを起動
function snapPicture () {
        navigator.camera.getPicture (onSuccess, onFail, 
            { quality: 50, destinationType: Camera.DestinationType.DATA_URL});

    // 撮影が成功した時のコールバック関数
    function onSuccess (imageData) {
        var image = document.getElementById ('picture');
        image.src = "data:image/jpeg;base64," + imageData;
    }

    // 撮影が失敗した時のコールバック関数
    function onFail (message) {
        alert ('Error occured: ' + message);
    }
}

// ネットワークの種類を判断
function check_network() {
    var networkState = navigator.network.connection.type;

    var states = {};
    states[Connection.UNKNOWN]  = 'Unknown connection';
    states[Connection.ETHERNET] = 'Ethernet connection';
    states[Connection.WIFI]     = 'WiFi connection';
    states[Connection.CELL_2G]  = 'Cell 2G connection';
    states[Connection.CELL_3G]  = 'Cell 3G connection';
    states[Connection.CELL_4G]  = 'Cell 4G connection';
    states[Connection.NONE]     = 'No network connection';

    confirm('Connection type:\n ' + states[networkState]);
}

// 画面が読み込まれた時に呼び出される処理
function init() {
    document.addEventListener("deviceready", deviceInfo, true);
}
```

編集が終えたらツールバー上の保存ボタンをクリック。（Ctrl+SでもOK）
右ペインのプレビューに変更が反映されます。
処理の記述と、その処理を出力するビューの定義は完了していますが、レイアウトが整っていません。

![ss11.jpg](https://qiita-image-store.s3.amazonaws.com/0/81226/ddab76a9-5c4d-f376-ade4-c693a2998dd9.jpeg)


これを整えるのがCSS＝スタイルシートの役目です。
ということで、最後にstyle.cssの編集です。
下記の通りコーディングしてください。

```lang:style.css
body {
    background:#000 none repeat scroll 0 0;
    color:#666;
    font-family:Helvetica;
    font-size:72%;
    line-height:1.5em;
    margin:0;
    border-top:1px solid #393939;
  }

  #info{
    background:#ffa;
    border: 1px solid #ffd324;
    border-radius: 5px;
    clear:both;
    margin:15px 6px 0;
    width:295px;
    padding:4px 0px 2px 10px;
  }
  
  #info > h4{
    font-size:.95em;
    margin:5px 0;
  }
     
  #stage.theme{
    padding-top:3px;
  }

  /* Definition List */
  #stage.theme > dl{
  	padding-top:10px;
  	clear:both;
  	margin:0;
  	list-style-type:none;
  	padding-left:10px;
  	overflow:auto;
  }

  #stage.theme > dl > dt{
  	font-weight:bold;
  	float:left;
  	margin-left:5px;
  }

  #stage.theme > dl > dd{
  	width:45px;
  	float:left;
  	color:#a87;
  	font-weight:bold;
  }

  /* Content Styling */
  #stage.theme > h1, #stage.theme > h2, #stage.theme > p{
    margin:1em 0 .5em 13px;
  }

  #stage.theme > h1{
    color:#eee;
    font-size:1.6em;
    text-align:center;
    margin:0;
    margin-top:15px;
    padding:0;
  }

  #stage.theme > h2{
  	clear:both;
    margin:0;
    padding:3px;
    font-size:1em;
    text-align:center;
  }

  /* Stage Buttons */
  #stage.theme a.btn{
    border: 1px solid #555;
  	border-radius: 5px;
  	text-align:center;
  	display:block;
  	float:center;
  	background:#444;
    width:308px;
  	color:#9ab;
  	font-size:1.1em;
  	text-decoration:none;
  	padding:1.2em 0;
  	margin:3px 0px 3px 5px;
  }
```

プレビューを見てみて下さい。
綺麗に整ったと思います。

![ss12.jpg](https://qiita-image-store.s3.amazonaws.com/0/81226/836df26f-af00-feb6-d566-be2af8ebd9d8.jpeg)


**動作確認**
自分の端末にデバッガーをインストールします。
App StoreまたはPlay Storeからmonacaを検索します。
![071.png](https://qiita-image-store.s3.amazonaws.com/0/81226/dac7fc7a-c443-60b8-e5e4-b0b3bd095fdd.png)

インストールします。Asial社が提供しているアプリですのでお間違えなく。
![072.png](https://qiita-image-store.s3.amazonaws.com/0/81226/feb49ace-cc25-ac4c-0201-9c073e72e5d9.png)

インストールが完了したらアプリを起動します。図のアイコンです。
![073.png](https://qiita-image-store.s3.amazonaws.com/0/81226/66fd33aa-a6e8-dcd4-2800-9906fe96bd8c.png)

本投稿の第二章で作成したアカウントでログインします。
![074.png](https://qiita-image-store.s3.amazonaws.com/0/81226/fded8dcc-d5f6-2638-a3a0-02670471b677.png)

WEBの左ペインに表示されていたプロジェクト一覧と同じリストが表示されます。
今回作成した「sensorapp_monaca」を選択します。
![Screenshot_2016-08-12-01-37-10.png](https://qiita-image-store.s3.amazonaws.com/0/81226/83d07a63-1244-ef09-1222-b79cac864823.png)


アプリが起動するので、各ボタンをタップします。
結果が表示される、または動作すれば成功です！
![Screenshot_2016-08-12-01-37-24.png](https://qiita-image-store.s3.amazonaws.com/0/81226/fef7e23b-31f1-5061-4c05-4a5976a4495e.png)