Google I/O 2017 Android 相關 Session 摘要 – 上集

部門內總是習慣大家分著看東西,再互相分享,這是我們團隊內保持快速移動的有效方法之一,今年我們也針對 Google I/O 2017 上百部影片中的 Android 相關議題做了分享,算一算這是我們第四年分享懶人包了呢 :P

What’s New in Android

  • Picture-in-Picture:在 Android N 時僅在 TV 有這項功能,如今在 Android O 得到全面開放。讓你在觀看影片的同時能操作其他事物。
  • Wide-gamut color:開發者現在可以從一些支援廣域色彩的機種得到顯示上的優勢,讓你的 App 色彩更豐富更具特色。
  • Multi-display:就像去年 Android N 提出的 Multi-window,若 App 已有支援便可運行。
  • Media enhancements:Media API 多了一些 API 支援,例如 MediaPlayer、MediaRecorder、MediaCodec、MediaExtractor 都有 getMetrics() 可以得到各種效能或設定的資訊。
  • WebView APIs:Google SafeBrowsing API 可以偵測木馬或不安全的網站避免使用者瀏覽;Termination Handle API 以及 Renderer Importance API 可以幫助開發者處理瀏覽 WebView 時發生的情況,例如記憶體低下,或意外 crash 時的對應。
  • AnimatorSet APIs:多了 seeking 讓你指定要到達的動畫位置;reverse 可以讓你操作類似返回的效果,不再需要分開做兩部動畫。
  • Auto-Fill:就像在桌機瀏覽網頁時一樣,會自動帶入資訊,例如 email 或實體地址等等,方便填寫表格之類的操作。
  • Downloadable Fonts and XML:開發者現在可以更輕易地引入需要的字型,不再像以前一樣有所限制,另外也能從外部即時載入,就像載網路圖片一樣。
  • Autosizing TextView:現在可以定義 TextView 的擴張,讓它可以在不同尺寸螢幕的機種或是動態內容之中更輕易地優化。
  • AccessibilityService Utilities:在系統的 navigation 區域可以加上 Accessibility button 讓使用者快速啟用;可以獨立控制 Accessibility 的語音音量;能使用指紋當作額外的操作方式,但要注意機種是否支援指紋辨識。
  • findViewById:現在不需要在 findViewById 時註明是何種 View Object!
  • Adaptive icons:launcher icon 可以因應各種機種系統及當下 UI 變化自身的形狀或效果。
  • Pinning shortcuts and widgets:可以從 App 定義想要快速啟用的功能到桌面。
  • Notification Channels:使用者可以定義 notification 的種類,讓它們可以集中管理瀏覽。
  • StrictMode APIs:detectUnbufferedIo() 可以偵測讀寫資料時是否沒使用緩衝;detectContentUriWithoutPermission() 檢測是否遺漏 permission 給其他欲使用你的 Uri 的 App;detectUntaggedSockets() 讓你使用網路流量時不忘利用 setThreadStatsTag(int) 說明是為了 debug。
  • Media File Access:可以定義 custom DocumentsProvider 提供 data 給其他 App。
  • Cached Data:現在每個 App 都會被分配到一些空間給 cached data 使用,而當系統要清理空間時,會從佔用這個空間最多的 App 開始處理,若開始清理你的 App cached data 時,會根據變動時間從舊的開始刪除。
  • Google Play Protect:檢測是否內含有風險的 App,無論你是透過 Google Play 或是 Adb 安裝。
  • Kotlin:Android 第二開發語言支持。
  • Architecture Components:讓開發者能更容易管理 Lifecycle 及其他有用的元件。

Engineer for High Performance with Tools from Android & Play

Google play console 現在提供了 Android Vitals 來幫助開發者優化 app 的表現。
他有幾個 Tab 如:ANR Rate、Crash Rate、Slow Rendering、Frozen Frames、Stuck Wake Locks、Excessive WakeUps,其中 ANR 和 Crash 一直是影響用戶使用意願的重要因素。

而 Stuck Wake Locks 和 Excessive WakeUps 可以幫助觀察 wake lock 和 wake up ,移除不必要的使用可以幫助節省電池用量,事實上 wake lock 大多可以用 Download Manager、Sync Adapter、JobDispatcher 或 Job Intent Service (supportLib v26+) 取代,就算必要也盡量用 try final 包起來以避免 leak。Network location 內部會用到 wake lock,所以須避免長時間不斷的 request。wakeup 也可以用 Firebase JobDispatcher 取代。

Slow Rendering 和 Frozen Frames 則是觀察 app 效能的表現,在目前的手機上正常流暢的畫面表現約是 60FPS,若有 UI Thread 卡住就會造成畫面卡頓,開發者遇到這種情況可以使用 FrameMetricsAggregator API (sup lib v26+) 來收集有疑慮部分的資料,然後使用 Systrace 來瀏覽該份資料。

Architecture Components – Introduction

Google 提供了幾個新的 Library 統稱為 Architecture Components。這組件目前還在 alpha 1.0 的版本,猜想之後應該會有更多的改變

Architecture Components 裡面包括了以下四點:

  1. Lifecycles as 1st-class citizen:LifecyclesOwner
  2. lifecycle aware observables:LiveData
  3. Lightweight ViewModel:ViewModel
  4. Object mapping for sqlite:Room

在 Lifecycle 中 (參考影片 10m 30s),現階段的問題是非同步的情況通常在 app 裡需要判斷 location 都會在 onStart 及 onStop 裡啟動或關閉 listener ,而在 onStart 中也有可能會加上 checkUserStatus 判斷權限,判斷完後再利用 callback 來啟動 location listener,如下圖示所示假如在 checkUserStatus 同時做了螢幕的旋轉,Lifecycle 就會進入到 onStop 關閉 location listener,再去 created 一個新的 activity ,不幸的此時 checkUserStatus 的 callback 回來了,去啟動了 location listener,如此這份 listener 就會一直存在浪費資源及電量,所以引進了 LifecycleOwner 及 LifecycleObserver 來改善此問題,讓 listener 能夠監聽 lifecycle 來判斷是否需要執行 start 或 stop。不過在這部份 listener 還是需要自行監聽 lifecycle ,因此再更進階一點就提供了 LiveData ,他可以保持完整的資料在 lifecycle,不需要依賴任何的 activity 或 fragment,可以達到簡單的測試。

另外通常在頁面載入時會把資料載入,但當螢幕旋轉時就又會再次要求再載入一次資料,可是我們會認為資料已經載入過一次了為什麼還要再載入一次,要解決這件事就有了 ViewModel 這個 library ,他可以幫你保存此頁面已經載入過的資料當螢幕旋轉時可以不必再去重新載入一次資料,而在 activity 結束後他也會自動的清除資料。

最後在一個好的 APP 大多都會保存資料在手機端,在 Android 平台可以保存資料的有三種方法,一個是 Content Providers 及 Shared Preferences 最後就是 SQLite,如果要保存大量資料都會用 SQLite,在目前撰寫 SQLite 都是寫語法在 code 裡,這會有一些不方便的地方,例如出錯通常都要等到編譯完執行時才會報錯,所以也提供了一個 Library 來解決這些問題,這裡稱為 Room ,是一個 ORM 技術的 Library。以上這些 Architecture Components 的引進也可以讓你的 APP 更容易簡單的做 unit test、Mock 等等的。

New Release & Device Targeting Tools

Sarah, Milena, Kobi 分別介紹 Google Play Console 新的發佈管理流程與裝置資訊工具更新,以幫助開發者更便利與安全的發佈應用程式。首先簡單回顧了去年 Google I/O 推出的 Open Beta,其可讓使用者參與測試並在 Play Console 交流意見,是一個測試應用程式更新的好方法。另一類似的計劃為 Early Access,使用者可以安裝正在開發中但尚未發佈的應用程式,此時使用者無法給予任何評價,而其意見、使用資訊、回訪率等等都是有助於開發者分析與改善應用程式的。

今年的發佈管理流程更新則包含 Staged rollout 與 Release Dashboard。新版的發佈流程在發佈應用程式前,在一些可能發生的危險上,根據嚴重程度提出警告或是停止發佈;而新功能的階段性發佈流程則是能漸進式的增加目標裝置百分比去安裝更新,同時監看 Release Dashboard,以在發現異常時即暫停,如 crash rate 或 uninstall rate 提高,待修復後再重新進行發佈。

Play Console 也開始支援 Release Instant App,詳細介紹可參考影片:Introduction to Android Instant Apps);並更新 Publishing API endpoints 與 Release notes flow 功能,且可以離線編輯 Release Notes。

Release Dashboard 每小時會提供最新的 crash rate、 ratings changes、uninstall rates、ANR rate、Release History 等資訊,詳細介紹可參考影片:Making data on Play work for you。

Google Play 也推出了 App Signing Key 的管理制度,其可自動產生一組 key 給新的應用程式,或是提供一個安全的管道給開發者,將已發佈應用程式所屬的 key 傳送給 Play Console。另一優化功能則是透過移除非裝置對應的解析度資源檔案降低 apk size,其詳細介紹可參考影片:How to secure and optimize your app with Google Play app signing。

最後,關於裝置資訊頁面的更新:Device Catelog 不再只有單一的模組名稱,在點擊卡片後,可以看到每個裝置的詳細資訊,如安裝數量、目前評價與收益等,也有篩選與搜尋裝置的功能。Device Gropus 則是整合了相同廠牌但不同模組的裝置資訊,此可搭配 Device exclusion rules 應用於發佈流程時排除特定的裝置或裝置群組,如硬體資源不足的裝置或特定模組的裝置發生錯誤時,而不影響其他裝置。

What’s New in Android Accessibility

Accessibility API 大致可分為 TalkBack, BrailleBack, SwitchAccess, VoiceAccess,TalkBack 可以讀出使用者觸碰到的物件內容,BrailleBack 是用點字的方式顯示使用者觸碰到的物件內容(需要特殊顯示器),SwitchAccess 可以外接一個裝置,並使用這個裝置操作 Android (有點類似使用搖控器操作 Android TV),VoiceAccess 則是可以用聲音來操作 Android。

Android O 上增加了 Accessibility volume,將 TalkBack 的音量調整獨立出來,讓使用者不會因為在看影片或聽歌時聽不到 TalkBack 的聲音;在指紋辨識器上也多了手勢控制(向上,下,左,右滑),每個手勢可自行定義各自的功能;在任何畫面下長按音量鍵(上+下) 即可開啟 TalkBack。
在 Testing of Accessibility 的部分,建議開發者可在 Google Play 下載 Accessibility Scanner App,可以用來分析我們的 App 是否有需要改進 Accessibility 的部分並給出建議。

Background Check and Other Insights into the Android Operating System Framework

Google 一直致力於電池耗電量的優化技術,在過去 Google 提供了 Doze 與 Standby 機制減低耗電量。
Doze or Doze Lite:當手機不處於充電狀態,並且螢幕持續關閉一段時間後進入 Doze 模式,系統間歇性地暫停 App 使用 CPU 與網路功能 Standby:應用程式未啟用或在背景一段時間之後,會被系統識別為閒置狀態進入 App Standby 模式被丟到系統背景,進入該模式下的 App 將被限制網路功能。

另外,Google 發現以下三個 Broadcast 是導致大量耗電的因素之一,應該避免使用而改用其他替代方法:CONNECTIVITY_ACTION、ACTION_NEW_PICTURE、ACTION_NEW_VIDEO

而節省耗電量的根本作法,就是限制應用程式在背景的行為,包括限制 Services 與 Broadcasts,限制掃描位置與網路

在現今 Google 進一步採取了更積極的省電作法,當 App 進入背景,並且沒有設定前景運行的情況下,短時間內便會被系統停止回收,除了兩種情況除外,一種是該 App 被加到 Doze 的例外白名單內,另一種是原廠就設定為不受省電監控的 App。

使用 GCM 應區別優先重要性,優先性高會取消 Doze Lite 的限制而被喚醒,例如像是發送火警警報訊息。優先性一般的系統根據電量狀況決定延後喚醒的時機,例如像是發送電視節目提醒訊息。也應避免系統同時喚起多個工作處理,這會導致在短時間內系統需要選擇砍掉 process 以釋放記憶體用量。另外也建議使用 AlarmManager,SyncAdapter 和 JobScheduler 非同步延後批次處理這些工作項目頻繁的查看位置或掃描 WIFI 會消耗大量電量,建議依照實際需求調整頻率。影片中也提到 Google 提供了新的電池設定選單,可以更好的優化耗電量並監控停用背景執行程式。

Other Insights:
System Alert Window 可以繪製在系統最上層也就是會顯示在 App 的上方,這會造成一些問題,像是畫面雜亂無章難以控制,圖層彼此的上下關係難以定義,系統層的元件被遮蔽等。在 Android O 新增加了 App Overlays,最大的差異是只能繪製在 Application 畫面的上方。沒錯!往後將不再允許繪製圖層覆蓋在系統畫面之上,而是在 Application 與 System 的 z 軸之間。

Assisting the Driver: From Android Phones to Android Cars

Android Auto 從 2016 年至今,搭載車機的數量提升了 10 倍以上,許多汽車廠商都將 Android Auto 設定為標準配備之一,其中像是知名的 Audi 與 Volvo 汽車公司更成為與 Google 合作的有力夥伴之一,另外 Google 也推出 app 的版本提供給尚未更換新車的 Android 使用者。

「安全性」是 Android Auto 在設計上最優先被考量的項目,虛擬駕駛情境的設備,在開發階段被用來測試如何將干擾降到最低,避免駕駛注意力被車機系統分散在顯示上使用模組化元件,更精確的延展或移動到符合各種裝置大小的畫面上。汽車裝置上顯示的版面被設計成更安全地符合大多數汽車共同預期的操作方式,例如音樂 App 在車機上使用,不會因為顯示畫面大小或是語系不同而干擾畫面的操作性,不同於手機 App 的排列方式,車機版面被精心設計成更容易進行畫面切換並更合適車機螢幕的畫面空間。

Google 致力於讓車機 app 的開發更加容易。針對 Audio 與 SMS 已有對應的開發版型,開發者可以簡單快速的開發出更加安全與符合車機使用的 App Google Assistant 也已整合在 Android Auto 當中,代替鍵盤輸入的操作能確保駕駛視線專注於前方行駛道路。

Android Performance: An Overview

講者在這次演講的主軸想要改善的效能問題有兩個

  1. 如何讓 app 維持每秒 60 個 frame 的流暢度
  2. 如何讓 app 啟動的速度變快

要解決問題前,必須要先發現問題,分析問題,講者介紹了兩個工具來輔助開發者處理上述兩個效能問題,首先是 gfx info,可以透過以下指令
adb shell dumpsys gfxinfo com.your.package.name

把處理畫面的資料叫出來分析,例如可以看到繪製畫面(rendering time)的張數,平均繪製畫面的時間 …等,在這邊我們所關注的是 90%,95%,99% 的繪製畫面時間,這個工具僅能告訴開發者 app 處理畫面是否流暢,沒辦法確切告訴開發者問題在哪,那為什麼還要使用呢?原因是可以結合自動化做效能測試,這樣就可以把每一段繪製畫面的部分量化,進而分析是做了什麼操作讓畫面變的不流暢。

講者接著介紹 Systrace 這個強力的工具,Systrace 提供開發者收集以及調查在機器上某段時間的處理資訊,可以顯示 CPU 大多的資源是花費在哪裡,開發者可以透過兩個方式取得 Systrace

  1. Android SDK 底下的 platform tools
  2. git clone https://github.com/catapult-project/catapult.git

另外要注意的是,Systrace 需要透過 python 來執行,務必先將 python 先安裝起來。

Systrace 是由三個物件所組成:

  1. ftrace:寫入系統的事件資訊到某一個檔案中,簡單說,開發者可以查看系統事件的紀錄。例如: 這個 process 是跑在某個 CPU 上。
  2. atrace:Android framework 的系統記錄事件功能,
  3. systrace:將 atrace 的資料透過 html 整理後呈現

開發者可以使用此指令
./run_systrace.py --list-categories

列出所有 systrace 想要追蹤的項目,例如 wm – window manger , am – activity manager …等。

講者簡單示範了一個指令執行 systrace 抓取 trace 的功能
./run_systrace.py sched freq idle am wm gfx view dalvik input binder_driver -t 5 -o io.html -b 16384

這些參數大多可以從 –list-categories 了解該參數的功能。我們執行上述指令後,會得到一個時間軸的 trace html,可以透過鍵盤上的 wsdf 來去左右移動,縮放事件。開發者也可以點按想要觀看的事件,最底下的 UI 會顯示該事件當下的詳細資料,此外還可以透過 highlight tool,關注想要處理的地方。

在看 Systrace 時可以特別關注 UI thread 這個顏色標注的直方區塊,這些直方區塊有五個型態,綠色代表 thread 執行,藍色代表 runnable,紅色代表 uninterruptible sleep,指的是 thread 在 kernal 層被 block 了,使用者沒辦法做什麼,這通常是系統或硬體上的錯誤;橘 色代表的是 uninterruptible sleep – block io,這是開發者必須處理的,指的是開發者在這段時間要求太多 IO 的工作了,試著不要同時存取太多的資源; 白色代表 idle,代表這段時間是閒置的,如果常看到這個出現,這是一件很奇怪的事情,很有可能和使用者空間鎖住互動有關。由上述的五個狀態,可以粗略地從 Systrace UI 上看出瓶頸在哪,另一個 Systrace 好用的工具是 input tag,用來顯示 input 的資料,比如說點按螢幕的某個按鈕 22.8 ms。

此外,如果想要追蹤 Application Code,可以在 code 中加上
import android.os.Trace;

Trace.beginSection("hello I'm an app trace section");
...
...
Trace.endSection();

這邊要特別注意的是,beginSection 和 endSection 是成對的,如果不成對出現,將會在 UI 上呈現很怪的結果。

關於開啟時間的快慢,可以透過 Systrace 的 view inflation 來分析,觀測繪製畫面的成本在哪,進而發現效率不佳的 code。另一個有效的工具是 resource tag,可以觀測什麼資源正在讀取,如果發現讀取資源的時間很長,這是值得去關注的。

要如何修正 jank (如何修正掉 frame 的問題),講者提供了兩個步驟可以透過 Systrace 發現 jank 並使用 Systrace 查看 jank 的詳細資料
我們可以透過觀察 Systrace UI thread 和 RenderThread 發現 jank 的所在,如果 UI thread 和 RenderThread 沒有在 16.7 ms 完成的話,就會造成 jank。

另一個觀察 jank 的方式可以透過 SurfaceFlinger ,SurfaceFlinger 可以把它想成 frame 的 dead line,如果有在時限內完成,代表 app 是有達成 每秒 60 frames,UI 看起來就會非常順暢,他用一個 counter 的方式,數值為 0 , 1 規律性的圖表來呈現,如果處於 0 的時間超過 16 ms,代表這邊有 jank 發生。

ExoPlayer: Flexible Media Playback for Android

Oliver 首先簡單比較 MediaPlayer 與 ExoPlayer 的特性,如 MediaPlayer 從 API level 1 就支援影音播放;而在 Google I/O 2014 發佈的 ExoPlayer 則支援更高階的格式,如 DASH、SmoothStreaming、HLS,並具客製化與延展性。由於依賴 MediaCodecAPI,因此僅支援 Jelly Bean(Android 4.1, API 16) 以上,ExoPlayer v2 也提供更容易使用的 Simple Exoplayer 與 playback UI 元件。

Andrew 接著說明 ExoPlayer library 的主要播放流程:LoadControl 通知 MediaSource 開始 buffering,然後由 MediaSource 載入 DataSource,其包含 TrackGroups,直到 loading 足夠播放的媒體檔案,MediaSource 開始處理哪些 tracks 可以輸出至 player,接著持續配置 buffer 且 renderers 執行解譯功能,完成後再由 LoadControl 通知 player 播放。

而在客製化部份則提到,自定義 LoadControl 可以改變播放器的 buffer 策略,自定義 Renderer 可實現 Android 本身不支援的視訊編解碼器。TrackSelector 也可設定自定義的參數,如固定 video size。且為避免因網路不穩定,而發生重複下載的問題,ExoPlayer 也提供了 SimpleCache 與 CacheDataSourceFactory,使 MediaSource 在載入 HttpDataSource 前,可先確認是否已有足夠的 cache 可使用。另一新功能 AdsMediaSource 可支援無縫插入前置、中間、後置廣告於媒體檔案,實作細節可參考 InteractiveMediaAds SDK、ImaAdsMediaSource。

最後談到下一步的計劃包含支援離線播放、提昇解碼效能、改善 track selction 與 buffering 策略,並提供更完善的文件。

What’s New for Android TV

Android TV 在過去一年的使用成長量增加了一倍,超過 20 家以上世界知名的公司生產 Android TV 系統的 Smart TV 或是 Set-top Box,支援的 App 也增加到 3000 個以上

根據 Netflix 提供的資料統計顯示,使用 TV 觀看的用戶比例大幅度成長,在短短半年從 20% 增加到 67%,快速取代電腦或手機等裝置,數據也顯示出大多數用戶在客廳裡觀賞。而當我們思考使用者為何被吸引在客廳觀賞這些內容時,透過比對發現了三點之前並未考慮到的共通問題!

  1. 現在的家庭有多種影片內容的管道來源,選擇的影片內容往往取決許多不同因素,像是當下的心情或是時段與觀看的地點。有趣的是,當你打開 TV 時,App 提供的影片內容往往必須要主動去開啟 App 之後才能知道,由使用者選擇因素來看這真的是件怪異的情況。即便如此,如果要將許多不同型態節目內容,不同 App 有來自付費免費租貸或是線上直播等等都整合在一起,讓使用者同時完全掌握多種不同的影片內容相當困難
  2. 觀賞者往往會受到影片截取的預覽片段所影響,像是 TV 推薦影片等。但是當我們提供了大量的影片清單時,反而會造成難以選擇,使得使用者會更加期待能在推薦影片清單就能發現喜愛的內容
  3. 相較於手機裝置,TV 也需要更多可客製化的設定,讓使用者能更自由的變更內容的排列呈現方式

針對這些主要的問題,在未來新版的 Android TV 做了以下調整

  1. Android TV 將支援 Google Assistant:
    使用者能更快速便利的尋找到喜愛的影片內容,提供與 TV 更好的互動體驗

  2. Launcher 全新改版:
    [Apps] Home Screen 最上方一排顯示所有已安裝的 App
    [Watch Next] 下方第二排顯示喜愛的 App 影片
    [App Channel] 接下來幾排全部都是屬於左方列表 App 的推薦影片
    這邊我們稱呼整排的影片叫做 “頻道” (Channle),每個頻道是由 Media App 所產生,當移動到頻道方格時可以在不開啟 App 的情況下直接播放預覽影片。而每格的影片我們稱為 “節目” (Program)

每個 App 可以自行為頻道命名,提供節目的 metadata 決定顯示的內容與排序,當某個影片被點選開啟 App 播放中途中斷,或使用者針對節目影片直接手動加入到我的最愛,就會自動加到第二排的影片清單當中,讓使用者可以快速找到未看完或喜愛的影片。使用者也可以自行設定左方顯示的 App 列表,如果該 App 有提供多種頻道選擇,也可單獨顯示該頻道節目,例如 YouTube 可單獨選擇 360 Videos 或 Recommended 頻道。另外,PlayBack 新增加了 seek thumbnails 的實用功能。接下來你也可以使用 Leanback 建立頻道與節目:
ContentProvider APIs:新增頻道與節目
BroadcastReceivers:接收頻道與節目異動的事件
Support Library:變得更加容易實作 (無詳細說明)

Architecture Components – Solving the Lifecycle Problem

以下為 Architecture Components 內含協助處理 Lifecycle 的主要元件。

  • Licycle:Architecture Components 的核心部分,擁有關於一個元件的 Lifecycle 狀態的資訊。
  • LifecycleOwner:給有 Lifecycle 的元件操作的核心介面,如 Activity,Fragment,或是自定義的元件。
  • LifecycleObserver:可在指定的 Lifecycle 狀態下進行想要的對應處理。
  • LiveData:觀察 Lifecycle 一舉一動的核心元件,最大的特點在於若 Lifecycle 處於不需要得到資料的時候便會自己取消訂閱,可以避免 UI 元件在已經結束時,才被呼叫處理原本請求的資料的這個老問題。
  • ViewModel:來自 MVVM 概念的元件,現在成為官方 class 釋出。他的功能在於準備好資料,讓任何對這些資料有關注需求的 View 作訂閱。而在 Android 的 ViewModel 有些設定:

ViewModel 可以保留狀態,遇到 onConfigutationChanged 時,也不需手動存取資料到 onSaveInstanceState() 之類的地方。
ViewModel 在 Activity 或 Fragment 之外獨自生存。
ViewModel 可以跨 Fragment 溝通,而不需要透過 Activity 協調。
ViewModel 會停留至整個 Lifecycle 確定永久結束,如 Activity finish 或 Fragment detach。

由於 ViewModel 超脫在外生存,所以他不能直接對任何 View 作 reference,也不能 hold 住 Context,這會造成 memory leaks,如果 ViewModel 需要 Application Context,可以繼承自 AndroidViewModel 並從 constructor 取得。

那這算不算是 RxJava 呢?
答案可以說是,因為他也是在倡導對 model 做 reactive programming。但也可以說不是,因為他專注於關注 Lifecycle,並且較簡單。由於 RxJava 的學習相對困難許多,這對新進的開發者來說並不是好事,可以嘗試這套 Library;若團隊原本就在使用 RxJava,只要處理好 Lifecycle,那他有更多強而有力的支援為你所用,倒也不需轉用這套 Library。

Test-Driven Development on Android with the Android Testing Support Library

寫 test 會讓開發變得緩慢,那為什麼要寫 test 呢?因為測試可以讓你提早發現開發中的問題,也提供一個安全網讓你能安心的調整能與重構。

通常測試可分成三層每層,每層各自有些取捨,沒法 cover 所有的內容。最底層的 unit test 跑的非常快,專注於每個元件的測試。而這部分的犧牲是,不是跑在實際環境,所以需要額外引入 mock 來測試。中層的整合測試與上層的 end-to-end 測試都需要確保測試環境不會造成失真,所以建議在實際裝置或是模擬器上執行,這部分的取捨是速度,所以每一層都是有其必要的。

雖然沒有一定的規定,Google 內部的測試專家建議在小 (unit test),中 (integration test)、大 (end-to-end test) 測試上取,70-20-10 的比例。在測試驅動開發中,開發流程是先寫測試,再寫 code 來符合測試結果。除了穩定性的問題,測試驅動開發也有以下好處:強迫你仔細思考架構與流程的設計、每個元件對外的 API。

Unit test 應該有全面、可重複、專注、完整行為、快速、簡潔等特性。當 Android 相依性出現的時候,我們就很難達到上面這些特性,這時候我們就能用 Roboletric 來解決。

整合測試背後的動作很複雜,包括編譯、res 處理、執行模擬器等,都很花費時間。因為 instrumentation 跑在跟 app 一樣的 process,當某個測試 crash 了,整個 process 都會被結束,當測試變得複雜這幾乎無法避免。Android Test Orchestrator 是一個用來解決此問題的 service 元件,他可以為每條測試單獨開
instrumentation,測試間的狀態共享也會消失,因為跑測試前,會先 clear data。這在下一版的 Android Test Support Library 會一起 release 並與 gradle、firebase 整合。在 end-to-end 測試中,很容易碰到真實環境的網路 delay 或是失敗,可以利用 Idling Resource 來告訴 Espresso 你的 App 與 Test 間如何同步。Espresso Intent 用來攔截、檢查 app 內的 Intent,可以用它來隔離不同 activity 之間的測試。

Fragment Tricks

這個主題關於 fragment 的一些使用技巧,並沒有介紹新的 fragment API。先介紹 fragment 的緣由,從 android 3.0 因應平板有較大的螢幕,可以顯示較多的內容,並以 Gmail 為例,在螢幕橫向的情況時,左半部為導引選單,右半部為信件內容,但在較小螢幕的手機上,要先點擊導引選單後,才會開啟信件內容,因應不同的螢幕大小,有不同的操作邏輯,這個要如何去完成呢?這時就可以用 Fragment API 來完成這個任務了,舉例來說:使用 fragment replace API 可以移出現在的 fragment 然後再加入新的 fragment,過程中可以設定 transaction,並可以把替換掉的 fragment 使用 addToBackStack(),加入要返回 tag,供返回時回到特定的頁面。

不只在大螢幕上有優點,在小螢幕上也可以控制 fragment 要顯示的範圍,有些固定的版面,例如底部導覽列,抽屜導覽列,在使用 activity 切換時,要保留不受影響是有困難的,但使用 fragment 就可以輕易達成此要求。

接者介紹 Navigation flow,以購物車的概念來呈現,在使用者點擊頁面時,需要維護 back stack,而非按了返回鍵,才動態決定要開啟哪一個頁面。例如:使用者結帳完後跳出完成頁面,再按返回,這時就不應該回到購物車的頁面,因已經完成結帳了。

接者介紹 synthetic back stack,有一些操作步驟,例如點擊通知列,會開啟正常需要點擊多次才會出現的頁面,那途中可能會開啟很多頁面,這樣的操作會耗費資源,可使用 setReorderingAllowed(ture),可以讓多個 fragment transaction 合成一個,直接執行最後判斷的行為。

點擊項目,畫面就直接跳出來,這樣不是很美觀,所以可以加入過場動畫,基本的 transition 有三種:fade, open, close,Support library 和 Framework 的 Fragment 都可以使用 animation,改變 scale, rotation, translation, alpha,在support library(26.0+) setCustomAnimation,使用的方法和就和 framework 的 fragment 使用方式相同,都為
animator。

在 activity transitions(lollipop+) shared element 從原本的 view 擴展到新的 view,fragment 也有類似的功能,使用 addSharedElement()。

Retain instance fragment 通常會使用在 configuration change 後 fragment 還會存在,物件可以保留,但要避免儲存以下的物件:
1. View
2. Context(Activity) 不應該存活比 activity 長
3. Callback reference

在做客製化元件時,要使用 viewGroup 還是 Fragment 呢?因責任分配不同,不要用 fragment 去做 view 的事情,fragment
可以處理一些運算比較多的功能,使用範例如 mapfragment。

Android Wear: What’s New & Best Practices

Complication(在錶面上顯示除了時間以外的資訊)能夠快速的檢視資訊及操作,很受使用者的喜愛,像是顯示會議的與會者及時間、顯示未讀訊息等… 但開發 Complication 不容易,因此新增了兩個元件在 Wear support library:TextRender 能自動調整文字大小;而 ComplicationDrawable 只要設定 location, style, size… 等資訊即可完整的 render complication,除此之外也在 gihub 放上了 watch face setting example 以及 open source test suit data provider 協助開發及測試。

除此之外 Google 也宣佈 Wear 2.0 將支援 Google play,未來可以直接再 Wear 上搜尋並下載 app,也會將手機已安裝的 app 推薦給使用者下載,而過去 Wear 1.0 是嵌在手機 app 裡的,使用者透過手機在 Goolge play 下載後再同步到 Wear 上,但未來會將會變成獨立的 apk 而且在 1.0 及 2.0 都可以使用;另外也將支援 Google Assistant,能夠用對話的方式操作裝置,若有開發 Google Home 或 Phone 的 Action,也會自動的接上 Wear,不用另外再開發。

Android O 也有相當多新的 API 提供給 Wear 開發者,下面是其中一些比較有趣的:

  • Notification:NotificationChannel 能讓使用者更簡單的組織及控制同類型的通知。
  • Autosizing TextView:透過設定大小範圍或 Preset list ( 定義數值的 List ),TextView 將會從中選擇最適合的大小。
  • Background limits:一般來說不是前景執行的程式及服務將被視為 idle,且不再支援 註冊於 AndroidManifest 中用以喚醒程式或服務的 broadcast( 還是可以在 runtime 註冊該類 broadcast ),建議使用 JobScheduler 及 AlarmManager 在適當的時間點執行背景作業。

另外在接收推播的時只能利用空檔使用 foreground service 來顯示,否則同樣會被視為 idle 狀態。除此之外也會限制接收位置資訊的行為,這邊推薦使用 Batch location API,如果像是運動 APP 需要高頻率的取得位置資訊的就使用 foreground service。

電力的消秏一直是很重要的議題,因此有以下的建議:簡化操作以減少螢幕開啟的時間、實作黑白配色的 Ambient mode、使用暗色系的主題、減少動畫、避免在背景使用網路同步資料、使用網路時最好批次作業

What’s New in Android Development Tools

今年 relase Android Studio 3.0,不但可以在註解裡使用 emoji,而且支援了 Kotlin:在新 project 一開始就可以使用 Kotlin,已存在的 project 也可以用 converter 將檔案從原本的格式轉換成 Kotlin 的寫法,Lint 也仍然可以使用在 Kotlin 上。

在 UI 部份,去年新加的 Layout editor, 今年新增了 chain 的功能,可以將幾個 view 組合成一個 chain,並決定這幾個 view 同步放大縮小及距離比例。(詳細操作請看影片 5:42 開始至 6:49。)
ListView 預覽顯示的資料現在可以在 item view 中選擇 sample data (JSON 格式) 。
Android O 以後支援除了預設字型之外的其他下載字型,image asset 現在可以設定其 icon 及簡單背景圖樣,不用自己切圖或加遮罩,另外 studio 終於支援瀏覽手機內的檔案資料。

為了幫助 Instent App 功能的實作,refactor 底下的 Modularize 可以幫助開發者把一個 Class 及其相關 class 一起拆分到新的 module。其他相關的支援仍在進行中。

APK Analyzer 新增用 mapping 檔將 ProGaurded 後的DEX 檔還原為未 ProGaurded 版本的功能。

新工具 Android Profiler 可以幫助我們掌握操作行為發生時裝置的 CPU memory & 網路連線的狀況,開發者需要了解使用者的 bug 發生情況時,也可以在 google play console 下載相關資訊到 profiler 以了解使用者發生問題當下的手機狀況。

Grade 4.0 做了很多 build thread 優化,使用 build cache 後切換 branch 將不再 recompiling,也可以分享給 team member 和 build server,另外還做了 Dependency flavors 的設定優化。

JAVA 8 支援的部分, jackOptions 可以被以下 code 取代
compileOptions{
  sourceCompatibility JavaVersion.VERSION_1_8
  targetCompatibility JavaVersion.VERSION_1_8
}

為了測試需求,Google 在 Android Emulator 中新增了 Google play store 、 OpenGL ES 3.0 還支援了 Proxy,另外還在 emulator 中新增了 Bug Reporting System,他會幫你截圖,你可以附上簡短的操作說明,就可以快速的匯報給 QA team 或其他相關人士。 emulator 中也新增了 Wear rotary support,並且優化了 layout inspector。

而在 Apk 瘦身方面,Android Go 可以減少 apk 的大小,使用後可以用 APK Analyzer 觀察效果。vector assets 很棒,但如果還是需要使用 bitmap 或 raster image,將圖檔從 png 轉成 JPEG,能省下大約 25% 的檔案大小,而且Studio 現在支援 WebP,也可以方便開發者轉換該檔案格式。

Best Practices to Slim Down Your App Size

關於 APK 大小的問題,通常有 20% 的人會因為檔案大小太大而取消下載,所以我們應該要盡可能的減少下載的 size,另外一個問題就是安裝大小的問題,通常手機空間滿了使用者會試著去移掉一些不需要或是過大的應用程式,有八成的機會占的空間過大的應用程式會被移除,因此這篇教你如何減少你的應用程式 size 。

首先我們先把 APP build 出一個 apk,然後再用 android studio 的 Analyze APK 去解析 apk 內容所占的資源,這樣可以一目了然自己的 apk 內容資源占的量,並且他可以載入 ProGuard mapping 檔,還原被混淆的 method 或變數名稱

減少 apk 大小首先先做 ProGuard ,他可以做到三件事,第一件事是可以在不改變程式邏輯的情況下優化你的 code,第二件事是他可以混淆 method 或變數名稱減少過長的名稱字元,最後就是可以消除不需要不會用到的 code 或 file

另外在圖檔部份也建議使用 Vector Drawable ,他可以適應各種不同大小的螢幕,解決為了適應平版、手機等所放的各種大小 PNG 檔,不過在第一次啟動應用程式時有可能會占用部份的 CPU 、RAM ,犧牲掉部份的效能換取更小的 size。

而部份應用程式會用特別的字體,這些字體會包在自己的應用程式裡,而這會造成 APK 的 size 過大,在 Android studio 3.0 中提供不同的字體可以選擇,這些可以幫助 APK 減少包入字體避免增加不需要的 size。

此外也提供了 AAPT2(Android Asset Packaging Tool) 功能,他讓 XML 編碼使用 UTF-8 、可以減少重覆的 resource 等等的,只要在 gradle properties 中加上 android.enableAapt2=true 就可以使用了。

在過去一年中遊戲類的 APP 用了許多方式去減少資料大小或資料載入到手機裡的 size,現在提供了新技術來解決這些問題,Brotli 一種新的壓縮技術,比 gzip 壓縮減少更多大小。

What’s New in Android Support Library

  • Android Support Library 是提供給開發者使用新功能時能兼容舊版本的工具庫,新的版本推出後已不再支援 API 14 以下的平台,並釋出 Google 自行維護的 Maven 庫,往後 Support Library 若有更新不需另行下載。
  • Google 回報問題的網站將從 Google Code 轉移到 Issue Tracker,向官方提交問題會更有效率地被處理,同時你也能在 https://android.googlesource.com/platform/frameworks/support/ 開源庫貢獻你的修正。
  • Support Library 26 新增了多項功能,包含了加載特定字型功能,可透過 FontsContractCompat API 取得 Google 伺服器上超過 800 種的免費字型,再也不用打包字型檔在 apk 內了。範例程式可在 https://github.com/googlesamples/android-DownloadableFonts 取得。
  • Emoji Support Library 的推出讓過去舊版裝置無法正常顯示新版定義圖案的問題可以得到解決。相關範例程式可在 https://github.com/googlesamples/android-EmojiCompat 取得。
  • TextView 則增加了新的屬性可以根據畫面自動調整大小。
  • 動畫部分新增了兩個物理特性動畫,如彈簧軌跡的 SpringAnimation 及拋擲軌跡的 FlingAnimation。
  • Wear Support Library 方面則改善了捲動效能的 WearableRecyclerView、新增了圓形及矩形手錶都能自適應的 BoxInsetLayout 及可滑動刪除的 SwipeDismissFrameLayout。
  • TV 的 Leanback Library 添加了可預覽快轉縮圖 的 PlaybackTransportControlGlue 及可顯示詳細內容的 DetailsFragmentBackgroundController。
  • 另外一些特別提出來改變的 API 如可以將 Preference 改存於雲端的 PreferenceDataStore;FragmentManager 的 executePendingTransaction() 及 commitNow() 方法將不再允許在 FragmentManager 狀態變更時調用。

Architecture Components – Persistence and Offline

Android 本地資料儲存除了原生的 SQLite, Shared Preference 可以使用,第三方的函示庫更是多不勝數,但對於初學者從中選擇卻是很困難的,但若不使用函式庫輔助,在開發過程中更是困難重重,因此官方釋出了 Room Persistence Library。

Room 提供開發者以 Annotation 的方式操控 SQLite,使得 撰寫 SQL 語句的程式碼更為輕鬆簡短。在程式撰寫的過程中,我們常常需要透過 SQLite 從資料庫取得資料,在 Room 中使用@Dao 定義存取資料庫的 DAO(Data Access Object),@Entity 定義資料的物件,通常對應到Table,而 query, insert, delete 等語句透過 @Query, @Insert, @Delete 表示,最後透過 RoorDatabase 連接 DAO 與 Entity。

Room 也提供許多進階的功能。定義 TypeAdapter 可以允許各種物件轉換成 SQLite 可儲存的資料型態。在 Entity 中使用 @Embedded 可以支援巢狀的資料結構,在維持良好的 Table 結構下也不影響 Java 層的資料結構。資料觀察者模式則支援 Architecture Components 的LiveData 和 RxJava 的 Flowable。而和一般 ORM Library 不同的是,Entity 間的 Relation 一般 ORM Library 都採取 Lazy Loading 的方式處理,Room 則是採取透過 Query SQL 只取需要的欄位並透過 DAO method 回傳事先定義好的 POJO Class。

在測試方面,Room支援 In Memory Database 加快測試的速度,在 View Model 測試的部分也可以很輕鬆的透過 Mockito mock DAO。資料庫升級的測試則是將舊 Schema 放在 assets folder,並在 gradle sourceSets 中簡易的設定,搭配 Room 的 Testing Lib 便可以模擬資料庫升級。

Room 目前已開放 Alpha 版,更多的詳細內容可以參考 Android Developer Page 和 Code Lab。

Making Data on Google Play Work for You

Play Console 增加了 Release Dashboard,當 release apk 的幾個小時之後,就可以看到相關的資訊(crashes, ANR, Ratings, Reviews, Install & Uninstall event),並可和之前 version 做比較。

Acquisition Report 增加了 country breakdown report,可知道 App 在某些國家的使用狀況,並可加以改進;可以匯出為 CSV 檔案。

Statistics Page 變的更有彈性,可選擇想觀看資料的日期區間、選擇另一日期區間做為比較、選擇某些 metrics 同時顯示,時間區間分的更細,最小可看到一個小時間的資料分析。

Introduction to Android Instant Apps

Instant App 是不用安裝也可以使用的 Android App,它可以透過 URL 直接開啟的,這意味著你可以在所有有 URL 的地方觸及你的 App。幫助你於不安裝 App 的狀況下也可以擁有完整體驗。想要進入 Instant App 的世界,提供了幾個指導步驟:

  1. One App:App 有 Instant App 以及 Installable App 兩種模式,不過不會共存。實作 Instant App 其實很簡單,不需要另外聘請人力來做,這跟原本開發技能相同,使用同一個 Project 、 Code Base 即可支援。根據 50 個合作夥伴提供的經驗,平均六週可以完成 instant app 的重構。
  2. Entering Your App:你需要思考使用者利用 URL 觸及你的 App 的 Use Cases ,大致為當使用者在某些情境時,即時需要某些資訊但又不想安裝 App 的情境,如: 朋友傳某個 app 的菜單給你時、網頁搜尋旅館點擊旅館細節時… 等。
  3. Decreasing Friction:假設使用 Instant App 時卻發現 App 需要登入才能使用,這樣使用者對你的 App 一無所知,發揮不了 Instatnt App 的優勢。為了減少使用中的摩擦點,提供了 Smart Lock、 Payment … 等 API,幫助你的功能可以順暢跑完整個 Use Case,不讓使用者用起來卡卡的。
  4. Installing Your App:官方提供了 Play Install API 可幫助 Instant App 使用者安裝 App,透過此 API 使用者可以不必透過進入 Play Stroe 即可安裝,下載途中還可以繼續使用 Instant App,不必重開 App。有兩個建議的方式,幫助你引導使用者安裝 App:
    • Explicit Installations:在你的 App UI 中加入 install 的字串或 icon ,引導使用者去安裝。
    • Implicit Installations:在點擊某些功能時跳出提示,安裝後才能使用完整功能以提示使用者去安裝。
  5. Tracking Success:Play Console 提供了一系列上傳、設定及 Firebase 追蹤功能,幫助你在實作完成後的調教與分析。

How to Manage Native C++ Memory in Android

這場主要在談的是 Java 與 C++ 一起使用的 case。即使你在寫的是純 Java 語言,但你用到的物件背後的實做可能還是會用到 native code,例如 BigInteger 這個類別。

講者給了一個做乘法的 Java code 範例,但真正的運算則是在 C++ 方面處理。Java 這邊真正擁有的是一個 long 的變數,其對應到的是 C++ 的指標。在 Java 端有 GC 可以在物件沒有被任何人參考的情況下回收掉 Java object,但在 C++ 端,必須自己呼叫 delete 來釋放記憶體,因此我們必須安排呼叫 delete 來處理這件事情。

一般的做法是有一個 delete function,並且在 Java finalizer 的地方呼叫它,但這會引起一些問題。當兩個物件已經沒有任何人參考的時候,這兩個物件的 finalizer 執行的時候是沒有順序性的,這也包含了當這兩個物件是互相參考,且同時解除參考的情況,因此可能會發生第二個要做 finalize 的物件去呼叫到已經在第一個做完 finalize 物件中已被 finalized 的物件,此種情況會造成 C++ heap 的 corrupting。更糟的是,Java runtime 也是依靠 C++ heap,因此當遇到這種狀況時,Java runtime 也會跟著被 corrupted。

Finalizer 另一個可能遇到的狀況,是物件 X 的 finalizer 可能會在 X 的 method 還在執行的時候被呼叫到,但講者說目前 Android 不需要擔心這件事情。

另外,Finalizer 預計會在 JDK 9 的時候 deprecate。另一種情況,當你的應用程式中用了大量的 native memory 以及相對少數的 Java memory,這時單靠 GC 可能還不夠,所以你可能會自己去呼叫 System.gc() 或 System.runFinalization(),但如果太常呼叫會造成應用程式變慢的情形。講者也有提到 Finalizer 也可能會造成延長 Java 物件的的生命週期。

如果對其他 Finalizer 可能產生的問題有興趣的話,可以參考 Joshua Bloch 的 “Effective Java” 這本書中的 “Avoid Finalizers” 這個章節當中。

那麼要如何真正的刪除 C++ 物件呢?講者推薦在結束物件的 scope 的時候呼叫 close 來做處理,但也同時說到,你很難決定要在什麼時間點做這件事情。因此講者給了另一個建議的做法,是使用 PhantomReference 來避免使用 Finalizer,他避免了 Finalizer 可以看到已經被 finalized 的物件,而且他可以確保物件已經真的不被使用的時候才去做 cleanup,這處理掉了一些 Finalizer 的 issue,但還沒辦法處理像是當物件的 method 還在執行時卻可以被 finalized 的問題,要解決這個問題,目前推薦的做法是除了 C++ 的 handle 外,也把 Java 物件的 reference 傳給 C++ 去做處理。目前 PhantomReference 要使用還相對複雜,需要等到 Java 9 的一些支援才會變得容易一些,像是 Java 9 的 Cleaner。

最後講者提到要注意的事情,像是不要在 Java 呼叫 thread-unsafe 的 C++ code,因為某些 Android framework 在內部有使用 C++ code,因此你必須正確的使用那些類別,避免你即使沒有寫 native code,也遇到了前面所提到的問題。

Securing and Optimizing Your App

講者點出了一個開發者的痛點,就是保管 sign key 這件事情。如果 sign key 遺失了,開發者將無法上傳新版本的 apk 給用戶更新,進而被迫取新的 package name 並簽上新的 sign key,變成不同的 app,這對開發者和用戶都是相當嚴重的事情。所以開發者必須要謹慎保管 sign key,不能讓 key 消失或者被盜取,否則將面臨上述麻煩的問題。

Google 為了解決這樣的問題,提出了一套方法來解決,Google Play App Signing,透過 Google Siging 機制,使用者將 siging key 存放在 Google 雲端上,幫助開發者能夠安全的保管 siging keys。先來看看一般的出版流程,開發者會先透過 signing key 來簽署 APK,接著將簽證完畢的 APK 上傳到 Google Play,使用者透過 Google Play 取得當初簽證完畢的副本。

現在,透過新的機制,開發者可以上傳 APK 但用的是 upload key 來簽署,將簽署完後的 APK 上傳到 Google Play, Google Play 檢查 APK 中含有 upload key,並用 upload key 來確認開發者的身份,Play 確定開發者為同一人後,拿取開發者的 signing key 來重簽 APK,使用者從 Google Play 下載到的 APK就是簽過 signing key 的 APK,如同原先的結果一樣,但不同的是 upload key 可以被重新設定,這樣做的好處是,開發者不需要擔心 signing key 不見或被盜取。整個處理的過程很簡單,上傳 signing key,註冊一把 upload key,就可以完成了。

接著,講者對 Google Play App Signing 有更細部的 Security 說明,在傳送 signing key 到 Google Play 的時候,為了避免在傳輸的過程中被人盜用, Google 提供了一個簡單的加密 tool PEPK,藉由 PEPK 增加 signing key 在傳輸過程的安全性。講者接著談到了 Key Management practices,在這系統的 key 並不會暴露在外部,只會拿來簽署 APK。

Upload key 的目的在於驗證開發者的身份,並非用來簽署任何 Android fraework 有關的檔案,因此,這把 upload key 是可以重新設定的,重新設定的方式需要聯絡 Google Play developer operations ,申請 key 需要被重新設定,這需要個幾天的時間來處理。

App Optimizations,講者來述說如何透過 Google Play App Signing 來最佳化 App,開發者提供 upload key 簽署的 APK 給 Google Play, Google Play 驗證是正確的開發者後,將 upload key 移除,在簽署 signing key 之前, Google Play 可以在這段時間來作最佳化的處理。最佳化的處理最顯著的地方在於減少 APK Size,從 Google Play 統計的資料來說,APK 的大小有 20.4% 在 SO, 18.7% 使用在 PNG,就這兩塊來說,就佔了 APK 40% 的容量。Android APK 是一個通用化的檔案,以圖片來說,包含了各種解析度的檔案,例如 mdpi, hdpi , xdpi, xxdpi …,就以 SO 來說,包含了 x86 , armeabi_v7a , mips … 等,但一支手機只會用到一個 so library,一個解析度的圖片,其他的 SO 和圖片資源都是浪費的,Google 在這點做了最佳化的處理,開發者只要上傳簽署過 upload key 的 APK,Google Play 會產生不同裝置所需要的 APK,把不必要的資源移除,藉而減少 APK 大小。

這些 APK 稱作 derived APK,行為和原本上傳的通用 APK 是相同的, version code 這些特有數值都會跟原來上傳的 APK 一樣,但不同的是,會多一個 deriverd APK ID 讓開發者可以去分辨,此外可以透過 Google Play developer Console 去下載到各個不同 deriverd APK 來做測試。Google 提供了一些 EAP 開發者的數據,透過 Google Play App Signing 機制, Deliveroo 減少了 33% 的 App 大小,由原先 13.6 Mb 降至 9.1 MB,Seven 這個 App 減少了 48% 的容量,由 53.7 MB 減少到 28.0 MB

如果開發者想要自行產生 deriverd APK,可以參考以下兩種做法
透過 Gradle config
{
  splits {
    density{
      enable true
    }
    abi {
      enable true
    }
  }
}

或使用 appt2
appt2 otimize app.apk -o app-hdpi.apk --target-densities hdpi

What’s New in Android Security

Google 致力於惡意軟體的防範,過去幾年來投入大量資源更運用機器學習等技術,掃描近單日 500 億個 APP,分析並觀察其行為,期望能保障用戶的資料和裝置安全。雖然近幾年用戶從 Google Play 上下載到惡意軟體的比例已相當低,但仍期望在其之外的範圍也能提供保障。

在這之前 Google 提供 Android Device Manager,然而也坦承也許是命名上的錯誤導致這項服務並不多人知道,新的命名改為 Find My Device,提供裝置電池及網路狀態及最後的定位等資訊。而今年亮相的 Google Play Protect 整合至今 Android 的各項安全服務(Find My Device),也在 Google Play Store 等處呈現 APP 的認證資訊及掃描狀態,讓用戶更加了解裝置目前的安全狀態。安裝不明來源APP 的設定則是更加細分,讓用戶有更大的彈性設定可信任的來源。

對於開發者提供了幾項 API:Verify APP API 檢查使用者的裝置是否安全,進而決定是否進行某些較為敏感的行為;SafetyNet Attestation API 可以確認裝置是否為已認證的 Android 裝置;reCAPTCHA 則提供區分是否為人為操作的驗證。OS Security 的部分,Android O 強化了 Verified Boot、bootloader 的解鎖機制、Encryption 機制、調整 Permission 免於用戶遭受勒索軟體的威脅、透過 Project Treble 改善了 MediaServer 長久以來的問題,也支援 Tamper-resistant hardware 驗證 pin 碼等敏感資訊,Kernel 的部分則是經過分析已知的 Bug 並提出了改善的機制。

APP Security 則是強化了 WebView 與身份/裝置認證。WebView 的 Render Process 在新的版本將會獨立,APP 不再受到任何在 WebView 發生的錯誤影響,除此之外 WebView 也開始支援已在 Chrome 支援已久的 Safe Browsing, 當導向已知的惡意位址可以適時地跳出警告告知用戶。身份/裝置認證則提供了 Key Store API、Key Attestation API、金鑰的保護機制、支援 FIDO U2F Security Keys。

Building an Android Instant App

這部影片將會提供一些例子,並教大家如何開始建立您的 Instant App。

首先先介紹何謂 Instant App?Instant App 是不用安裝也可以使用的 Android App,它可以透過 URL 直接開啟的,這意味著你可以在所有有 URL 的地方觸及你的 App (Improve Discoverability)。Instant App 是 Installable App 的一部分,並非獨立切割出來的模組。他們有著相同的 package id 以及 code base,因此不必為此重開一個新專案。

由於 Instant App 是透過 URL 開啟的,所以你需要實作 Android App Links 使其 URL adressable。將各項功能對應到各 Domain Name 以透過 URL 開啟你相對應的 Activity。越多的功能實作了 URL 入口,代表著你的 App 越容易被觸及。關於安全性的部分,Instant App 也需要透過 Runtime Permissions 確認才能使用到裝置資源或得到使用者資訊。提供 Ad ID and Android ID 但無法得到 裝置識別資訊如:IMEI 、 MAC address … 等。也禁止了 查詢裝置安裝了哪些其他App 以及 System Broacasting。而效能的部分,由於 Instant App 是透過 URL 開啟,當開啟時動態載入,所以各 Instant App 的 module binary 檔案的大小對於開啟的延遲影響非常大。越小的 module binary 越能提升使用者的使用經驗,所以需要將許多不必要的 resource、reference 拿掉。

Instant App 依造 產品功能 切割出許多 Feature Module,性質很接近以前的 Library Module ,但 Instant App 在 Instant App 會包成 .apk 而在 Installable App 則會包成 .aar。你可以將各 Feature Module 共用的程式碼放在 Base Feature Module ,這個 module 會一直存在於 Instant App 中,不過由於 Instant App 是需要動態載入的,所以必須限制每個 module 的大小。

在 Android Studio 3.0 將會有一系列工具幫助使用者建立 Instant App,大致分為四個步驟:

  1. 透過 SDK Manager 設定好 Instant Apps SDK
  2. 為每個入口點建立對應的 feature module
  3. 建好專案的結構來同時建置 Instant App 以及 Installable Apps
  4. 透過 Google Play Console 上傳 Instant App

接下來影片的內容將會一步一步詳細介紹,實作 Instant App 的細節、方法。有興趣的人可以跟著影片 Step by Step 操作練習。

What’s New in Android Design Tools – New Features for Rapid UI Development

Google 希望以具體的呈現 UI 以及互動式的拖拉元件來簡化 UI 設計,因此推出了 Constraint Layout 以及 Android Studio Layout Editor。

Android Studio 中包含了可拖拉元件的 Palette、即時顯示 UI 設計的 Design surface(XML Editor mode, preview, blueprint)、列出元件參數且可對參數進行修改的 Inspector、Component tree、Toolbar、Right-click menu …等。除了這些基本的工具外,比較有趣的是 Inference 及 sample data:Inference 提供開發者在 Design surface 上排列好元件後自動產生每個元件的相對位置的連結,而 Sample data 可以提供 RecyclerView, ImageView, TextView …等元件的即時預覽,只要把相關的資料放進 sampledata 的資料夾就可以。

去年 2016 I/O 發佈的 Constraint layout 1.0 提供了更彈性的 layout 設計,能在 Layout editor 上 操作 UI 元件,並自動的在 xml 中產生,且能以百分比的方式( bias )設定元件該往哪邊靠、加入 Guidelines 供元件對齊、以 Chain 的概念調整一組元件之間的相對位置、更可以將 元件的相對關係放入 ConstraintSet 後切換不同的 ConstraintSet 或 apply 到 layout 上。

除了操作簡單外也能扁平化 layout 提高效能,更重要的是它與 Android Studio Layout Editor 有著高度的整合性。
有興趣的也可以到 constraint layout 的社群看看 https://constraintlayout.com/。

而今年發佈的 Constraint Layout 1.1 beta 1 提供了一些新功能:

  • Place holder:提供了 template 的概念,layout 上的元件利用 id 與 place holder 做對應,系統會自動將元件放在 place holder 上定義的位置,這個對於有些相同元件但排序不一樣的 layout 來說相當方便。
  • Barriers:有點像是 Guidelines 的元件,也提供元件做對齊,但可以設定最大最小值動態調整 Barriers 所 reference 到的元件位置。

還有 Google I/O 2017 Android 相關 Session 摘要 – 下集

This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License.

This entry was posted in Android. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *