投稿日:

Androidで必須なのに意外に抜けている処理


Androidでアプリ作ってたら普通にハンドルしなきゃ行けない処理だろうだけど、意外に抜けてしまっているっぽい処理エトセトラです。見積もりやディレクションの際にも抜けないように注意したいですね。

インターフェース

  • もろもろ処理に時間が掛かって ANR 発生
    ⇒時間のかかる処理は別スレッドで処理
  • 何かでユーザーを待たせたら…
    ⇒プログレスを出す。終わったら知らせる

ネットワークアクセス

  • ネットはだいたい時間掛かるので
    ⇒別スレッドで処理
  • オフラインに処理しようとして失敗
    ⇒処理前にオフラインチェックして、オフラインの時はユーザーに知らせる
  • 通信に時間が掛かり過ぎて帰ってこない
    ⇒タイムアウトを設定する
  • 通信に失敗
    ⇒適切に例外をハンドリング。必要なら処理をリトライさせる

スレッド

  • 複数のスレッドが同じ変数に同時にアクセスして時々変になる
    ⇒synchronized や volatile を使って正しく同期制御する。
  • いくつかのスレッドが同時に走って重たい。そもそも同時に走る必要無ければ…
    ⇒タスクのキューを用意して、1つ以上のスレッドでタスクを順次処理
  • スレッドを途中でキャンセル(UI的にキャンセルに見せて、実際にはキャンセルしないで走らしたままじゃないか?)
    ⇒Interrupt を正しく使い、また適切に自分で終わらせる(スレッドの基礎知識は正しく身に付けましょう)
  • ボタンタップでスレッド起動する処理とかで、連打されて同じ処理のスレッドが乱立するようになっていないか?
    ⇒今の処理が終わるまで次の処理要求はスキップする
    ⇒今の処理をキャンセルして、次の処理要求を実行する
    ⇒今の処理が終わるまでボタンを無効にして連打できないようにする
  • ファイル保存(インターネットやカメラなど、さまざまなデータをデバイスに保存する時)
    • どこに保存するかちゃんと検討する?(ローカル領域 or SDカード)
    • そのまま保存してても大丈夫か考える?(データを抜かれるリスクと対策の検討?)
      ⇒暗号化して保存するなど
    • ディスクいっぱいでエラー(大きなファイルなら意外にある)
      ⇒ちゃんと例外を処理しよう

他にもあると思いますが、ご指摘いただけると幸いです。

投稿日:

Androidでのプッシュ通知の検討と実装メモ


お知らせなどのプッシュ通知の実装は、ユーザービリティなどを考慮すると、非常にセンシティブな要件項目です。情報を出したいお客様は、時に過度な情報送信を主張されますが、それがお客様の目的と合致するかというと、必ずしもそうではない…というか、私の経験上は、どちらかというと間違った選択であることが多いですね。ディレクションにおいてはお客様とよく相談し、お客様にプッシュ通知の利害をよく説明し、ご理解いただくこと、またご理解頂けるように説明する能力が、制作会社にも求められると思います。

さて、例えば目覚まし時計などのように、通知されること自体が、ユーザーがアプリケーションに求める主たる機能である場合を除いては、コントローラブル(ON/OFF可能)であること、かつ「あまりうるさく無い」こと、といったあたりが良い落としどころのようです。

今回は、先日制作したアプリケーションについて、その仕様検討・実装のメモを残しておきます。

通知仕様の検討

アプリケーションの概要

まず、アプリケーションの要件は次のような感じでした。

  • 定期的に電力会社の情報をチェックする
  • 電力不足になると、ユーザーに通知する

アプリケーションの目的は、「節電」です。ユーザーはアプリケーションをインストールすることで、節電の為の行動を促される仕組みを持っています。通知は、電力不足の傾向が高まった時にそれをユーザーに知らせて、さらなる節電を促すものです。

ユーザー特性

今回、ユーザーには次のような特性があると推定しました。

  • 能動的に節電に取り組む意思がある
  • ある程度頻繁な通知も、許容される可能性が高い
  • 通知はなるべくタイムリーに欲しいと考えている
  • 電池消費の多いアプリは困る
  • 過度な通知を嫌う

検討

これをもとに、次のような検討をしました。
  • どんなふうに通知するか? 画面表示だけで良いか?
    …音声やバイブレーションでの通知は過剰ではないか?
  • 画面表示だけの通知なら、お知らせは画面ONの時だけで良くないか?
    …OFFの時はどっちみち見えないし
  • じゃ逆に、画面OFFの時は、電力チェックしなくて良い
    …電池節約できる
  • 最低チェック間隔は必要か?
    …頻繁に画面ON/OFFする人もいると思われる
  • 電源つないでデスクトップに置いてる人もいるよね?
    …画面ONの時だけじゃしばらくお知らせ出ないから、画面ON時は定期的なポーリングが必要
  • 通知のON/OFFは必須

決定された仕様

以上から、結果的に以下の通知仕様とすることになりました。

  • 通知方法
    • Notificationで表示する
    • 音やバイブレーションでの通知はしない
    • 次回の電力チェックで通知要件が無くなったらNotificationをキャンセルする
  • 電力チェックのタイミング
    • スクリーンON時、電力チェックする
    • 最低チェック間隔を設けて、過度な電力チェックをスキップ
    • スクリーンON中、定期的にポーリングして、電力チェックする
    • ポーリング間隔は、電力会社の情報更新間隔と合わせる

実装メモ

今回は上記の仕様を満たす為に、以下のような実装を行いました。

  • BroadcastReceiver
    • android.intent.action.SCREEN_ON
      1. bindService して、サービスの checkAndNotify() でチェックして必要なら通知
      2. Alarmで次回の定期チェックをセット
    • android.intent.action.SCREEN_OFF
      1. Alarmをクリア
    • android.intent.action.BOOT_COMPLETED
    • android.intent.action.PACKAGE_CHANGED
      1. SCREEN_ON/OFF 用の IntentFilter を登録(これらは動的にしか登録できないから)
  • Service
    • checkAndNotify
      1. 前回チェック時間を確認、最低チェック間隔を超えていたら:
        1. 別 Thread でチェック~必要なら通知
      2. 前回チェック時間として現在時間を保存(Preference)

 

 

 

投稿日:

Android の Service は常駐しない


検索で Android の Service 関連の情報を探していると、しばしば「常駐」というキーワードが出てきます(2011年5月現在)。そしてそれはどちらかというと「Serviceは常駐するものだろうに、よく落ちるよー。ちゃんと落ちないようにするには工夫が必要だよー。やっかいダヨネー」という雰囲気のものが多いように思います。

私も最初はそう思っていたのですが、よくよく Service 周りを調べてみると、どうもちょっと違うようです。で、今は次のような考えが正しいと思っています。

「Android の Service は、何らかの常駐的な機能を提供するコンポーネントでは無い」

で、それでそう考えると、例えば次のような、Service の仕様もしっくり納得できます。

  • startService は別スレッドで実行されるわけじゃない
  • stopSelf しなくても、いつの間にか kill されて落ちてたりすることもあったりする
  • Service が kill されて再起動した時、onCreate は呼ばれるが、onStart は呼ばれない

まぁ、そう気付いてから↓改めてリファレンスを見ると、なんとなくそういうことが書いてあったりして、ちょっとお恥ずかしい感じです……。(*^ ^*;

http://developer.android.com/intl/ja/reference/android/app/Service.html#WhatIsAService

(↓What is a Service? の部分の翻訳が含まれている記事もありました)
http://d.hatena.ne.jp/adsaria/20100914/1284435095

でもちょっと遠まわしな記述ですよね?(私、最初は意味がわからずに読み飛ばしてました)

で、そんなことに気付いたところで、あんまり意味も無いものかも知れませんが、私個人的には、最初にどう作ろうか考えている時点で、早めに正しい方向性を見出せるような気がいたします。

では常駐はどう作るか?

ってか、そもそも「常駐」って言葉の定義も結構曖昧ですが(笑)、例えば、定期的なプログラムの実行であれば AlarmManager を利用するのが良さそうです。また、外部からの何らかのアクションに対応するには、BroadcastReceiver を使うのが良さそうです。

以上でーす。久しぶりの記事がこんなんですみません。(^ ^;

でも、とりあえず、Service が「常駐」のための正しい手段だと思ってると、ちょっぴり問題のある設計をしていまいそうにも思ったので、それだけです。

ではー。

追記です。

ブックマークしてくださった方のコメントに、「 『Android の Service は、何らかの常駐的な機能を提供するコンポーネントでは無い』 メモリが足りなくなったりしない限り、サービスは残ると思っていた。」とありましたので、補足ですが、基本、startService すれば、stopService しない限り、service は起動していると思います。

ただ、再起動したらサービスは落ちてますし、メモリが足りなくなってキルされたりしたときの挙動とか見ていると、「『Serviceが常駐の為の機能』と思っていると、間違った設計をしてしまう可能性がある」ことや「Serviceそのものを有効に利用できない」ということを記事には書いているつもりでした。誤解のありませんように、です♪

投稿日:

IE8 で white-space:nowrap が指定範囲の外まで影響する問題の回避方法


すこしはまったので、メモ&情報共有です。
この問題、Webで調べると、よく float:left; での解決が示されていますが、今回の自分の事例ではレイアウト的にそれができなくて、困りました。

で、結局、色々試した結果、display:inline-block; で解決でした!

具体的には次の css を書きました。

1行目が、white-space:nowrap の指定で、2行目で、ハックを用いて IE8 のみに、display:inline-block を適用しています。

以上、ご参考まで。

投稿日:

eepy – Python コード埋め込み形のシンプルなテンプレートエンジン


Python コードを埋め込む形式のシンプルなテンプレートエンジンです。Ruby の ERB のような感じです。まだ検討したいところも多々ありますが、もしお役に立ちそうに思われた方はご自由にお使いください。で、何か不具合があれば教えてください♪

特徴

  • Ruby の ERB 風の記法
  • Python のインデントブロックを意識せず、テンプレートを記述可(”end” キーワードの使用)
  • フィルタ。値の埋込み時に、html クォートなどのフィルタを自動的・全般的に適用可
  • キャッシュ。Renderer 利用時に利用可
    • メモリ保持で揮発性の1次ファストキャッシュ(1トランザクション内でのテンプレートの繰り返し利用の為)
    • 2次キャッシュ。コンパイル済みのテンプレートの永続化。現在、File ベースと、Gae Memcache ベースのストレージを準備。他の DB ストアなど、必要に応じてストレージを追加可
  • ヘルパ。幾つかの便利なヘルパを提供
    • extends と block。Django のような、テンプレートを継承・拡張するスタイルを利用可
    • include。テンプレート中で、他のテンプレートを読み込み

なお、eepy は、yuin さんの embpy をベースとした派生ライブラリです。
また、キャッシュのストレージ仕様は、kuwata-lab.compyTenjin を参考にさせて頂いています。

embpy との主な相違点(2010.02.10時点)

  • ブロックの終わりの明示は end キーワードでのみ可
  • インラインでブロックを記述する時に、{: ~ :} の記述が不要(普通に書けます)
  • 複数行のコードパートにブロックを書く時は、end キーワードは不要(普通に書けます)
  • 三項演算子が利用可
  • render の戻り値は、unicode

ドキュメント

モジュール、クラス、メソッドに記載の doc を参照してください。

テンプレート(template.html/utf8):

Python コード:

出力結果:

ソースコード

次の URLにて公開しています。

https://github.com/yuka2py/eepy