読者です 読者をやめる 読者になる 読者になる

Androidアプリ開発で素早くフィードバックをえるためのライブラリを作りました

モバイルファースト室の山下(@tomorrowkey)です。

f:id:tomorrowkey:20141211162434g:plain

Androidアプリを開発していて、ふとした時に不具合を見つけたりしませんか。
クラッシュであればDeploygateやCrashlyticsなどでクラッシュレポートを送ることができますが、表示崩れを報告をするにはスクリーンキャプチャを撮ってメールアプリを開き、画像を添付して、送信する、といった手順が必要でなかなか面倒です 。
アプリを開発する側は不具合のあったスクリーンショットがほしい、不具合を報告する人は報告する手順がめんどうといったギャップを解決するためのライブラリを作りましたので、紹介します。

不具合報告する機能を作りました

冒頭のアニメーションgifで一通りの挙動を見ることができます。
このライブラリを使っているアプリを開くと通知領域に「不具合を報告する」という項目が増えます。 不具合を見つけた時にこの通知を選択するとスクリーンショットが撮影されメール作成画面が開きます。
不具合を報告する人はこのメールを送るだけで表示崩れなどの不具合を報告することができます。

メールが届きます

実際に受信したメールがこちらです。

f:id:tomorrowkey:20141212133658p:plain

スクリーンショットが添付されているので開くと表示されます

アプリのスクリーンショットなので、ステータスバーが表示されませんが、不具合報告するには十分なものが撮れます。

f:id:tomorrowkey:20141212133713p:plain

この機能をアプリで使うには

この機能はライブラリとして作りました。
https://github.com/cookpad/issue-reporter-android

不具合報告機能をつけたいActivityに、Fragmentを追加する処理を書き足します。
BaseActivity.java といった基底クラスがあれば、それに書き足すだけでアプリ全体にこの機能を追加することができます。

MainActivity.java

@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);

  String mailAddress = "support@example.com";
  String subject = "Report an issue";
  IssueReporterFragment.apply(this, mailAddress, subject);
}

簡単に原理を説明すると、ActivityのRootのViewであるDecorViewを取得して、描画するためのキャッシュ(Bitmap)を取得してそれをメールアプリにIntentで飛ばしているだけです。
なにも特殊なことをしていないため、Permissionの追加も必要ありません。

まとめ

素早くモバイルアプリを開発するためには、開発とテストとフィードバックのサイクルをいかに早く回すかが鍵となります。
このライブラリを使えばフィードバック時のコミュケーションコストを少し抑えることができるようになると思います。
ぜひご活用ください。

/* */ @import "/css/theme/report/report.css"; /* */ /* */ body{ background-image: url('http://cdn-ak.f.st-hatena.com/images/fotolife/c/cookpadtech/20140527/20140527163350.png'); background-repeat: repeat-x; background-color:transparent; background-attachment: scroll; background-position: left top;} /* */ body{ border-top: 3px solid orange; color: #3c3c3c; font-family: 'Helvetica Neue', Helvetica, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', Meiryo, Osaka, 'MS Pゴシック', sans-serif; line-height: 1.8; font-size: 16px; } a { text-decoration: underline; color: #693e1c; } a:hover { color: #80400e; text-decoration: underline; } .entry-title a{ color: rgb(176, 108, 28); cursor: auto; display: inline; font-family: 'Helvetica Neue', Helvetica, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', Meiryo, Osaka, 'MS Pゴシック', sans-serif; font-size: 30px; font-weight: bold; height: auto; line-height: 40.5px; text-decoration: underline solid rgb(176, 108, 28); width: auto; line-height: 1.35; } .date a { color: #9b8b6c; font-size: 14px; text-decoration: none; font-weight: normal; } .urllist-title-link { font-size: 14px; } /* Recent Entries */ .recent-entries a{ color: #693e1c; } .recent-entries a:visited { color: #4d2200; text-decoration: none; } .hatena-module-recent-entries li { padding-bottom: 8px; border-bottom-width: 0px; } /*Widget*/ .hatena-module-body li { list-style-type: circle; } .hatena-module-body a{ text-decoration: none; } .hatena-module-body a:hover{ text-decoration: underline; } /* Widget name */ .hatena-module-title, .hatena-module-title a{ color: #b06c1c; margin-top: 20px; margin-bottom: 7px; } /* work frame*/ #container { width: 970px; text-align: center; margin: 0 auto; background: transparent; padding: 0 30px; } #wrapper { float: left; overflow: hidden; width: 660px; } #box2 { width: 240px; float: right; font-size: 14px; word-wrap: break-word; } /*#blog-title-inner{*/ /*margin-top: 3px;*/ /*height: 125px;*/ /*background-position: left 0px;*/ /*}*/ /*.header-image-only #blog-title-inner {*/ /*background-repeat: no-repeat;*/ /*position: relative;*/ /*height: 200px;*/ /*display: none;*/ /*}*/ /*#blog-title {*/ /*margin-top: 3px;*/ /*height: 125px;*/ /*background-image: url('http://cdn-ak.f.st-hatena.com/images/fotolife/c/cookpadtech/20140527/20140527172848.png');*/ /*background-repeat: no-repeat;*/ /*background-position: left 0px;*/ /*}*/