アシアルブログ

アシアルの中の人が技術と想いのたけをつづるブログです

Monacaデバッガーのカスタムビルド版を使ってみよう

Monacaアプリをデバッグする際には3つの方法があります。



  1. Monaca IDE上のプレビューを使う
  2. Monacaデバッガー(App Store/Google Playからダウンロード)を使う
  3. アプリをデバッグビルドする
  4. Monacaデバッガーのカスタムビルド版を使う


プレビューは簡易的に表示や機能を試せますが、スマートフォンならではの機能は利用できません。Monacaデバッガーは動作の確認はできますが、幾つかの制限があります。



  1. あらかじめMonacaデバッガーに組み込まれたCordovaプラグインしか使えません
  2. USBデバッグに対応していません
  3. Monacaデバッガー経由でのアプリインストール機能、ネットワークインストールに対応していません


アプリをデバッグビルドすることもできますが、コードを編集するたびにアプリをインストールし直すのは手間がかかります。そこで今回はMonacaデバッガーのカスタムビルド版を紹介します。



Monacaデバッガーカスタムビルド版の特徴



  1. 自作プラグインをはじめすべてのCordovaプラグインが使えます
  2. ネットワークインストール対応
  3. Chromeを使ったデバッグに対応
  4. Monaca IDE上でビルド


カスタムビルド版の作成方法



まずはMonaca IDEを使ってプロジェクトを開きます。





環境一覧



アプリとしてビルドしますので、設定メニューからビルド設定を行います。





設定メニュー



開発者証明書などをアップロードしてください。





iOSビルド設定画面



そしてデバッガーメニューからiOS向けデバッガーのインストールを選択します。Androidの場合はAndroid向けデバッガーのインストールを選択してください。





デバッガーのインストール



今回はビルドしてインストールの方を選択します。





ビルドウィンドウ



ビルドする際にはプロビジョニングプロファイルが必要です。iOS Dev Centerであらかじめ作成しておいてください(iOSの場合)。





プロビジョニングプロファイルの指定



ビルドが終わったらダウンロードして、iTunesなどを使ってインストールします。





ビルド完了






Monacaデバッガーのカスタムビルド版は見た目はMonacaデバッガーと変わりません。ただし任意のMonacaプラグインが使えることと、LocalKitを使っている時にGoogle Chromeを使ったデバッグがサポートされます。使い慣れたDevToolsを使えばMonacaアプリ開発が格段にスムーズになるはずです。



任意のCordovaプラグインが使えるのはGoldプラン以上ですが、これによってMonacaアプリの可能性が格段にあがります。ぜひお試しください!

Monacaアプリ(iOS)をネットワーク経由で配布する方法(In Houseビルドについて)

開発したアプリをストアに公開せず、複数の人たちで使う方法としてはAdHocビルドとIn Houseビルドがあります。不特定多数という訳ではありませんので限られたメンバーや社内利用でのビルドになりますが、逆にその制限が目的に合っている場合も多いでしょう。



そこで今回はMonacaアプリを特定利用者に対して、自前のサーバから限定配布する方法について紹介します。



AdHocビルドとIn Houseビルドの違い



まずAdHocビルドとIn Houseビルドの違いについて紹介します。



Ad Hocとは限定目的という意味になります。そのためAdHocビルドされたアプリは限定目的のためのアプリと言うことです。この場合、評価目的配布になります。AdHocは最大100台までの配布が可能です。そしてデバイスを追加するごとにUDIDを登録したり、プロビジョニングファイルの更新、リビルドが必要になります。



In Houseは配布できるデバイスが無制限というのが特徴です。つまりUDIDの管理が不要です。ただし無制限に配布できると言うことはApp Storeを無視することもできてしまうため、In Houseビルドされたアプリが不当に広まったりしないよう厳重な管理が規定されています。



料金もAdHocビルドとIn Houseビルドで異なります。AdHocビルドは一般開発者の年間11,800円(2015年4月現在)で可能です。In Houseビルドを行うにはiOS Developer Enterprise Programに登録が必要で、こちらは年間37,800円(2015年4月現在)となっています。



必要なもの





ビルドについて



今回はIn Houseビルドを想定しているので、AdHocビルドで行ってください。



plistファイルの用意



OTAによる配布の際にはplistファイルを用意する必要があります。基本的な形は以下のようになります。





<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>items</key>
    <array>
        <dict>
            <key>assets</key>
            <array>
                <dict>
                    <key>kind</key>
                    <string>software-package</string>
                    <key>url</key>
                    <string>(IPAファイルのURL)</string>
                </dict>
            </array>
            <key>metadata</key>
            <dict>
                <key>bundle-identifier</key>
                <string>アプリケーションのID(mobi.monaca.appなど)</string>
                <key>bundle-version</key>
                <string>1.0.0</string>
                <key>title</key>
                <string>(アプリ名)</string>
                <key>kind</key>
                <string>software</string>
            </dict>
        </dict>
    </array>
</dict>
</plist>


このXML中の (IPAファイルのURL)、アプリケーションのID(mobi.monaca.appなど)、(アプリ名)をそれぞれ書き換えてください。



そしてこのplistファイル(例えばapp.plist)をHTTPSが使えるサーバ上にアップロードします。手軽なところとしてはAmazon S3DropboxのPublicフォルダがありますが、セキュリティには気をつけてください。



配布用HTMLの作成



次にWebブラウザからアクセスするためのHTMLファイルを用意します。もっとも基礎的な形は次のようになります。





<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="width=device-width" />
    <meta charset="utf-8">
    <title>ダウンロードページ</title>
  </head>
  <body>
    <h1>ダウンロードページ</h1>
    <a href="itms-services://?action=download-manifest &url=plistファイルのURL">インストール</a>
  </body>
</html>


大事なのはplistファイルのURLになります。このURLはHTTPSでなければなりません。なので、HTML/plist/ipaファイルは同じディレクトリにある方が楽でしょう。



試してみよう



では実際に試してみます。ファイル構成は次のようになります。





ファイル構成



そしてこのHTMLに対してアクセスします。今回はDropboxを使っています。そしてインストールのリンクをタップします。





Mobile Safariからアクセス



そうするとインストールが開始されます。





アプリのインストール中



無事アプリが立ち上がりました。










基本的な流れはIn Houseビルドでも変わらないかと思います。AdHocでのビルド、plistとHTMLファイル、HTTPSで行うといった点に注意しください。



ぜひMonacaアプリ開発でお役立てください!



Monaca - HTML5ハイブリッドアプリ開発プラットフォーム

「クラウドでできるHTML5ハイブリッドアプリ開発」で紹介されているサンプルプロジェクトの使い方

先日、Monaca公式ガイドブックとしてクラウドでできるHTML5ハイブリッドアプリ開発が出版されました。本書では多くのサンプルプロジェクトを通してMonacaの利用法を紹介しています。



サンプルプロジェクトはMonaca - Monaca公式ガイドブック「クラウドでできるHTML5ハイブリッドアプリ開発」のページにてダウンロードができますが、今回はそのプロジェクトを使う方法を紹介します。



必要なもの





サンプルプロジェクトの選択



サンプルプロジェクトはMonaca - Monaca公式ガイドブック「クラウドでできるHTML5ハイブリッドアプリ開発」にてご覧いただけます。全32種類のプロジェクトが登録されています。今回はMonacaカウンターを使ってみます。





サンプルプロジェクト一覧



まずプロジェクト名の下にあるダウンロードを右クリックしてURLをコピーします。ダウンロードする必要はありません。





ダウンロードを右クリックしてURLをコピー



Monacaにて新しいプロジェクトの作成



Monacaにログインして、プロジェクトの作成をクリックします。





プロジェクトの作成をクリック



プロジェクトテンプレートが並んでいるのが確認できると思います。そして右上にあるImport Projectをクリックします。





Import Projectをクリック



モーダルウィンドウが表示されます。その中のインポート方法で、URLを指定してインポートを選択し、先ほどコピーしたURLを貼り付けます。プロジェクト名は適当に決めてください。





URLを貼り付け



後はインポートボタンを押せば完了です。





プロジェクト一覧に登録



インポートが無事終わると、左側のプロジェクト一覧に新規作成したプロジェクトが登録されているのが確認できるかと思います。これでデスクトップ側の作業は終わりです。



Monacaシミュレータを起動



続いてiOSまたはAndroid側で実行してみましょう。使うのはMonaca デバッガーです。iOSApp StoreAndroidGoogle Play通常版ハイパフォーマンス版)をそれぞれダウンロードできますのでインストールしてください。Monaca デバッガーを起動すると、最初にログイン画面が表示されます。MonacaのIDとパスワードでログインしてください。





プロジェクト一覧



ログインすると先ほど登録したプロジェクトが表示されているかと思います。タップするとコードをMonacaクラウドからダウンロードし、実行します。





ダウンロード中





Monacaカウンター実行中



このようにしてソースコードに一切触れることなくプロジェクトが試せるようになっています。






もちろんプロジェクトはサンプルなので、Monaca IDEを使ってソースコードを見たり、カスタマイズができます。クラウドでできるHTML5ハイブリッドアプリ開発と一緒にご利用ください。

書籍『[iOS/Android対応]HTML5ハイブリッドアプリ開発[実践]入門』書きました

久保田です。『HTML5ハイブリッドアプリ開発[実践]入門』という本を書きました。技術評論社より12月20日付けで発売されます。



HTML5ハイブリッドアプリとは



HTML5ハイブリッドアプリとは、通常のiOSアプリやAndroidアプリと同じようにストアからインストールできるけれども、アプリの内側ではHTML5などのウェブ技術で開発されているアプリです。AndroidiOSなどの複数のプラットフォームに対応できる点や、標準化されているHTML5などのウェブ技術によって開発でき、かつモバイルOSのネイティブAPIを利用できる点などで注目を浴びています。

本書は、今までHTML5ハイブリッドアプリを開発したことがない人向けの入門的な内容から、ハイブリッドアプリの裏側の仕組みなどのアプリ開発に関わるエンジニアのための高度な知識まで、HTML5ハイブリッドアプリ開発に関することの多くを網羅した実践的な一冊です。

内容



本書の内容は前半の基礎編と後半の実践編のふたつに分かれています。
基礎編では、HTML5によるハイブリッドアプリの概要、iOSAndroidアプリの開発環境の構築、ハイブリッドアプリを開発するためのフレームワークであるApache Cordova(PhoneGap)の導入などの入門的な内容を解説しています。

後半の実践編では、より良いモバイルアプリを開発するための実践的なノウハウの紹介、モバイルアプリ特有の事情の紹介、ハイブリッドアプリ特有のデバッグ手法やセキュリティに関する知識、アプリ開発に使える各種ストレージの解説、WebViewを使ったハイブリッドアプリの裏側の仕組み、WebViewの使い方などの実際にアプリを開発する際に必要となる知識を解説しています。

筆者が実際に関わったHTML5ハイブリッドアプリ開発やハイブリッドアプリ開発プラットフォームであるMonacaでの開発で得られた知識やノウハウなどをこの一冊に集約しています。本のタイトルには「入門」という言葉がついていますが、入門的な内容だけではなくHTML5ハイブリッドアプリに関する高度な内容も多く記述しています。

以下、目次です。



PART 1 基礎編
 第1章 ▶ HTML5ハイブリッドアプリとは
1.1 HTML5ハイブリッドアプリの概要
1.2 アプリ開発の課題
1.2.1 マルチプラットフォーム対応の必要性
1.2.2 マルチプラットフォーム対応の難しさ
1.3 HTML5ハイブリッドアプリの登場
1.4 アプリケーションの型
1.4.1 ネイティブアプリ
1.4.2 Webアプリ
1.4.3 ハイブリッドアプリ
1.5 ハイブリッドアプリの仕組み
1.6 ハイブリッドアプリの利点
1.7 ハイブリッドアプリの欠点
1.8 ハイブリッドアプリの事例
1.9 まとめ
第2 章 ▶ ハイブリッドアプリ開発の基盤
2.1 Web 技術
2.1.1 HTML
2.1.2 CSS
2.1.3 JavaScript
2.1.4 ライブラリ・フレームワーク
2.2 WebKitレンダリングエンジンの開発環境
2.3 iOSの開発環境
2.3.1 iOSアプリの開発環境を構築する
2.3.2 必要とする環境
2.3.3 Xcodeをインストールする 
2.3.4 Xcodeを起動する
2.3.5 新しいプロジェクトを作成する
2.3.6 プロジェクトを編集する
2.3.7 プロジェクトを実行する
2.3.8 実機での開発
2.4 Android の開発環境
2.4.1 Android(Android SDK+Eclipse)の開発環境を構築する
2.4.2 必要とする環境
2.4.3 Android SDKをインストールする
2.4.4 プロジェクトの作成
2.5 まとめ 
第3 章 ▶ ハイブリッドアプリ開発のためのフレームワーク
3.1 フレームワークの概要
3.2 フレームワークは何をしてくれるのか
3.3 Cordova(PhoneGap)
3.4 Triaina 
3.5 フレームワークを利用しない場合
3.6 サーバ・クラウド環境
3.6.1 PhoneGap Build
3.6.2 Trigger.io
3.6.3 Monaca
3.6.4 Icenium
3.7 まとめ
第4章 ▶ Cordovaを用いたアプリ開発の流れ
4.1 Cordovaを用いた開発環境を構築する
4.1.1 Node.js のインストール
4.1.2 cordova のコマンドラインツールをインストールする
4.1.3 プロジェクトを作成する 
4.1.4 Android 向けのコンポーネントをインストールする 
4.1.5 プロジェクト構造を確認する 
4.1.6 Androidエミュレータを利用する 
4.1.7 iOSシミュレータを利用する
4.1.8 実機でプロジェクトを実行する
4.1.9 基本的な開発の流れを理解する
4.1.10 ブラウザで確認する
4.1.11 cordovaコマンドの管理
4.2 Cordovaを用いてアプリを開発する 
4.2.1 www ディレクトリ以下の構造を確認する 
4.2.2 index.html
4.2.3 cordova.js
4.2.4 devicereadyイベント
4.3 アプリの設定
4.3.1 config.xmlの構造
4.3.2 アプリに関する設定
4.3.3 設定を反映させる
4.3.4 Android 特有の設定項目
4.3.5 iOS 特有の設定項目
4.3.6 アプリのアイコンを設定する 
4.3.7 アプリのスプラッシュスクリーンを設定する
4.3.8 ドメインホワイトリストを設定する
4.4 プラットフォームごとにカスタマイズする 
4.4.1 HTML5 側をプラットフォームごとに切り替える
4.4.2 ネイティブ側をプラットフォームごとに切り替える
4.5 Cordovaプラグインを利用する 
4.5.1 プラグインを導入する
4.5.2 プラグインを管理する
4.5.3 プラグインのインストールを理解する
4.5.4 プラグインの仕組み
4.5.5 組み込みプラグインの一覧
4.5.6 Android 向けのCordovaプラグインを実装する
4.5.7 Android 向けのプラグイン開発の詳細
4.5.8 iOS 向けのCordovaプラグインを実装する
4.5.9 cordovaコマンドからインストールできるプラグインを実装する 
4.6 その他のコマンドの解説
4.7 既存のアプリにCordovaを組み込む
4.7.1 Cordovaフレームワークのダウンロード
4.8 Android のプロジェクトにCordovaフレームワークを導入する 
4.8.1 画面の一部でCordovaを用いる
4.9 iOSのプロジェクトにCordovaフレームワークを導入する
4.9.1 画面にCordovaを用いる
4.9.2 wwwディレクトリに配置する
4.9.3 Cordovaフレームワークを呼び出すコードを記述する
4.10 plugmanコマンドを使ってCordovaプラグインを導入する 
4.10.1 plugmanコマンドのインストール
4.10.2 plugmanコマンドを使ってCordovaプラグインを導入する
4.11 まとめ 
PART 2 実践編
 第5章 ▶ より良いアプリを開発するためのテクニック
5.1 aタグやclickイベントは使わない
5.1.1 Tappableを使う
5.1.2 FastClickを使う
5.2 jQueryの代わりにZepto.jsを利用する 
5.2.1 Zepto.js の導入
5.2.2 Zepto.jsを利用する
5.3 ダイアログを表示する
5.3.1 Cordova のNotificationプラグインを利用する
5.4 タップ時のハイライトを消す 
5.5 ポップアップメニューを消す
5.6 ユーザが文字を選択できないようにする
5.7 コンテンツの一部に慣性スクロールを用いる 
5.8 iOS版よりもAndroid 版を先に開発する
5.9 インジケータを利用する 
5.9.1 Spin.jsの導入
5.10 文字の大きさの自動調整を無効にする
5.11 DOMツリーに加える変更を減らす
5.11.1 再描画のコストを減らす
5.11.2 DOM 操作の繰り返しが描画を遅くする
5.11.3 DOM への挿入を一度にまとめる
5.11.4 一度DOMツリーから切り離して操作した後に挿入する
5.12 レイアウトの再計算のコストを抑える 
5.12.1 レイアウトの再計算について
5.12.2 要素の大きさを固定する
5.12.3 絶対位置を指定する
5.12.4 CSS Transformsを用いる
5.12.5 DOMツリーを複雑にしない
5.13 実機で確認する
5.13.1 iOSシミュレータの欠点
5.13.2 Androidエミュレータの欠点
5.14 JSONを扱う
5.14.1 JSONをパースする,JSON に変換する
5.14.2 JSON の文法
5.14.3 JSON の誤ったパース
5.15 CSSアニメーションを利用する
5.15.1 JavaScriptでアニメーションしない
5.15.2 CSSアニメーションとは
5.15.3 transitionスタイルプロパティを使う
5.15.4 JavaScriptからCSSアニメーションを利用する
5.15.5 CSSアニメーション関連のイベントを把握する
5.15.6 CSSアニメーションをJavaScriptからキャンセルする
5.15.7 CSSアニメーションをより滑らかに描画する
5.15.8 iOS 端末でのちらつきを抑える
5.16 アプリを実行している端末の情報を得る
5.16.1 ユーザエージェントからプラットフォームを判別する
5.16.2 Cordova(PhoneGap)を用いて端末の情報を取得する
5.17 Android 4.03のWebViewとassetに関するバグに対処する 
5.17.1 バグを再現する
5.18 Androidデバイスのボタンに対応する 
5.18.1 Cordovaを使っている場合
5.18.2 WebViewの場合
5.19 イベントの移譲 
5.19.1 イベントバブリング
5.19.2 イベントの移譲
5.19.3 Zepto.jsを使ったイベントの移譲
5.20 HTML5とネイティブの切り分け
5.20.1 HTML5だけですべて実装できない状況
5.20.2 ある画面・ある箇所のみネイティブで実装する
5.20.3 HTML5とネイティブとの弱点を補い合う
5.21 まとめ 
第6章 ▶ ストレージ 
6.1 ストレージの概要 
6.2 WebStorage
6.3 LocalStorage 
6.3.1 HTML5 ハイブリッドアプリでの利用
6.3.2 Android のWebViewで利用する
6.3.3 iOS のUIWebViewクラスで利用する
6.3.4 データを保存する
6.3.5 データにアクセスする
6.3.6 データを削除する
6.3.7 容量の制限
6.3.8 残りの容量を知る
6.3.9 利用シーン
6.4 SessionStorage 
6.4.1 性質
6.4.2 LocalStorageと同じAPI
6.4.3 Android,iOS のWebViewで利用する
6.4.4 容量
6.4.5 利用シーン
6.5 ファイルストレージ 
6.5.1 ファイルストレージAPIとは
6.5.2 実装されているAPI
6.5.3 セットアップ
6.5.4 ファイルストレージAPI の利用
6.5.5 ファイルの読み込み
6.5.6 ファイルを書き込む
6.5.7 ファイルをテキストとして読み込む
6.5.8 ファイルやディレクトリの移動・コピー・削除・その他の操作
6.5.9 ファイルストレージの詳細
6.5.10 制限
6.5.11 利用シーン
6.6 WebSQLデータベース
6.6.1 WebSQLデータベースの概要
6.6.2 Androidで利用する
6.6.3 iOSで利用する 
6.6.4 CordovaのWebSQLデータベースを用いる 
6.6.5 利用できるSQL
6.6.6 データベースの利用
6.6.7 データベーステーブルの作成
6.6.8 トランザクションの発行 
6.6.9 トランザクション内でロールバックする
6.6.10 明示的にロールバックする 
6.6.11 読み込み専用のトランザクションを発行する
6.6.12 SQLを発行する 
6.6.13 プレースホルダ 
6.6.14 マイグレーション 
6.6.15 SQLite のバージョンを調べる
6.6.16 外側から実体ファイルを取り出してSQLiteで操作する
6.6.17 利用シーン
6.7 モバイルBaaS
6.7.1 モバイルBaaSがやってくれること
6.7.2 モバイルBaaS の紹介
6.7.3 オープンソースのモバイルBaaS
6.7.4 利用シーン
6.8 まとめ
第7 章 ▶ モバイル特有の事情
7.1 タッチの検知
7.1.1 JavaScriptから扱うイベント 
7.1.2 touchenter,touchleaveイベント
7.1.3 イベントのプロパティ
7.1.4 タッチオブジェクト 
7.1.5 タッチ座標を得る 
7.1.6 スクロールを防止する
7.1.7 Chromeでタッチイベントを発生させる
7.1.8 マウス関連のイベントの兼ね合い 
7.1.9 マウス関連のイベントを利用しない
7.1.10 Androidでtouchstartイベントとtouchendイベントがしばしば対応しない 
7.2 ジェスチャの検知 
7.2.1 ジェスチャイベント
7.2.2 Androidでもジェスチャを検知するには 
7.3 ジェスチャを判別するライブラリ
7.4 端末のオリエンテーション
7.4.1 端末のオリエンテーションを知る 
7.4.2 端末のオリエンテーションが変わるときを検知する 
7.4.3 端末のオリエンテーションをメディアクエリから扱う
7.4.4 Android 4.03 のメディアクエリにオリエンテーションを指定するときのバグ 
7.4.5 オリエンテーションを判別するメディアクエリをJavaScript から呼び出す
7.4.6 オリエンテーションに対応しないという選択肢もある
7.5 viewportに対応する 
7.5.1 viewportとは
7.5.2 基本
7.5.3 パラメータ
7.5.4 iPhone,iPod touch 向けベストプラクティス 
7.5.5 Androidでのviewport 
7.5.6 target-densitydpiパラメータを指定する 
7.5.7 densityの違いを検証する 
7.5.8 target-densitydpiパラメータを指定したときのレイアウト 
7.5.9 width パラメータをJavaScriptでエミュレーションする
7.6 まとめ 
第8 章 ▶ デバッグ
8.1 weinreによるWebインスペクタ
8.1.1 weinreでできること 
8.1.2 weinre の導入
8.2 iOSでのリモートWebインスペクタ
8.2.1 利用できる機能 
8.2.2 利用するための準備 
8.2.3 リモートWebインスペクタを開く
8.3 Chrome のリモートWebインスペクタ 
8.3.1 Android 4.4 以降でChrome のインスペクタを利用する
8.4 AndroidでJavaScript のエラーやログを記録する 
8.4.1 Androidアプリのログを取得する 
8.4.2 エラーログを記録する 
8.5 まとめ 
第9 章 ▶ メモリの計測・節約
9.1 メモリ節約の重要性 
9.1.1 メモリスワッピングを利用できないiOSとAndroid
9.2 iOSやAndroid 端末のメモリ容量 
9.2.1 iOS 端末の持つメモリ容量
9.2.2 Android 端末の持つメモリ容量
9.3 メモリ使用量を計測する 
9.3.1 仮想メモリ 
9.3.2 iOSでメモリを計測する
9.3.3 Androidでメモリを計測する
9.4 メモリを節約するテクニック 
9.4.1 HTML5 ハイブリッドアプリが消費するメモリ
9.4.2 JavaScript のメモリ管理
9.4.3 サイズの大きな画像の利用を抑える
9.4.4 オブジェクトをプールする 
9.4.5 JavaScriptで必要のない参照をしない 
9.5 まとめ 
第10 章 ▶ HTML5ハイブリッドアプリのセキュリティ
10.1 Webアプリとは違ったHTML5ハイブリッドアプリのセキュリティ問題
10.2 Android・iOSのサンドボックス 
10.2.1 サンドボックスとは
10.2.2 iOS のサンドボックス 
10.2.3 Android のサンドボックス
10.3 HTML5ハイブリッドアプリでのXSSの危険性
10.3.1 XSSを通じてネイティブブリッジを利用される 
10.3.2 iOS の場合の危険性
10.3.3 Android の場合の危険性
10.4 改ざんやコードをのぞかれる可能性を考慮する
10.4.1 Android のapkパッケージに含まれているリソースを取り出す 
10.4.2 iOS のipa パッケージに含まれているリソースを取り出す
10.4.3 パッケージの内容の盗難・改ざんを考慮する 
10.5 console.logメソッドを用いて大事な情報を書き込まない
10.6 まとめ
第11章 ▶ JavaScriptとネイティブとのブリッジ
11.1 JavaScript からネイティブの機能を呼び出すいくつかの方法 
11.2 ネイティブブリッジに必要とされる要件 
11.3 addJavascriptInterface 方式
11.3.1 実装 
11.3.2 値の受け渡し
11.3.3 Java 側ではスレッドセーフにする
11.3.4 適用範囲の制限
11.3.5 セキュリティ上の懸念
11.3.6 公開するメソッドを制限する
11.4 ネイティブからJavaScriptへ値を渡す
11.4.1 iOS の場合
11.4.2 Android の場合
11.4.3 値を渡す
11.5 カスタムURL スキーム方式
11.5.1 Androidでの実装
11.5.2 iOSでの実装 
11.6 iOSで特定のページの読み込みを制限する
11.6.1 webView:shouldStartLoadWithRequest:navigationType:を用いる 
11.6.2 NSURLProtocolクラスを用いる 
11.7 JsAlert 方式
11.7.1 実装 
11.8 ローカルHTTPサーバ方式
11.8.1 ローカルにHTTP サーバを構築する
11.8.2 トークンによる利用の制限
11.9 まとめ
第12 章 ▶ WebViewを使ってHTML5ハイブリッドアプリを開発する
12.1 Android のWebViewを使ってHTML5ハイブリッドアプリを開発する
12.1.1 WebViewを表示する
12.1.2 WebViewを設定する
12.1.3 WebSettingsを設定する
12.1.4 WebViewClientを設定する
12.1.5 WebChromeClientを設定する
12.1.6 ダイアログを設定する
12.1.7 consoleオブジェクトの挙動を設定する
12.1.8 アクティビティのライフサイクルに対応する
12.1.9 WebViewからJavaScriptを実行する
12.2 iOSのWebViewを使ってHTML5ハイブリッドアプリを開発する
12.2.1 基本となるコード
12.2.2 UIWebViewクラスを設定する
12.2.3 UIWebViewDelegateを設定する
12.2.4 ViewControllerクラスが破棄されたときにUIWebViewオブジェクトを破棄する
12.3 まとめ
コラム:アプリのマーケット公開のポイント


終わりに



発売日は12月20日ですが早い書店だともう並んでいるようです。Kindle版も同時発売です。HTML5ハイブリッドアプリに興味がある方は是非読んでみてください。

【iOS】カスタムSegueの作り方

こんにちは、橋本です。

今日はiOSのSegueのカスタム方法について書いていきたいと思います。
久々のiOSネイティブネタです。

Storyboardで画面を作っていて画面遷移を作成するときに、画面をSegueでつないで選択肢に出てくるpushやmodalをそのまま使っている方は多いかと思います。
modalを選択すると、デフォルトで4種類のアニメーションが選択出来るので、それでまかなえることも多いですよね。
ただ、pushに関してはアニメーションが基本のスライドアニメーション以外選択できないので、なんとなくスライドのままという方もいるのではないでしょうか。
カスタムで動きを実装するのはなんとなく大変そうですもんね。
気持ちは分かります。

ただ、作り方さえ分かってしまえば、CustomのSegueを作ってスライドアニメーションを独自のアニメーションに置き換えるのはすごく簡単なんですよ。
今回はこのCustomのSegueの作り方について説明していきたいと思います。


では、順を追って作り方を見て行きます。

まずは、テスト用のプロジェクトを作成してください。今回は「Single View Application」を選択しました。



NavigationViewControllerを使用している際のカスタムSegueの作り方を説明していきたいと思いますので、既存のViewControllerをNavigationControllerに紐づけていきます。
Storyboard上のViewControllerを選択した状態でメニューの「Editor > Embed In > Navigation Controller」を選んで、既存のViewControllerをNavigationControllerに紐付いた状態にします。



次に、遷移先のViewControllerを追加して既存のViewControllerと繋ぎます。
まずはViewControllerを一つStoryboard上に追加します。
次に既存のViewControllerにボタンを一つ追加し、ボタンと追加したViewControllerをSegueでつなぎます。
繋ぐ際に、Segueの形式を選ぶ選択肢が出ると思うので、Customを選択しておいてください。



ではいよいよカスタムのSegueを作成していきます。
プロジェクトにファイルを追加します。

Objective-Cファイルを選択し、Class名はFlipSegue、親のClassにはUIStoryboardSegueを選択します。



次に.mファイルを開き、performメソッドをオーバーライドしていきます。
performメソッドは画面遷移時の動きを担当するメソッドです。

以下のように実装していきます。



#import "FlipSegue.h"

@implementation FlipSegue
- (void)perform {
    UIViewController *sourceViewController = (UIViewController *)self.sourceViewController;
    UIViewController *destinationViewController = (UIViewController *)self.destinationViewController;
    
    [UIView transitionWithView:sourceViewController.navigationController.view
                      duration:1
                       options:UIViewAnimationOptionTransitionFlipFromLeft
                    animations:^{
                        [sourceViewController.navigationController pushViewController:destinationViewController animated:NO];
                    }
                    completion:nil];
}
@end


UIStoryboardSegueのsourceViewControllerが遷移元、destinationViewControllerが遷移先のViewControllerになります。
id型になっているので、UIViewController型にキャストしていったん変数に入れておきます。

UIVIewのトランジションアニメーションを使って現在表示されているViewにアニメーションを追加していきます。
optionsにUIVIewAnimationOptionTransitionFlipFromLeftを指定することで簡単にフリップアニメーションを実装することができます。

animationsの中で、NavigationControllerに遷移先のViewControllerを追加しています。animatedにNOを指定することで、デフォルトのスライドアニメーションを消すことができます。

あとは、この完成したSegueをStoryboard上で先ほど作成したSegueに設定すれば終わりです。
Storyboard上でSegueを選択し、Attribute InspectorのSegue Classに「FlipSegue」を設定します。



では、実行してみましょう。
ボタンを押すと画面がクルッと回って次の画面が表示されるのが確認できると思います。
簡単ですね!

足早でしたが、CustomのSegueの作り方について説明していきました。
すごく簡単なので、ぜひ試してみてください。

次回は、遷移後に遷移先に戻る動きのカスタム方法(Custom Unwind Segue)について書きたいと思います。

WebView 中の HTML のデバッグ方法まとめ

iPhone, Android で WebView を用い、HTML5 + CSS3 + Javascript でアプリを開発するケースは、PhoneGap (Cordova) が登場して以来増えつつあるのではないでしょうか。

HTML 開発には Firebug や Web Inspector といったデバッグツールはもはや必須ですよね。
そこで今回は WebView 中の HTML のデバッグ方法をまとめてみました。

1. Android 全般・iOS4 (実機・シミュレータ)・iOS5 (実機)



weinre (ワイナリー)というツールが利用できます。
weinre はウェブサーバとして動作し、そのサーバが提供するスクリプト・ページにアクセスすることで、ブラウザ上でデバッグが行えます。
(なお、この方法は後述する iOS5, 6 においても利用可能です)

・インストール・サーバの起動



weinre は Javascript で記述されており、動作させるには node.js が必要になります。
node.js のインストール方法はいくつかありますが、ここでは nvm を用いてインストールする方法をご紹介します。
nvm (=Node Version Manager) は異なるバージョンの node のインストール・環境切り替えを行うツールで、Ruby における rvm に相当します。


$ git clone git://github.com/creationix/nvm.git ~/nvm
$ . ~/nvm/nvm.sh
$ nvm install 0.8.11
$ nvm alias default 0.8.11


node のインストールが完了したら、weinre をインストールします。


$ npm install weinre


続いて weinre のサーバを起動させます。
デフォルトでは 8080 ポートで待ち受けします。


$ weinre --boundHost -all-


・使用方法



weinre サーバが起動したので、いよいよデバッグを開始しましょう。
まずはデバッグを行いたい HTML の head タグの中に下記を記述します。(IP アドレスは上記サーバを起動させたマシンのものに置き換えて下さい)


<script src="http://192.168.1.99:8080/target/target-script-min.js#identification"></script>

続いて、デバッグツールを動作させる PC で、下記アドレスに WebKit ベースのブラウザでアクセスします。(IP アドレスは上記サーバを起動させたマシンのものに置き換えて下さい)
http://192.168.1.99:8080/client/#identification
その後、アプリを起動し、上記 script タグを埋め込んだページを開くと、先ほどのブラウザにてデバッグが行えるようになります。

また、weinre はマルチユーザに対応しており、上記 URI の #identification の部分を変更すると別のセッションになります。

・所感



weinre は機種を問わず同一の UI で利用できる点が良いですね。
サーバを一個立ちあげておけば複数人で利用できるのも便利です。
難点としては動作速度が少々遅いことがあげられます。

2. iOS5 (シミュレータ)



WebKit の Web Inspector が利用できます。

・使用方法



AppDelegate に下記コードを追加します。


[NSClassFromString(@"WebView") performSelector:@selector(_enableRemoteInspector)];


その後、アプリを起動し、Chromium のバージョン 12 で下記アドレスにアクセスします。
http://localhost:9999/

シミュレータ上からデバッグを行いたいページに移動後、上記ページを更新し、対象の HTML 名のリンクをクリックすればデバッグが行えます。

・所感



iOS5 のシミュレータ専用であり、ブラウザのバージョン(正確にはブラウザが実装している WebSocket のプロトコルのバージョン)も限られる為、汎用性は低いですが、その分高速で Web Inspector ならではの恩恵が受けられます。
利用出来る状況ならば積極的に利用したいですね。

3. iOS6 (実機・シミュレータ)



Safari の Web Inspector が利用できます。

・使用方法



実機・シミュレータにて設定→ Safari →詳細→ Web インスペクタをオンにします。

続いてアプリを起動し、デバッグを行いたいページに移動します。
その後 Safari のメニュー→開発に、シミュレータなら iPhone Simulator、実機なら端末名が表示され、マウスホバーするとページの一覧が表示されますので、対象のページをクリックすれば Web Inspector が起動します。

・所感



XCode 4.5 以上で Safari 6 が必要になりますが、シミュレータ・実機共に高速で Javascript のステップ実行なども行え、とても便利です。
こちらも利用出来る状況ならば積極的に利用したいですね。

以上、駆け足ではありましたが WebView 中の HTML をデバッグする方法まとめでした。

【iOS】MemoryWarningSenderでメモリ警告バグを効率的に見つける

こんにちは。松田です。
iOS用アプリを作成していると、予期しないバグが発生することが多々ありますが、その原因として多いのが「メモリ警告」です。メモリ警告が発生すると、非表示状態のviewが破壊されるため、開発者の意図しない動作を引き起こす事があります。

この状態をテストするには、iOSシミュレータの「メモリ警告をシミュレート」機能を使うことができますが、発生させるタイミングは開発者次第で尚且つショートカットキーも無い(たぶん)ため、なかなか効率的に活用することができません。

これを解決するためのツールがMemoryWarningSenderです。
これを利用すれば、iOSシミュレータの実行中に定期的にメモリ警告を発生させることができるため、想定外のバグの発見につなげることができます。

MemoryWarningSenderは、ブログ「ゆめ技」で、ちきん(@mokemokechicken)さんが作成し公開しています。
http://yumewaza.yumemi.co.jp/2012/03/memorywarningsender_in_ios_simulatorios.html
この記事を読めば使い方はわかりますが、こっちにも簡単に記述しておきます。


インストール



SIMBLのインストール


iOSシミュレータを機能拡張するために、SIMBLが必要になります。
http://www.culater.net/software/SIMBL/SIMBL.php
上記URLからSIMBL-{バージョン番号}.zipをダウンロードし、解凍後にSIMBL-{バージョン番号}.pkgをインストールします。

MemoryWarningSenderのインストール


https://github.com/mokemokechicken/MemoryWarningSender
上記URLでgithub登録されています。
「ZIP」リンクからダウンロードし、解凍するとMemoryWarningSender.pkgが入っているので実行してインストールします。


使い方



iOSシミュレータを起動してメニューの「ハードウェア」を開くと、「メモリ警告を繰り返し送る」が追加されています。


5秒毎、15秒毎、60秒毎の選択肢があるので、どれか一つを選択します。

あとはこの状態でアプリをぐりぐり実行させるだけです。
定期的にメモリ警告が発生するので、想定外のバグが発見できるかもしれません。
是非お試しください!



メモリ警告関連バグの対処法



備忘録も兼ねて・・・

ViewControllerからViewを生成する場合、大まかに以下のような流れになります。


1. ViewControllerの初期化メソッド(initなんちゃらメソッド)の実行
2. ViewControllerのloadViewの実行
3. ViewControllerのviewDidLoadの呼び出し


しかし、メモリ警告でviewが破壊されると、1の初期化メソッドが呼び出されず2と3だけが実行されることになります。そのため、初期化メソッド内でviewの操作を行っているとメモリ警告後におかしな動きになってしまうことになります。

これを踏まえて、

  • ViewControllerの初期化メソッドでviewの操作をしないこと
  • viewの操作をしたい場合はviewDidLoadで行うこと

この2点を守りながらコーディングすればメモリ警告によるバグはだいぶ防げるはずです。

もうアイコン画像はいらない! Webフォントを使って、iOS風タブバーとアイコンを作成する方法

こんにちは、鴨田です。

最近、アイコンがセットされたWebフォントを使うことで、
画像を使わずにアイコンを表示するという手法が流行っていますね。

すごく興味はあったのですが、なかなか使う機会もなく、
便利そうだなと思っていただけで、今まで使ったことがありませんでした。

しかし、先日、とある案件でやっと使う機会に恵まれたので、やり方をご紹介いたします。
(プロトタイプだけ作って、結局プロダクトとしては使いませんでしたが・・・)

1.アイコンWebフォントをダウンロードする



最近話題になっていたこちらのサイトがとても便利です。

Fontello - http://fontello.com/



使いたいフォントを選択します。
ここでは、「Entypo」フォントから5つ選択します。



選択が終わったら、上部のタブから「Edit codes」をクリックします。



イコン画像の上部のバーをクリックして、アイコンに割り当てる文字列を決めます。
英語で頭文字を取るとか、abc~とかにするとかですかね。



文字列の指定が終わったら、フォントファイルのダウンロードを行います。
サイト右上にある「Download webfont(n)」をクリックしましょう。
「fontello-xxxxxxxx.zip」がダウンロードされます。

解凍して中身を見てみましょう。

fontello
cssフォルダ
 -icons.css
 -icons-codes.css
 -icons-ie7.css
 -icons-ie7-codes.css
-fontフォルダ
 -icons.eot
 -icons.svg
 -icons.ttf
 -icons.woff
-config.json
-demo.html
-LISENSE.txt
-README.txt

が入っています。

どんな作りになっているのかは割愛します。
重要な箇所に関しては、後で説明しています。
とりあえず中身を知りたい人は、ライセンスとリードミーを読んだ後、
(特にフォントのライセンスについては特に確認した方がいいと思います)
demo.htmlとicons.cssを見てみてください。

それでは、iOS風タブバーを作っていきましょう。

2.HTMLとCSSRetina対応のiOS風タブバーを作成する



html
cssフォルダ
 -reset.css
 -style.css
-fontフォルダ
 -icons.eot
 -icons.svg
 -icons.ttf
 -icons.woff
-index.html

reset.cssは、HTML5用の既知のreset.cssであれば何でも構いません。
以前に記事にした「HTML5+CSS3の導入時に役立つ7つの設定」も参考にしてください。

「font」フォルダは、先ほどダウンロードしてきたフォルダをそのままコピーします。

まずは、tab.htmlを書きましょう。

index.html


<!DOCTYPE html>
<html>

<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <title>iOS風タブバー</title>
  <link rel="stylesheet" media="screen" href="css/reset.css" />
  <link rel="stylesheet" media="screen" href="css/style.css" />
</head>

<body>

  <!-- header -->
  <header id="header">
    <h1>タイトル</h1>
  </header>

  <!-- tab menu -->
  <nav id="tab">
    <ul>
      <li><a href="" class="on"><span><i class="icon-home"></i>HOME</span></a></li>
      <li><a href=""><span><i class="icon-camera"></i>カメラ</span></a></li>
      <li><a href=""><span><i class="icon-picture"></i>アルバム</span></a></li>
      <li><a href=""><span><i class="icon-bookmark-1"></i>お気に入り</span></a></li>
      <li><a href=""><span><i class="icon-info-circle"></i>お知らせ</span></a></li>
    </ul>
  </nav>

</body>
</html>


特に何の変哲もないHTMLのソースコードです。
これに関しては、何も言うことがありません。

続いて、style.cssを書きます。

style.css


/* font */

@font-face {
  font-family: 'icons';
  src: url("../font/icons.eot");
  src: url("../font/icons.eot?#iefix") format('embedded-opentype'), url("../font/icons.woff") format('woff'), url("../font/icons.ttf") format('truetype'), url("../font/icons.svg#icons") format('svg');
  font-weight: normal;
  font-style: normal;
}

.icon-home:before { content: '\68'; } /* 'h' */
.icon-info-circle:before { content: '\69'; } /* 'i' */
.icon-picture:before { content: '\70'; } /* 'p' */
.icon-camera:before { content: '\63'; } /* 'c' */
.icon-bookmark-1:before { content: '\66'; } /* 'f' */

/* common */

#header {
  position: fixed;
  z-index: 2;
  width: 100%;
  height: 44px;
  top: 0;
  left: 0;
  background: #eee;
  background: -o-linear-gradient(top, #fff, #fff 50%, #ddd 50%, #ddd);
  background: -moz-linear-gradient(top, #fff, #fff 50%, #ddd 50%, #ddd);
  background: -webkit-gradient(linear,left top,left bottom, color-stop(0.5, #fff),color-stop(0.5, #ddd));
  border-top: 1px solid #666;
  border-bottom: 1px solid #444;
  text-align: center;
  overflow: hidden;
}


#tab {
  position: fixed;
  z-index: 2;
  width: 100%;
  height: 49px;
  bottom: 0;
  left: 0;
  border-top: 1px solid #444;
  background: #ccc;
  background: -o-linear-gradient(top, #fff, #ccc);
  background: -moz-linear-gradient(top, #fff, #ccc);
  background: -webkit-gradient(linear,left top,left bottom, color-stop(0, #fff),color-stop(1, #ccc));
  float: left;
  overflow: hidden;
}

/* header */

#header h1 {
  line-height: 44px;
  display: block;
  font-size: 20px;
}

/* footer */

#tab ul {
  width: 100%;
  height: 49px;
  float: left;
}

#tab li {
  width: 20%;
  height: 100%;
  text-align: center;
  display: block;
  float: left;
}

#tab li a {
  width: 100%;
  height: 100%;
  display: block;
  color: #777;
  text-decoration: none;
  font-size: 8px;
}

#tab li a.on, #tab li a:hover {
  color: #09c;
}

#tab li a span {
  margin: 3px 6px;
  padding: 0 0 2px;
  display: block;
}

#tab li a.on span {
  margin: 2px 5px;
  background: rgba(255,255,255,0.2);
  border: 1px solid rgba(0,0,0,0.2);
  border-radius: 4px;
}

#tab li a i {
  font-family: 'icons';
  font-size: 30px;
  font-style: normal;
  display: block;
  padding: 0 0 2px 0;
}

#tab li a.on i, #tab li a:hover i {
  text-shadow: 0px 1px 0 rgba(0, 0, 0, 0.6);
}


注目するところは、以下ですね。



@font-face {
  font-family: 'icons';
  src: url("../font/icons.eot");
  src: url("../font/icons.eot?#iefix") format('embedded-opentype'), url("../font/icons.woff") format('woff'), url("../font/icons.ttf") format('truetype'), url("../font/icons.svg#icons") 

format('svg');
  font-weight: normal;
  font-style: normal;
}


まずは、Webフォントの読み込みを行います。



.icon-home:before { content: '\68'; } /* 'h' */
.icon-info-circle:before { content: '\69'; } /* 'i' */
.icon-picture:before { content: '\70'; } /* 'p' */
.icon-camera:before { content: '\63'; } /* 'c' */
.icon-bookmark-1:before { content: '\66'; } /* 'f' */


:beforeセレクタとcontentプロパティを使うことで、
HTML自体に余計な文字列が紛れ込むのを防いでいます。
SEOユニバーサルデザイン的にもあまりよろしくないですからね。

そして、最終的に重要なところはここです。



#tab li a i {
  font-family: 'icons';
  font-size: 30px;
  font-style: normal;
  display: block;
  padding: 0 0 2px 0;
}


アイコンを表示させるべき箇所で、font-familyプロパティに、さきほどセットした"icons"を使用します。
displayプロパティはblockにしてください、地味に重要です。
後は、アイコンの大きさとちょっとしたパディング設定とイタリック体の解除を行っています。

これだけです。これだけでこうなります。
デモなので、ロールオーバーとかします。



なんて便利!
もういちいち画像を使って、タブバーを作るのが面倒くさくなってしまいます。

動作確認は、iOS5.0ではSafariChrome、Android4.0および2.3では標準ブラウザで行っています。
PCブラウザであれば、各最新版のSafariChromeFirefoxOperaで問題ありません。
IEは9以降で、グラデーション等が使えないですが、Webフォント自体は使えるようですね。

一応、横幅はどんなサイズであろうとも、対応しています。
ただし、もろもろの事情により、先日書いた「CSS3だけで作るレスポンシブデザイン対応ナビゲーションバーの作り方」とは違い、古風な手段で対応しています。

Opera対応しようと思っただけなのですが、Operaはbox-flex使えないので・・・
 多分、スマホサイトでしか使わないと思うので、
 OperaIEを気にしないのであれば、上記記事と組み合わせて、モダンなCSSでいけるはずです。

是非、一度試してもらえたらと思います。

GitHubソースコード一式を公開したので、煮るなり焼くなり、
自由にダウンロードやフォークしてみてください。

jsdo.itにも公開しておきます。ただし、SVGファイルしか置けなかったので、
ChromeSafariでしか、ちゃんと表示されません。

【iOS】Viewの開発・デバッグに役立つ色々

こんにちは、中川です。

最近はちょっとPHPから離れてMonacaを使ったiOSアプリの開発を行なっています。
Monacaでは基本的にHTML+CSS+JSでの開発となりますが、
今回開発中のものはObjective-Cを使ったネイティブの画面をカスタムで組み込んで利用したりしています。

HTML+CSSであれば画面を作るのは慣れていることもあり比較的簡単なのですが、
UIKitでのネイティブ画面となると微妙なズレの調整などで苦労する場面が多々ありました。
そんな時に役立ったTIPSなどをご紹介したいと思います。

■位置やサイズのログ出力


CGRect, CGSize, CGPoint など、NSStringFromXXXXXで簡単にログ出力することができます。


NSLog(@"frame: %@", NSStringFromCGRect(self.view.frame));
NSLog(@"size: %@", NSStringFromCGSize(self.view.frame.size));
NSLog(@"center: %@", NSStringFromCGPoint(self.view.center));

※出力結果


2012-01-23 15:51:51.125 Sample[23110:f803] frame: {{0, 0}, {320, 411}}
2012-01-23 15:51:51.127 Sample[23110:f803] size: {320, 411}
2012-01-23 15:51:51.128 Sample[23110:f803] center: {160, 205.5}

知ってる人には常識なことかもしれませんが、知るまでは size.width, size.heightなどと個別に出力してました。。。

■Viewのログ出力


UIVIewのframeなどは、上記のようにしなくとも、


NSLog(@"view: %@", view);

これで、


view: <UIView: 0x68aa750; frame = (0 0; 320 411); autoresize = W+H; layer = <CALayer: 0x68aa7d0>>

このように確認することもできます。

■Viewを再帰的にログ出力


指定したViewを再帰的にダンプすることができます。



NSLog(@"%@", [view performSelector:@selector(recursiveDescription)]);


※出力例


<UIView: 0x68ccc40; frame = (0 0; 320 411); autoresize = W+H; layer = <CALayer: 0x68cccc0>>
   | <UILabel: 0x68c3cc0; frame = (54 98; 212 43); text = 'First View'; clipsToBounds = YES; opaque = NO; autoresize = W+BM; userInteractionEnabled = NO; layer = <CALayer: 0x684d680>>
   | <UITextView: 0x68cce10; frame = (20 181; 280 88); text = 'first view...'; clipsToBounds = YES; opaque = NO; autoresize = W+BM; userInteractionEnabled = NO; layer = <CALayer: 0x68cc200>; contentOffset: {0, 0}>
   |    | <UITextSelectionView: 0x68cd230; frame = (0 0; 0 0); userInteractionEnabled = NO; layer = <CALayer: 0x68c47a0>>
   |    | <UIImageView: 0x68cdea0; frame = (273 54; 7 34); alpha = 0; opaque = NO; autoresize = LM; userInteractionEnabled = NO; layer = <CALayer: 0x68cdf10>> - (null)
   |    | <UIWebDocumentView: 0x718dc00; frame = (0 0; 280 34); text = 'first view...'; opaque = NO; userInteractionEnabled = NO; layer = <UIWebLayer: 0x68d15f0>>
   |    |    | <TileHostLayer: 0x68d1b00> (layer)
   |    | <UITextSelectionView: 0x68dbb80; frame = (0 0; 0 0); userInteractionEnabled = NO; layer = <CALayer: 0x68dbbe0>>

※スクショ:

■DCIntrospect


https://github.com/domesticcatsoftware/DCIntrospect

ちまちまログでやってられないって時に。
シミュレータ上でリアルタイムにビューの位置の確認、調整、ダンプ、カラーリング
などが行えます。これを知るまではViewの調整に非常に苦労しました・・・。

上記ページからダウンロードして「DCIntrospect」をプロジェクトに追加します。
DCIntrospect内で「QuartzCore.framework」を利用しているようですのでこちらも追加してください。
あとはAppDelegateなどで、以下のように組み込みます。


:
:
[window makeKeyAndDisplay]

// always call after makeKeyAndDisplay.
#if TARGET_IPHONE_SIMULATOR
    [[DCIntrospect sharedIntrospector] start];
#endif
:
:

これでシミュレータでアプリを起動してPCのキーボードのスペースを押すと
インスペクタが起動します。

Viewにボーダーや背景色を付けてデバッグしやすくしたり、Viewを矢印キーで移動させたりできます。
他にも画面上のViewを選択して「p」や「v」などで、ログ出力がアプリを起動しながら行えます。

「?」でヘルプ画面を表示できるという親切設計です。


■Stats


https://github.com/shu223/Stats
メモリ使用量やViewの数を表示しておくことができます。
使い方はいたって簡単で上記githubからダウンロードして、
AppDelegateなどに仕込んでやるだけと簡単です。


#import "Stats.h"

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
:
:
  Stats *stats = [[[Stats alloc] initWithFrame:CGRectMake(10, 30, 100.0, 60.0)] autorelease];
  [self.window addSubview:stats];
:
:
  return YES;
}

これで以下のように常に画面に表示しておくことができます。



※参考: http://d.hatena.ne.jp/shu223/20110428/1303930059

■(おまけ) UIWebView内のデバッグ


あと、PhoneGapなどで開発していると、WebView内のHTML,JS,CSSデバッグしたくなりますよね。
そんな時には以下のものが役に立ちました。
・weinre ( http://phonegap.github.com/weinre/ )
scriptタグをひとつ追加するだけで、WebkitのWebInspectorを使ったデバッグができるようになります!

・remoteデバッグ
シミュレータかつiOS5からとなりますが、以下の方法でもPCのSafariのWebInspectorを利用したデバッグが可能です。
こちらは、ブレークポイントも使えるJSのデバッグが可能になります。
AppDelegateなどで、


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
:
:
[NSClassFromString(@"WebView") performSelector:@selector(_enableRemoteInspector)];
:
:
}

として、アプリを起動しWebViewの画面を表示します。
そしてPCのSafariで、http://localhost:9999/ にアクセスしてみてください。
WebViewの一覧のリンクが表示され、それをクリックするとWebInspectorが利用できます。



■最後に


上記でご紹介した方法はいずれもデバッグ用ですので、
リリースアプリに組み込んだままにならないようご注意ください。

Monacaで作ろう 簡単スマフォアプリ!

こんにちは、志田です。
今回は、弊社で開発しているスマートフォンプラットフォーム「Monaca」を使って、アドレス帳検索アプリを作ってみます。


1. Monaca開発準備



まずはMonacaで開発できる環境を整えましょう。
弊社松田の記事を参考に、Monacaアカウントを取得、プロジェクトを作成しましょう。
Monaca + enchant.js でお手軽スマフォゲームアプリ開発

そして、実機にMonacaデバッガをインストールしてください。
http://docs.monaca.mobi/manual/debugger/

2. 表示部分 index.htmlの編集



今回のアプリはとても簡単な作りですが、このような作りのアプリにしたいと思います。
(1) 入力フォームに検索したい文字列を入力する
(2) 携帯のアドレス帳を検索する
(3) 検索フォームの下に、検索結果を表示

まず、表示部分であるindex.htmlを編集しましょう。



<!DOCTYPE HTML>
<html>
  <head>
    
    <meta name="viewport" content="initial-scale = 1, user-scalable=no" />
    <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
    <title>PhoneGap</title>
    <link rel="stylesheet" href="css/master.css" type="text/css" media="screen" title="no title" charset="utf-8">
    <link rel="stylesheet" href="css/jquery.mobile-1.0b2.css" type="text/css" media="screen" title="no title" charset="utf-8">
        
    <script type="text/javascript" charset="utf-8" src="js/jquery-1.6.2.min.js"></script>
    <script type="text/javascript" charset="utf-8" src="js/jquery.mobile-1.0b2.js"></script>
        
    {% if Device.Platform == Android %}<script type="text/javascript" charset="utf-8" src="js/phonegap.0.9.5.1_android.js"></script>{% endif %}
    {% if Device.Platform == IOS %}<script type="text/javascript" charset="utf-8" src="js/phonegap.0.9.5.1_ios.js"></script>{% endif %}

    <script type="text/javascript" charset="utf-8" src="js/main.js"></script>  
                
  </head>
    
  <body onload="onLoad();" data-role="page" data-theme="c">

    <div data-role="header" data-theme="b"><h1>アドレス帳検索</h1></div>
        
    <div data-role="content" data-theme="b">
      <input type="text" id="search">
      <input type="button" value="Search!" onClick="search_user()">
            
      <div id="info">
      </div>        
    </div>

    <div data-role="footer" data-theme="b">
      <div>Powered by Monaca</div>
    </div>

  </body>
</html>


上記のようなコードで、このようなアプリの見た目が完成しました。


それでは、これから機能部分を実装していきます。

3. 機能部分 main.jsの実装





// PhoneGapの読み込みを待機
//
function onLoad() {
  console.log("logging start");
  document.addEventListener("deviceready", onDeviceReady, false);
}

// PhoneGap準備完了
//
function onDeviceReady() {
  $("#info").append("<p>アドレス帳からユーザを検索します</p>");
}

//ボタンを押すとアドレス帳を検索
//
function search_user() {
  var options = new ContactFindOptions();
  options.filter = document.getElementById('search').value;
  var fields = ["displayName", "name", "phoneNumbers"];
  navigator.service.contacts.find(fields, onSuccess, onError, options);
}

//エラー
//
function onError() {
  alert("エラー発生");
}

//検索結果
//
function onSuccess(contacts) {
  $("#info").empty();
  $("#info").append('<p>「<span style="font-weight:bold; color: orangered;">' + $("#search").val() + '</span>」の検索結果</p>');
  if (contacts.length == 0) {
    $("#info").append("<p>アドレス帳に登録されていません。</p>");
  }
    
  for (i=0; i<contacts.length; i++){
    var name = '';
    if (contacts[i].name.formatted != null) {
      name = contacts[i].name.formatted;
    } else {
      if (contacts[i].name.familyName != null)
        name = name + contacts[i].name.familyName;
      if (contacts[i].name.givenName != null)
        name = name + contacts[i].name.givenName;
      }
      var string = '';
      string = "<p>" + name + "</p>";
      for (j=0; j<contacts[i].phoneNumbers.length; j++) {
        string = string + "<p> &nbsp; &nbsp;" + contacts[i].phoneNumbers[j].value + "</p>";
      }
        
      if (contacts.length -1 != i)
        string = string + "<hr />";
      $("#info").append(string);
  }
}


まず、index.htmlのbody onLoadで指定されているとおり、main.jsのonLoad()が呼ばれます。
onLoad()では、PhoneGapの読み込みを待機し、DeviceReady状態になるとonDeviceReady()が呼ばれています。

onLoad()内で、console.log()という処理を行えば、デバッグログに文字列を残すことができます。
onDeviceReady()では、処理の初期化などを行うと良いですね。

index.htmlを見ると、検索ボタンを押すとsearch_user()を呼ぶようになっていることがわかります。
main.jsのsearch_user()で何をしているかというと・・・



function search_user() {
  // 検索オプションを作成します。
  var options = new ContactFindOptions();
  // 検索オプションのフィルターに、入力文字列を使います。
  // ここで指定された値でアドレス帳を検索します。
  options.filter = document.getElementById('search').value;
  // 検索結果に返してほしいフィールドを指定します。
  // この例だと、連絡先名称、個人名に関するオブジェクト、電話番号を指定しています。
  var fields = ["displayName", "name", "phoneNumbers"];
  // アドレス帳から指定したフィールドを、指定したオプションで検索します。
  // 成功時はonSuccess、失敗時はonErrorに遷移します。
  navigator.service.contacts.find(fields, onSuccess, onError, options);
}


このように、検索オプションを指定して検索を行っています。
さて、検索が成功した後はどうしているかというと・・・



// 成功時は、onSuccessにcontactsが引数として渡されます。
function onSuccess(contacts) {
  // まず、div#infoの中身を空にします
  $("#info").empty();
  $("#info").append('<p>「<span style="font-weight:bold; color: orangered;">' + $("#search").val() + '</span>」の検索結果</p>');

  // 検索結果の件数は、contacts.lengthで取得できます。
  if (contacts.length == 0) {
    $("#info").append("<p>アドレス帳に登録されていません。</p>");
  }
    
  // 取得できたcontactsのぶんだけ、div#infoに表示していきます。
  for (i=0; i<contacts.length; i++){
    var name = '';
    // 連絡先のフルネーム:formatted
    if (contacts[i].name.formatted != null) {
      name = contacts[i].name.formatted;
    } else {
      if (contacts[i].name.familyName != null)
        name = name + contacts[i].name.familyName;
      if (contacts[i].name.givenName != null)
        name = name + contacts[i].name.givenName;
    }
    var string = '';
    string = "<p>" + name + "</p>";
    // 登録されている電話番号を全部表示
    for (j=0; j<contacts[i].phoneNumbers.length; j++) {
      string = string + "<p> &nbsp; &nbsp;" + contacts[i].phoneNumbers[j].value + "</p>";
    }
        
    // 区切りのhr
    if (contacts.length -1 != i)
      string = string + "<hr />";
    // div#infoに追加
    $("#info").append(string);
  }
}


コードを見ても分かるとおり、簡単なJavaScriptjQueryで、contactsの検索ができます。



4. アプリとしてインストール



デバッグビルドを行えば、アプリとしてインストールすることができます。
今回は、実機がAndroidなので、右上のメニューからAndroidをクリックし、「ビルド」を選択。
下図のような画面が出ますので、「デバッグビルド」をクリックします。



少し待つと、デバッグビルドが終了します。
そうすると、Monacaデバッガからネットワークインストールすることができます。



インストールが完了すると、端末にインストールされたネイティブアプリと同様に、起動・利用できるようになります。

スプラッシュ画面が表示された後・・・


アプリ起動!


はじめの画面と見比べるとわかりますが、デバッガのメニューが表示されておらず、ネイティブアプリとして動いていることがわかります。

まずはAPIを見てみよう



Monacaでアプリを開発するにあたり、いろいろなネイティブの機能を利用することができます。
加速度センサー、カメラ、位置情報、ネットワーク、ストレージ…
全て、簡単なJavaScript等で記述できます。

機能を利用するためのAPIドキュメントはこちら。
http://phonegap-fan.com/docs/

Monacaアプリ開発がもっと身近なものになると思います。
みなさんも、楽しいアプリを作ってみてください♪