GoogleAnalytics

SyntaxHighlighter

2012年2月14日火曜日

[Glaeja] 怯えろ!竦め!Glaejaの性能を生かせぬまま…

…まぁ死ななくてもイイんですけどねw

というわけで、『Glaeja』のver.2.0.0で実装された「ウィジェット変数」を用いた作例を1つご紹介します。

※ウィジェット変数にあった不具合をver.2.0.1で修正しました。下記内容は修正されたver2.0.1でないと正しく動作しません


0.はじめに

「ウィジェット変数」は、ウィジェット内のどのレイヤーからでも同じ値が参照でき、ウィジェット更新を超えて値が永続する変数として実装されました。

「ウィジェット変数」を実装しようと思ったきっかけは、マーケットのレビューにあった以下のような一言でした。

ウィジェットの更新間隔を複数用意し、画像フォルダを指定してフォトフレームとして使用したいです。 

画像フォルダとして「com.gmail.kanitawa.glaeja」下以外を指定するのは、ちょっと思うところがあり実装しないでおいたのですが、『ウィジェットの更新間隔を複数用意する』ってのを実装してみることにしました。

で、普通に考えれば、ウィジェットタップで開くウィジェット設定画面に[○分間隔で更新する]みたいな項目を追加すればイイんでしょうが、これですとそのウィジェット全体の更新間隔が変わってしまうため、「3分間隔のフォトフレームにデジタル時計を重ねる」みたいなことができません。

かといって、「スプライト レイヤーに「○分間隔で更新する」という項目を拡張する」ってのも、いまいちスジが良くありません。

単純に考えれば、3分ごとに画像を変更するのであれば、「イメージ レイヤーの画像ファイル名を、現在の分の数値を3で割った余りがゼロのときだけ乱数で変更する」とかすればイイように思えます。ですが、これには穴が2つあります。

1つは、「ウィジェットの描画更新が1分間隔だけではない」ということです。上記した「現在の分の数値を3で割った余りがゼロのときだけ乱数で変更する」とすると、例えば、6分のときに2回描画更新されると、画像が2回変更されてしまいます。さて、Glaeja設定の[更新トリガー]で全てをオフにすれば、基本的には1分間隔の更新になるのですが(一部例外あり)、ウィジェットタップで設定画面を開いて、閉じると無条件に描画更新がかかってしまいます。なので時刻によっては、ウィジェットをタップするたびに画像が変更されるはめになるわけです(これはこれで面白いのですが…)。

2つめは、「更新間隔が厳密に一定ではない」ということです。上記した方法で更新させる場合、例えば3分ごとなら[0、3、6、、、54、57、0]ときっちり3分間隔になるのですが、これが7分ごとなら[0、7、14、、、49、56、0]と最後に4分間隔が混ざってしまいます。その程度問題ないと言えばそうなんですが美しくありませんねw

となると、「前回更新された時刻を記憶して、次の更新時に参照し、正しい間隔であれば変更する」というアクションができなければならないのです。そのためには、「ウィジェットが存在している間は常にその値が永続する変数」を実装する必要があり、それを汎用化したものが「ウィジェット変数」となった、というわけです。

さて、能書きが長くなりすぎましたが、どのようにすれば「○分間隔で画像を変更する」ことができるのか、実際にやってみましょう。

1.○分ごとに画像をランダムに変更するウィジェットの作例

画像をランダムに変更するんですから、[イメージ]レイヤーのファイル名を「rand@x@」使ってランダムにマッチさせればできそうですが、それを決められた分ごと(ここでは3分としましょう)にやるにはどうすればイイんでしょうか?

もし、[前回更新された時刻]を[prev_uptime]、[現在表示されているファイルの番号]を[curr_imgnum]という永続する変数で保持できるとしたら、以下のようなアルゴリズムで実現できそうです。

if ( 現在時刻が[prev_uptime]より3分以上多い ) { [prev_uptime]に現在時刻を代入; [curr_imgnum]に乱数で新しい値を代入; }curr_imgnum]の画像ファイルを表示

この、普通のプログラミング言語で書くと簡単なアルゴリズムを、「@...@」のスタックを駆使して実現するわけなんですが、スタックでできることって基本的には条件分岐と代入だけですので、かなり苦労しますw しかも、「caladd@x@」を使った時間の計算は、結構バッドノウハウがあるんですよね…

とにかく、こんな感じで実現できました。画像ファイルとして[img000.png, img001.png, ... img008.png, img009.png]という名前のものが10枚あるとしています。


01 3@p@ 02 prev_uptime@q@ 03 caladd@x@ 04 $yyyyMMddHHmm$@p@ 05 <=@x@ 06 dup@x@ 07 $yyyyMMddHHmm$@p@ 08 prev_uptime@q@ 09 rot@x@ 10 tern@x@ 11 prev_uptime@Q@ 12 10@p@rand@x@ 13 curr_imgnum@q@ 14 rot@x@ 15 tern@x@ 16 dup@x@ 17 curr_imgnum@Q@ 18 img03.0@0/4/\P@

一番左のバックが水色の数字はわかりやすくするための行番号です。実際に[イメージ]レイヤーのパターン文字列に書く場合には全部をつなげて「3@p@prev_uptime@q@caladd@x@$yyyyMMddHHmm$@p@<=@x@dup@x@$yyyyMMddHHmm$@p@prev_uptime@q@rot@x@tern@x@prev_uptime@Q@10@p@rand@x@curr_imgnum@q@rot@x@tern@x@dup@x@curr_imgnum@Q@img03.0@0/4/\P@」と記述してください。

さて……全く意味がわかりませんねwww ちょっと簡単に解説していきましょう。

010203行目は、更新間隔である[3]分と、前回更新時刻である[prev_uptime]を「caladd@x@」で時刻として加算しています。
04行目で現在時刻をスタックにプッシュし、05行目でそれらの大小を比較しています。この場合、現在時刻のほうが大きい(つまり現在の時刻は予定された更新時刻より後)のであればスタックには[1]がプッシュされ、そうでなければ[0]がプッシュされます。

この[0][1]の結果を使って、後の[prev_uptime]や[curr_imgnum]に代入する数値を「tern@x@」で分岐させるわけですが、「tern@x@」で1回分岐させるとその値は消えてしまいますので、2回行わせるために06行目の「dup@x@」で複製しておきます。

まず最初に[prev_uptime]への代入分岐をさせましょう。07行目で結果[1]のとき(つまり現在の時刻は予定された更新時刻より後)の場合に代入する[$yyyyMMddHHmm$]をプッシュし、次に08行目で結果[0]のときには値を変更させないために元の変数値である[prev_uptime]を「@q@」でプッシュしておきます。この段階で結果[0][1]の値はスタックの底に沈んでいますので、それを09行目の「rot@x@」で最上段に引っ張り上げておきます。そして10行目の「tern@x@」を実行すれば、結果に応じた値(0708行)がスタック最上段に残ります。これを11行目で[prev_uptime]に代入します。

1217行目は、同様の操作を[curr_imgnum]に対して行なっています。これで描画する画像ファイルの通し番号を処理しています。16行目での「dup@x@」は、[curr_imgnum]への代入の後に、18行目での文字列出力に使うために複製するためです。

実際に[イメージ]レイヤーに記述して動作させてみたのが以下のスクショになります。画像ファイルには「無料写真素材配布サイト-PAKUTASO」様の写真を使わさせていただきました。













キチンと3分ごとに画像が切り替わっているのがわかるかと思います。この間、ウィジェットをタップして設定画面を開いても画像は変化しません。

また、[prev_uptime][curr_imgnum]を名前を変えてやれば、1つのウィジェットに更新間隔の異なる複数の[イメージ]レイヤーを置くことも可能です。ご興味のある方は、是非ともチャレンジしてみてください。


…さて、開発者本人からの 『これがGlaejaを「使いこなす」っちゅうこっちゃ(ドヤァ』 はいかがでしたでしょうかw?

このエントリで、「使いこなす」と「カッコいいホームを作る」は無関係である、ことがご理解いただければ幸いです。
以前は、コメ欄に「誰もついてこれない機能は追加したくない」とかほざいてたんですが、最近は「@...@」に関しては好きなようにやろう、と思えるようになってきましたw

11 件のコメント:

匿名 さんのコメント...

こんにちは、愛用させてもらってます。
某板で話題提示した者です。マーケットの直近の感想も私です。

<症状の報告>
ウィジェットの追加から、「glaeja 1x1」を選択
テキストは初期のまま、$HH:mm$(略、または'new'で実験

「他のアプリを開く...」で、機種標準の電話アプリ「電話」を選択
スキンの保存で、「test.skin」と保存

ホームからウィジェットをタッチすると、
「エラー android.process.acoreが予期せず停止しました。やり直してください。」と表示され、「強制終了」のボタンが出ます。毎回再現されます。


isw11f os2.3
http://www.au.kddi.com/seihin/ichiran/smartphone/isw11f/spec.html
ホームアプリ ADW launcher EX
LauncherProでも同じ結果になります。
他のアプリは試した範囲では問題ありませんでした。

他に必要な情報等がありましたらお伝えください。

kanitawa さんのコメント...

> 某板で話題提示した者です。マーケットの直近の感想も私です。
いらっしゃいw

acoreなぁ……

とりあえず「android.process.acoreが予期せず停止しました」でググってみました。
http://www.google.co.jp/search?q=android.process.acore%E3%81%8C%E4%BA%88%E6%9C%9F%E3%81%9B%E3%81%9A%E5%81%9C%E6%AD%A2%E3%81%97%E3%81%BE%E3%81%97%E3%81%9F

…ホームに何かタスクキラーのウィジェットとか置いてませんか?

他には、電話アプリもContactにアクセスするためにacore使ってるのもあるんですよね…

端末標準の電話アプリ以外の電話アプリ(なんかおかしな表現ですが、"Dialer One"とか"TouchPal Dialer"とか)をインストールできるのであれば、それを登録した場合はどうでしょうか?

匿名 さんのコメント...

レスどうもです。タスクキラー系はインストールしていません

>"Dialer One"とか"TouchPal Dialer"とか
二つともインストールしてみましたが、二つとも問題なくタッチから起動しました

検索先の上位を見てみましたが、端末を初期化して直った例がありましたが
最終手段はこれしかないですかね

kanitawa さんのコメント...

> 二つとも問題なくタッチから起動しました

そうすると、端末標準の電話アプリ自体の問題でしょうかね。

> 端末を初期化して

試せるのであれば試してみるのが手ですが、
ファクトリー・リセットで治るとも限りませんからねぇ…

匿名 さんのコメント...

マーケットのコメントで今回のエントリ内容の要望を書き込んだ者です。
お礼が遅れてしまったことをお許しください。

フォルダに関して今までGlaejaで画像を使ったことがなく知識不足でした。imagesフォルダだけで十二分に活用できそうです。

要望の対応と解説ありがとうございました。

susi-paku さんのコメント...

おお、pakutaso の画像使っていただき感謝です
('A')ノ

http://www.pakutaso.com/

匿名 さんのコメント...

始めてコメントさせていただきます。

この場で失礼かと思いますが、バッテリー残量に応じて、画像を変更するにはどうしたらよいのでしょうか・・・
よければ公開してもらえないでしょうか?

大変失礼かと思いますが、よろしくお願いします。

kanitawa さんのコメント...

「バッテリー残量に応じて画像を変更する」スキンを探して、
それを改造するなり中を見て理解するなりすればよろしいかと存じます。

> よければ公開してもらえないでしょうか?

「自分では作れないので変わりに作ってください」
という要望にはお応えいたしません。

匿名 さんのコメント...

遅くに失礼します。
先日から使用させていただいてます。
時間帯で画像を変化させる事についてなのですが、$k$@p@18@p@>=@x@$k$@p@5@p@<@x@and@x@.0@P@_****.jpg
という文字列をイメージレイヤーに入れたのですが、対応する画像が表示されないです。
*印には画像と同じ名前にしているのですが…
どこか間違ってるところがあるんでしょうか?

匿名 さんのコメント...

上の件、解決できました!
文字列で決めた時間になって初めて反映されたみたいです。
失礼しました。

kanitawa さんのコメント...

解決したようでなによりです。