Androidアプリのアクセシビリティを高める方法


# 背景
- 以前Androidのアクセシビリティを調査したことがあり、まだあまり知られていないことがたくさんあると感じているので少しでも情報を出していこうと思う。
- ちなみにAndroidアプリのアクセシビリティガイドラインはココにあります[Making Apps More Accessible](https://developer.android.com/guide/topics/ui/accessibility/apps.html)(英語)

# Androidのアクセシビリティ機能
- 設定→ユーザ補助から各種機能をON/OFFできる
- TalkBack(音声読上げ機能)、フォントサイズ指定、拡大表示、字幕、色補正(色弱)、色反転等がある
- 本記事では特にアプリケーション開発上考慮しなければならないTalkBack, フォントサイズ指定機能について取り上げる

# TalkBackとは？
- 目の不自由なユーザ向けのAndroid標準搭載支援ツール。タップした場所あるいはフォーカスが当たった場所を音声で読上げる機能を有する。ONにすることによりタッチ操作体系も変わり、シングルタップでフォーカス、ダブルタップで確定、画面スクロールは二本指での操作となる

# TalkBackをONにされたときにアプリが気をつけるべきこと

## ContentDescriptionをきちんと書く
- TalkBackは音声読み上げ機能があるが、ViewのcontentDescriptionが記載されていないとImage等テキスト情報がないものは読み上げてくれない
- EditTextはhint属性を設定することで読み上げ可能
- TextViewはcontentDescriptionを設定しなくても設定されているTextを読み上げてくれる
- SurfaceViewを使っていると、読み上げてくれないので自分で読み上げる必要がある
- WebViewも読み上げるところ、読み上げないところがあるのでちゃんと確認する
- lintをかけるとMissing contentDescription attribute on imageが出ることがある
- Image以外でも表示されているテキストより詳細をここに記載しておくことで読み上げ時にわかりやすくすることができる
- contentDescriptionには必要最低限の説明を記載すること

例) Googleのサンプルから抜粋(https://developer.android.com/guide/topics/ui/accessibility/apps)

~~~xml
<ImageButton
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:layout_alignParentBottom="true"
   android:layout_alignParentLeft="true"
   android:layout_alignParentStart="true"
   android:contentDescription="@string/share"
   android:src="@drawable/ic_share" />
~~~

~~~java
ImageView playPauseImageView = new ImageView();
boolean mediaCurrentlyPlaying = true;
...
private void updateImageButton() {
    if (mediaCurrentlyPlaying) {
       playPauseImageView.setImageResource(R.drawable.ic_pause);

       // In res/values/strings.xml, "pause" contains a value of "Pause".
       playPauseImageView.setContentDescription(getString(R.string.pause));
    } else {
       playPauseImageView.setImageResource(R.drawable.ic_play);

       // In res/values/strings.xml, "play" contains a value of "Play".
       playPauseImageView.setContentDescription(getString(R.string.play));
    }
}
~~~

## キーボードでも操作できるようにする
- TalkBackを有効にするとフォーカスありきの操作体系に変わる。そのため、操作できるGUI部品にはフォーカスできるようにしておかないといけない。また、操作できないラベルなどもフォーカスが当たり読み上げられることを確認する必要がある
- 具体的にはfocusable属性をtrueにする

## AccessibilityEventを発生させる
- 任意のタイミングで読み上げを行うにはAccessibilityEventを発生させることができる

例)

~~~java
public void sendAccessibilityEvent(String text, View source) {
    AccessibilityManager manager = (AccessibilityManager) getSystemService(Context.ACCESSIBILITY_SERVICE);
    if(manager.isEnabled()){
        AccessibilityEvent event = AccessibilityEvent.obtain();
        event.setEventType(AccessibilityEvent.TYPE_ANNOUNCEMENT);
        event.setClassName(getClass().getName());
        event.getText().add(text);
        event.setSource(source);
        manager.sendAccessibilityEvent(event);
    }
}
~~~

## TalkBackのON/OFFをチェックして広告をオフにする
- 広告は目の見えない、もしくは見えにくい人にとっては間違って触った時にもう戻ってこれなくなる上、危険なサイトに誘導されてしまう可能性のある非常に厄介なものになりうる。非表示にすると当然クリックしてもらえなくなるが、アクセシビリティを優先すべきと考える。

- AccessibilityManagerのisEnabled(), isExploreByTouchEnabled()あたりを使うとTalkBackのON/OFFをチェックできる。

```
AccessibilityManager am = (AccessibilityManager) getSystemService(ACCESSIBILITY_SERVICE);
boolean isAccessibilityEnabled = am.isEnabled();
boolean isExploreByTouchEnabled = am.isTouchExplorationEnabled();
```

[参考URL](http://stackoverflow.com/questions/5116867/how-to-know-if-android-talkback-is-active)

# TalkBack以外で気をつけること

## 文字を大きくする、設定で文字を大きくしてもレイアウトが崩れないようにする
- Android標準設定でフォントサイズを変更する機能がある
	- 設定→ディスプレイ→フォントサイズから変更可能

![フォントサイズ.png](https://qiita-image-store.s3.amazonaws.com/0/29493/e98a04b8-972f-7d07-ed75-d16178ea051f.png "フォントサイズ.png")


- アプリは設定でフォントサイズが変えられることを想定してつくらないとレイアウトが崩れる、文字が切れて見えなくなるなどの不具合になる
例) ※キャプチャ画像は2018/03/30時点のものですでに修正されている可能性あり
 ![Screenshot_20180330-084701_1.png](https://qiita-image-store.s3.amazonaws.com/0/29493/e007660b-924a-57ec-cdf4-cababf2db7db.png)

- 根本解決ではないが設定の影響を受けなくする方法
	- spではなくdpを使う
		- 設定に関わらずフォントサイズを固定したい場合はフォントサイズ指定をspではなくdpにすると良い。ただし、端末のフォントサイズ設定に合わせてアプリも文字を可変にするのが本来あるべき姿なので、lintに怒られることになる

## 背景黒地に白文字にする
- コントラスト強調され、こちらの方が見やすいという人がいる。参考ページは以下
	- [白黒反転トップページ（福祉用具プラザ北九州）](http://www.kati.gr.jp/wb-index.html)
	- [利便性の先にある、ひとの気持ちをデザインする。視覚障害当事者の学生起業家が語るユニバーサルデザイン。(プラスハンディキャップ)](https://plus-handicap.com/2016/01/7022/)
	- [Apple アクセシビリティ](http://www.apple.com/jp/accessibility/iphone/vision/)
	- [Android 5.0 Lollipopの新機能「色反転」の設定方法。](http://androidlover.net/android-os/android-5-0-lollipop/android-5-0-lollipop-tone-reversal.html)
- iPhone(iOS10)、Android 5.0 以降の設定にもある、OSレベルで反対色(反転色、補色ではない)にするのでアプリ単位で気にする必要はない
- OSレベルで勝手に変えられるのでUDを意識して黒地に白フォントで作成していたアプリは逆に見にくくなってしまう、アプリ作成者は反転ONにしてテストした方がよさそう
- Androidのこの機能は Android 7.1.2 現在まで試験運用という位置付けでパフォーマンスにも影響があると記載があるが、Nexus 5XでPokemon Goを動かしてみた限りでは特に影響なさそうに感じた

## 音声読み上げ機能を付ける(TalkBackをOffにしている前提)
- TalkBackをONにしていなくても音声読み上げをがあったほうがいい場合がある、老眼で細かい字を読みにくくなった人向け、外出中使用を想定してない場合は音声出力しても問題ない
- Androidの場合、TTS(TextToSpeech)機能を利用する
- 昔は日本語に対応していなく、N2TTS等を別途インストールする必要があったが、最近のAndroid(6.0から？)では日本語読み上げをサポートしている
- 読み上げスピードには変えられると良い、視覚障害者で慣れた人はかなり早くても瞬時に認識することができる