2017/07/25

Denbunライブラリでメッセージの表示頻度を調整する

tl;dr

はじめに

モバイルプラットフォームでは, ユーザ向けに何かしらのメッセージを表示することがよくあります.
それは, イベントの発生を知らせるものであったり, ユーザのアクションが完了したことを知らせるものであったり, エラーの発生を知らせるものであったりと様々です.
これらのメッセージは重要なものですが, 中には退屈と思われてしまうものもあります.

  • ユーザがアプリケーションの振る舞いを学習するのに重要なメッセージが, アプリケーションを使い慣れた後になっては, ただのお節介なメッセージになってしまうケース
  • 毎回閉じるだけの”お知らせダイアログ”といった類のもの
  • コンテンツの削除確認といった誤操作防止目的のもの
  • Backキーを押した際の「アプリケーションを終了しますか?」なもの

ユーザを退屈させないためにも, メッセージの表示頻度を調節することが重要です.

Denbun

メッセージの表示頻度を調整するためのアプローチはいくつかあります.

  • ダイアログに「今後表示しない」チェックボックスをつけてユーザ主動でダイアログ表示をやめさせる方法
  • 一度しか表示しないような回数限定メッセージ
  • 一週間のうち決まった曜日にだけ表示する定期的なメッセージ など…

これらのアプローチをとるためには, 表示設定や表示回数といった内容を永続化して都度, 表示頻度を調整する必要があります.
そこで, メッセージの前回表示時間や表示回数といった情報を保存し, 表示頻度の調整をサポートするDenbunライブラリをリリースしました.



このライブラリは, 次のようなメッセージ通知を実現したい場合に有効です.

  • 「今後表示しない」 オプション付きメッセージ
  • N回だけ表示するメッセージ
  • 定期的に表示するメッセージ(1週間に1回の頻度で表示. 月曜日に1回だけ表示. etc.)
  • N回表示した後は, n時間経過するまで表示しないメッセージ

メッセージの表現系(Dialog, Toast, Snackbar, etc.)は問いません.
このライブラリは, メッセージの前回表示時間や表示回数をSharedPreferenceに保存しており, これらの情報を駆使して”今, メッセージを表示すべきかどうか” を判断することで, メッセージの表示頻度を調整します.

使い方

まず初めに, Application.onCreateなどで, DenbunBoxを初期化します.
DenbunBoxはこのライブラリの起点となる重要なクラスです.

DenbunBox.init(new DenbunConfig(this));

DenbunBoxの初期化が終わったら, メッセージを表現するDenbunインスタンスを取得します.
メッセージの表示頻度の調節はこのDenbunインスタンスを通して行います.

Denbun msg = DenbunBox.get(ID);

Denbunインスタンスのshow()を呼び出すことで, 表示時間や表示回数の情報が更新され永続化されます.

Denbun msg = DenbunBox.get(ID);
msg.shown();

メッセージの最適な表示頻度はメッセージ毎に異なりますので, Denbunインスタンスを取得する際に最適な表示頻度を算出できるFrequency Adjusterを指定します.
例えば, 下記の例は1回限りのメッセージ通知を実現する例です.

// This message is displayed only once.
Denbun msg = DenbunBox.get(ID, new CountAdjuster(1));
...
msg.isShowable(); // true
msg.shown();
msg.isShowable(); // false

あるいは, メッセージを直接的に今後表示しなくすることも可能です.

Denbun msg = DenbunBox.get(ID);
msg.suppress(true);

メッセージによっては表示頻度の計算が複雑になるものもあるでしょうから, Frequency Adjusterは自前のものを実装してDenbunBox.getに指定することもできます.

実際にDialogやToastを表示する際には, DenbunインスタンスのisShowable()の値を確認してから表示すると決められた頻度でメッセージを表示することができます.

テスタビリティ

Denbunライブラリを使ったコードをテストしたい場合は下記が参考になります.
DenbunConfigにはDenbunライブラリとSharedPreferenceのI/Oを取り持つDAOのgetter/setterが用意されています(このメソッドは@VisibleForTestingです)

DenbunConfig conf = new DenbunConfig(app);

// spy original DaoProvider
Dao.Provider origin = conf.daoProvider();
conf.daoProvider(pref -> (spyDao = spy(origin.create(pref))));
DenbunBox.init(conf);

DenbunBox.find(ID).shown();
verify(spyDao, times(1)).update(any());

おわりに

Denbunライブラリを使い始めるには次の一文をbuild.gradleに追記するだけです.
<latest version>には最新のライブラリバージョンを指定してください.

compile 'com.yuki312:denbun:<latest version>'

近々v1.0.0をリリース予定です.
PRやIssueがあればGitHubの方に登録していただけると幸いです.

以上です.