Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
大きい画像をたくさんアップロードするために
Search
Yoshihiro WADA
December 11, 2018
Programming
1
510
大きい画像をたくさんアップロードするために
2018/12/11に開催されたOtemachi.apk #1にて発表した「大きい画像をたくさんアップロードするために」のスライドです。
Yoshihiro WADA
December 11, 2018
Tweet
Share
More Decks by Yoshihiro WADA
See All by Yoshihiro WADA
AndroidデバイスにFTPサーバを建立する
e10dokup
0
330
Gradleの実行環境設定を見直す
e10dokup
0
930
Firebase App Distributionのテストアプリ配信を試しやすくする
e10dokup
0
600
アプリに署名する 〜GitHub ActionsでのCIも見据えて〜
e10dokup
0
1.2k
Profileable buildでより正確なパフォーマンスを掴む
e10dokup
0
730
[DroidKaigi 2021] メディアアクセス古今東西 / Now and Future of Media Access
e10dokup
0
3.6k
今更「dp」を考える / Let's think about "dp" now
e10dokup
0
5.6k
1から学ぶAndroidアプリデバッグ - アプリの動作を追いかけよう / Learn Android application debugging from the scratch - track apps' behaviors
e10dokup
10
3.2k
Guide to background processingを読んでみる / Reading "Guide to background processing"
e10dokup
0
260
Other Decks in Programming
See All in Programming
Enterprise Web App. Development (1): Build Tool Training Ver. 5
knakagawa
1
120
UMAPをざっくりと理解 / Overview of UMAP
kaityo256
PRO
3
1.4k
Lambda(Python)の リファクタリングが好きなんです
komakichi
4
240
The Nature of Complexity in John Ousterhout’s Philosophy of Software Design
philipschwarz
PRO
0
160
AI時代の開発者評価について
ayumuu
0
230
Ruby's Line Breaks
yui_knk
4
2.8k
読書シェア会 vol.4 『ダイナミックリチーミング 第2版』
kotaro666
0
110
Empowering Developers with HTML-Aware ERB Tooling @ RubyKaigi 2025, Matsuyama, Ehime
marcoroth
2
950
The Evolution of the CRuby Build System
kateinoigakukun
1
760
Jakarta EE Meets AI
ivargrimstad
0
780
Browser and UI #2 HTML/ARIA
ken7253
2
170
The New Developer Workflow: How AI Transforms Ideas into Code
danielsogl
0
100
Featured
See All Featured
Building an army of robots
kneath
305
45k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
667
120k
The MySQL Ecosystem @ GitHub 2015
samlambert
251
12k
The Pragmatic Product Professional
lauravandoore
33
6.6k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
34
2.2k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
507
140k
Art, The Web, and Tiny UX
lynnandtonic
298
20k
Reflections from 52 weeks, 52 projects
jeffersonlam
349
20k
The World Runs on Bad Software
bkeepers
PRO
68
11k
How To Stay Up To Date on Web Technology
chriscoyier
790
250k
How to train your dragon (web standard)
notwaldorf
91
6k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
47
2.7k
Transcript
大きい画像をたくさんアップロードするために Cyber Agent Inc. Yoshihiro Wada a.k.a. @e10dokup 2018/12/11 Otemachi.apk
自己紹介 • Yoshihiro Wada a.k.a. @e10dokup • 大体左のアイコンで息をしています • CyberAgant
Inc. / Ameba • Amebaブログやってます • We’re Hiring • カメラ沼 • 財布の透過率が高いのが最近の悩み
今回のお話 • 大きい画像をいっぱいアップロードしたい • スマホで撮った写真とか • デジタルカメラやFlashAirからWi-Fiで持ってきた写真とか • 別に画像に限った話ではない •
立ちはだかる壁 • 通信量 • モバイルネットワークでやると無限にギガが減る • メモリ • 展開の仕方によってはOOMでドゥンとクラッシュしてしまう
普通に考えると… • そもそも大きい画像を扱わないようにする • スマートフォンの小さい画面に2000万画素オーバーの大きさのサイズはオーバースペック • 500万画素くらいの大きさならまだわかるレベルになる • 「Android 画像
リサイズ」で検索すると出てくるようなお話 • UI上に扱う画像を表示する際はもちろんリサイズは大事 • 今回本当にやりたいこと • UI上の表示ではなく、Google Photosのようなアルバムサービスへのアップロード • できるなら撮影した画質そのままで扱いたい • 圧縮しようのないデータのアップロード
というわけでやっていきましょう
まず一連の流れを把握 • 扱う画像・ファイルを取得する • ストレージだったり、FlashAirだったり、LAN内のNASだったり… • この時点で端末メモリ上には配置される • 端末メモリ上に配置したファイルをアップロード •
ファイルアップロードが完了するまでメモリ上には当然残る • 失敗したら…の処理も存在する • これがファイル1つに対しての処理の流れになる • 複数存在している場合は当然複数回繰り返す、並列に走らせるといった対応が必要
だいたいこんな感じ…? ファイル取得 アップロード ファイル取得 アップロー とか ファイル取得 アップロード ファイル取得 アップロード
時系列
要するに、同時に走る処理の数を いい感じに制限してあげればいい
やってみる • ファイル一覧がListで存在 • 画像取得、アップロードを行う処理を作る • 具体的な処理についてはキリが無くなるので省略で…
Rxだとこんな感じ Observable.fromIterable(fileList) .concatMap { // ϑΝΠϧऔಘॲཧ } .concatMap { //
Ξοϓϩʔυॲཧ } .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe { // ௨৴ྃ࣌ॲཧ }
Rxだとこんな感じ Observable.fromIterable(fileList) .concatMap { // ϑΝΠϧऔಘॲཧ } .concatMap { //
Ξοϓϩʔυॲཧ } .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe { // ௨৴ྃ࣌ॲཧ } ファイルリストをObservableに
Rxだとこんな感じ Observable.fromIterable(fileList) .concatMap { // ϑΝΠϧऔಘॲཧ } .concatMap { //
Ξοϓϩʔυॲཧ } .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe { // ௨৴ྃ࣌ॲཧ } 流れてくるストリームをファイル取得に使う。 (ストレージアクセスなりネットワークアクセスなり)
Rxだとこんな感じ Observable.fromIterable(fileList) .concatMap { // ϑΝΠϧऔಘॲཧ } .concatMap { //
Ξοϓϩʔυॲཧ } .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe { // ௨৴ྃ࣌ॲཧ } 流れてきたファイルをアップロード
えっ、これで大丈夫なの? • fromIterableでファイルリストの中身を一つずつストリームに流している • flatMapではなくconcatMapでストリーム順序を優先するようにした • 50MBのファイルがストリームに流れると流石にOOMが出るので注意 • Android Profilerでメモリアロケーションを見てるとGCがだいぶ愉快
という感じなんですが 手元では問題無く動いているように見えるだけで 自信がないので詳しい人に助けてほしい…
• ファイル一つに対しての処理は以下の感じ • ファイルを取得する • その結果をawaitして、アップロードにつなげる • この処理自体もawaitして、終わり次第次のファイルについて同様の処理をする… といった再帰的な実行をすることになりそう たぶんCoroutinesだと
ファイル取得 アップロード await await 全部終了 まだ次がある
アクセシビリティに気をつける • ファイルサイズが大きいぶん、当然アップロードまでにかかる処理が長い • 画面でダイアログ出してぐるぐる…なんてやってるとキリがない • アップロード処理をフォアグラウンドサービスに移行させる • アップロード中であることの通知をしっかりさせる •
巨大なアップロードになるのでモバイルネットワーク通信時にアップロードさせない • NetworkInfoのTypeがTYPE_WIFIになっている時以外はブロックする…といった処理も 検討する
フォアグラウンドサービスでアップロードさせる • サービス起動時にフォアグラウンドで通知させることが必要 • Android O + API Level 26から
• Context.startForegroundService() で起動 • サービス起動から5秒以内に Service.startForeground() しないとクラッシュする • RemoteServiceException • アップロードする観点では起動直後に通知させるで良さそう • 処理が終了したら stopSelf(), stopForeground() で止めないと通知が残り続ける • ちゃんと止めよう
サービス起動 fun start(context: Context) { val intent = Intent(context,ForegroundService::class.java) if
(ifVersionLaterThanO()) { // check SDK_INT context.startForegroundService(intent) } else { context.startService(intent) } }
起動直後に通知して処理を実行 override fun onCreate() { super.onCreate() // Ξοϓϩʔυ௨༻ʹnotificationΛ࡞͓ͬͯ͘ startForeground(NOTIFICATION_ID, notification)
uploadItems() { // ΞοϓϩʔυྃͰαʔϏεΛऴྃ͢Δ stopSelf() } }
おわり