SmartTrainingがPebble SDK 2.0に対応しました

はじめに

SDK 2.0の情報が出始めたのが2013/11中旬頃、既にPebble熱は冷め、完全にスルーしようと思っていましたが、1月下旬にとあるユーザさんから「Pebble 2.0対応しないの?」みたいなメールをいただき、遅ればせながら対応を開始しました。で、おかげさまで、無事に2.0への対応を完了し、Pebble AppStoreでPublishしましたのでマイグレーションまでの手順をざっくりとメモしときます。ただ、現時点ではまだPebble AppStoreは公開されていません。そのうち、公開されるんじゃないですかね?

SDK 2.0の準備

公式サイトをみてそのままやるだけです。
現時点ではまだPebbleアプリ自体がベータ版なので、上記手順に従ってアップグレードします。たぶん、ハマるところはないと思います。

コードのマイグレーション

今回のSDKのバージョンアップは結構大きな変更を含むので、以下のページにマイグレーション手順がまとめられています。
こちらもそのままやればハマるところはないと思います。
というのは半分正解で半分ウソです。
実際問題、この手順でやればいいのですが、細かく説明されていない箇所もちょくちょくあって、SDK付属のサンプルアプリのコードを見て真似する形で修正しました。あと、コアなAPIのI/Fが結構変わっているので、手順に従って修正していても超不安でした。
Githubにブランチを切ってみましたので、diffを見てみましょう。

公式マイグレーション手順以外でのポイント

公式のマイグレーション手順に記載されているところはそちらを参照して頂くとして、それ以外でハマった箇所だけピックアップしていきます。

window_set_window_handlers()

サンプルコードを見ているとinit()系関数内で以下のような記述がよく出てきます。 いつからこんな書き方をするようになったのかわかりませんが、SDK付属の各サンプルはシレっとこんな書き方をしています。パッと見、画面の読み込みと破棄のタイミングのイベントハンドラを登録しているように見えます。それぞれのイベントハンドラでは、画面内のUIインスタンスの準備および破棄処理を行うのが慣例のようです。
window_set_window_handlers(configWindow, (WindowHandlers) {
    .load = window_load,
    .unload = window_unload,
});

BmpContainerをGBitmapに変更する

画像リソースでBmpContainerはもう使わないみたいです。代わりにGBitmapを使うようです。これに伴い、初期化処理と画像リソースへのアクセス方法の変更が必要になります。何故こうなったのかはよくわかりません。

変数定義:
BmpContainer icons[2];
GBitmap *icons[2];

画像コンテナ初期化:
bmp_init_container(IMAGE_RESOURCE_IDS_CONTROL_ICON[i], &sel_control_window_data.icons[i]);
sel_control_window_data.icons[i] = gbitmap_create_with_resource(IMAGE_RESOURCE_IDS_CONTROL_ICON[i]);

画像コンテナへのアクセス:
sel_control_window_data.menuItems[i] = (SimpleMenuItem)
{
    .title = NULL,
    .icon = &sel_control_window_data.icons[i].bmp,
    .callback = sel_control_window_select_item_callback
};
sel_control_window_data.menuItems[i] = (SimpleMenuItem)
{
    .title = NULL,
    .icon = sel_control_window_data.icons[i],
    .callback = sel_control_window_select_item_callback
};

画像リソース開放処理:
bmp_deinit_container(&sel_control_window_data.icons[i]);

gbitmap_destroy(sel_control_window_data.icons[i]);

Layerへのアクセス方法変更

各UIのLayerへのアクセスはLayerプロパティを直接参照していたのが*_layer_get_layer()という関数を使ってアクセスするようになりました。

&train_window_data.focusUpperRightLayer.layer

inverter_layer_get_layer(train_window_data.focusUpperRightLayer)

リソースID指定による画像リソースの読み込み方法の変更

リソースIDを指定して画像リソースを読み込む方法が変更になりました。

void load_training_bitmap(uint32_t resource_id) {
    const ResHandle h = resource_get_handle(resource_id);
    resource_load(h, train_window_data.training_bitmap_data, BITMAP_BUFFER_BYTES);
    mkbitmap(&train_window_data.training_icon_bitmap, train_window_data.training_bitmap_data);
}
void load_training_bitmap(uint32_t resource_id) {
    train_window_data.training_icon_bitmap = gbitmap_create_with_resource(resource_id);
    bitmap_layer_set_bitmap(train_window_data.training_icon_layer, train_window_data.training_icon_bitmap);
}

タイマー系イベントのI/F変更

なんだかよくわかりませんがいろいろ変わっています。全般的にAppContextRefが廃止になった影響かと思います。
void handle_timer(AppContextRef ctx, AppTimerHandle handle, uint32_t cookie)
void handle_timer(void *data)
void handle_second_tick(AppContextRef ctx, PebbleTickEvent *t)
void handle_second_tick(struct tm *tick_time, TimeUnits units_changed)


まとめ

たまたま自分のアプリが古い書き方をしていたりしたせいで公式のマイグレーション手順に載っていない影響が出ているかもしれませんが、とりあえず、上記のような変更を加える事で新しいSDKでもビルドしてそれっぽく動作することを確認しました。全般的に見ると、構造体のメンバに直接アクセスしたりとか生々しい書き方をする部分が多少減ったような気がします。

最後によくわかっていないのが、appinfo.json内で定義されたversionLabelの値へのコードからの参照方法です。画面にバージョン情報を表示したいのですが、せっかくなのでversionLabelの値を参照して表示したいんですよね。APIリファレンスをざっと見る限りそんなAPIは見当たらないので、また生々しいことをしないといけないんですかね。誰か教えてください。

コメント

このブログの人気の投稿

Execノードを使う

Joinノードを使う(その4)

SendGridのX-SMTPAPIヘッダの使い方(Section Tags、Substitution Tags編)