TitaniumSDK5 系の appicon 作成機能


まずはこちらのリリースノート(抜粋)をごらんください。

Icons and Launch Images

(中略)

You are recommended to add a 1024 x 1024 PNG image, 
named DefaultIcon.png placed in the project's root folder, 
which is used to generate all or only omitted icons for 
the project. New Titanium projects will have 
the DefaultIcon.png file.

SDK5 系から、XCode の Asset Catalog に対応したようです。
それに伴い、不足しているアイコン画像ファイル を勝手に作成してくれる機能が追加された、だそうです。DefaultIcon.png って名前で 1024 x 1024 サイズの画像を、プロジェクトのルートフォルダに用意しておけば OK とのこと。

なにはともわれ、プロジェクト作ってみます。

$ ti create --id dev.sushi --name sushi --platforms all --type app --workspace-dir .
$ cd sushi

この時点で、プロジェクトのルートフォルダに Default.png ファイルが作成されています。(SDK4 系では、 Resources/iphone/appicon.png ってファイルがありましたが、いまは見当たりません。)
このファイルをアイコンとして使用したいファイルに差し替えてビルドします。

$ cp -f ../sushi.png Default.png
$ ti build -p ios --build-only
・・・
[DEBUG] Missing 10 app icons, generating missing icons
[DEBUG] Found DefaultIcon.png (1024x1024)
・・・

なんかそれっぽいログが出ております。
build/iphone/Assets.xcassets/AppIcon.appiconset フォルダ内に Default.png を元にリサイズされたアイコン画像ファイルがズラーッと展開されてます。

手動でリサイズして画像を用意することを考えたら、デザイナさんに用意してもらう画像も1つでいいし、リサイズ間違いとかすることもないので楽でいいですね。もちろん、今まで通りあらかじめアイコン画像を用意しておけば、勝手に作成されることはありません。ちなみに Default.png がアルファチャンネルを含んでいると、作成される画像もアルファチャンネルを含んでいます。ios の場合は気をつけないといけません。

実装を覗いてみる

SDKの中身とか見たことなかったので、どう実装しているのかザックリ覗いてみることにしました。issuesはこちら

ios ビルドの際のリソースコピー時に、不足しているアイコンを集めてます。
1個でも不足アイコンがあれば generateAppIcons に渡しているわけですね。

Titanium/mobilesdk/osx/5.0.2.GA/iphone/cli/commands/_build.js
iOSBuilder.prototype.copyResources = function copyResources(next) {
//・・・中略
    if (missingIcons.length) {
        this.logger.debug(__n(
            'Missing %s app icon, generating missing icon',
            'Missing %s app icons, generating missing icons',
            missingIcons.length
        ));

        this.generateAppIcons(missingIcons, next);

generateAppIcons はデフォルトアイコンのサイズチェックやバリデーション的なことをして、作成可能なアイコンをフィルタし appc.image.resize を呼んでます。

Titanium/mobilesdk/osx/5.0.2.GA/node_modules/titanium-sdk/lib/builder.js

Builder.prototype.generateAppIcons = function generateAppIcons(icons, callback) {
//・・・中略
    appc.image.resize(defaultIcon, icons, function (error, stdout, stderr) {
        if (error) {
            this.logger.error(error);
            this.logger.log();
            process.exit(1);
        }

        rename.forEach(function (file) {
            fs.renameSync(file.from, file.to);
        });

        callback();
    }.bind(this), this.logger);

最終的に、imgscalr というJavaのライブラリ使ってイメージをリサイズしています。

Titanium/mobilesdk/osx/5.0.2.GA/node_modules/node-appc/lib/image.js
exports.resize = function (src, dest, callback, logger) {
    try {
        if (!src) throw new Error('Missing source');
        if (!fs.exists(src)) throw new Error('Source "' + src + '" does not exist');
        if (!dest) throw new Error('Missing dest');

        Array.isArray(dest) || (dest = [dest]);

        var cmd = [
            'java -jar "' + require('path').resolve(module.filename, '..', '..', 'tools', 'resizer', 'resizer.jar') + '"',
            '"' + src + '"'
        ];
// ・・・中略
        require('child_process').exec(cmd, function (error, stdout, stderr) {
            callback && callback.apply(null, arguments);
        });

TiConsImageMagick を使っているから、こちらもてっきりそうかと思っていましたが違いました。

SDK5.1.x

SDK5.1系では、Windowsにも対応したようです。
(先に Android 対応して欲しかったなぁ。)
それにともない、プラットフォーム毎の DefaultIcon.png を用意できるようになりました。

DefaultIcon-(platform名).png というファイルを用意するだけです。
上記ファイルがあれば、そちらを使用して不足しているアイコン画像ファイルを作成します。(なければ DefaultIcon.png を使います)

e.g. DefaultIcon-ios.png

Alloy(1.7.24)

$ alloy new すると、 DefaultIcon.png と DefaultIcon-ios.png の2ファイルが作成されています。違いはアルファチャネルを含んでいるか否かです。

alloy は app/assets/iphone/appicon 配下に一通り appicon シリーズを作成してくれちゃっているので DefaultIcon.png を使わせるなら、あらかじめ削除する必要があります。
で、同様にビルドすると、DefaultIcon-ios.png をリサイズしたアイコン画像ファイルが build/iphone/Assets.xcassets/AppIcon.appiconset フォルダ内に展開されます。

残念なところ

  • ios、Windows しか対応していない。
  • スプラッシュスクリーンも対応してほしい。

Android のことを考慮すると、まだ TiCons が有用かと思います。こちらはスプラッシュスクリーンも作ってくれますし。
でもまぁ、公式ブログ で他のプラットフォームにも順次対応してくよ〜、と言っているので座して待ちましょう。

We will add support for DefaultIcon.png to the other platforms soon. 
Bye bye TiCons 😉