X

Android開発者が知るべき10のこと

本記事はAndroid DevelopersのDesigning for Seamlessnessを意訳、加筆したものです。Androidアプリをシームレスに連携させるためのノウハウを紹介します。

特性を理解する

アプリケーションが高速に動作し、レスポンスが良くても、アプリケーション遷移やダイアログ表示を乱用した無計画なUI、不用意なデータの喪失、意図しないタイミングでの操作妨害など知らず知らずのうちにUXの良くない設計になっているかもしれません。これらの問題はどのように避ければ良いでしょう?

  • アプリケーションが動作するコンテキスト
  • Androidフレームワークの特性(アプリケーションへどんな影響を与えるか)

を理解することが開発の手助けになります。

ユーザ操作を妨げない

Original Update by mujitra

ユーザ操作のシームレス性で問題になるケースとしてよくあるのが、他のアクティブなアプリケーションを無視して、自分のダイアログを表示してしまう場合です。つまり、内部動作としてはアプリケーションのバックグラウンドで動作するプロセス(サービス、ブロードキャストレシーバー)が何らかのイベントに反応してダイアログ表示するケースです。

とくにエミュレータ上でアプリケーションを開発、テストしていると他の要素が排除されているため、上記は無害に感じるでしょう。しかし実際のデバイス上で実行される場合では、バックグラウンドで実行中のプロセスがダイアログを表示しようとした場合、必ずしもアクティブではありません(ユーザーフォーカスを持っていないかもしれません)。
ユーザーが何をしていても、ダイアログをポップアップするのは良くありません。

この問題を避けるためには、アプリケーションはユーザーに通知するための適切なフレームワーク(Notification)を使うべきです。Notificationによりアプリケーションは、(バックグラウンドで検知したイベントのため)現在のユーザー操作を遮ることなくステータスバーにアイコンを表示して通知できます。

また別の課題としてonPause()や他のライフサイクルメソッドを正しく実装していないために起こる作業中データの破棄や状態不正があります。
アプリケーションで使用するデータを公開するなら、標準規格の生データやデータベース経由で行うよりも、ContentProviderを利用したほうがAndroidらしく、連携しやすいでしょう。

これら例が共通して示すことはシステムと他のアプリケーションと協調することの重要さです。
Androidシステムはブラックボックスのソースコードの集合より、疎結合したコンポーネントの集合としてアプリケーションを扱うように設計されています。

アプリケーションを「疎結合したコンポーネントの集合」として扱うことで、
他のアプリケーションとシームレスかつ美しく統合することができる利点があります

Android開発者が知るべき10のこと

つづきをどうぞ

1.ユーザデータを守る

Don’t Drop Data
Androidはモバイルプロットフォームです。別のActivity(たとえば電話の着信)がいつ急に割り込んでくる可能性が常にあります。このとき、 onSaveInstanceState() と onPause() メソッドが呼ばれ、アプリケーションは終了させられます。
ユーザがデータを編集していたなら、あなたのアプリケーションは、おそらくそのデータを失うでしょう。
最初にするべきことは、データ保存です。

メールアプリの挙動が典型的でしょう。メールを書いている途中に、別のActivityが
起動したら、メールアプリは作成中のメールを草稿として保存します。

Androidでの賢いやり方は、onSaveInstanceState()メソッドをoverrideして、適切な形で保存することです。
ユーザーがアプリケーションに戻ってきたとき、データを復旧できるように実装します。

参考情報:データ保存方法

  • データを簡単に保存する方法(Preference編)
  • データを簡単に保存する方法(SQLite編)
  • データを簡単に保存する方法(シリアライズ編)
  • SDカードにファイルを保存する
  • データを簡単に保存する方法(ファイル入出力編)
  • Applicationクラスを継承して、データの共有をする

2.生データでやりとりしない

Don’t Expose Raw Data
生データを見せることももちろん可能ですが、通常、良い方法ではありません。アプリ同士が連携しようとしたらデータ形式を理解する手間がかかるほか、データ形式に変更があった場合、自分だけではなく他のアプリケーションも影響を受けるからです。
ContentProviderを利用することで、インターフェイスをそのままに生データを抽象化し、データ形式の変更にも対応可能です

参考情報:Intent

  • Intentを使ってアプリを連携させる(暗黙的Intent)
  • Intent.ACTION_SENDで他のアプリケーションと連携する

3.ユーザ操作を妨げない

Don’t Interrupt the User
アプリケーションはユーザからの入力など直接的なレスポンスを除いて現在のActivityから別のActivityへの遷移は避けるべきです。バックグラウンドプロセス(BroadcastReceiversかServices)からstartActivity()を呼び出さないでください。
強制的なActivity遷移はユーザーに不快感を与えるほか、タイミングによっては遷移前のアプリケーションに対しユーザーが入力したキー入力の一部を誤って受け取ることもあります。

直接バックグラウンドからActivityを呼び出さない代わりに、NotificationManagerを使ってステータスバーに表示してください。ユーザは表示内容を確認して、ゆっくりと見ることができます。
(※自分のActivityがフォアグランドにあるケースには適用されません。フォアグラウンドにある場合は、ユーザーは入力に応じたActivity遷移を期待しています)

参考情報:Notification

  • Notificationを使ってステータス通知する
  • タイトルバーにアイコンを表示する

4.スレッドを使う

アプリケーションで長く時間がかかる処理を行う場合はスレッドを活用してください。長期間Activityが応答を返さない際には”Application Not Responding”(ANR)ダイアログが表示され、ユーザーに強制終了を確認します。
正常に動作している限り、ANR表示は避けるべきです。
実行時間が長いコードはイベントハンドラの動作を妨げるため、UIスレッドから追い出して、別スレッドで行う必要があります。

参考情報:スレッド処理

  • Asynctaskを使って非同期処理を行う
  • IntentServiceを使って非同期処理を行う

5.ひとつのActivityで何でもしようとしない

Don’t Overload a Single Activity Screen
アプリケーションは、大抵いくつかの画面で構成されています。UI画面を設計する際には、必ずActivityオブジェクトの複数インスタンス化を前提に設計します。アプリケーションを、いくつかのActivityの集合だと考えてください。
Androidのアプリケーション履歴の”backstack”モデルと親和性が高く、不具合の起きにくい良いコードになります。

参考情報:Activity

  • Activityとライフサイクル
  • 図解Androidのライフサイクルとプラットフォーム
  • Intentを使って画面を遷移する(明示的Intent)

6.テーマを活用する

Extend System Themes
Androidでのルック&フィールと自分のアプリケーションのUIで調和を保つことが重要です。予測した動作と異なったアプリはユーザーを動揺させます。
UI設計時は、変わったことを避け、代わりにテーマを使用してみてください。他のすべてのアプリケーションと同じルック&フィールを提供できます。

参考情報:カスタマイズ

  • スタイルを使ってレイアウトを定義する
  • テーマを使ってレイアウトを定義する
  • 画面の向きによってレイアウトを変更する

7.多解像度に対応したUI

Design Your UI to Work with Multiple Screen Resolutions
レイアウトとdrawableがさまざまなスクリーン上で、適切に表示できることは、とても重要です。
たとえば絶対位置でのレイアウト指定の代わりに相対的にレイアウトを指定してください。様々なサイズに対応するためにdrawableに9-patchを適応するなど多解像度対応が主な作業です。システムが自動的に最適なレイアウト、drawableを使い、どんなデバイス上でも表示できるようになります

参考情報:リソース

  • 解像度・ピクセル密度の異なる複数の端末に対応する方法
  • リソースの多言語対応

8.ネットワークは遅い

Assume the Network is Slow
Android端末は様々な環境でつかわれるため、いろいろなネットワーク接続が想定されています。3G接続のように高速なものもあれば、GSM,GPRSに代表される非3G接続も考えられます。現実には非3G接続のような遅いネットワークで使われることがほとんどです。

エミュレータには、より遅いネットワーク速度をシミュレートする設定があります。Eclipseの構成の「エミュレータ設定」タブ
またはエミュレータを始動するときのコマンドラインのオプションで調整して、通信速度が遅い場合の挙動を確認してみてください。

参考情報:開発環境

  • デバッグログを使いこなす
  • adbを使いこなす
  • DDMSで効率的にデバッグする

9.特定のハードウェアに依存しない

Don’t Assume Touchscreen or Keyboard
Androidは様々なハードウェアで提供されています。キーボードが完全なqwerty配列を持つのか、12キーしかないのか、タッチスクリーンの有無、それぞれデバイスによって異なります。
アプリケーションを作る際はハードウェア上の仮定を無くし、十分留意してください(特定のキーボード配列に依存するなど)

10.モバイル端末のバッテリーは有限

Do Conserve the Device Battery
モバイル機器では電力は有限です。もっとも電池消費が大きいのはCPUと通信です。アプリケーションのなかで、それらの消費が最小となるように記述してください。ネットワークの使用を最小限に押さえるのが重要です。
たとえばネットワーク接続に失敗した場合、何度も接続を試みるよりも、ユーザ操作によって再試行を促してください。自動で行うと電力の著しい消費を招きます。

ユーザは開発者の想像以上に賢明です。
アプリケーションがCPUパワーやネットワークを過度に利用している場合、すぐにアンインストールされてしまいます。

参考情報:デバイス制御

  • AndroidでGPSセンサを利用する方法
  • カメラの使用方法(1)
  • カメラの使用方法(2)
  • センサを使ってAndroid端末の傾きを知る
  • Androidのセンサーを利用する
  • バイブレーションを使う
  • 画面(バックライト)の明るさを変える
mhidaka: Software Engineerだよ。DroidKaigi Organizer / Androidと組込とRe:VIEW。techbooster主宰。mhidaka's writings http://booklog.jp/users/mhidaka 技術書典! http://techbookfest.org