Skip to content

Instantly share code, notes, and snippets.

@kikuchy
Created April 25, 2015 09:03
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kikuchy/ee9a3fa5b82b2f79dac0 to your computer and use it in GitHub Desktop.
Save kikuchy/ee9a3fa5b82b2f79dac0 to your computer and use it in GitHub Desktop.
2015/4/25のDroidKaigiメモ

マッチョなActivityにさよならする

http://www.slideshare.net/yanzm/droid-kaigi2015-yanzm?ref=http://www.slideshare.net/yanzm/slideshelf

Activityに書いていたものをどこに移すか?

  • Fragment
  • CustomView

まずは特徴を知ろう。

役割

どれも、独自レイアウトとロジックを持てるもの。

Activity

"シングルなユーザーができることにフォーカスしたもの"

CustomView、Fragmentでできないこと全部。

Fragemnt

"Activityのインターフェイスと振る舞いをおきかえるもの"

どちらかといえばActivity寄り。

ネットワーク、画面回転しても保持したいこと。

CustomView

描画を受け持つもの。

描画、バリデーション。

CustomViewのパターン

  • 既存View組み合わせたGroupView
  • 独自ルールで配置されるGroupView
  • 独自計算でサイズが決まるView
  • 独自の見た目のView

できることできないこと

Activityはだいたい何でもできる。 一番の特徴は、他の画面から呼び出せること。入り口を分けたかったらActivityを分けるしかない。 Orientationの指定できる。 Fragmentを子に持てるのはActivityだけ。 ただ、一画面に複数おくことはできない。

Fragemntは画面回転の前後でインスタンスが保持してくれる。

画面に描画を行えるのはCustomViewのみ。 CustomView以外はテストがしづらい。

マッチョにさよならしてみる

実演

改修前 https://gist.github.com/yanzm/1d2fa37e2375cf4dee6f

  • ViewのマニピュレーションはActivityに書かない。Viewにやらせる。
  • 入力中の値の保持だとかはViewにやらせる。View.BaseSavedStateとかある
  • CustomViewに独自のデータクラスを作って持たせるとget/setが楽
  • ネットワーク処理やファイル処理、Preference処理は別クラスにやらせる

改修後 https://gist.github.com/yanzm/d0a759300cfa1356c0b5

Fragmentの注意点

  • コンストラクタ
  • 引数付きコンストラクタは使わない。(ドキュメントに書いてる)
  • 引数なしのコンストラクタはpublicに
  • 初期値設定はgetArguments()/getArguments()使う
  • ActivityへのコールバックはonAttach()で
  • FragmentのBackStackは難しい
  • むやみに使うと危険
  • FragemtnからstartActivityしないほうがいいハマる。
  • Fragment in Fragment
  • FinFでLoaderは使わない
  • childFragementでstartActivityForResultは使わない。なぜかparentFragmentの方に値が帰ってくる

開発を効率的に進めるまでの道のり

各所に潜むボトルネック

  • ソースコード書くの大変→ライブラリ使うとかいいIDE使うとか
  • 管理大変→git使えば
  • テスト→JUnitあるでしょあと自動化
  • テスト版配布→Deploygate使いましょう

開発してるとよくある話

「バグゼロでお願いします」 いやむりっしょ。エクセルでてんこ盛りのチェック表、エビデンスという名のスクショ・・・

小さなリファクタしてもやっぱり壊すことがある。

テストを書きましょう。 最初はテストをかく。 要件表の一番上からテストに落として行く。 そこから始められればいいのだが・・・

途中からテストを導入する

アプローチ。

  • アプリの外部に依存する部分にDIを入れる。
  • グローバル変数を取る。
  • シングルトンという名のグローバル変数も取る。
  • 投げっぱなしスレッドを止める。
  • 最小限のリファクタリング
  • ひたすらテストを書く

どうやって外部文を差し替えるか。

  • DaggerとかのDIを使う。

SharedPreferenceの差し替え

Factoryクラス(シングルトン)をかます。 テスト時はFactoryを差し替える。

SQLiteOpenHelperの差し替え

通信処理の差し替え

便利クラスに通信処理を固める。 テスト時はDIで偽の通信処理に差し替える。 偽の通信データは、AndroidTestのassetに入れると便利。

ひたすらテストを書く

  • ブラックボックステスト
  • コンバージョンにつながる部分は重点的に書く
  • テストの粒度はマチマチでもいい(やりすぎない程度で)

具体例

使うもの

  • JUnit4
  • 実機テスト
  • Espresso
  • Clashliitics
  • Mockito

標準で用意されているもので十分強力。

絶対に落ちないアプリ

そんなものはない。

なぜAndroidアプリは落ちるのか

  • バージョンが多様
  • ベンダによる謎カスタマイズ
  • カメラアプリは鬼門
  • プログラマーの無知や怠慢←ここは乗り越えよう!!!!!

Crashliticsで実際にクラッシュが多いランキング

まずはバグに向き合うこと。 マナボでは、毎週月曜にCrashlitics

  1. FragmentTrasactionの取扱ミス
  2. 死んでるコントローラへのアクセス
  3. API連携ミス
  4. とか

ライフサイクルの理解

本当にライフサイクルを理解しているのか、と疑うようなコードをプロも書く。

初心者編

開発者向けオプション「アクティビティを保持しない」をオンにすること!!!

これで、onSaveStateとかちゃんと使うコードがかけるよ!

非同期処理

非同期処理は寿命が大事。

投げっぱなしにしたAsyncTaskとか、Activityより長生きする。 もともと少なくとも2~3秒で終わる処理のためのクラス。 画面回転で結果を引き継げない。画面回転するとActivityはonDestroyを迎えてしまうが、AsyncTaskがインスタンスを握っているのでGCされない。典型的なメモリリークの例。 AsyncTask継承クラスをstaticクラスにする、弱参照でActivityを掴んでおく、細かくキャンセルされているかを確認する、とかすればだいぶマシになる。

Loaderを使うという手もある。こいつは回転をしても生き残る。

ただLoaderよりEventBusの方が使われる。 オブザーバーパターンのクラスで、使い方によっては便利。(LoaderはManagerとActivityの1対1対応のためのもの)

Contextってなんぞや

大きく分けて、ActivityContextとApplicationContextがある。

だいたいのケースでApplicationContextが使える。

Fragment

引数なしコンストラクタを使うこと。メモリ足りなくなった時はBundleにシリアライズされ、復帰時はBundelからリフレクションで展開される。

初学者に優しいAndroid開発環境

環境・ライブラリ

  • AndroidStudio。特に何も設定しなくてもIDEがいろいろ教えてくれる

  • 困ったらShiftキー2回押し。

  • Genymotion

  • AndroidStudio用プラギンも合わせて

  • Butter Kinfe

  • フィールドとIDの対応付けや、Viewのイベント取得が簡単になる。

  • これもプラギンがあって、自動的にアノテーション付けてくれる。

  • コードがし視覚的に分かりやすくなる

  • 他にはAndroidAnnotationsというのがあるが、いろいろできすぎるので、初心者には向かないかも

  • EventBus

  • 任意のインスタンスに任意の通知を飛ばせる

  • データ詰め込める、スレッドも飛び越える

  • 受信側が死んでてもアプリが落ちない

  • Retorofit, OkHttp, Gson

  • WebのAPIを叩いて結果を受け取るときにつかえる。

  • 画像の読み込みにはpicassoが使える。

  • ORMはActiveAndroid、Realmがおすすめ

MVC

AndroidにはMVCという考え方がない。 とりあえずMVCをAndroidに取り入れる説明。

  • Model ふつうのJavaクラス
  • Controller Fragment(or Activity)
  • View レイアウトXMLだったりViewクラスだったり

Model -> ViewはEventBusで通信する

Model

データの保持とデータの操作メソッド。

データはControllerからこちらに追い出す。 エベント取得やViewの操作はしない。

複数の画面で使い回すものとかは、長寿のモデルに。 長寿モデルはシングルトンにしておく。

データ構造を表現するEntityは別に用意しておく。 EntityはModelで扱うListの中で使ったりする。

Model <-> View

まずはFragmentはModelからのEventを購読する。何か飛んできたら何も考えずに画面更新するメソッド叩く。 Modelはデータが更新されたらすぐEventBusのイベントを飛ばす。

View

イベントは全部Controllerになげる。Viewに処理はさせない。

Activity

以前はIntentでActivityを切り替えていくものだったが、今はアプリケーションにActivityは一つ。その中でFragmentを切り替えていく。

Fragmentが太り出したら、サブコントローラーに切り出す。 普通のjavaクラスにonStartとかonResumeとかメソッドを作っておいて、Fragmentから叩かせる。

学習リソース

書籍

  • AndroidエンジニアのためのモダンJava
  • Effective Java

参考ソース

  • AndtroidStudioのプロジェクト雛形
  • 同じく自動生成されたFragment
  • Googleさんのサンプル

学び方

  • mixiのTrainingは最初は難しいので後回し
  • 通信やSQLまわりはライブラリ使う前提で
  • 端末の向きは固定で
  • タブレットの2ペインレイアウトは最初はやらない

ナレッジ共有

okano shinobuさん

http://www.slideshare.net/shinobuokano7/android-47395733 https://github.com/operando/DroidKaigi

最初期

今は本読まなくて良い。ドキュメントが沢山ある。 最初はクソコードを書きまくって、読みまくることが大切。 OSSのアプリのソースを読みまくると良い。 WordpressのAndroidアプリとか良い。

デベロッパーになる

技術的判断が求められる立場。 そのための材料が必要。

バージョンごとの機能を理解する。 Google Play Service使う。 最新情報をキャッチアップ。

デザインを、どんなViewをつかって実装するか決める必要が有る。 とりあえずいろんなアプリをみるために、TRENDINGカテゴリのアプリを手当たり次第落として見てる。 Wishlist便利。危なそうなアプリはエミュレーターで試す。

フレームワーク

ちょっと頭のおかしいリージョン。 技術的負債の塊だったり。

Androidソースコード検索サービスを使う。 AndroidXRef。 Firefox + Tree型タブで、メソッドの呼び出しを分かりやすく読める。

ログ大事。 logcatでログ出しまくる。 mainとsystemだけでなく、eventsとかradioあたりも見てみると良い。 adbコマンド大事。

# 入力が楽になったりするよ!
adb shell input text hogehoge@example.com

とりあえず気になるところから読んだ方が良い。

メルカリ登録コード pHe625

メルカリのナレッジ

いいアプリを作るために

常に自分たちのアプリを疑う。 アプリの改善にひつような考え。

三種の神器

  • Github
  • DeployGate
  • Slack

Cheklist

プルリクのチェックリスト。 実装に対して、チェックの範囲の認識を共有するために設けている。

PullRequestくれたら改善します!!!

Testing

最初はメルカリにもテストコードがない。

ロジックのテストからやり始めた。 一番大切なのはテストする文化。

進化するART

@kmt_t

概要

Android RunTimeの略。 KitkatまではDalvikだった。LolipopからARTになる。

Dalvikから完全書き換え。 CからC++11になってる。 JITコンパイラからAOTコンパイラになった。(インストール時にコンパイルするようになってる) ガベージコレクションが改善された。 64bitCPU対応。

実行ファイル

OATとdexの二つ。

OATファイルは、AOTコンパイラが吐き出す機械語のファイル。 DEXはOATに埋め込まれる。メタデータなんかはそのままdexから使われる。

OATファイル

ELF形式で書かれている。OATは共有ライブラリ。 リンカとローダはLinuxのものを使わずに独自のものが使われている。

ELFの概要

共有ライブラリではセクションが重要

OATをobjdumpする

だいたいLinuxのセクションと同じだが、ART独自のデータが含まれていたり、ART独自のセクションがあったりする。

.rodataセクション

DEXファイルとガイド情報

.oat_patchesセクション

イメージファイルの再配置情報

イメージファイルはランダムにメモリに配置される。 このランダマイズはわざと行われている。多分セキュリティ対策。

ARTのコンパイラ

Quickコンパイラ以外のコンパイラが消えた。

Quickコンパイラ

DalvikのJITコンパイラベースのコンパイラ

利点

JITコンパイラより早い。 時間のかかる最適化が可能。

ART固有の最適化が可能。LLVMを使っていないので、LLVMで最適化できない部分がどうにかできてる。

Bitmatpは強くない

wasabeefさん

どう考えてもBitmapは怖い OutOfMemoryErrorェ…

Bitmapとは

画像扱うAPI。 Factoryでオブジェクト生成。

4.0+ならwebp画像も使える。

BitmapFactory.Option

  • inJustDecodeBounds 画像のサイズだけ先に取得するときなど
  • inSizeSample BitmapにFilterをかけるときにとても有効。
  • inPreferredConfig 読み込むフォーマット

Bitmap.Config

  • ARGB_8888
  • ARGB_4444 API13以降でdeplecated
  • RGB_545 AlphaがないRGB。Alphaがない画像に使えばメモリを節約できる
  • ALPHA_8 アルファ値のみとるときにつかったり。シャドーとして使いたいときとか。

最近はOSSライブラリ使うことが多い

Picasso

Square謹製ライブラリ。

TransformationとかCachingとかLoaderもセット。べんり。 .fit() とかのメソッドを使うと、ビューのサイズでBitmapを作ってくれるのでメモリが節約できる。

生Bitmapを取り出すことができる。

Glide

アニメGifやビデオも扱える。 サムネイルという機能で表示の体感速度が速くなってよい。

生Bitmapを取り出すときにサイズ指定が必要なのでそこは面倒。

BitmatShader

ブラーかけるのに便利。

GPUImage for Android

GPUで画像処理させるライブラリ。 CAがホストしてる。

Fresco

XMLでトランスフォームの指定とかかける。 ただ、widthとheightの値を自分で指定しないといけない。warp_contentとかできない。

最後の手段

android:largeHeap="true"

使えるGradleプロジェクト

http://www.slideshare.net/MakotoYamazaki/20150425-droidkaigi-gradle zaki50さん

Gradleとは

汎用ビルドツール。 依存管理、マルチプロジェクトサポート。

2年くらい前からAndroidはGradleでのビルドを前提としたプロジェクトになった。

知っておきたいセキュリティ事項

谷口岳さん TaoRiskFinderとか作ってる。

資料 http://www.taosoftware.co.jp/blog/2015/04/cf5c5d90.html

セキュリティホールがあるアプリを作らないためにはどうしたらいいのか。

セキュリティの学習方法

日本語で読めるのは2冊だけ。

  • AndroidSecurity
  • Androidアプリのセキュア設計・セキュアコーディングガイド(PDF、無料)

IPAが出してるAnCoLeも良い。 自習用アプリケーション、EclipseプラギンなのでMacでも動く。

https://www.ipa.go.jp/security/vuln/ancole/

最低限知っておきたいこと

ファイルアクセス制限の不備

自分のアプリデータが他のアプリから見えてしまう。

コンポーネントアクセス制限不備

Activityの乗っ取りが生じる可能性がある。

ConponentProviderのアクセス制限設定、昔のAndroidではデフォルトで公開になっていた。

コンポーネントは外部非公開にすること export = false

SSL通信の実装不備

テスト時にオレオレ証明書使うことは多い。 オレオレ証明書だとSSL使用時に例外が出るので、それを無視するコードにしておいて、本番になっても直すの忘れてたりして脆弱性を生むことがある。

不必要なパーミッションの取得

マルウェアと間違えられたりする。 外部ライブラリが悪さして、勝手に電話帳取り出したりすることがあるかも。 不必要なパーミッションは与えない。

ライブラリに注意

ライセンス観戦

GPL汚染とかのこと。

自分で公開するときはライセンスを明らかにしておきましょう。

ライブラリのセキュリティホール

この前のAFNetworksとか。 ちょっと前だとOpenSSLとか。 第三者モジュールの脆弱性は、そのままアプリケーションの脆弱性になる。

マルウェア感染

広告モジュールとかの中でも悪質なものは、勝手に電話帳を参照したりしてるものがある。 電話帳と、ならくても電話番号やANDORID_IDとかを送信していることは多い。 海外の広告モジュールは特に注意。

プライバシーの問題

ライブラリがどんなデータを取っているのか、ドキュメント化されてないことが多い。 プライバシーポリシー描きづらい。

プライバシーポリシー

何の個人情報を取得しているのか、きちんとドキュメント化しておくのが良い。

総務省の指針

  1. プライバシーポリシードキュメントの作成
  2. 重要なデータ取得時はユーザーに許可を求める

ただし、インストール時に出す権限を求めるダイアログはユーザーの同意取得のためのダイアログではないので注意。

法律云々よりも、自分の親や子供が安心して使えるということを考えると良い。

データ同期プラクティス

Nkznさん

http://www.slideshare.net/Nkzn/ss-47398311

ユーザーはどんな場所にいる?

通信網も何もない時にも使えるようにするには? Gmailでも使われているような同期の仕組みはSDKにあるのだが。

例:アグリノート

マスターテーブルとユーザーテーブルがあるタイプのアプリ。

SyncAdapter というのがAPI lv5から入っている。

ボイラープレートがめんどくさいが、お手本があればなんとかなるレベル。

有名になったのはGoogle I/O 2013あたり。でも出てたのは2009年。

SyncAdapterの使い方は、mixiのAndroidTrainingみればわかる。

参考にした資料

Full Sync, Incremental Sync

  • Full Sync…依存関係だとかは保証できる。ネットワーク負荷は重くなる
  • Incremental Sync…クライアントが持っているデータ量をサーバに申告し、足りない分だけ送ってもらう

差分の請求は、最終同期時刻を覚えておいて、DBのmodified_atを見てデータを取り出すとかする。

Darty Flag

4つのステータス

  • CLEAN サーバから受け取ったまま
  • ADD サーバにないデータ
  • MOD サーバから受け取ったものを変更した
  • DELETE サーバにあるものを消した

流れ

  1. とりあえずデータ取ってくる
  2. サーバで削除されていたらクライアントでも削除
  3. サーバで更新されていたものもクライアントで更新
  4. ADD, MOD, DELETEされたデータをサーバに飛ばす
  5. フラグをCLEANにし、最終同期時刻を記録

競合問題

サーバーとクライアントでデータが食い違った場合。

とりうる対応策

  1. 常にサーバが勝つ
  2. 常にクライアントが勝つ(アグリノートはこれ)
  3. クライアント側でマージしてからサーバに送る(Evernoteはこれ)

同期パターンの確認

開発時は表を作って、開発者同士ですり合わせをした。

Fire side talk

HogeBaseActivityとかって作る派ですか?

  • 作りたくないけどライフサイクル絡むと誘惑に負ける
  • 5段階extends見たら使いたくなくなった
  • 人によって「使っていい人」「使っちゃいけない人」でわける
  • 規約で縛れればOK
  • is-a関係ができる場合のみ。昨日の共通化が目的ならdelegateするのが良い。

ApplicatonからLifecycle callback使ったことある人いる?

あんまりいない

Support Libraryに入れて欲しい機能とかありますか?

  • マテリアルデザインのAlertDialogつらいので入れて
  • PreferenceActivityとPreferenceFragment(似た者同士)が併用できないのどうにかして
  • マテリアルデザイン系だと、PolymerにはあるけどSupport Libraryにないのがあったりするので、入れてもらえると嬉しい。
  • リリース予定がわかるだけで心が安らかになるとおもう

DroidKaigiの開発秘話

ひだかさんのABCのアプリを引っ張ってきて、三日くらいで作られた。

Deploygateでみんなで配信。 PR出しまくり。

アプリ出したかったのは、アンケートに答えやすくしたかったから。 QRコードとったり、短縮URL打つのはだるい。

Android界隈のIoTについて

AndroidのBTLEは闇。 Wearはけっこうみんな持ってる。

Android対応バージョン、いくつ以上にしてる?

  • リニューアルの際に4.0以上にした
  • 2.3はそろそろ切りたい
  • ICS以上がいいなぁ
  • 新規で作るなら、API13 (4.0.3)以上
  • 2.3問題は大きい。アップデートで切るのは経営判断なのでつらい

(おちばひろい)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment