【G1】ケーススタディセッション「C++Builder を用いたマルチ OS 対応一般コンシューマ向けスマートフォンアプリ開発事例」
カシオ計算機 (株) コンシューマ事業部 企画部
園城 浩行

アジェンダ• 会社紹介 & 自己紹介
• 開発の概要– 「撮ってキャラスタジオ」アプリのご紹介– C++Builder を導入した経緯について• 「撮ってキャラスタジオ」のソフトウェア論理構成と、それぞれの開発事例• Android/iOS それぞれで苦労したこと• まとめ
2

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

「C++Builder を用いたマルチ OS 対応
一般コンシューマ向けスマートフォンアプリ開発事例」

会社紹介 & 自己紹介

3

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

会社紹介・ 社名

カシオ計算機株式会社 （Ｃａｓｉｏ Ｃｏｍｐｕｔｅｒ Ｃｏ.,Ｌｔｄ.）

・ 創立

１９５７年６月

・ 資本金

４８５億９，２００万円

・ 連結売上高３，２１７億６，１００万円（２０１３年度）

・ 従業員数・ 社長

１０，９９２名（２０１４/３/３１連結）

4

樫尾 和雄

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

電子レジスター

ページプリンタ

金 型

水中無線機

時 計

データプロジェクター

その他

ハンディターミナルシステム

１２，０５８(３．７％)

４５，２９９(１４．１％)

電子辞書

３２１,７６１
百万円

コンシューマ２６４，４０４(８２．２％)
電 卓

電子文具

電子楽器

デジタルカメラ

5

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

自己紹介
••
•
•

名前: 園城 (おんじょう) 浩行
所属: カシオ計算機 (株)趣味: 野球観戦 (関東生まれ関東育ちのトラキチ)
仕事: ソフトウェアエンジニア– 2001年入社– 入社‐現在: サーバーサイドのエンジニア

スマフォアプリ開発未経験者しかいない• 開発言語・フレームワーク (最近): JRuby on Rails• ミドルウェア: Apache, Tomcat• データベース: MySQL– 昨年4月に新組織発足！⇒ スマフォアプリも担当することに (しかも、Android/iOS 両方。。。)

今日のプレゼン: スマフォアプリ開発ド素人チームによるドタバタ開発事例 (^_^;;;;
6

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

「C++Builder を用いたマルチ OS 対応
一般コンシューマ向けスマートフォンアプリ開発事例」「撮ってキャラスタジオ」アプリのご紹介と、C++Builder を導入した経緯について

7

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

人の写真から”いい感じ” のスタンプ画像を生成
写真を撮影します

雰囲気の似たキャラクターを自動生成

顔の特徴抽出8

ポーズとセリフを合成

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

メッセンジャのスタンプに弊社製スタンプメーカー「ポムリエ」を繋げてリアルスタンプも2013年11月発売2値化

9WiFi でポムリエに送信するとリアルなスタンプも作れます

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

「撮ってキャラスタジオ」開発の概要• 開発スタート: 2014年11月• 開発人員: (スマフォアプリ開発素人) 1.7人
※ UI のパーツデザインはデザイン会社様に外注• 開発ツール: C++Builder• 最初のリリース– Android アプリ: 2015年03月26日– iOS アプリ:
2015年04月06日
10

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

開発に使った C++Builder のバージョン

11

開発スタート

初回リリース

イマココ

XE7

XE7

XE8

XE7

XE8

XE8

Beta 10

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

C++Builder 導入を決めた経緯-1• ワンソースマルチ OS 開発のアプローチを取りたかった– コンシューマ向けアプリ ⇒ 開発スピードが大事– しかし• 開発人数少ない• スマフォアプリ開発以外の仕事もある• HTML5 ベースのツールも話題にあがったけれど– サクサク動くか不安– 完全にワンソースにするのは難しい– メンテナンス性に不安

12

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

C++Builder 導入を決めた経緯-2• 上司が C++Builder の情報を知っていた– 完全にデバイスネイティブになるみたいだ• HTML5 ベースよりはサクサク動かせそう• 全レイヤーをワンソースにできそう– C++ なら経験者がいるぞ• ただし、Delphi も経験者は誰もおらず

じゃあ、C++Builder でチャレンジしてみよう
13

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

C++Builder に対する印象の変化• 最初の印象– Android/iOS それぞれの開発環境に比べると、できることは限られているが、両 OS 対応アプリが簡単に作れる• 使ってみて– Android/iOS それぞれでできることは (大抵のことは) なん
でもできる。ただし、ちゃんとしたアプリを作るためにはがっつり勉強する必要がある
14

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

「C++Builder を用いたマルチ OS 対応
一般コンシューマ向けスマートフォンアプリ開発事例」「撮ってキャラスタジオ」のソフトウェア
論理構成と、それぞれの開発事例

15

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

「撮ってキャラスタジオ」ソフトウェア論理構造(1) UI
アプリ全体制御・各機能の呼び出し(2) キャラ変換エンジン(3) ポムリエ連動モジュール

顔パーツ検出

スタンプ画像2値化

似顔絵パーツ決定

ポムリエとの WiFi 通信

スタンプ合成16

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

(1) UI 部分の開発について(1) UI
アプリ全体制御・各機能の呼び出し(2) キャラ変換エンジン(3) ポムリエ連動モジュール

顔パーツ検出

スタンプ画像2値化

似顔絵パーツ決定

ポムリエとの WiFi 通信

スタンプ合成17

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

(1) UI 部分の開発について: スタイルデザイン• 標準のコンポーネントだけで構成されるアプリはさほど問題なく作れそう• コンシューマ向けアプリの場合、凝った UI を求められる⇒ スタイルデザインがさっぱりわからない• エークリッパー・インク 羽生さんに講義をお願い– 3日かかるというものを1日で教育していただくことに⇒ スタイルデザインは試行錯誤するしかない– それにしても IDE がよく落ちる。。。
18

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

(1) UI 部分の開発について:スタイルデザイン• 羽生さんからいただいたアドバイス: ワークフローにスタイルデザインの工程を入れること

19

要件
↓
仕様
↓デザイン(モック)↓
スタイル設計→スタイルファイル※エフェクトやアニメの組み合わせ↓
UI レイアウトの作成↓
アプリ実装 本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

(1) UI 部分の開発について: UI デザイナさんとのやりとり

従来の Android/iOS の開発環境とはUI のはめ込み方が異なるので、C++Builder に合わせたパーツの組込み指示書の作成をデザイナさんに依頼

20

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

(2) キャラ変換エンジンの開発について(1) UI
アプリ全体制御・各機能の呼び出し(2) キャラ変換エンジン(3) ポムリエ連動モジュール

顔パーツ検出

スタンプ画像2値化

似顔絵パーツ決定

ポムリエとの WiFi 通信

スタンプ合成21

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

(2) キャラ変換エンジンの開発について: 概要• 弊社研究部門 (別部門)と協力会社さんの共同研究でアルゴリズムを開発• 研究成果のソースコードをもらい、アプリに組込み実装– プログラムは Visual Studio のプロジェクトで開発されていた• そのままでは C++Builder ではビルドすらできない。。。

– 粛々と C++Builder に移植

22

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

(2) キャラ変換エンジンの開発について: 手順• C++Builder で1つ1つコンパイルして環境依存のコードを修正 ⇒ 動作確認
– とても泥臭い作業でした• とはいえ、C++ 同士なので普通にソースを読み込めば特別なことをしなくても作業開始できます• 効率のよい方法をご存知の方、教えてください＞＜23

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

(3) ポムリエ連動モジュールの開発について(1) UI
アプリ全体制御・各機能の呼び出し(2) キャラ変換エンジン(3) ポムリエ連動モジュール

顔パーツ検出

スタンプ画像2値化

似顔絵パーツ決定

ポムリエとの WiFi 通信

スタンプ合成24

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

(3) ポムリエ連動モジュールの開発について: 前提• 別部門が開発したポムリエと連動するアプリがあった– Android/iOS それぞれの開発環境で構築

25

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

(3) ポムリエ連動モジュールの開発について: 最初の設計戦略• 折角動いているプログラムがある• ちゃんとライブラリ化もされている

じゃあ、C++Builder から Android 用/iOS 用
それぞれのライブラリをリンクして使えば効率よさそう！などと思っていたらドツボにハマりました orz
26

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

(3) ポムリエ連動モジュールの開発について: Android の場合• java2op で jar ファイル ⇒ Delphi への I/F を作成– jdk1.8 では動かず、jdk1.7 へ path を変えたり。。。

• java2op で作成された *.pas を C++Builder でビルド ⇒*.hpp ファイルを作成– これが I/F になるんだな、どれどれ (ソースを見てみる)– Delphi へのラッパとおぼしき記述がずらり• Delphi の知識がないので、どう使っていいかわからず– 1W くらい試行錯誤してみたものの、やっぱりわからず
27

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

28

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

29

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

(3) ポムリエ連動モジュールの開発について: iOS の場合• (当時) java2op に相当するツールが見当たらず。。。

30

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

(3) ポムリエ連動モジュールの開発について: 結局• 既存のライブラリをリンクして使うことをあきらめる• C++Builder でフルスクラッチで開発– 2値化エンジンはもともと C++ で作られていたので流用• 教訓– Android/iOS それぞれの開発環境で作られた資産を使いたい、と思ってもそれが本当に最適解か計画段階で検証すべき• 想像するよりハードルが高いです31

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

「C++Builder を用いたマルチ OS 対応
一般コンシューマ向けスマートフォンアプリ開発事例」

Android/iOS それぞれで苦労したこと

32

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

Android でアプリが固まる• 処理中に画面を連打するとアプリが固まる (ANR)– メインスレッドで5秒以上かかる処理を実行していた• メインスレッドで何をするか、サブスレッドで何をするか、をきちんと再設計した (その他、細かい工夫を色々追加)• 処理中にアプリを最小化するとアプリが固まる– ライフサイクルの監視と適切な処理をしていなかった orz• Embarcadero さんにサポートをいただき、ライフサイクルを監視して、適切な処理を行うよう再設計• その他、実装を見直し
33

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

_di_IFMXApplicationEventService AppEventService;
if (TPlatformServices::Current->SupportsPlatformService(__uuidof(IFMXApplicationEventService)) &&(AppEventService = TPlatformServices::Current->GetPlatformService(__uuidof(IFMXApplicationEventService)))) {AppEventService->SetApplicationEventHandler(HandleAppEvent);} else {// Application Event Service is not supported}bool __fastcall TSampleForm::HandleAppEvent(TApplicationEvent AAppEvent, System::TObject* AContext){bool _return = true;
switch (AAppEvent) {case TApplicationEvent::EnteredBackground:// バックグラウンドに入ったときにすべき処理が入る
break;
case TApplicationEvent::BecameActive:// アクティブに戻ったときにすべき処理が入る
break;// その他コードの記述が続く。。。
}
return _return;}34

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

iOS 64ビットサポートが必須に！
• 2015年2月1日以降 ⇒ XE7 は iOS 64 bit 未対応– 仕方ないので XE8 のベータ版で申請することに• iOS 側の開発は XE8 ベータに移行– ベータ版なのでちょいちょい落ちる– 毎週のようにアップデートが– 作成される ipa がおかしいことが？？？
バタバタしながらも なんとか審査に出す。。。
35

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

結果、リジェクト orz

iOS データストレージガイドライン違反

Apps must follow the iOS Data Storage Guidelines or they will be rejected
On launch and content download, your app stores ○○ MB,
which does not comply with the iOS Data Storage Guidelines.
Next Steps

アプリを入れただけで iCloud にデータがいっぱいバックアップされちゃってるよPlease verify that only the content that the user creates using your app, e.g., documents,
new files, edits, etc. is backed up by iCloud as required by the iOS Data Storage Guidelines.
Also, check that any temporary files used by your app are only stored in
the /tmp directory; please remember to remove or delete the files stored in this location
when it is determined they are no longer needed.
Data that can be recreated but must persist for proper functioning of your app - or because
users expect it to be available for offline use - should be marked with the "do not back up"
attribute. For NSURL objects, add the NSURLIsExcludedFromBackupKey attribute toprevent the corresponding file from being backed up. For CFURLRef objects,
use the corresponding kCRUFLIsExcludedFromBackupKey attribute.
36

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

リジェクトの原因••

本アプリはプログラム内部データを山盛り持っている (パーツ画像、学習データ等)
それらを StartUp¥Documents に配置していた[docwiki: iOS アプリケーションの作成]

37

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

iOS Data Storage Guidelines

これに違反

1. Documents フォルダに置いていいのはユーザー作成のデータのみおくべし
2. ユーザ生成のデータではないファイルや、キャッシュデータなどは置いてはいけないです。
3. 再ダウンロード出来るデータ、再作成できるデータは/Library/Cachesに置くべし
4. テンポラリーファイルは /tmp に置くべし
5. バックアップが不要なファイルは "do not back up" attribute を付けるべし
参考: http://qiita.com/tototti/items/8646405f47cc56a59722
38

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

結局どうしたか？
•本アプリはサーバー連動などはしていないので、データが消される可能性のある /tmp や /Library/Caches には置けない•

プログラム内部データをあるフォルダにまとめておいてそのフォルダに“do not back up” 属性を付与して対処_di_NSURL NSU = TNSURL::Wrap(TNSURL::OCClass->fileURLWithPath(StrToNSStr(path)));_di_NSString key = StrToNSStr("NSURLIsExcludedFromBackupKey");
System::PPointer err;
NSU->setResourceValue(TNSNumber::OCClass->numberWithBool(true), key, err);

これでなんとかアクセプトされました！
39

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

「C++Builder を用いたマルチ OS 対応
一般コンシューマ向けスマートフォンアプリ開発事例」

まとめ40

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

開発経験から考えたこと• 素人がどたばた開発を経てなんとかリリースできました• C++Builder は、ちゃんと使ってあげると効果絶大！
– 素人 1.7人で両 OS 対応アプリをリリースできたのは C++Builder のおかげ
– ただし、銀の弾丸ではない• ちゃんと使うには iOS/Android の知識は必須– Apple/Google 各社が出している開発者向けドキュメントはきちんと読み込むべし (ここが不十分で色々痛い目に)• Delphi もちゃんと知っておいたほうが確実に良い– が、私もぜんぜんできていない＞＜41

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

C++Builder or 従来の開発環境• C++Builder はワンソースで大抵のことは実現できるが学習コストは高い• 何を目指すか？
– 工数の削減？機能の追及？細部へのこだわり？

• C++Builder が向いていそうなケース– 短期間で Android/iOS 同時リリースをしたい– 開発ラインを2ライン組むだけのリソースがない– C++ の中級者以上が複数人存在する
42

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

Thank you!