やらなイカ?

たぶん、iOS/Androidアプリの開発・テスト関係。

Google Cloud Messaging (GCM) の新機能 Topic Messagingを試したメモ

Google I/O 2015で発表された Google Cloud Messaging(以下GCM)の新機能、Topic Messagingを試してみました。

環境、前提条件などは、先の記事を参照してください。

nowsprinting.hatenablog.com

Topic Messaging とは

Topic Messagingとは、従来のGCMおよびApple Push Notification Service(以下APNs)のような送信先デバイスのトークンを指定してのPush通知ではなく、Publish/subscribeモデルのPush送信を行なう機能です。

Publish/subscribeモデルとは、各デバイスから購読(subscribe)したいトピックをあらかじめ登録することで、メッセージ送信(publish)側では個々のデバイスを意識することなく、トピックに対してメッセージを送ることで購読デバイスすべてにメッセージを配信できるものです。

これによって、例えば、

  • ニュースの更新などをPush通知したいだけであれば、サーバアプリケーションでは受信デバイスのRegistration Tokenを管理する必要がない
  • 送信機能もクライアントアプリに持たせる場合、サーバアプリケーション自体を立てる必要がない

といった構成が実現できるようになります。

制約・制限

GCMのTopic Messagingには、以下の制約・制限があります。

  • トピックのキーは、/topics/[a-zA-Z0-9-_.~%]+の書式
  • アプリあたり*1の購読数は100万件まで
  • トピックに送信できるメッセージのペイロードは2KBまで

購読数については、ユーザが1トピックづつ購読して100万ユーザまで、平均2トピックなら50万ユーザまで…となるので、インストール数が見込まれるアプリでは注意が必要です。

トピックの購読

以下、前回同様 Try Google Cloud Messaging for iOS のサンプルを使用して試していきます。

トピックの購読は、次のメソッドで行ないます。(メインスレッドから呼ぶ必要があります)

[GCMPubSub subscribeWithToken:topic:options:handler:]

サンプルのGcmExampleでは、起動時にトピック/topics/globalを購読するようになっています。

トピックへのメッセージの送信

続いて、同じく"Get started"のサンプルプロジェクトにあるGcmServerDemoを起動すると次のウィンドウが表示されます。

f:id:nowsprinting:20150607043716p:plain

apiKey欄にGCMのAPI Keyを入力し、"Send to topic"ボタンをクリックすると、送信メッセージの(本来、宛先のRegistrationTokenを設定する)toに、/topics/globalを設定して送信が行われます。

具体的には、以下のメッセージが送られます。

[
    "to": "/topics/global",
    "notification": [
        "body": "Hello from GCM"
    ]
]

これだけで、トピック/topics/globalを購読しているデバイスすべてにPush通知が送信されます。

トピックメッセージの受信

受信は通常のPush通知と同様です。受信側でトピックメッセージ固有の処理を行いたい場合は、 [UIApplicationDelegate application:didReceiveRemoteNotification:]メソッドで以下のように判定できます。

-(void)application:(UIApplication)application
        didReceiveRemoteNotification:(NSDictionary)notification {
    if ([notification[@"from"] hasPrefix:@"/topics/"]) {
        // トピックメッセージを受信した
    } else {
        // 通常のメッセージを受信した
    }
}

なお、今のところ、購読されているトピックのリストを取得するようなインタフェースは、サーバ側にもクライアント側にも定義されていないようです。

その他、エラーハンドリングなど詳細は公式のガイドを参照してください。

Implementing Topic Messaging

App nameとBundle ID, Androidアプリとの関連

GCMの利用登録を行なうページでは、"App name"と"iOS Bundle ID"を入力します。ここで、"App name"は、Google Developer Console(API Console)の"Project name"となります。

f:id:nowsprinting:20150615112845p:plain

これに対し、"iOS Bundle ID"は1:nの関係で登録することが可能です。 同様にAndroidアプリ場合、Bundle IDの代わりに"Android package name"欄にパッケージ名(ApplicationID)を登録しますが、これも1:nの関係になります。

トピックメッセージを送信するためのAPI Key、およびSender IDは、"App name"単位に割り当てられます。これに、複数の"iOS Bundle ID", "Android package name"を紐付けられますので、iOS版とAndroid版、また、Lite版やOEMしたアプリなどに対し、一括してトピックメッセージを送信することができます。

なお、iOSアプリ向け設定ファイルであるGoogleService-Info.plistにはSender IDしか書かれていませんので、複数のビルドターゲットで共有することができます。

Androidアプリ向けのgoogle-services.jsonには、Sender IDのほかに登録されたパッケージ名が書かれますが、登録されたパッケージ名が全て配列で書かれるようです。 そのため、フレーバーを定義して複数のアプリをビルドする場合でも、ひとつのgoogle-services.jsonを共有して問題ありませんでした。

*1:おそらく、Google APIs ConsoleのProject単位のこと

Google Cloud Messaging (GCM) でiOSデバイスにPush通知を送る

Google I/O 2015で発表された、Google Cloud Messaging(以下GCM)を使ってiOSデバイスにPush通知を送る手順が公開されていたので試してみました。

developers.google.com

なお、GCMを使うと言っても最終的にiOSデバイスにPush通知を行うのは従来通りiOS標準のApple Push Notification Service(以下APNs)です。 従来、サーバアプリケーションが直接デバイストークンを管理し、APNsにメッセージを直接送信していましたが、サーバアプリケーション→GCM→APNsと、GCMを介してPush通知を行なうことができます。

GCMにおいて端末固有のトークンとなるRegistration Tokenは、iOSの(APNsの)Device Tokenとは異なる、次のような*1文字列です。

bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1pLTQ/8t-5QNiXbYwZYEWiSFD-frQKlsV8lgI

iOSアプリでGCMを利用するメリットとしては以下が挙げられます。すでにMBaaSのPush通知サービスなどを使っているのであれば、実現できているものだと思います。

  • iOSAndroidのデバイストークン(Registration Token)を一元管理できる
  • iOSAndroidのPush送信ロジックを共通化できる
  • Topic Messagingを利用することで、デバイストークン指定でなくトピック文字列指定で該当するデバイスにPush通知できる

環境

今回試した環境は以下の通りです。

  • OS X 10.10.3
  • Xcode 6.3.2
  • iOS 8.3(Push通知を受けるには実機である必要があります。シミュレータはNG)
  • GCMクライアントライブラリ 1.0.7

なお、GCMクライアントライブラリを利用するには、iOS 7以上が必要です。*2

事前準備

前述の通り、APNsを利用することになりますので、App IDごとの"Push Notification"を許可し、APNsのSSL証明書を生成しておく必要があります。

証明書は、Development(sand box)、Productionいずれも利用可能です。今回はDevelopmentのみ試しています。

サンプルアプリのビルド

以下、Try Google Cloud Messaging for iOSの手順について補足します。

  1. CocoaPodsでサンプルを取得します

    $ pod try Google

    使用するサンプルを聞かれるので、 4: Samples/gcm/GcmExample.xcodeprojを選択。Xcodeでサンプルプロジェクトが開きます。

    サンプルプロジェクトには、クライアント二種類(Objective-C版とSwift版)、送信側のMacアプリケーションの、計3つのビルドターゲットが含まれます。

  2. Google Developersサイトで、GCMのAppと、iOSアプリのBundle IDを登録します

    Try Google Cloud Messaging for iOSページにある"GET A CONFIGURATION FILE"ボタンで登録ページに遷移できます。

    ここでApp Name(Androidアプリと共有するならば同じ名前で)、アプリのBundle IDを入力し、続いてAPNsのSSL証明書(p12形式)をアップロードします。すると、API KeyとSender IDを取得でき、GoogleServices-Info.plistがダウンロードできます。

  3. GoogleServices-Info.plistをサンプルアプリ(クライアント側)に取り込みます

    GoogleServices-Info.plistには、Sender IDが書かれています。

  4. サンプルアプリ(クライアント)を実行します

    実行すると、GCMにRegistration Tokenが設定され、Push通知を受け取る準備が整います。また、Topic Messagingのためのトピック/topics/globalにも登録されます。

    なお、このときコンソールにRegistration Tokenが出力されていますので、文字列をコピーしておきます。

送信サンプルの実行

サンプルプロジェクトのGCMServerDemoが送信側のサンプルです。起動すると下図のウィンドウが表示されます。

f:id:nowsprinting:20150607043716p:plain

apiKey欄にGCMのAPI Key、Registration TokenにクライアントのRegistration Tokenを入力し、"Send notification"ボタンをクリックすると、該当するiOSデバイスにPush通知が届きます。

f:id:nowsprinting:20150607044650p:plain

送信フォーマット

GCMに渡すメッセージが、APNsの形式に置き換えられてデバイスに届きます。例えばサンプルでは以下のフォーマットをGCMに送っています。

[
    "to": to,
    "notification": [
        "body": "Hello from GCM"
    ]
]

デバイス側ではPush通知のuserInfoとして、以下の形式で受け取ることができます。

aps =     {
    alert = "Hello from GCM";
};
"gcm.message_id" = "0:1433613206212203%4deaf3f24deaf3f2";

badge, sound

badgeとsoundも以下のように指定できました。

[
    "to": to,
    "notification": [
        "body": "Hello from GCM",
        "badge": 10,
        "sound": "default"
    ]
]

iOSデバイスのアプリアイコンにバッジが付き、またPush通知の受信音が鳴ります。 またアプリでは下記形式で取得できました。

aps =     {
    alert = "Hello from GCM";
    badge = 10;
    sound = default;
};
"gcm.message_id" = "0:1433613206212203%4deaf3f24deaf3f2";

その他のパラメタ

上記以外のパラメタは、notification下、もしくはdata下に設定することでアプリに渡すことができます。

[
    "to": to,
    "notification": [
        "body": "Hello from GCM",
        "key2": "value2"
    ],
    "data": [
        "key1": "value1"
    ]
]

アプリでは下記形式で取得できました。

aps =     {
    alert = "Hello from GCM";
};
"gcm.message_id" = "0:1433613206212203%4deaf3f24deaf3f2";
"gcm.notification.key2" = value2;
key1 = value1;

notification下に書いたkey2は、受信側ではgcm.notification.key2というキーに置き換わっています。構造を見る限り、data下に置くほうがよさそうです。

ペイロードに指定できる内容の詳細はリファレンスを参照してください。

Notification payload support

Topic Messaging

Topic Messagingについては次の記事を参照してください。

nowsprinting.hatenablog.com

*1:GCMのサイト内にサンプルとして掲載されていたもので、実在のトークンではありません

*2:ただし、サンプルアプリをそのままiOS 7で動作させるとクラッシュします。iOS 8で導入された[UIApplication registerUserNotificationSettings]を呼んでいるためで、iOS 7以前では[registerForRemoteNotificationTypes]を使用するように書き換える必要があります

#TwitterFlock でFabricの話を聞いてきたメモ

Twitter社主催のアプリ開発者向けイベント"Twitter Flock Tokyo"に行ってきました。このイベントはTwitter社が提供しているFabricについてのもので、各都市で開催されています。

f:id:nowsprinting:20150520075937j:plain

Fabricではいくつかのサービスが提供されています。これまで、ベータ版配布サービス"Beta"、クラッシュログ解析サービス"Crashlytics"については導入事例も聞いており、興味を持っていました。

しかしそれだけでなく、ユーザ認証、Twitter連携、広告までひとまとめのSDKで提供されています。むしろ逆に、『広告SDKに、"Beta"、"Crashlytics"、ユーザ認証などの機能が無償でついてくる』くらいの印象を持ちました。

それぞれ(有償の)競合サービスが出ている中、これら機能を無償で提供して広告でマネタイズするということなので、頭ひとつ抜けたというか、もう別格と考えて良さそうです。

以下、セッションの内容のメモ。

Keynote

はじめに、サービスの全体像、Fabricの機能を一通り紹介。

実装サンプル"Cannonball"は、iOS/AndroidそれぞれGitHubにプロジェクトが公開されている。iOS版はSwiftで書かれている。

github.com

github.com

iOS/Androidとも、SDKの組み込みは非常に簡単。

日本企業の導入事例として、Cyber Agentさん、cameranさん、OneNewsさんの紹介。

Twitter主催のスタートアップコンペ"Hatch"の紹介。

DIGITS

  • DIGITSは、電話番号認証。Fabricの"Twitter Kit"に含まれる。
  • モバイルを前提としたサービスでは、電話番号認証はとても有効
  • これまでも類似サービスは存在したが、以下の理由で難しく、サービス利用も高額だった
    • SMS APIは国・キャリアによって異なる
    • 電話番号からキャリアを判断する必要もある
  • Twitterでは独自にこの機能を構築しており、9年の実績がある。DIGITSはこれを一般の開発者に無償で提供するもの。
  • 認証用ボタン、認証画面はSDKで提供。コールバックを書くだけで使える
  • 認証画面のbackgroundColor, accentColorなどカスタマイズ可能
  • userID, authToken, phoneNumberを取得可能
  • SMSメッセージはローカライズされる
  • AndroidではINTERNETパーミッションが必要
  • Androidで以下のパーミッションを許可すれば、1タップでログインも可能
    • READ_PHONE_STATE
    • RECEIVE_SMS
  • iOS/Androidネイティブアプリだけでなく、html5でも利用可能
  • digits.comで、電話番号変更やTwitterアカウントとの統合などを行える
  • 電話帳マッピングで友達のアカウントを探す

Crashlytics Kit

  • stability, testing, analyticsにまつわるサービスが統合されている
  • デバイス、OSバージョン、3G/WiFi、メモリなどの情報も収集
  • ユーザセションに属性をセットすることで、セグメント分析も可能
  • answersは、リアルタイムの分析エンジン。セットアップするだけでいくつかの指標で分析できる
    • ダッシュボードで見るほか、Emailでレポート
    • stability alert。安定度がしきい値を割るとアラートメールを送ってくれる
    • カスタムイベント(beta)
    • アプリのバージョンアップ当日、以前のバージョンとのクラッシュ率などを比較

Twitter Kit

  • "Fablic.with(TwitterKit)"で利用可能。様々なモジュールがあるので、"with"で宣言。"start"なども検討したけど"with"に。
  • Twitterアカウントによるシングルサインオン
  • シェア
    • TweetComposerクラスにチェインで指定。text().url().image().show()
    • 埋め込みツイート。リアルタイム、コンテンツの補完
    • TWTRTweetViewで表示もViewレベルで提供。サイズ、テーマなど設定が可能
    • TweetViewDelegete
      • willShareTweet
      • didSelectTweet
      • etc..
  • ゲスト認証(limitはある)
  • REST API Client
  • 使いかたはCannonballを参照

広告

  • オーガニック
    • Twitter Card。いくつか種類がある中に、App card。
    • アプリのページにmeta tagで書く
  • deep link
    • アプリのURLスキーム起動、Twitterカードからインストール通知を受けられる
    • カード表示のとき、URLスキームを見て「ストアで開く」か「アプリ起動」ボタンになる
  • full deep link
    • URLスキームに続けてパラメタを渡す
  • 分析
    • analytics.twitter.com
    • アプリのコンバージョン測定
    • Twitter card経由のインストールも計測できる
    • cardのインプレッション、アクティビティ
    • インフルエンサーと人気コンテンツを計測(インプレッション、インストール)。インフルエンサーに直接コンタクトできるのがTwitterの強み
    • CrashlyticsのアカウントとTwitterアカウントを連携することで、cardの計測が可能
  • プロモーション(paid)
    • セグメントを絞って広告を出せる。id指定もできるので、既存ユーザのみ、既存ユーザを除く、といった指定も可能。
    • ペイド:オーガニックには相関関係がある。ペイドの3.9〜5.2倍のオーガニック(インプレッションやクリック)が得られる

MoPub

  • 広告SDK
  • AdMob, iAdなど、他の広告ネットワークにも接続できる
  • 表示される広告は、MoPubと広告ネットワーク混在でオークションされ、高値の広告を表示できる

所感

評判の良い"Beta"、"Crashlytics"に、Analyticsの"Answers"もセットになってるなら使ってみよう、くらいに思っていましたが、他の機能も強力。

MoPubも筋が良さそうな印象で、広告SDKに対する締め付けも色々出てきている中、単に「セットだから」でなく、これ単体でも十分検討に値するのではないかと。

また、Twitter連携、DIGITSは、MBaaS各社とも競合しそうですね。この先もしPush通知などをサポートしてくると、MBaaSでなくFabricだけで足りるというアプリも出てきそう。 (Twitter社としては、Push相当のことをTwitterでやらせたいような気もするので、実現性は低いかも)

第1回 #DroidKaigi に行ってきました

AndroidエンジニアのAndroidエンジニアによるAndroidエンジニアのためのカンファレンス、第1回*1 DroiKaigiに参加してきました。

f:id:nowsprinting:20150427003737j:plain

発表資料は公開されていますので、簡単なメモと感想だけ残します。

droidkaigi.github.io

基調講演(@yanzmさん)

  • マッチョなActivity
    • Android 2.2までは個人開発者の時代
    • Android 4.3まで、アプリベンチャーの時代
    • Android 5.0はインフラ化の時代。Material Designはアニメーションに本気で取り組むと大変
    • Activityにすべて書いていたら破綻する
    • Activityはテストしにくい
  • 分割先の選択肢として、FragmentとCustomView
    • FragmentはActivity寄り
    • CustomViewについては『Android Pattern Cookbook』の第6章参照
  • Activityがマッチョになる要因と対策
    • 画面回転のときの値保持は、CustomViewのonSave/RestoreInstanceState()に実装する(Activityに書かない)
    • データとViewのマッピングもCustomView内に実装する
    • バリデーションも同様
  • Fragmentではまらないために
    • FragmentへのコールバックはsetTargetFragment()を使う
    • バックスタックは難しい
    • FragmentからstartActivity()ははまる。startActivityForResult()はもっと危険。
    • Fragment in Fragment、Loaderとの組み合わせは危険。startActivityForResult()も危険。

Fragmentは手を出すのが遅かったので未だに恐る恐る使っていますが、このセッションを聴いて恐怖++と同時に、このままFragmentを使っていくという方向は腹をくくっていいのかな、と。

データとViewのマッピングやバリデーションは、私はViewModel的なクラスに実装することが多いかも。分量次第ですが。

参考書籍。『Master of Fragment』は、ベータ版を脱するための加筆候補がたくさんあるそうです。

tatsu-zine.com

CardboardのUXをカメラで向上する(@ken1_takaさん / Room B)

  • Oculus Riftはケーブルとか面倒
  • Cardboardはお手軽。でもタッチパネルが使えないので操作に難あり
  • Cardboardにはカメラ穴があいてるので利用したい
  • Cardboard SDK: 複眼ビュー、樽ゆがみ、マグネットボタン
  • OpenCVでカメラ画像を認識させて、ジェスチャー操作させる

デモアプリが(高速化に失敗して)動かなくなったとのことで残念。OpenCVで指の形状・ジェスチャーを認識できるデモは見ることができました。

なお、OpenCVで頑張るほか、Leap MotionAndroid SDK(今はアルファ版)を待つという選択肢もありますね。

www.leapmotion.com

あるゲームアプリケーションの構成とアップデートサイクル(@iizukakさん / Room B)

  • KLabさんの某音ゲーAndroid 2.3以降対応、2〜3ヶ月に一度アップデートしている
  • ビルド〜デプロイプロセスを「パイプライン」と呼んでいる。GitHub, Jenkins, API, アセット類はAmazon S3にデプロイ
  • 50MBが非Wi-Fiでのapkサイズ限界。ゲームでは足りないので、リソースは追加ダウンロード
  • アップデート、Google Play(apk)は2〜3ヶ月ごとに、追加DLで済むものは数週間ごとに実施。
  • 開発後半は、apkはデイリーで作成してテストエンジニアに配る
    • リリース向けのDL版でなく、アセットを全部バンドルした「フル版」数百M〜数GBのapkを使う
    • 開発終盤はDL版でテスト
    • 実装者は思い込みや見落としがあるので、テストエンジニア重要
  • クラッシュレポート、Developer Consoleはあまり参考にならないので、ほかのサービスを使う
    • 遅延なく監視できるのか、NDK部分を分析できるか
    • Crashlytics, SmartBeat

ビルド〜デプロイプロセスの自動化は、テスト自動化を伴わないとしても開発効率を上げるものなので、KLabさんのように専業のパイプラインエンジニア(ビルド職人)がいなくても、ちょっと時間を取って整備するといいですね。

内部テスト向けの配布はDL版でなくフル版を配る、というのは良さそう。ぜひ真似したい。

紹介されていた書籍。ビルド職人の端くれ(兼業)として、ポチりました。

ゲーム・映像制作パイプライン構築マニュアル

ゲーム・映像制作パイプライン構築マニュアル

ソフトウェア一般としてはこちらもオススメ。

継続的デリバリー 信頼できるソフトウェアリリースのためのビルド・テスト・デプロイメントの自動化

継続的デリバリー 信頼できるソフトウェアリリースのためのビルド・テスト・デプロイメントの自動化

アプリの企画、プロトタイプからリリースに至るまで(@__chocomelonさん / Room A)

  • pixivマンガ。少人数のチーム、ファーストリリースまで3ヶ月
  • 以下の順で開発
    1. ストアの紹介文をメンバー全員で持ち寄って大喜利。アプリの売りを明確化
    2. 雑なプロトタイプ。機能ごとに、雑に。メンバーが物理的に近いことが大事。
    3. イメージ共有後、デザイナーがSketchでライブデザイン
    4. アプリのプロトタイプを作る
      • これもコードは捨てる前提。言語、ライブラリなどを試す。
      • DeployGateで社内で使ってもらう
      • バグの印象がユーザに残ってしまうので、雑過ぎなのもよくない
      • 毎日やっていると、バグフィックスなどに追われて本来のプロトタイプとして機能しなかったので、3日サイクルくらいに。
      • ふりかえり
    5. コーディング。プロトは捨てる
      • サービスで使う言葉を統一する("編集部オススメ"→"EditorsPick"とか)
      • CircleCIでdevelopブランチの変更ごとにビルドして、DeployGateにcurlで上げる
      • 新規開発なのでPull Requestが巨大になりがち。こまめにコミット、こまめにPR
      • ちゃんとKPTでふりかえるようにした。週一。
      • リリース前2weekをバグフィクスにあてる。機能の多さよりクオリティを担保。
  • 以降のリリースサイクルは2week、月曜から段階的に20% → 50% → 100%
  • リリース前週の水曜にコードフリーズ、金曜にチェックシート
  • 朝会後、5〜10分チームメンバー全員でドッグフーディング(立ったまま)
  • 毎週、KPTとはべつに、アプリの今後を全員で考える「ヴィジョナリータイム」実施。エモい。
  • チャットツール(idobata)にcrash hook。Crashlytics連携でメインのチャットに投げられる
    • Play Storeのレビューもhook。gsutilで取得する。ただし2日遅れ
    • ご意見フォーム(id入力とかの要らないカジュアルなもの)もhook

ストアの紹介文から入る点、機能ごとの「雑なプロトタイプ」を作る点と、それでイメージを共有した上でデザイナさんがデザインを作っていく、というプロセスは面白そう。

チャットにクラッシュやユーザの反応を流していくのも良いアイデアだと思いますが、それをissue化する作業が誰か(当事者意識を持った人)に依存してしまう恐れがありそう。真似るなら、KPTや「ヴィジョナリータイム」もセットでやらないと危険かも。

大容量データのダウンロード戦略(@misyobunさん / Room A)

  • android.app.DownloadManagerを使う選択肢。ただし、
    • アプリ内でやりたい。統一されたUIを提供したい。
    • Googleのダウンロードアプリに状況を出したくない
  • 自力で実装。android.app.DownloadManagerのソースを参考にする
  • DLタスクの状態を管理するContentProvider
  • Serviceを使う。Activityをまたぐ処理を行なう場合
    • Serviceから、startForeground()でNotificationを出せる。プライオリティも上がるので死ににくい
    • Activityとプロセスを分けると、ヒープも別になり死ににくい。AndroidManifestに書ける
    • IntentServiceはシリアル実行なので、パラレルしたければ自力でServiceから書く。
    • 生死ハンドリング、プロセス名を使って生存確認
      • onTaskRemoved()は機種によっては呼ばれないので注意

進化するランタイムART(@kmt-tさん / Room A)

  • ARTを理解するには、まず『Android仮想マシン Dalvik編』を読むべき
  • LollipopからはART
  • OATファイル、OATコンパイラが吐く
  • DEXファイルは、OATファイルに埋め込まれる。Annotationなどのメタデータ
  • OAT
    • ELF形式、共有ライブラリ(.so)と同じ
    • リンカ、ローダはOAT独自
    • .rodataセクション:Linux標準のものに加え、DEXそのもの、GCガイド情報など
    • .oat_patchesセクション:OAT独自。イメージの再配置情報
  • QuickコンパイラJITコンパイラベース(だけどARTでは高速化されている)
  • ほかのコンパイラは最新のmasterでは削除されている
  • Quickは、LIR層までCPU依存でない(DalvikはLIRはCPU依存だった)

他のセッションと比較して、はじめからハードル高めな低レイヤの話でした。まずDalvikを知るべし。

tatsu-zine.com

買ってあるけど読めてません…

ARTのメモリ管理(@haru067さん / Room A)

  • GC ルートスキャンと再マークの一部を並行実行されるので、停止は3msくらい
  • LOS(large object space): 大きいオブジェクト専用スペースを設け、フラグメントを抑える
  • 並行(concurrent)GCの実行タイミングが賢くなった
  • 並列(parallel)GC、マルチコアな端末に向けて
  • 世代別GC
  • アロケータ、ResAlloc。並行メモリ割り当てが改善され、ロック不要になった
  • 質疑応答
    • コンパクションは基本やらない。backgroundのアプリを対象

GC(Garbage Collection)の話。Androidはmark and sweepだという認識を持ったままでしたが、色々進化していることを知りました。

つかえるGradleプロジェクトの作り方(@zaki50さん / Room A)

  • 設定するとできること
    • buildToolsVersionなどの一元管理
    • デバッグ証明書をプロジェクトに含めて管理
    • リリースapkへの署名
    • バージョンコード設定
    • git hashを埋め込む
  • Android StudioGUIでもかなり色々設定できる(build.gradleに反映される)
  • 記述方法は、『Android実践プログラミング』第5章および、GitHubで公開しているandroid_gradle_templateリポジトリを参照

techbooster.booth.pm

github.com

アプリを公開する前に、最低限知っておきたいセキュリティ事項(@tao_gakuさん / Room A)

Android Security 安全なアプリケーションを作成するために

Android Security 安全なアプリケーションを作成するために

Material Design を取り入れたデザインリニューアル(@ninjinkunさん、@yuki930さん / Room A)

Fril 3.xにおける、マテリアルデザインのキャッチアップから実装まで。

design

  • キャッチアップ。Feedlyが参考になる。Googleガイドラインは頻繁に更新されている。
  • ユーザテストを実施。既存ユーザの体験を損なう変更があった。
    • 画面下にあったタブをドロアに入れたため、
      • お知らせを開くのに2タップ必要になった
      • 未読バッジが見えなくなった
    • ActionButtonでお知らせに遷移するように変更した。標準的なUIから外れるが、ユーザテストの結果を尊重した
    • ユーザの動線。タイムラインを見た後、お知らせがあれば見て終了、という流れだった
  • 標準のタイポグラフィに合わせると日本語フォントに合わないので調整した
  • Sketch向けUIパーツがGoogleから配布されている
  • アイコンはsvgをIcoMoonというサイトでフォント化して使用。アプリサイズも削減できる。
  • textAppearanceを活用。styleの切り分けが楽に。

code

  • Support Libraryが出る前だったので、UI部品も自力で実装。後のバージョンでSupport Libraryに切り替え
  • リニューアルと同時に構造もモダンに。Fragment, Retrofit, RxJavaを導入
  • calligraphy。textViewに外部フォントを読み込み可能にしている
  • ListViewスクロールに合わせてActionBarを隠す
  • @yanzmさんに加わってもらったことを契機に、メンバー増加に備えた
    • コーディング規約などを整備、CONTRIBUTIONS.mdに集約した
    • JavaDocはちゃんと書くようにした。API Clientは特に丁寧に書く。
    • ActivityやFragmentの継承(BaseActivity/Fragment)をどうすべきか問題。Frilでは使わないこととした
  • リニューアル後、滞在時間2倍くらい、継続率も伸びてる、売買の成約率も上昇。
  • 登録の動線も見直し、離脱率も削減。
  • Googleの2014 Best Appに選ばれた
  • Android 4.0以上にした。2.3向けに旧バージョンを提供はしている。

今ならSupport Libraryがあるとは言え、「導入しました」では済まないところなので大変参考になりました。

なかでも、ガイドラインユーザビリティのくだりは身につまされました。ActionButtonをタブのように使うのは気持ち悪いだろうな、と。でも、既存ユーザの慣れの問題なのか、動線の問題なのかまで踏み込んでいるので、気持ち悪いながらも決断したというところでしょうか。

所感

connpassによる募集は瞬殺、大量のキャンセル待ちを抱えたイベントでした。通常、首都圏のこの手の参加費無料イベントは当日キャンセルも多く、6〜7割くらいの入りになってしまうものですが、今回は10:00の開始時点でかなり席が埋まっているという状態。しかも年齢層が若い。

Android関係の開発者コミュニティの活動が鈍っている、という話はかなり前から聞き、また実感していたところですが、これを見ると需要はあって、個々のコミュニティでうまく世代交代ができずに失速しただけなのかも。

またスタッフの人数も多く、とても至れり尽くせりなイベントでした。スケジュールアプリの提供と、アプリからアンケートフォームを開き、回答してくれた人にステッカーを提供、という流れはとても良いですね*2。 アンケートの回答率がどれくらいだったか、大本営発表が楽しみです。

主催の@mhidakaさん、スタッフ、登壇者の皆さん、また会場提供のサイバーエージェントさんに感謝。 次はDroidcon Tokyoを開催してJeke神を呼ぶ、という話がかなり現実的に聞こえて(見えて)いるので、引き続き期待しています。

*1:と言っていい気がしたけど、次はDroidcon Tokyoになる可能性も?

*2:この手のイベントを主催するとだいたいいつも問題になるので、できれば真似したい

Unite 2015 TokyoにおけるVR・AR関係ネタまとめ #unite2015tokyo

Unite 2015 Tokyo に行ってきました。主にVR・ARに関する講演についてざっくりメモのみ。 講演資料等は公開されるはずなので*1、詳しくは公式サイトをご確認ください。

f:id:nowsprinting:20150414135953j:plain

Unity 5.1でのVRサポート

パルマー氏の基調講演から。まもなくリリースされるUnity 5.1では、さらにVR連携が強化される。

  • Oculus Rift, Gear VR向けの出力は、Player Settingのインスペクタでチェックを入れるだけ
  • HMDに出力しながらも、Unityのゲームビューは分割・樽型歪みでなく、通常の一画面表示で確認できる

Morpheus

SCEさんの講演にて。

  • 2016/上に発売目標
  • 1920x1080
  • リフレッシュレート 120Hz
  • レイテンシ 18ms以下
  • 5.7inch
  • 視野角 約100度
  • 9点のトラッキング用LED
  • Re-projection mode (60Hzのコンテンツを120Hzで動いているように見せられる)
  • Morpheus向けのビルドは、playerに"for PS4"を選択し、ディスプレイに"1920x1080_vr"を選択するだけ

VRコンテンツ開発の勘所

Oculus井口さんの講演。

Gear VR

  • 一般向けは2015/12月予定
  • アクセラレータは端末ものではなく、Gear VR側に高精度のものを搭載している

Oculus Platform

  • これまでのOculus Shareは開発者同士をつなぐものだが、Oculus Platformは開発者とユーザをつなぐもの
  • 米国ではすでにオープンしている。日本でもGear VR Innovator Editionの発売にあわせて公開
  • アプリ公開にはOculusの審査あり。ガイドラインはOculus Dev Center参照。一発で通ったコンテンツは皆無。
  • Gear VRには専用のネイティブアプリがあり、アプリの検索から購入までVR空間内で完結できる
  • Gear VRでのデバッグ実行には端末シリアルIDをDeveloperサイトに登録し、シグニチャファイルを生成する必要がある
  • Unity 5.1ではUnity Integration plugin不要に。

Oculus Remote Monitor

  • Gear VRと同一ネットワーク上のPCで、Gear VRで表示しているものと同じ画面を表示できる
  • 最近のSDKには入っている?

視覚誘導性自己運動感覚(ベクション)

  • 必殺技みたいな名前
  • 止まっている電車に乗っていて、目の前の車両が動き出したら自分が動き出したように錯覚する。VR酔いの原因。
  • 低速のほうが(高速に動くより)酔いにくい
  • 等速のほうが(速度が変化するより)酔いにくい
  • 直線運動のほうが(曲線より)酔いにくい
  • 壁や地面が遠くにあるほうが酔いにくい

操作系

  • Gaze Cursor(注視カーソル) マウスカーソルなどの代わりに視線でオブジェクトを選択する。Gear VRはパッドでタップできるので、Gazeしてタップ*2
  • Bluetoothケームパッドが使用できる(「コントロールR」がいい感じらしい)

白猫プロジェクトでの事例

コロプラの「白猫プロジェクト」のOculus Rift版、Gear VR版の制作(改善)に関して。

  • 三人称視点、プレイヤーキャラの後ろから見る形。
  • Oculus Rift版では、プレイヤーキャラの動きとピーキーに連動し、かつカメラから近かった。連続攻撃によるキャラの前進やノックバックでもカメラが動いていた。
  • Gear VR版ではキャラが画面中央付近にいる間はカメラが動かないよう改善。カメラとの距離も遠目にした。酔いは軽減したはずだが、臨場感は薄れてしまったのでバランスが大事。
  • 操作はAndroidアプリ(colopad)で行なう。Gear VR側面のパッドでも操作できる。
  • 側面のバックボタンは、ショートタップ、ロングタッブが可能。
    • ショートタップでは一つ前の画面に戻る(AndroidのBACKキーと同じ)
    • ロングタップでGear VRのユニバーサルメニュー*3を表示。この挙動はガイドラインに書いてある

Qualcomm Vuforia

Qualcomm社のリリースしている、ARライブラリの紹介。

3D Objects

  • 最新*4SDK 4.0では立体物の認識もできる
  • 認識できる(向いている)もの
    • Rigid: 硬い、変形しないもの
    • Details: 特徴点が多いもの
    • Table top: テーブルに載る程度のスケール
  • スキャンツールAndroidアプリとして配布している(developerサイトから、apkと認識時に使う紙のpdfがダウンロードできる)
  • 特徴点のスキャンに色は関係ない。形状のみで判断(質疑応答にて)

Smart Terrain

  • 空間認識。Environment
  • SDK 3.xから利用可能

Digital Eyewear向けSDK

  • モバイルデバイスだけでなく、Eyewear向けのSDKも(SDK 4.1 Betaから)
    • Gear VR
    • Moverio BT-200
    • ODG R-7
  • Stereo rendering
  • Background removal(透過型向けに背景を消して描画)
  • Virtual Buttons
  • Unityのサンプルも配布している

SDK

  • モバイルデバイス:Android 4.0以降、iOS 7以降
    • Android向けは、スライドでは"Eclipse"とありましたが普通にNDKでビルドできる
    • もちろんUnity pluginもあり
  • EyewearはAndroidのみ

開発者登録・ダウンロードは下記サイトから。

developer.vuforia.com

費用など

  • 3D Objectsの認識をアプリにバンドルし、かつQualcommロゴを表示するならば、無償で利用可能
  • ロゴを消す、もしくはクラウド認識を利用する場合は有償($99/moから)

その他、ブースで聞いた話

  • 端末にKinectのような深度を測れるカメラが搭載されると、認識率は上がる。その場合でもアプリ側は同じように利用できる(SDK側で処理する)
  • 部屋に家具などを置くシミュレーションでは、深度が取れればサイズも再現できる。現状ではマーカーを使えばサイズは再現できる。
  • 日本語でもサポートが受けられる。 mailto: AskVuforiaJapan at qce.qualcomm.com
  • その他、デモも見せてもらいつつ色々伺いましたが、テキストで表現できない。

Crescent Bay デモ

Oculus Riftの次世代機、Crescent Bayのデモを体験できたので、その感想。

  • 被った感じ、DK2に比べて軽さを感じた
  • 解像度は良い。それなりに明るいシーンでも、網目状に見えたりしなかった
  • 追随性も良い。ただこれはコンテンツやマシン性能もあると思う
  • デモの中では、崖上に立っているシーンがなかなかヒュンと来て良かった

その他

ステッカー、貼っちゃうよね

f:id:nowsprinting:20150414220908j:plain

*1:スライドの写真撮ってる人いっぱいいましたが

*2:パッドが無いHMDでは1〜2秒注視する方式が多いですね

*3:パススルーカメラを起動できたり、輝度調整できたりする(5/1実機で確認)

*4:2月にリリースされた

testotips.io(Appium回)に行ってきました #testotipsio

クックパッド株式会社さんで開催された、testotips.io 第1回*1に行ってきました。

connpass.com

testotips.ioは、iOS/Androidの開発系Tips共有会として続けられているpotatotipsのテスト版を指向していて、s.io==塩味*2という意味がある(かもしれない)とのこと。

今回のお題はAppium。スライドは追々connpassに張られていくと思うので、以下メモのみ。

Introduce Appium(松尾さん)

  • Appiumはnodeベースのツールで、iOS/Androidのネイティブアプリおよびブラウザの操作を自動化、GUIテストができる
  • GUIのテストについて。E2E test、Feature testなどと呼ばれているもの。テストケースの量は、Unit test > Integration test > GUI Test
  • 内容はappium.jsを追っていけばだいたいわかる
  • Capabilities*3でAppiumサーバの振る舞いを指定する
    • platform: ios, android, selendroid, chrome, safari, firefoxos
    • iOS: calendarFormat, sendKeyStrategyとかも指定できる
    • Android: unicodeKeyboard(マルチバイト文字を使う場合)
  • Tips
    • Appium 1.3.6では、iOSのplistがバイナリだと文字化けしていた。1.3.7betaで修正
    • Viewの取得、XPathだけでなく、UI Automation(iOS)/uiautomator(Android)の書式でも取得可能
    • Appiumサーバは複数実行できる(listen portを分ける)。ただしiOSはひとつしか実行できない
  • 実行には時間がかかるので、夜間にまわして翌朝チェックしている
  • DroidDriver

テスト結果レポートをSahaginで作ってみる(伊藤さん)

  • Sahagin==さはぎん。伊藤さんが作った
  • 今のところJavaのみ対応。もともとSelenium WebDriverのテスト結果のレポーターで、Appiumでも使用できる
  • テストコードから、日本語+画面キャプチャのレポートをhtmlで出力
    • スクショはステップごとに自動で撮ってくれる
    • findとかasertも日本語に置き換えて出力している
  • PageObjectパターンを使う場合、setterに@TestDocでコメントを書くとそれが表示に使用される
  • Jenkins Sahagin pluginで、Jenkinsのジョブ画面に表示できる
  • Selendroidだとスクショのタイミングがちょっとずれる
  • Tips
    • Jenkinsで実行するとき、テストの前後にAppiumサーバの起動と停止をすると安定する
    • Android emulatorのブラウザでスクショが取れない(Chrom Driverの問題?)
    • Xcode 6.2ではiOSシミュレータのSafariが使えない
    • Appiumのキャプチャが遅い
    • Appiumサーバはrootで起動できないので注意

AppiumのPHPクライアントを使う上で行っている工夫(高橋さん)

  • Yahoo!社内でPHPクライアントを使った自動化の試み
  • JavaScriptはコールバックが多くて嫌だった。社内のサーバサイドで多く使われていたPHPを選択。でも他のクライアントライブラリに比べて機能が足りない
  • テストフレームワークにはPHPUnit
  • Appium PHP Clientを継承したHelperクラスを作り、それを継承した個々のTestCase作成。Helperには足りない機能を書いている
  • コンストラクタでsessionStrategy=isolatedにされていたので、テストケースごとにアプリインストールが走っていた
  • sleepを極力しない工夫。findをラッピングして、例外を返さず、waitしてリトライすることをHelperに実装。テストコードをシンプルに保つ
  • swipeが座標指定なのをラッピング
  • UI操作のスモークテストにAppiumを使用。細かい操作のテストにはEspressoを使用している

Appiumを使ってiPhone Safari、Andorid Chromiumを使ってアプリをテストするTips(浅黄さん)

  • ブラウザのテストにAppiumを使用している
  • Androidは、SelendroidだとWebViewで実行されるので、最近はChromeDriverで直接Chromeを使用するようにしている
  • Selenium Grid Serverを使って実行。ただし、Appiumはキックできるけど、ChromeDriverはキックできないのでGrid Severを経由していない。
  • テストケースは、Excelの表形式で書いたものからJavaのコードを生成する。共通処理(ログイン等)、シナリオ、PageObject、それぞれExcelファイルで書ける

Running appium tests on Jenkins(Vishal Banthiaさん)

  • AppiumによるiOS/AndroidテストをJenkinsから実行するデモ
  • テストはRSpecで、失敗したらスクショを撮っている
  • buildとtestはジョブをわけて、pipelineでつなぐ
  • テストは機能ごとにジョブを分けている(これは増えていくとつらいと思うので私は否定派)
  • デモのリポジトリにはHeplerも入っている
    • servermanager.rb: Appiumサーバの管理。startで、前のプロセスをkillしたりとか。
    • screenshot_embedded_html_formatter.rb: スクリーンショット

所感

懇親会も込みで、他の会社で実際どのように運用しているとか、という話が聞けるのはとても有益でした。Tips紹介だけだとこれは得られないので、テスト自動化まわりはこんな感じに(ツール縛りくらいで)情報交換できる場はいいですね。

*1:とは言っていませでしたが続くといいですね!

*2:プロレスファンとしては「しょっぱい」に余り良いイメージを持てませんが、それはそれ。これはこれ。

*3:Capability==ケーパビリティ。Capacityはキャパシティなのに!

モバイル向けテスト手法勉強会に行ってきました #33testing

先週、クラウド名刺管理のSansan株式会社さんで開催された『最新事例から学ぶ!モバイル向けテスト手法勉強会』に参加させていただき、また「テストの種類とBDD」と題してお話してきました。

テストの種類とBDD

どうしても前提となる話が増えてしまってテスト実装の話まで入れられませんでした。このプレゼンがつまらなくても、テストのことは嫌いにならないでください。

後半は、BDDか、テクニック的な話(テストダブル、テストファースト、TDDとか)にするか迷ったのですが、今回の感触だとテクニックの話のほうがよかったかも知れません。しかし元々20分ギリギリ話すつもり&電エースの話をしすぎた結果、BDDの部分は全部飛ばすはめになった今となってはどちらでもよかったですね。

テストのテクニックに関しては、拙著『iOSアプリテスト自動化入門』の2.3、2.4に書いてありますので、そちらを参照頂けましたら幸いです。

なお、BDDのところで紹介しているテスト自動化ツールの連載は、昨日第6回が公開されました。

ほかの方々の講演

聴講メモが混ざってしまっていたので、以下まとめて全体の話として書きます。

テストを書いてるひとはまだ少ない
  • UIのテストを過剰に自動化しようとする(そして挫折する)よりはいいと思います
  • 岸川さんの話にあったように、モデル(MVCのM)を中心に、ユニットテストは自動化していったほうがいいでしょう
    • ただし、「6〜7割実装してからテストを書きはじめる」のはテストを書いたことが無い人が真似しようとしても難しいです。テストしやすい実装になっていないと、テストを後から書くのは困難なので。
  • ユニットテストのメリット、運用(岸川さん)
    • 変更を入れる際の安心感
    • テストはgreenな状態を維持する
    • カバレジはあまり気にしすぎない。テストを書くモチベーションになるなら使う
      • ユビレジさんの場合、サーバサイドで80%、クライアントは全体で15%、ViewControllerを抜いて25%くらい
ビルド、AdHoc配布までの自動化は進んでいる
  • テストはまだなくても、CIサービスを使ってビルド、AdHocでテスター向け配布までは自動化している
  • ブランチモデルにgit-flowを使い、developにマージされるごとにビルド・AdHoc配布
    • スプリントのQA期間など、5〜10/day以上になり、ビルド待ちが発生することも多い
  • CIサービスとしては、Circle CIが多く、次いでTravis CI
    • Circle CIはタスクの並列化が難しいので、例えばテスト実行と平行してAdHoc配布を行なうといったことはTravis CIのほうが向いている
    • Greenhouse CIは、スクリプトを書かずにできる範囲が広く、ほぼスクリプトレスで構築できる。ただし高度なことを行なうには壁がある
    • Jenkinsでもいいけれど、プラグインに頼りすぎずRakefileMakefileに書くように(岸川さん)
    • Rakefileが巨大になったので、XCJobsを作った(岸川さん)
  • AdHoc配布は、Fabric.ioが多い
    • 最近までTestFlightを使い、Fabric.ioの"Beta by Crashlytics"に乗り換えた
      • TestFlightはiOS8以上なのがネック
    • Crashlytics(クラッシュログ解析)を利用していたのでそのまま
    • iOS/Androidで同じサービスのほうが、テストする人はありがたい
    • 弊社はTestFlightがAndroidを切ったタイミングでDeployGateに移ったのですが、もう少し様子見。
  • 自動化にはfastlaneが便利
    • ビルド、テスト実行(xctool)、署名、AdHoc配布などのコマンドは、fastlaneを使うと便利
    • KrauseFx/fastlane · GitHub
  • チャットでコントロール
    • Hubotに"release"を指示すると、リリースブランチを切り、PR、Travisでビルド、配布が流れる
    • チャットにログが残るので、可視化、かつ、作業単位での分担・引き継ぎが容易
Xcodeプロジェクト
  • プロジェクトをcheckoutしたらすぐビルドできるように。プロジェクト固有ルールでの初期設定はなくす。CocoaPodsのようなデファクトを積極的に使う
  • Target、Configurationがたくさんあるとどれを使うべきかわからない。Schemeもたくさんあるとわからない。
  • 依存ライブラリのコードをプロジェクトに混ぜない。CocoaPodsを使えばlockファイルで差分もわかる
    • なお、"混ぜない"は、プロジェクト内で修正を入れたりしないことが重要で、Podsから取得したコードをバージョン管理に含める運用の是非ではないです。
Android
  • Google Playの段階的リリースを使用している
  • 引き継いだ時点でテストコードなし
  • Robotiumを使用
    • リリースビルドをテストできないので、Appiumを検討中
    • まずスモークテスト
    • solo.getView()などをラップして、スクリーンショットを撮るようにする
    • 極力sleep()は使わず、waitForXxxx()を使う
    • ローカライズを意識して文字列はハードコーディングでなく文字列リソースを使う

所感

  • 過剰にUIのテストをしよう!みたいな雰囲気でなくて良かった
  • ビルド・配布から自動化に手を付けるというのは、良い傾向
  • とは言え、あとからテストを書くのは困難なことが多いです。CIを導入しているなら、サイクロマティック複雑度を計測して酷いものからリファクタリングしていくアプローチもあり。『iOSアプリテスト自動化入門』の8.2あたりが参考になるはず