Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Android Lintで正しさ
を学ぼう
2015.02.18 DroidKaigi 2016
Yukiya Nakagawa / @Nkzn
ROOM:B 13:00-13:50
#DroidKaigiB
Who are you?
• Yukiya Nakagawa / @Nkzn
• ウォーターセル株式会社@新潟
• 農業向けサービス「アグリノート」
• エンジニア募集中です
• Androidは2009年からチマチマと
Recent Activity
• C89コミケ
• とびだそう!Androidプロ
グラミングレシピ
• https://techbooster.booth.pm/
• Android Lintネタ書いてました
Target
• まだAndroidプログラミングのベストプラク
ティスが分からない初学者
• Androidアプリの品質を表す指標がほしい

品質担当者
Agenda
• Android Lintとは
• 初学者がやりがちなミス
• もっと上を目指す人のために
• 品質指標としてのAndroid Lintを考える
Android Lintとは
Lintとは
Another HTML-lint HTMLの構文チェックツール
JSLint, JSHint, ESLint JavaScriptの構文チェックツール
textlint 日本語の構文チェックツール
lintとは、主にC言語のソースコードに対し、コンパイラより詳細かつ
厳密なチェックを行うプログラムである。
• 型の一致しない関数呼び出し
• 初期化されていない変数の参照
• 宣言されているが使われていない変数
• 同じ関数を参照しているが...
Javaの場合?
Android Lintとは
• Google公式
• 222個のルール(ver25.0.4現在)
• Category, Severity, Priorityで分類される
• 結構手広い
• 不具合予備軍の検出
• ユーザビリティチェック
Category
カテゴリ名 チェックする内容
Correctness SDKの使い方の正しさ
Correctness:Messages Correctnessのうち、特にメッセージ
Security セキュリティ
Performance パフ...
Severity
レベル 意味 アプリへの影響
Fatal 致命的 ビルドや実行に必ず失敗する
Error エラー
ビルドはできるが実行時エラー
を引き起こす可能性が高い
Warning 警告
動作はするが修正したほうが
より良いアプリになる
...
チェックできるファイルの種類
• https://android.googlesource.com/platform/
tools/base
• com.android.tools.lint.detector.api.Detector

htt...
1. Manifest file
2. Resource files, in alphabetical order by resource type
3. Java sources
4. Java classes
5. Gradle files
6....
Priority
• 1から10まで
• あまりあてにならない
どんな問題を解決するのか
お作法分かりづらい問題
https://twitter.com/konifar/status/698760224409169920
Android Way is どこ
https://twitter.com/konifar/status/698760496837603328
Googleによる正解集
(あるいはアンチパターン集)
Android Lint
事例紹介
Part 1. 初学者がやりがちなミス
Case 1. LinearLayoutに並べたビューが
表示されないのは何故?
(Orientation)
こんなコード書いてませんか
<LinearLayout

android:layout_width="match_parent"

android:layout_height="match_parent">

<TextView

androi...
Orientation
• Summary: Missing explicit orientation
• Priority: 2 / 10
• Severity: Error
• Category: Correctness
何故いけないのか?
デフォルトのorientationはhorizontal
こう書きましょう
<LinearLayout

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="ve...
Case 2: Fragmentが表示されない
こんなコード書いてませんか
@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setCon...
CommitTransaction
• Summary: Missing commit() calls
• Priority: 7 / 10
• Severity: Warning
• Category: Correctness
何故いけないのか?
• beginTransaction()から始まるメソッドチェーンは、
commit()が呼び出されてから描画処理に入ります
• そりゃcommit()を呼んでなきゃ何も表示されません
• DBのトランザクションみたいなイメ...
こう書きましょう
@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentV...
Case 3. SharedPreferenceが
保存されない
こんなコード書いてませんか
SharedPreferences pref =
PreferenceManager
.getDefaultSharedPreferences(this);

SharedPreferences.Editor edi...
CommitPrefEdits
• Summary: Missing commit() on
SharedPreference editor
• Priority: 6 / 10
• Severity: Warning
• Category: ...
何故いけないのか?
• SharedPreferencesにデータを保存する場合、
実際に保存されるタイミングはcommit()のと
き
• そりゃcommit()を呼んでなきゃ何も表示されません
こう書きましょう
SharedPreferences pref =
PreferenceManager
.getDefaultSharedPreferences(this);

SharedPreferences.Editor editor =...
おまけ: commit()とapply()
• SharedPreferencesはアプリ内領域のXMLを読
み書きすることでデータを永続化している

/data/data/[applicationId]/shared_prefs/hoge.x...
こう書くとなおよい
SharedPreferences pref =
PreferenceManager
.getDefaultSharedPreferences(this);

SharedPreferences.Editor editor ...
Case 4: Toastが出ない
こんなコード書いてませんか
Toast.makeText(
this,
“this line is passed”,
Toast.LENGTH_LONG)
なんでだ、絶対にこの行を通ってるはずなのに!
なんでトーストが出ないんだ!!!!
ShowToast
• Summary: Toast created but not shown
• Priority: 6 / 10
• Severity: Warning
• Category: Correctness
こう書きましょう
Toast.makeText(
this,
“this line is passed”,
Toast.LENGTH_LONG).show()
Case 5: なんかこのOKボタン
押しづらくない?
こんなコード書いてませんか
<LinearLayout

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:orientatio...
ButtonOrder
• Summary: Button order
• Priority: 8 / 10
• Severity: Warning
• Category: Usability
何故いけないのか?
• デザインガイドラインに書いてある

https://www.google.com/design/spec/components/dialogs.html#dialogs-specs
• 単にダイアログを閉じるだけの「キャ...
こう書きましょう
<LinearLayout

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:orientation="ho...
おまけ: 検出条件
1. targetSdkがAPI Level 14以上
• API Level 13まではOKが左で正しかった
2. ラベルが”OK”, “Cancel”, android.R.string.ok, android.R.st...
Case 6: このアプリ英語化して
こんなコード書いてませんか
<TextView

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="ユーザーを選択し...
HardcodedText
• Summary: Hardcoded text
• Priority: 5 / 10
• Severity: Warning
• Category: Internationalization
検出対象
• レイアウトXML(res/layout/)
• android:text
• android:contentDescription
• android:hint
• android:prompt
• AndroidManifest...
何故いけないのか?
• 文字列リソースに抜き出したほうが総合的に
メリットが多い
• Java側で言語情報を切り替えることもできな
くもないがかなり煩雑
• リソースファイルの自動切り替えに頼ったほ
うが遥かに楽
こう書きましょう
<TextView

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text=“@string/selec...
おまけ
• デモ
• クイックフィックス
• 言語コードごとにstrings.xmlを用意した場
合のAndroid Studioの挙動
事例紹介
Interlude: konifar/droidkaigi2016
./gradlew lint
app/build/outputs/lint-results.html
👍
事例紹介
part2. もっと上を目指す人のために
Case 7: アプリが管理していた個人情報が
別のアプリから奪われた!
こんなコード書いてませんか
<!—- AndroidManifest.xml —->
<provider

android:name=".provider.MyContentProvider"

android:authorities="inf...
ExportedContentProvider
• Summary: Content provider does not require
permission
• Priority: 5 / 10
• Severity: Warning
• C...
何故いけないのか?
• 実は<provider>にはexportedというパラメータがあ
り、デフォルトでtrue
• 外部のアプリからでも content://hogehoge のよう
なURIでデータにアクセスできてしまう
• Dropbo...
こう書きましょう
<!—- AndroidManifest.xml —->
<provider

android:name=".provider.MyContentProvider"

android:authorities=“info.nkz...
Case 8: これ、何を入力する欄?
こんなコード書いてませんか
<EditText

android:layout_width="match_parent"

android:layout_height="wrap_content" />



<EditText

androi...
TextFields
• Summary: Missing inputType or hint
• Priority: 5 / 10
• Severity: Warning
• Category: Usability
何故いけないのか?
• ユーザーはhintを見て何を入力する欄なのかを
判断するので、無いと不便
• inputTypeを指定すれば適切なキーボードが現
れることが多いので、キーボードを切り替え
る手間が省けて便利
こう書きましょう
<EditText

android:hint="メモを入力してください"
android:layout_width="match_parent"

android:layout_height="wrap_content" /...
Case 9: やっぱりアイコンは
カラフルじゃなきゃ
こんなアイコン作ったことありませんか
色がついててみづらい
色がついててみづらい
IconColors
• Summary: Icon colors do not follow the
recommended visual style
• Priority: 6 / 10
• Severity: Warning
• Cate...
何故いけないのか
• マテリアルデザインの登場などもあり、ステータスバーや
ActionBarの色はアプリごとに鮮やかに変わるようになった
• アイコンと同系色の背景になったときに見づらくなってしまう
• 通知アイコンは白、アクションアイコンは...
こうしましょう
おまけ
// com.android.tools.lint.checks.IconDetector.java
for (int y = 0,
height = image.getHeight();
y < height; y++) {

for...
Case 10: 文字は正しく使いましょう
こんなコード書いてませんか
<string name="continue_to_read">続きを読む...</string>
3点リーダ(…)の入れ方わかんないから
ピリオド3つでいいや
TypographyEllipsis
• Summary: Ellipsis string can be replaced with
ellipsis character
• Priority: 5 / 10
• Severity: Warni...
何故いけないのか
• フォントによってはピリオドが都合よく…と見えてく
れるかどうかはわからない
• ISO-8859-1で…は”…”として定義されてお
り、各フォントも…が3点リーダとして見やすくなる
ようにしてくれているはず
• 用意されて...
こう書きましょう
<string name=“continue_to_read”>続きを読む…</string>
<!—- または —->
<string name=“continue_to_read”>続きを読む…</string>
品質管理担当者の方へ:
品質指標として使ってみませんか
エンジニアの勝手な言い分
• Googleが「これやると良くないアプリになるよ」と言って
いるものを回避しているので、相対的にアプリの品質は上がっ
ていると言っていいのでは
• こんな重箱の隅を突くようなチェックを200項目以上も回避
するのは...
品質指標に使う場合
• 優先度が低いルールは事前に設定でignoreしておく(Bi-
directional Textカテゴリなど)
• 予算やスケジュールに応じて事前に「Fatal, Errorはすべ
て直す」「Warningは15件以内の検...
エンジニアの方へ:
abortOnErrorを切らないで
abortOnError,
checkReleaseBuilds
// build.gradle
android {
lintOptions {
abortOnError false
checkReleaseBuilds false
}
}
a...
趣味でやってたり
プロトタイプならともかく
お仕事でやるときに
falseにするのよくないと思います
本当に対応しないルールだけ
ignoreしましょう
droidkaigi2016/app/build.gradle
lintOptions {
abortOnError false
disable 'InvalidPackage'
}
😡
さいごに
• Android Studioがソースコードに黄色いのと
か赤いのとか付けてたら、マウスオーバーし
て何が起きてるか見てね!
• すべてのルールを倒したら胸を張ろう
• Android Lintと俺達の戦いはこれからだ!
ご清聴ありがとうございました
参考文献
• lint | Android Developers

http://developer.android.com/intl/ja/tools/help/lint.html
• Improving Your Code with lin...
Upcoming SlideShare
Loading in …5
×

AndroidLint #DroidKaigi

15,257 views

Published on

DroidKaigi2016で講演したAndroid Lintについての資料です

Published in: Technology
  • Be the first to comment

AndroidLint #DroidKaigi

  1. 1. Android Lintで正しさ を学ぼう 2015.02.18 DroidKaigi 2016 Yukiya Nakagawa / @Nkzn ROOM:B 13:00-13:50 #DroidKaigiB
  2. 2. Who are you? • Yukiya Nakagawa / @Nkzn • ウォーターセル株式会社@新潟 • 農業向けサービス「アグリノート」 • エンジニア募集中です • Androidは2009年からチマチマと
  3. 3. Recent Activity • C89コミケ • とびだそう!Androidプロ グラミングレシピ • https://techbooster.booth.pm/ • Android Lintネタ書いてました
  4. 4. Target • まだAndroidプログラミングのベストプラク ティスが分からない初学者 • Androidアプリの品質を表す指標がほしい
 品質担当者
  5. 5. Agenda • Android Lintとは • 初学者がやりがちなミス • もっと上を目指す人のために • 品質指標としてのAndroid Lintを考える
  6. 6. Android Lintとは
  7. 7. Lintとは Another HTML-lint HTMLの構文チェックツール JSLint, JSHint, ESLint JavaScriptの構文チェックツール textlint 日本語の構文チェックツール
  8. 8. lintとは、主にC言語のソースコードに対し、コンパイラより詳細かつ 厳密なチェックを行うプログラムである。 • 型の一致しない関数呼び出し • 初期化されていない変数の参照 • 宣言されているが使われていない変数 • 同じ関数を参照しているが、戻り値を使う場合と使わない場合がある • 関数が戻り値を返す場合と返さない場合がある など、コンパイラではチェックされないが、バグの原因になるような曖 昧な記述についても警告される。 https://ja.wikipedia.org/wiki/Lint
  9. 9. Javaの場合?
  10. 10. Android Lintとは • Google公式 • 222個のルール(ver25.0.4現在) • Category, Severity, Priorityで分類される • 結構手広い • 不具合予備軍の検出 • ユーザビリティチェック
  11. 11. Category カテゴリ名 チェックする内容 Correctness SDKの使い方の正しさ Correctness:Messages Correctnessのうち、特にメッセージ Security セキュリティ Performance パフォーマンス(動作速度) Usability ユーザビリティ(使い勝手) Usability:Icons Usabilityのうち、特にアイコン Usability:Typography Usabilityのうち、特に文字 Accessibility アクセシビリティ Internationalization 国際化・多言語化 Bi-directional Text Right-to-Leftモードでの見た目
  12. 12. Severity レベル 意味 アプリへの影響 Fatal 致命的 ビルドや実行に必ず失敗する Error エラー ビルドはできるが実行時エラー を引き起こす可能性が高い Warning 警告 動作はするが修正したほうが より良いアプリになる Information 情報 ほぼ問題ないが頭の片隅に 置いておいたほうがよい Ignore 無視 問題があったとしても 検出しない
  13. 13. チェックできるファイルの種類 • https://android.googlesource.com/platform/ tools/base • com.android.tools.lint.detector.api.Detector
 https://android.googlesource.com/platform/tools/base/+/master/lint/libs/ lint-api/src/main/java/com/android/tools/lint/detector/api/Detector.java
  14. 14. 1. Manifest file 2. Resource files, in alphabetical order by resource type 3. Java sources 4. Java classes 5. Gradle files 6. Generic files 7. Proguard files 8. Property files
  15. 15. Priority • 1から10まで • あまりあてにならない
  16. 16. どんな問題を解決するのか
  17. 17. お作法分かりづらい問題 https://twitter.com/konifar/status/698760224409169920
  18. 18. Android Way is どこ https://twitter.com/konifar/status/698760496837603328
  19. 19. Googleによる正解集 (あるいはアンチパターン集) Android Lint
  20. 20. 事例紹介 Part 1. 初学者がやりがちなミス
  21. 21. Case 1. LinearLayoutに並べたビューが 表示されないのは何故? (Orientation)
  22. 22. こんなコード書いてませんか <LinearLayout
 android:layout_width="match_parent"
 android:layout_height="match_parent">
 <TextView
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:text="one" />
 <TextView
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:text="two" />
 <TextView
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:text="three" />
 </LinearLayout>
 何故かアイテムがひとつしか出ない・・・?
  23. 23. Orientation • Summary: Missing explicit orientation • Priority: 2 / 10 • Severity: Error • Category: Correctness
  24. 24. 何故いけないのか? デフォルトのorientationはhorizontal
  25. 25. こう書きましょう <LinearLayout
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:orientation="vertical">
 <TextView
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:text="one" />
 <TextView
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:text="two" />
 <TextView
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:text="three" />
 </LinearLayout>
  26. 26. Case 2: Fragmentが表示されない
  27. 27. こんなコード書いてませんか @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_commit_transaction);
 
 getSupportFragmentManager().beginTransaction()
 .add(R.id.container, new MyFragment());
 } あれー? Fragmentが表示されないなー?
  28. 28. CommitTransaction • Summary: Missing commit() calls • Priority: 7 / 10 • Severity: Warning • Category: Correctness
  29. 29. 何故いけないのか? • beginTransaction()から始まるメソッドチェーンは、 commit()が呼び出されてから描画処理に入ります • そりゃcommit()を呼んでなきゃ何も表示されません • DBのトランザクションみたいなイメージ
  30. 30. こう書きましょう @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_commit_transaction);
 
 getSupportFragmentManager().beginTransaction()
 .add(R.id.container, new MyFragment()) .commit();
 }
  31. 31. Case 3. SharedPreferenceが 保存されない
  32. 32. こんなコード書いてませんか SharedPreferences pref = PreferenceManager .getDefaultSharedPreferences(this);
 SharedPreferences.Editor editor = pref.edit();
 editor.putLong("now", new Date().getTime()); pref.getLong("now", -1); // -1 SharedPreferencesに保存したはずの データが取れないなあ
  33. 33. CommitPrefEdits • Summary: Missing commit() on SharedPreference editor • Priority: 6 / 10 • Severity: Warning • Category: Correctness
  34. 34. 何故いけないのか? • SharedPreferencesにデータを保存する場合、 実際に保存されるタイミングはcommit()のと き • そりゃcommit()を呼んでなきゃ何も表示されません
  35. 35. こう書きましょう SharedPreferences pref = PreferenceManager .getDefaultSharedPreferences(this);
 SharedPreferences.Editor editor = pref.edit();
 editor.putLong("now", new Date().getTime()); editor.commit(); // consider using apply() instead pref.getLong("now", -1); // 1455620005841
  36. 36. おまけ: commit()とapply() • SharedPreferencesはアプリ内領域のXMLを読 み書きすることでデータを永続化している
 /data/data/[applicationId]/shared_prefs/hoge.xml Editor XML Memory Cache commit()は待つ apply()は待たない
  37. 37. こう書くとなおよい SharedPreferences pref = PreferenceManager .getDefaultSharedPreferences(this);
 SharedPreferences.Editor editor = pref.edit();
 editor.putLong("now", new Date().getTime()); editor.apply(); // OR // if(editor.commit()) { // pref.getLong(“now”, -1); // 1455620005841 // }
  38. 38. Case 4: Toastが出ない
  39. 39. こんなコード書いてませんか Toast.makeText( this, “this line is passed”, Toast.LENGTH_LONG) なんでだ、絶対にこの行を通ってるはずなのに! なんでトーストが出ないんだ!!!!
  40. 40. ShowToast • Summary: Toast created but not shown • Priority: 6 / 10 • Severity: Warning • Category: Correctness
  41. 41. こう書きましょう Toast.makeText( this, “this line is passed”, Toast.LENGTH_LONG).show()
  42. 42. Case 5: なんかこのOKボタン 押しづらくない?
  43. 43. こんなコード書いてませんか <LinearLayout
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:orientation="horizontal">
 <Button
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:text="@android:string/ok" />
 <Button
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:text="@android:string/cancel" />
 </LinearLayout>
  44. 44. ButtonOrder • Summary: Button order • Priority: 8 / 10 • Severity: Warning • Category: Usability
  45. 45. 何故いけないのか? • デザインガイドラインに書いてある
 https://www.google.com/design/spec/components/dialogs.html#dialogs-specs • 単にダイアログを閉じるだけの「キャンセル」のよう なものは左、本来やりたかった操作を続ける「OK」 のようなものは右に置く • 「削除」はネガティブなイメージなので左に置いてし まいがちだけど右
  46. 46. こう書きましょう <LinearLayout
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:orientation="horizontal">
 <Button
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:text="@android:string/cancel" />
 <Button
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:text="@android:string/ok" />
 </LinearLayout>
  47. 47. おまけ: 検出条件 1. targetSdkがAPI Level 14以上 • API Level 13まではOKが左で正しかった 2. ラベルが”OK”, “Cancel”, android.R.string.ok, android.R.string.cancelのいずれか 3. 親レイアウトの設定上、並びが明らか • LinearLayoutかTableRowで、orientationがhorizontal • RelativeLayoutで、toRightOf, toLeftOfの関係で順序が分かる • RelativeLayoutで、alignParentLeft, alignParentRightの関係で順序が分かる
  48. 48. Case 6: このアプリ英語化して
  49. 49. こんなコード書いてませんか <TextView
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:text="ユーザーを選択してください" />
 
 <ImageView
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:contentDescription="犬のアイコン"
 android:src=“@drawable/ic_dog” />
 
 <EditText
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:hint="入力してください" /> 日本語が表示されるところを全部探して 英語に書き直す・・・? 1日じゃ無理だよ!
  50. 50. HardcodedText • Summary: Hardcoded text • Priority: 5 / 10 • Severity: Warning • Category: Internationalization
  51. 51. 検出対象 • レイアウトXML(res/layout/) • android:text • android:contentDescription • android:hint • android:prompt • AndroidManifest.xml • android:label • メニューXML(res/menu/) • android:title
  52. 52. 何故いけないのか? • 文字列リソースに抜き出したほうが総合的に メリットが多い • Java側で言語情報を切り替えることもできな くもないがかなり煩雑 • リソースファイルの自動切り替えに頼ったほ うが遥かに楽
  53. 53. こう書きましょう <TextView
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:text=“@string/select_a_user“ />
 
 <ImageView
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:contentDescription=“@string/dog_icon“
 android:src=“@drawable/ic_dog” />
 
 <EditText
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:hint=“@string/input_please“ />
  54. 54. おまけ • デモ • クイックフィックス • 言語コードごとにstrings.xmlを用意した場 合のAndroid Studioの挙動
  55. 55. 事例紹介 Interlude: konifar/droidkaigi2016
  56. 56. ./gradlew lint app/build/outputs/lint-results.html
  57. 57. 👍
  58. 58. 事例紹介 part2. もっと上を目指す人のために
  59. 59. Case 7: アプリが管理していた個人情報が 別のアプリから奪われた!
  60. 60. こんなコード書いてませんか <!—- AndroidManifest.xml —-> <provider
 android:name=".provider.MyContentProvider"
 android:authorities="info.nkzn.mycontentprovider" /> ContentProviderを使うときはマニフェストに 書くんだろ? そんなこと知ってるよ!
  61. 61. ExportedContentProvider • Summary: Content provider does not require permission • Priority: 5 / 10 • Severity: Warning • Category: Security
  62. 62. 何故いけないのか? • 実は<provider>にはexportedというパラメータがあ り、デフォルトでtrue • 外部のアプリからでも content://hogehoge のよう なURIでデータにアクセスできてしまう • Dropboxが2011年にやらかしてた
 http://codezine.jp/article/detail/6286
  63. 63. こう書きましょう <!—- AndroidManifest.xml —-> <provider
 android:name=".provider.MyContentProvider"
 android:authorities=“info.nkzn.mycontentprovider" android:exported=“false" /> ※ minSdkVersion, targetSdkVersionが   両方とも17以上なら、デフォルトでfalseになります   http://developer.android.com/intl/ja/guide/topics/manifest/provider-element.html
  64. 64. Case 8: これ、何を入力する欄?
  65. 65. こんなコード書いてませんか <EditText
 android:layout_width="match_parent"
 android:layout_height="wrap_content" />
 
 <EditText
 android:id=“@+id/phone_number" android:hint=“電話番号を入力してください" android:layout_width="match_parent"
 android:layout_height="wrap_content" />
 
 <EditText
 android:id="@+id/pin"
 android:hint=“PINコードを入力してください" android:layout_width="match_parent"
 android:layout_height="wrap_content" />
 
 <EditText
 android:id="@+id/site_url"
 android:hint=“サイトのURLを入力してください" android:layout_width="match_parent"
 android:layout_height="wrap_content" /> 電話番号を入れたいのに日本語キーボードが 出てきて切り替えるの面倒くさい・・・ 何入れたらいいのか わからない・・・
  66. 66. TextFields • Summary: Missing inputType or hint • Priority: 5 / 10 • Severity: Warning • Category: Usability
  67. 67. 何故いけないのか? • ユーザーはhintを見て何を入力する欄なのかを 判断するので、無いと不便 • inputTypeを指定すれば適切なキーボードが現 れることが多いので、キーボードを切り替え る手間が省けて便利
  68. 68. こう書きましょう <EditText
 android:hint="メモを入力してください" android:layout_width="match_parent"
 android:layout_height="wrap_content" />
 
 <EditText
 android:id=“@+id/phone_number" android:hint=“電話番号を入力してください” android:inputType=“phone” android:layout_width="match_parent"
 android:layout_height="wrap_content" />
 
 <EditText
 android:id="@+id/pin"
 android:hint=“PINコードを入力してください” android:inputType="numberPassword"
 android:layout_width="match_parent"
 android:layout_height="wrap_content" />
 
 <EditText
 android:id="@+id/site_url"
 android:hint=“サイトのURLを入力してください” android:inputType="textUri" android:layout_width="match_parent"
 android:layout_height="wrap_content" />
  69. 69. Case 9: やっぱりアイコンは カラフルじゃなきゃ
  70. 70. こんなアイコン作ったことありませんか 色がついててみづらい 色がついててみづらい
  71. 71. IconColors • Summary: Icon colors do not follow the recommended visual style • Priority: 6 / 10 • Severity: Warning • Category: Usability:Icons
  72. 72. 何故いけないのか • マテリアルデザインの登場などもあり、ステータスバーや ActionBarの色はアプリごとに鮮やかに変わるようになった • アイコンと同系色の背景になったときに見づらくなってしまう • 通知アイコンは白、アクションアイコンはグレーにしておけば、 なんとなく大体の色に合う • というような話が developer.android.com/design に載っていた ような気がするのだけれど、www.google.com/design に移った ときにその辺の話がなくなってしまった気がする
  73. 73. こうしましょう
  74. 74. おまけ // com.android.tools.lint.checks.IconDetector.java for (int y = 0, height = image.getHeight(); y < height; y++) {
 for (int x = 0, width = image.getWidth(); x < width; x++) {
 int rgb = image.getRGB(x, y);
 if ((rgb & 0xFF000000) != 0) {
 int r = (rgb & 0xFF0000) >>> 16;
 int g = (rgb & 0x00FF00) >>> 8;
 int b = (rgb & 0x0000FF);
 if (r != g || r != b) { 1pxずつ色を評価していて執念を感じた
  75. 75. Case 10: 文字は正しく使いましょう
  76. 76. こんなコード書いてませんか <string name="continue_to_read">続きを読む...</string> 3点リーダ(…)の入れ方わかんないから ピリオド3つでいいや
  77. 77. TypographyEllipsis • Summary: Ellipsis string can be replaced with ellipsis character • Priority: 5 / 10 • Severity: Warning • Category: Usability:Typography
  78. 78. 何故いけないのか • フォントによってはピリオドが都合よく…と見えてく れるかどうかはわからない • ISO-8859-1で…は”…”として定義されてお り、各フォントも…が3点リーダとして見やすくなる ようにしてくれているはず • 用意されている文字はちゃんと使おうというスタンス
  79. 79. こう書きましょう <string name=“continue_to_read”>続きを読む…</string> <!—- または —-> <string name=“continue_to_read”>続きを読む…</string>
  80. 80. 品質管理担当者の方へ: 品質指標として使ってみませんか
  81. 81. エンジニアの勝手な言い分 • Googleが「これやると良くないアプリになるよ」と言って いるものを回避しているので、相対的にアプリの品質は上がっ ていると言っていいのでは • こんな重箱の隅を突くようなチェックを200項目以上も回避 するのはそれなりの経験値がないと難しい • 正しくAndroid SDKを使えるように気を使いながら開発でき ているという点は、品質上の成果として計上して、取引先や 経営層が評価してもらえると嬉しい
  82. 82. 品質指標に使う場合 • 優先度が低いルールは事前に設定でignoreしておく(Bi- directional Textカテゴリなど) • 予算やスケジュールに応じて事前に「Fatal, Errorはすべ て直す」「Warningは15件以内の検出」などの品質目標 を定めておく • カテゴリ単位での採用・不採用を各プロジェクトごとに 定めるのもよいと思います
  83. 83. エンジニアの方へ: abortOnErrorを切らないで
  84. 84. abortOnError, checkReleaseBuilds // build.gradle android { lintOptions { abortOnError false checkReleaseBuilds false } } abortOnError: 危険度がErrorまたはFatalのルールに抵触したらビルドを中断する checkReleaseBuilds: リリースビルド時にFatalのルールに抵触したらビルドを中断する
  85. 85. 趣味でやってたり プロトタイプならともかく お仕事でやるときに falseにするのよくないと思います 本当に対応しないルールだけ ignoreしましょう
  86. 86. droidkaigi2016/app/build.gradle lintOptions { abortOnError false disable 'InvalidPackage' } 😡
  87. 87. さいごに • Android Studioがソースコードに黄色いのと か赤いのとか付けてたら、マウスオーバーし て何が起きてるか見てね! • すべてのルールを倒したら胸を張ろう • Android Lintと俺達の戦いはこれからだ!
  88. 88. ご清聴ありがとうございました
  89. 89. 参考文献 • lint | Android Developers
 http://developer.android.com/intl/ja/tools/help/lint.html • Improving Your Code with lint | Android Developers
 http://developer.android.com/intl/ja/tools/debugging/improving-w-lint.html • Android Lint - Android Tools Project Site
 http://tools.android.com/tips/lint • Writing a Lint Check - Android Tools Project Site
 http://tools.android.com/tips/lint/writing-a-lint-check • platform_tools_base
 https://android.googlesource.com/platform/tools/base • LintOptions - Android Plugin 1.5.0 DSL Reference
 http://google.github.io/android-gradle-dsl/current/ com.android.build.gradle.internal.dsl.LintOptions.html

×