2014年10月21日火曜日

Life/Biorhythm Logger (LB Logger) の v1.4 をリリース

今回のバージョンアップで
  • ログ一覧をインクリメンタルサーチする機能を追加
  • バグ修正
という修正を行いました。

1点目について、このブログでより詳細を書きます。

次の画像のように、ログ一覧の上に検索文字列を指定する領域が追加され、そこに入力した文字列でログの絞り込みを出来るようになりました。



入力する文字列は任意の文字列で、日付・種類・メモ部分のどこでも良いので文字列が一致したもので絞り込むことが出来ます。
メモ部分に特定のキーワードを(タグ的に)入れるなどしておけば、後で一気に抽出することなども可能です。

このように新しい振り返り方ができるようになりましたので、ぜひ活用してみて下さい。

2014年10月15日水曜日

Life/Biorhythm Logger (LB Logger) の v1.3 をリリース

今回のバージョンアップで
  • メニュー → エクスポート(メール)、メニュー → 一括エクスポート (SD) コマンドの追加
    ログデータを CSV 形式でエクスポートできます。
    SD への出力のため、権限でストレージ書き込みが必要となりました。
  • グラフ描画の処理を最適化
という修正を行いました。

1点目について、このブログでより詳細を書きます。

次の画像のようにメニューに「エクスポート(メール)」「一括エクスポート (SD)」というコマンドを追加しました。

どちらのコマンドもログを CSV 形式でエクスポートすることが出来ます。

メールへの出力の場合、次の画像のように連携したメール送信画面からログを送信することができます。
この際、エクスポートされるのは現在開いているログ画面(生活/バイオリズムのどちらか)のものとなります。


SD への出力の場合、次の画像のようにファイルを出力したフォルダが表示されます。
このフォルダ配下に、生活・バイオリズムそれぞれの単位で一括してファイルに出力されます。


他のアプリ・パソコンなどでデータを参照する際などに利用して下さい。

2014年10月10日金曜日

Life/Biorhythm Logger (LB Logger) の v1.2 をリリース

今回のバージョンアップで
  • "メニュー → 過去ログ削除(指定日以前)" コマンドを追加 : 指定した日以前のログを一括削除する機能
  • 画面デザインや語句の見直し
という修正を行いました。

1点目について、このブログでより詳細を書きます。

次の画像のようにメニューに「過去ログ削除(指定日以前)」というコマンドを追加しました。


このコマンドを実行すると次の画像のように


日付を指定する画面が出てきます。
  • 「削除」ボタンを押すと、この画面で指定した日付以前のログを一気に削除することが出来ます
  • 削除対象となるログは現在開いているログ(生活 or バイオリズム)だけとなります。
    もう一方の方は削除されません
ログの量が増えてきて、以前のものが必要なくなった際などに利用して下さい。

2014年10月4日土曜日

Titanium Tips: Titanium で図形描画、WebView の利用

Titanium の開発で図形描画の解決方法として、デザインの統一性さえゆるせば WebView +Javascript の描画ライブラリを使うという方法があります。
実際、私のアプリケーションではグラフを描くのに、WebView と Flot: Attractive JavaScript plotting for jQuery を組み合わせて実現しました。

公式の Using Local Web Content with WebView にあるように WebView は local な HTML/javascript などを読み込み可能です。
例えば、Alloy の View 側で app/assets/etc/local.html を読み込むには次のように
<Window title="hogehoge">
        <WebView id="webview" url="/etc/local.html"></WebView>
</Window>
という指定になります。
local.html 側では
<head>
<title>Local HTML</title>
<link rel="stylesheet" type="text/css" href="local.css"/>
<script src="local.js"></script>
</head>
と書くと local.html と同階層=app/assets/etc 配下の local.css, local.js を読み込み、利用することが出来ます。
(もちろん、local.html 内でも Javascript を記述可能)

また、local な Javascript の利点として次の2点があります。
特に、Ti.App.fireEvent() と Ti.App.addEventListener() を使うことで、Titanium 側の通常の Javascript のコードと WebView内の Javascript とで相互に通信が出来るのは、必須とも言える機能です。詳しい説明やサンプルは公式の Communication Between WebViews and Titanium を参照してみて下さい。

注意点としては、javascript を script タグなどで静的に読み込みしてしていなくて、生成した HTML で読み込むようなケース。
そのような場合には
For local JavaScript files not referenced in static local HTML files, for example, a dynamically-genereated HTML file referencing a local JavaScript file, rename the file extension of the local JavaScript files to '.jslocal' instead of '.js'.
とあるように拡張子を .js → .jslocal に変える必要があるようです。

2014年10月3日金曜日

Titanium Tips: Alloy のモジュール間での汎用的なデータのやりとり方法

前回のTitanium Tips: Alloy での部品化でソースを分割する方法をまとめましたが、今回はそれぞれに依存しないようなパーツ間でのデータのやり取り方法の(自分用)まとめ。

選択方法としては
  1. Alloy.Globalsなど
  2. Ti.App によるユーザ定義のイベント通信
から選べそうです。
(他にもありそうですが、私自身は見つけられていない…)

ただ、どちらもグローバルにリソースを食うことになるので、使いすぎやメモリリークには注意しましょう。

1.  Alloy.Globalsなど

公式の Alloy クラスをみれば分かりますが、次のような全 controller からアクセス可能なデータ格納用オブジェクトが用意されています。
(一部は controller 以外からのアクセス方法もあり)
  • Globals: 任意の変数・関数をプロパティとして格納可能
  • CFG:  app/config.json で定義した Key/Value 値
  • Collections: Collection用
  • Models: Model用
Globals, CFG は特に使いやすいと思われます。

2. Ti.App によるユーザ定義のイベント通信

公式の Application-Level Events に
App-level events are global to your app. They are accessible in all contexts, functional scopes, CommonJS modules, and so forth.
とあるように Ti.App.addEventListener() で定義したカスタムイベントは Ti.App.fireEvent() でコンテキストを超えて呼び出し可能です。
WebView を扱う際には必須ともいえる方法です → Communication Between WebViews and Titanium

removeEventListener() で登録解除できますが、引数に add した際の関数を渡す必要があるので、無名関数の場合には関数の参照を保存しておく必要があるので注意して下さい。
登録時
var listener = function() { Ti.API.info("Event listener called."); }
window.addEventListener('click', listener);

解除時
window.removeEventListener('click', listener);
 また、上記の WebView での例ではイベント名に "app:fromTitanium" のように "app:" という prefix をつけて、名前衝突が起こるのを推奨しています(もちろん必須ではありません)。

2014年9月29日月曜日

Titanium Tips: Alloy での部品化

Titanium の開発の中で部品化のために出てくる
  1. View 内から require で別の View を読み込む 
  2. Controller 内から createController で 別 View/Controler を動的生成
  3. controller 内で require による CommonJS モジュールの読み込み
辺りについて簡単なメモ。
(半分自分向けのポイントのみのまとめです。
 実例を交えた詳しい説明はすでに色々なサイトでされているので・・・
 後、widget という手もありますが、手を出してないので省略)

1. View 内から require で別の View を読み込む

公式ドキュメントとしては Alloy XML Markup内の Require Element

この方法で View 内で別の View を読み込むことが出来ます。
<Require type="view" src="about" id="aboutTab"/> ← about.xml に定義した View
View に対応した Controller(~.js)はあっても無くてもOK。
("Views can be created without controllers with an optional style sheet"@ Views without Controllers

また、クラスのインスタンス化的に同じ View を複数回 require しても可。

<Alloy>
 <Window layout="vertical">
    <Require id="button1" src="foo" type="view"/>
    <Require id="button2" src="foo" type="view"/>
    <Require id="button3" src="foo" type="view"/>
  </Window>
</Alloy>

単純にソースの見やすさ・管理のしやすさ、ということだけではなく、一つの View 定義の使い回しが可能です。

では、その分かれた View に対して、require する側からアクセスするには、 xml で指定した id ベースになります。
汎用例:var object = $.requireId.getView('objectId');
例えば、require で指定した id が aboutTab、読み込む src 内にある view の id が aboutView の場合、それを取得するには、
var aboutView = $.aboutTab.getView('aboutView'); 
となります。
ちなみに、 undocumented なやり方ですが id をつなげるだけでもアクセスできるようです。
例えば、上の例ならば次のような形になります。
$.aboutTab.aboutView

2. Controller 内から createController で 別 View/Controler を動的生成

公式ドキュメントとしては Alloy Controllers 辺りでしょうか。

Controller 内から独立した View, Controller を動的生成する場合には Alloy.createController() を使い、getView() で View を取得します。
var about = Alloy.createController('about', args).getView();
about.open();
これで about.xml, about.tss, about.js で定義された1セットをインスタンス化できるわけです。
またこの際に、引数を渡すことができるので(上記の args)、そこで様々な情報を引き渡すこともできます。

3. controller 内で require による CommonJS モジュールの読み込み


公式ドキュメントとしては CommonJS Modules in Titanium
複数の Controller で使うコードを、独立・共通化して記述することが可能です。

app/lib/ 配下に .js ファイルを配置して、require で読み込めば利用できます。

モジュール側は CommonJS に則った書き方になりますが、
  • exports - a free variable within a module, to which multiple properties may be added to create a public interface
  • module.exports - an object within a module, which may be REPLACED by an object representing the public interface to the module
とモジュール側からの公開方法は2通りの方法があります。

exports は require で読み込んだ側のオブジェクトでプロパティを参照する方式。

module.exports の場合には、require で読み込んだオブジェクトがそのままモジュール側で指定したものに置き変わる形。
module.exports はクラスを定義してそれを丸ごと公開するようなものに向いています。
(公式ドキュメントの Person の例などが分かりやすい)

2014年9月24日水曜日

Titanium Tips: TableView + dataFilter で上位~個だけ表示

今回アプリを作るにあたって、実装で少し苦労・工夫したところの一つは、Alloy の TableView  の dataFilter と Model を組み合わせて、表示内容を上位~個だけ表示させる実装でした。

私がやりたかったことは、TabbleView に binding して自動的にリスト表示されている SQLite のデータから、そのままでは全データが表示されてしまうものを、表示する個数を制限する、ということでした。

それを、TableView の dataFilter を使う方法で実現をしました。

TableView の dataFilter は、Alloy Data Binding - Titanium 3.X - Appcelerator Docs の説明を引用すると
dataFilter: specifies an optional callback to use to filter data in the collection. The passed argument is a collection and the return value is an array of models.
とあるように、 binding されたデータをフィルタリングする機能です。
サンプルなどでは、書籍データの中から著者(author)で絞り込みをするような、SQL でいうところの where 句での絞り込みのようなものをしていることが多いです。
例えば、上記の「Alloy Data Binding」でも dataFilter用の関数では
// Show only book models by Mark Twain
function filterFunction(collection) {
    return collection.where({author:'Mark Twain'});
}
ただ、結果として「the return value is an array of models.」とモデルの配列を返せば良いので、Filter の仕方に特定の制限はなさそうでした。
そこで
function filterFunction(collection) {
var i=0;
    collectionTopMost = new Array();
    // Collection 中、上位~だけを配列として取りだし(この例では 10個固定)
    for(i=0; i<10 && i<collection.length; i++){
  collectionTopMost.push(collection.at(i));
    }
return collectionTopMost;
}
といった形で必要な個数の配列を返すように実装しました。

この方法でリスト表示数に制限をかけられるようになりました。



Android アプリを Titanium Studio/Alloy を使って作ったので、その際にひっかかったことを、Tips で書いていってます。
実際に同じところで躓いた人がいて、それの解決のお役に立てば、と思っています。
ちなみに環境は Windows + Titanium Studio 3.3 + Android用開発となっています。

ただ、まったくのピンポイントでの Tips なので、まとまっての記述を期待している人にはすいません。

2014年9月23日火曜日

Titanium Tips: Model の comparator で時間の降順にソート

今回アプリを作るにあたって、実装で少し苦労・工夫したところの一つは、Alloy の Model で指定できる comparator の実装でした。
私がやりたかったことは、SQLite に格納した日時の値(yyyy/MM/dd HH:mm:ss)を使っての降順のソートでした。

comparator を実装すればソートとかが出来るようなことを
に書いてあるわけですが、今ひとつこの説明だけでは分かりません。
ベースとなっている Backbone.js の仕様も参照しないと分からないです。
では、comparator に実装する関数について
"sortBy" comparator functions take a model and return a numeric or string value by which the model should be ordered relative to others.
"sort" comparator functions take two models, and return -1 if the first model should come before the second, 0 if they are of the same rank and 1 if the first model should come after.
  • 1つのモデル中のデータを使って、何かソートの基準となる値を1つ返す方法
  • 2つのモデルの値を比較して(モデル中の複数の項目を比較して良い)、その結果、2つをソートしたい順番に応じた値(-1,0,1)を返す方法
の2種類の方法を用意しています。
(実装例などはこちらを参照 → Backbone.js 日本語リファレンス

私自身のは、単純に1項目(日時)で降順にしたかっただけなので、
  • 前者の方法を取り
  • yyyy/MM/dd HH:mm:ss からいわゆるUNIXタイムスタンプを取得し、それをマイナスした値を返すようにした
    (これで大きい日付の方が、小さい値を返すことになるので)
実際の実装はこんな感じです。
comparator : function(item) {
   return -(new Date(item.get('date_when')).getTime());
}
このように分かってみれば、モデルのデータを基に、何らかの形で希望の数値・文字列に加工して返すだけでソートが実現できますので簡単で便利だと思います。

この Model を Table View 辺りに binding すれば、それだけで希望のソート順で表示できるようになります。



Android アプリを Titanium Studio/Alloy を使って作ったので、その際にひっかかったことを、Tips で書いていってます。
実際に同じところで躓いた人がいて、それの解決のお役に立てば、と思っています。
ちなみに環境は Windows + Titanium Studio 3.3 + Android用開発となっています。

ただ、まったくのピンポイントでの Tips なので、まとまっての記述を期待している人にはすいません。

2014年9月20日土曜日

Titanium Tips: いわゆる国際化/多言語化対応について…

Titanium でのいわゆる国際化/多言語対応ですが、Titanium Studio 3.3 での開発では公式のTitanium SDK のマニュアル
の通りでした…、というのもアレなので少し付け足すと、
基本、
  • プログラム中では /i18n/ISO 639-1で定義された言語名/strings.xml ファイルでの定義と  L() マクロの組み合わせ
  • アプリの名称については /i18n/~/app.xml 中に appname で定義する
で出来るようになっています。

日本語の解説では
がまとまっています。
ただ、ホーム画面に表示されるアプリの名称を多言語対応する場合については、上記の記事と最新版(Titanium SDK 3.2 以降)では違っていて、
にあるような /i18n/~/app.xml を使う方式に統一されたようです。

また、L() マクロを使える場所についてですが、 Alloy での開発で view用の xml ファイルでは一部制限があるようです(styles の tss, controllers の js ファイルは特に問題なし)。
にあるように確かに view でも使える場所はあります。
次のように
<Window title="L('test')">
といったプロパティ値などでは働きます。
ただ、 Label や Button などの平文のところ
<Label id="labelTest">L('test')</Label>  
<Button id="buttonTest">L('test')</Button> 
といった場合には働いてくれません(でした。少なくとも Titaniaum Studio 3.3 環境では)。
こういう箇所については tss 側で記述する必要があります(view 側は空文にした上で)。
"#labelTest":{
  text:L('test')
}  
"#buttonTest":{
  title:L('test')
記述の綺麗さという観点からなら、 view ではなく tss 側にまとめた方が良いのかもしれません。

他にも
のページも参考になると思います。

2014/10/07 追記
上記の tss ファイルでの L() マクロ利用の制限ですが、SDK 3.4(Alloy 1.5.0) から無くなったようです(Label のみの一部?)。
情報ソースはこちらから。





Android アプリを Titanium Studio/Alloy を使って作ったので、その際にひっかかったことを、Tips で書いていってます。
実際に同じところで躓いた人がいて、それの解決のお役に立てば、と思っています。
ちなみに環境は Windows + Titanium Studio 3.3 + Android用開発となっています。

ただ、まったくのピンポイントでの Tips なので、まとまっての記述を期待している人にはすいません。

Titanium Tips: Tishadow で困ったとき…

Tishadow/Tishadow Express は Titanium で Rapid な開発をしたい際にはとても役立つツールです。
特に、ソースコードの修正を、エミュレータなどの環境に動的に反映できるというのは、コードや画面の試行錯誤ではとても重宝しますし、とても時間の節約になりいます。

とはいえ、単純なことながら困ることなどもあります。
私の場合はこんなことがありました。

そもそもインストールとかコマンド実行をどこでやるのか?(Windows環境)

インストール例などは Mac 環境で書いている方が多くて UNIX のコンソール環境があるの前提だったりで、最初は分からなかったんですが…

Titanium Studio にはターミナルが用意されていて、そこから全てできました。
表示されていない場合には、
  • Window メニュー → Show View → Terminal
で表示されます。
そこでシェル/コマンドライン環境を使えるようになっています。
(Git と一緒にインストールされた MinGW の bash?)

なんか途中でエラーになるなどでアプリの実行まで行かないんだけど…

結構、良く起きました。
再実行で解決することもありますが、そうでないときは…
  • Tishadow ではなく、通常のエミュレータで実行する

    結構、これで原因が分かったりします。
    例えば、アプリ起動中の Exception は Tishadow 経由だと隠れてしまうことがありました。

    また、Tishadow 上ではどうしても正しく動かないものもありました。
    (WebView の ローカルHTML 内で script で読み込んでいる javascript の動作など)
  • コマンドを手動で実行してみる

    コマンドがエラーになっていても詳細の原因が表示されない、というのが良くありました。
    そういうとき、コンソールで実行ログが出ているコマンドをコピペして直接実行してみると、具体的なエラーメッセジがでて解決することがあります。

    例えば、adb によるインストールの場合など
    'C:\android-sdk-win\platform-tools\adb.exe' -s emulator-5554 install -r 'd:\hogehoge\build\appify\build\android\bin\hogehoge.apk'
    注意点は"\" などが正しく扱われるように ' や " でパス全体をくくりましょう。
  • ti のオプション指定方法を変えてみる

    --device-id のオプションが働かなかったのですが、省略形の -C の方を使うとうまく行きました。
    例: ti build -p android -T emulator -C AVD_for_5_1_WVGA --shadow

Tishadow のインストールや実際の利用方法などは公式サイト


などを参考にして下さい。



Android アプリを Titanium Studio/Alloy を使って作ったので、その際にひっかかったことを、Tips で書いていってます。
実際に同じところで躓いた人がいて、それの解決のお役に立てば、と思っています。
ちなみに環境は Windows + Titanium Studio 3.3 + Android用開発となっています。

ただ、まったくのピンポイントでの Tips なので、まとまっての記述を期待している人にはすいません。

2014年9月18日木曜日

Titanium Tips: Kitchen Sink が動かないとき…

Titanium を入れた際、参考にするのが必須とも言えるサンプルプログラムが Kitchen Sink です。
様々な API を使った見本となっていて、Titanium で何が出来るかの総覧となっていますし、コピペ元としても重宝します。

現状(Titanium Studio 3.3)、Dashboard の Develop タブから IMPORT を指示することで、手元のワークスペースにインポートすることができます。
ところが、ビルドしてもエミュレータで動かない時があります。

実機で動かす、というのも一つの手です。
ただ、やっぱりエミュレータで動かしたいのにどうしても動かないというケースで、
  • Google API がインストールされていない仮想環境のエミュレータで実行しようとしている
というのがあります。

実際、自分の場合がソレでした。
(Titanium のインストール手順の中で Android SDK もインストールしますが、そこでは Google API を入れる指定がなかったような…)

その場合は、
  1. SDK Manager を使って希望のバージョンの Google API を追加
    (SDK Manager は SDK をインストールしたディレクトリの tools/android.bat で実行可能。
     この起動が気持ち悪い人は http://stackoverflow.com/questions/19015587/failed-to-execute-tools-android-bat-solution を参考に、AVD Manager.exe や SDK Manager.exe を SDK のルートに置くと吉)
  2. Titanium Studio の Windowメニュー>Preferences、開いたダアログから Studio>Platforms>Android の Manage AVDs... から AVD Manager を開く
  3. 新しく Target を Google API の入りものを選んで新しくエミュレータを作るか、既存のエミュレータの Target を Google API 入りのものに変更する
  4. そのエミュレータで Kitchen Sink を実行
で実行できるようになる、
かもしれません。

ここら辺りについては、ちょっともととなる Titanium Studio のバージョンが古いですが、



Android アプリを Titanium Studio/Alloy を使って作ったので、その際にひっかかったことを、Tips で書いていってます。
実際に同じところで躓いた人がいて、それの解決のお役に立てば、と思っています。
ちなみに環境は Windows + Titanium Studio 3.3 + Android用開発となっています。

ただ、まったくのピンポイントでの Tips なので、まとまっての記述を期待している人にはすいません。


2014年9月13日土曜日

ちなみにこんな Windows アプリも作ってます...

Mutter Launcher

スタートメニュー等の内容を部分文字列で検索&起動可能な半コマンド型ランチャー。

Mutter Launcher 紹介 http://hp.vector.co.jp/authors/VA022068/soft/bin/mlnch/
Vector のダウンロードページ http://www.vector.co.jp/soft/win95/util/se149792.html

実は、今年になってから、今更&何年ぶりだと言われそうな更新+機能追加をしてました。

Keyboard Mouser AHK

再帰的に画面を分割したマップ的+4方向のカーソル移動、加えてクリック動作等を任意のキーで行えるソフト。

Keyboard Mouser AHK マニュアル http://hp.vector.co.jp/authors/VA022068/soft/bin/km/KeyboardMouser.htm
Vector のダウンロードページ http://www.vector.co.jp/soft/winnt/util/se506667.html

これまた構想としてはずっとあったのですが、今年になってフト作ってみました。
実は AHK/AHK_L をはじめて使ったのですが、逆にそのおかげで作れたような部分もありました。




どちらもキーボードを主体に使って何かをするというのが共通点。
私自身がキーボード主体派なので、結果的にそれがそのまま反映されています。

そんな私は ThinkPad のトラックポイント付きキーボードが大好きで、デスクトップ用にもわざわざThinkPad トラックポイント・キーボー ドを使ってます。

Life/Biorhythm Logger (LB Logger) をリリース

Life/Biorhythm Logger (LB Logger) という Android 向けアプリを公開したついでに blog を作ってみました。





生活やバイオリズムの記録とグラフによる視覚化が、気楽で手軽にできるアプリです。
機能はシンプルですが、逆に面倒な操作を必要としません。
ユーザの手間を取らせずに、生活習慣を振り返る手伝いを出来るアプリを目指しています。

近いソフトは他にもありますが、他のものより手軽さと視認性の良さを両立させたつもりです。
こういった記録をつけるアプリは、面倒くささから結局入力をやめてしまうことが多いと思いますが、その点の敷居を低くし、ユーザが継続して記録を続けることができるように意識しました。

<記録項目>

  • 生活分野: 起床・就寝・朝食・昼食・夕食の時間
  • バイオリズム分野: 身体・感情・知性・便通・生理の程度(5~-5 の段階評価)

<特徴>

  • 設定不要で気軽で手軽に記録・見返し
    (カスタマイズや自由度は低いですが、悩まずにサクサクと記録・視覚化が出来ます)
  • ログ用とグラフ用の2つのタブ
  • 生活用とバイオリズム用の2つのビュー(スワイプで切替)
  • タブ、ビューともにワンアクションで素早く切替可能
  • ログは追加、変更、削除が可能
  • ログには1行メモを入れられます
  • グラフの形式は折れ線グラフになります
  • グラフは全ての項目を1画面内で表示し、簡単に比較することが可能



今日、ver 1.0 を公開したばかりで、ダウンロードも認知度もまったく無いですが、これから定期的にアップデートをしていく予定ではいます。

もし気になる点があれば、気軽にアプリを試してもらえたら。
もちろん無料です、但し、広告が出ますが…