作者:KKBOX Android Team,本文經作者授權轉載。原文網站連結

Google I/O 2015 已經結束蠻久了,但是隨著 Google I/O 2015 落幕而開始的 100 Days of Google Dev 卻才剛在9月初結束,Google去年在 YouTube 上大概在 2、3 週內就將 I/O Bytes 的影片全數釋出了,今年改為 1 天 1 部影片,弄得人家心癢癢的不太舒服。

完整影片參考連結:Google I/O 2015 – 100 Days of Google Dev

無論如何,我們部門(編按:KKBOX Android Team)內的成員平時就有在追 YouTube 上的 Google Developers 頻道,所以眾人也順便將 100 Days of Google Dev 的影片做了每篇 2~300 字的中文摘要貢獻給台灣的 Google 相關技術開發人員嘍。因為 100 部影片摘要這個量不算少,將會拆成上、中、下三集。

對了,假如你還沒看完 Google I/O 2014 的 I/O Bytes 影片,可以順便參考我們去年的共筆文件:https://goo.gl/n5pjp4

承 100 Days of Google Dev 上集,這一篇收錄了我們所撰寫的第 34~66 部影片中文摘要,希望透過簡單的文字描述能讓軟體業的 PM/RD 們,從 Google 在 2015 所釋出的技術中,激發一些能夠應用在自己產品中的新創意。

 

34 Web Bluetooth

 

bluetooth 設備由於便宜且耗電量低,用的地方也越來越廣,但有個常見的問題,就是使用者必須安裝特定的 App 來和特定的裝置連線,這樣會安裝太多可能只使用一次的 app;現在可以使用 Physical Web 來做到,Physical Web 是智慧手機的一部分,所以不需要額外安裝 App。

Web Bluetooth 可以讓使用者找到周圍的 bluetooth 裝置並連線,也可以讓開發者做出誇平台的 web App;使用者可以透過 Physical Web 找到周圍的 bluetooth 裝置,並導至對應的 web app,當使用者在 web 上操作後,會透過手機 bluetooth 通知對應裝置並做出適當處理。

35 Fetch API

 

目的:

Fetch API 和 XMLHttpRequest (XHR) 很相似,目的是用來產生 network request 卻又不會像 XMLHttpRequest 系列的 API 一樣,有可怕的 callback 地獄,Fetch API 使用 Promises,可以讓 API 變得更加的簡潔與乾淨,希望能夠使用 Fetch API 取代 XHRs。

內容:

  1. fetch() 相當容易使用,只需要 fetch(url,option),他會以 Promise 的方法回傳回來,不會像 XHR 需要一堆 callback 來處理回傳的資訊
  2. fetch() 使用到 Promise,基本上 Promise 有的特性, Fetch API 都可以使用
  3. Fetch 可以 shared logic 在各個 Fetch Request 之間
  4. fetch mode options 有以下四種
    • same-origin : 只允許相同 origin 去存取資源,其他的 request 將會被 reject
    • cors : 允許相同 origin 和其他 origin 帶有 CORs headers 的 request 來存取資源
    • cors-with-forced-preflight : 在創造 action request 之前必須使用 preflight check
    • no-cors : make request 給其他沒有 CORs header 和其他 opaque response

36 Android Auto Backup for Apps

 

Android M 開始支援備份完整的 APP 資料,而資料是儲存在 user 的 Google account 裡,因此必須使用使用 User 的 Google 帳號登入,若資料是跟著 Device,那就不適用備份的機制。當裝置閒置、連接 Wi-fi 且裝置充電時,才會開始備份資料,而你的 APP 不需要去管理備份的時機,而備份的資料會被加密並儲存在 User 的 Google Drive 裡,也不會佔用到 User Google Drive 的空間額度,但備份資料仍有大小限制,目前一個 APP 的備份資料最大只能 25MB,當備份資料的大小超過這個限制便會停止備份。當 APP 重新安裝時,不論 APP 安裝來源(Google Play或其他第三方的 App Store)與使用的網路連線為何,APP 的備份資料就會被下載並還原。自動備份的功能也可以透過 AndroidManifest 來管理,例如關閉自動備份、只備份特定資料、不備份特定資料。Google 也提到一些較敏感的資料像是 User credentials 或 Device 的 token 則不建議備份詳細設定請參考,https://developer.android.com/intl/zh-tw/preview/backup/index.html

37 Custom Views and Performance

 

繪製 custom view 時常犯的三大類型效能錯誤:重繪並沒有發生變化的東西、畫被擋住不會顯示的部分、在 onDraw() 中跑太多程式碼

所有繪圖動作都從呼叫 VIew.invalidate() 開始,所以如果畫面沒有任何變化就不需要呼叫。必要呼叫時一定要傳送一塊矩形區域給它以提示畫面中有變化的部分,系統會依此協助判定呼叫 ondraw 的時機。

在 onDraw 裡需要儘量避免繪製沒有被顯示或被蓋住的部分,因為繪製每個像素都會對系統造成兩階段 (讀取點陣圖、寫入畫格緩衝區) 的負擔,雖然使用 Canvas.clipRect 可以限制被繪製的區域,在低階 GPU 上效果非常好,但在 GPU 強大的裝置上反而會因為計算 clipRect 而花費過多 CPU 效能,而 custom view 最重要的效能問題就是減少 onDraw 對 CPU 造成的負擔,因此不要繪製任何不需要的東西。
另外 Canvas.quickReject 可識別螢幕外的繪圖物件,回傳值為 true 時(代表完全看不到),就不需繪製。

不要使用沒有硬體加速的繪圖方法
– 硬體加速的方法使用的是 GPU,未支援則是先用 CPU 再傳送至 GPU 做合成
– 請參考網址內表格,http://developer.android.com/guide/topics/graphics/hardware-accel.html

不要在 onDraw 或任何 onDraw 會呼叫到的程式碼中做 new()。

若畫面是動畫, onDraw 會在 UI thread 被呼叫 60次/每秒,非常容易造成 ANR,因此 onDraw 極盡所能節省每一分效能。

38 Google’s International Fonts Noto

 

介紹 Google 所釋出的開源字型 Noto,此字型名稱為 No More Tofu 的縮寫, Tofu 為 Unicode 顯示不出字的時候經常出現的方框,設計此字型的目標是為了不讓大家再看到豆腐。
Noto 已支援 300+ 的語言,它可以幫助開發者在不同的語言當中保持相同的高度,尤其是在同一段文字中出現不同的語言, Noto 會將其正規劃成為相同的粗度及大小,讓使用者較好閱讀。 Noto 也提供了各種不同的 Style 讓我們去美化文字。過往讓程式支援所有語言對於開發人員是種麻煩的事情,有了Noto之後就可以更容易處理字型問題了,歡迎下載 Noto 開始國際化的第一步。

39 Iron Icons — Polycasts #20

 

Google I/O 2013 發表了 Polymer 的 web UI 框架,提供與 Material Design 連續且一致的設計風格。
Google I/O 2015 則正式發佈了 Polymer 1.0 版本。

Polymer 包含 Foundation、Core、Element 三部份。
Polymer library 提供 element sets,是用在 web pages 與 Apps 的標籤。
Iron elements 是一個實用的元素集合,包含通用的 UI 元素與非 UI 元素的功能(如 AJAX)。
其中 iron icon 就是用來支援顯示一個預設為 24 像素的矩形圖示,可以 custom style。

https://elements.polymer-project.org/elements/iron-icon

40 Introduction to Google Cast Remote Display

 

Google Cast Remote 的目的是解決某些遊戲需要大型的顯示器,單純只撰寫遊戲機的版本時,會失去數十億的 mobile 用戶群,這時用戶可以使用 Google Cast Remote API 來試著解決這個問題,這組 API 目前支援 Android 與 iOS。首先用戶會面臨到的是必須設計兩個畫面,一個是電視、一個是手機,在這種情況下手機的畫面及操作方式會比較類似於遙控器,當然 Google 建議你的遊戲需要設計成可以單獨在手機上使用,當偵測到 Google Cast 時才詢問用戶是否切換為 Remote Display 模式。音效方面開發者則不用做任何改變,會像使用 Google Cast 一樣將聲音投放到大型顯示器上播放,手機本身是處於靜音與接收狀態的。

41 Build a video chat app for Android, iOS and the Web

 

Google 介紹了如何透過 WebRTC(註1) 技術建立在 Android、iOS 和 Web 上的串流影片與即時聊天功能。

過去要實現這種功能需要架設伺服器讓裝置間能互相傳送資料,成本較高,透過 WebRTC 可讓裝置間直接點對點連線,無須經過另一台 server。

實作上,需要先取得音樂或影片並轉為串流資料,在不同平台上會依據 API 的差異使用上有些不同
Web: getUserMedia + video tag
Android: VideoCapturer + VideoRenderer
iOS: RTCVideoCapturer + RTCVideoRenderer

接下來傳送資料時會透過 RTCPeerConnection 在裝置間傳送串流與處理 codec 及安全加密部分,在不同平台間也有一些相對應的 API
Web: RTCPeerConnection
Android: PeerConnection
iOS: RTCPeerConnection

這樣的開放技術目前是免費開放給開發者與使用者,可用來應用在文件共享、音樂協作、直播影片、醫療服務、機器人、甚至是遊戲等等。

註1: WebRTC(Web Real-Time Communication) 是一個利用點對點技術支援瀏覽器進行即時語音對話的開源標準 API。

相關介紹
https://g.co/webrtc

42 Improving Urban Mobility By Connecting Citizens

 

本篇在介紹 Waze 應用程式,藉由 App 分享交通訊息,能幫助駕駛人更即時掌握路況,改善交通擁擠問題,用此分享方式稱為「連接公民計畫」(Connected Citizens)。
例如通報交通意外事故、氣候影響、路面坑洞、道路施工、遊行改道等相關資訊,與各城市交通管理中心配合,將彙整的資訊即時廣播給駕駛人提供選擇更理想的路線規劃。
從城市的觀點來看 Waze 帶來的好處: 蒐集資料到交通管理中心、建立政府與市民的溝通管道、累積大量交通數據以幫助做出更聰明的決策,參考:https://www.waze.com/ccp

43 Audio latency: buffer sizes

 

在 Audio 中有一件事是 delay , 例如麥克風從操作系統到編解碼器及放大器到最後的播放器,基本上就是一種 delay ,也因此就需要緩衝。

用雞當例子,一隻雞要過馬路車子都以相同的速度相同距離而要讓雞通過馬路,有一位 Android 上校付責管理雞過馬路的時機點,但有一次上校不小心開錯門讓雞通過,雞代表 Audio 處理程序而車代表音頻硬體用相同速度餵音檔,在車的距離是固定的緩衝區,而上校是 kernel 控制調度音頻編碼如何運作,但在調度出錯時在 UI 或視頻就是被當作被丟棄的 frame,如果只是偶爾發生是還好,但如果太常發生沒有人會喜歡的。

用 systrace 工具可以觀察這些問題,在例子一個音頻花 130毫秒完成,這有可能是發生了 delay 此時通常都是加大 buffer ,但這不一定是最好的方法,在 kernel 中解決這些問題,目前正在與一些設備合作夥伴解決此問題。這樣就可以讓 buffer 變小,並降低音頻 delay 。

44 Batching Background Work Until Later

 

教您的 App 如何省電。效能跟省電脫不了多少關係,擁有高效能就要 Doing less works。
一般 App 都會連接多種硬體,啟動越多也就越耗電,所以硬體廠為了節能需求,設計了不同階段的 Sleeping 和 Waking 模式,例如 WCDMA 的四個階段做省電。
只要沒有人使用該硬體,就會進入睡眠模式做省電。但問題是每個 App 都有自己的背景執行lifecycle,手機在每個時間點,都有不同 App 排程要做,這樣手機無法真正的 Idle,無法 Idle 就無法進入睡眠模式讓手機省電。Android 提供了幾三種 API 來做到把所有 App 的背景執行排程整合在一起。第一,可以使用 AlarmManager 這個 class 是最簡單的,利用 AlarmManager.setWindow() 來執行單次排程,如果想要用重複排程的話,就使用 AlarmManager.setInexactRepeating(),最後也是最不建議的,需要確切執行時間點時,例如鬧鐘 App,AlarmManager.setExact()來執行。第二,也是比較複雜的,可以使用 SyncAdapter 達成,可以提供批次的排程,還有自動重試的機制。最後,如果您的 App 只支援 5.0 的話 JobScheduler 是你最好的選擇,它整合以上 AlarmManager & SyncAdapter 機制,使用起來也更方便,可排程指定條件 (例如:充電中、使用 Wifi…等等),只要使用 JobInfo.Builder 這個 API 來達成以上目的。

45 Developing with Beacons

 

Beacon 就像古早的燈塔一樣,指引著人們所需要的資訊。Google 提供了一種名為 Eddystone 的開源共通格式的 beacon,讓它有著跨平台的特性。在 API 方面,App 可以透過 Proximity Beacon API 在 developer console 註冊以及存取一些配套資料,容量限制在 1K 之內,當然他們並不希望你將圖片編碼後丟入。另外一支則是 Nearby API,App 利用來發現附近的信標,並找出與當下情境相關的內容,比如行進的公車班次或是某間商家。想知道更多細節可以到這些地方:

Google beacon platform
developers.google.com/beacons

Google Nearby
developers.google.com/nearby

Eddystone
github.com/google/eddystone

46 Using Nearby with Beacons

 

使用 Nearby message API 可以從 beacons 抓取資料再將資訊傳到手機上的 App。舉例來說,當你經過一個公車站,beacons 可以傳輸公車到站資訊到你的手機上,如果你常搭的公車已經過站了,它還可以提供其他路線給你!

要開始使用 Nearby message API 之前有三個步驟:
1. 你需要有 beacons,確認你的 beacons 是支援 Eddystone format。
2. 找到 beacons 供應商讓 App 可以啟動開啟廣播與訊號功能,使用 Beacon API 註冊一些資料到這些 beacons 上,這些資料就是當你的手機遇到 beacons 後 Nearby message API 會回給你的資料。
3. 如果你成功整合 Nearby message API 到 App 裡,當 App 開啟時他會自動搜尋附近有沒有你註冊過的 beacons,詳細的使用方法可以參考相關網站與文件。

47 Nearby Messages

 

Nearby Messages 可以讓 Android 或 IOS 之間在短距離互相通訊。
可以很方便的設定特定的群組、共同會議、分享資料給處於同個空間的人們,使用 publish – subscribe API 在相距一百英尺內的裝置間傳遞訊息,可由 wi-fi, bluetooth, ultrasonic modem 來分享。

Nearby 的預設範圍是 100 英尺,在某些情況下可能會太遠,我們可以限制 Nearby 的範圍到 5 英尺在只使用 ultrasonic modem 的場所,可以在 publish 前使用 Strategy.Builder.setDistanceType(DistanceType.EARSHOT)。
有幾個設計時的注意事項,不要讓 publish 或 subscribe 一直在開啟的狀態,否則會很耗電;要有明確的 button 來開啟 Nearby;離開程式時必須停止所有正在活動的 publish 或 subscribe。

48 Introduction to the Physical Web

 

目的:
有越來越多的 smart 實體裝置在公共區域或家中可以使用,例如販賣機,公車站,玩具,公車 …諸如此類的裝置,但這些裝置一直缺乏一個可以和手中智慧型裝置簡便產生互動的方法,以往我們要控制實體裝置,就必須要安裝特定的 App 才可以接送裝置的訊息,這並非我們所想的,我們希望能夠更加簡便的取得這些裝置的訊息,就像看 web 頁面一樣,輕鬆點擊就能取得所需要得資訊。
例如到公車站牌附近,就會有公車到站的相關資訊傳送到手機,或是到電影院,就會傳送電影上檔相關資訊到智慧型裝置之中,諸如此類的應用。

作法:
Physical Web
1. 使用 low engery bluetooth 裝置每秒不斷的發送 URL,這些裝置只需要五年充一次電(這麼神?)
2. 手機需要有 scanner 的程式,接收 URL 導到 web page 或使用 App deep link 瀏覽 App
3. URL 種類有三種,完整可以互動的 web page、簡單小型的 web page、App deep link

範例:
路邊停車計費裝置與手機互動收費流程
1. 路邊停車計費裝置發送 URL
2. 手機收到 URL,導到實際的 standard URL on Server
3. Server 收到手機 trriger 後,開始和路邊停車計費裝置連結
4. 三方形成 connection loop ,對手機的使用者來說,他就像在瀏覽網頁一般輕鬆

49 Gaming with Android TV

 

如何讓你的遊戲 APP 也可以在 Android TV 上執行:

  1. 調整 AndroidManifest,isGame、banner、Leanback 的支援(required設為 false)、gamepad(required設為 false)、configChanges
  2. 新增顯示在 Android TV 上的 banner 檔案,每種語系都要一張 banner,大小則是320 * 180,banner 通常具有辨識 APP 的文字,例如 APP 的名稱
  3. AndroidManifest 中必須明確的定義在 Android TV 不需要哪些硬體的支援,例如觸控螢幕、相機、Accelerometer…等
  4. 使用 UiModeManager 在程式中判斷裝置是否為 Android TV
  5. 使用 PackageManager 在程式中判斷硬體是否支援,例如是否可以觸控螢幕
  6. 須考慮 Android TV 的網路還可能連接到 Ethernet
  7. 注意遊戲控制的裝置,有遙控器和進階的遊戲遙控,必須在 Play Store 明確說明
  8. UI 上需要注意 Android TV 的特性,橫向、Overscan…
  9. 將 Android TV設定為主螢幕,手機設定為第二螢幕呈現遊戲控制的選項也是可行,詳細請參考 Nearby Connections

50 Android Auto Voice Actions

 

車子上的 Android 非常需要聲控支援,原本已經支援普通簡單的聲控,但現在可以支援呼叫各類播放器播放音樂。
支援播放需要:

  1. 在 AndroidManifest 加入 intent-filter action [android.media.action.MEDIA_PLAY_FROM_SEARCH]
  2. implement MediaSession.Callback 並 override onPlayFromSearch(String query, Bundle extras)

其中 String query 會是 keyword,Bundle extras 則會由 Google 幫你判斷 keyword 是哪種類型,但這不一定準確,因此仍要準備僅用 keyword 搜尋的狀況,另外 keyword 也有可能是空的。
若無法很及時地搜尋出結果,請將 playback 的 state 設置為 PlaybackState.STATE_CONNECTING 並將搜尋行為擺在 async thread 中。

控制指令的部分需要在 onCreate 時就 new MediaSession(this, “Music Service”),再對它setFlags(MediaSession.FLAG_xxx|MediaSession.FLAG_xxx),然後 override callback 中的相關指令。

51 Smaller Pixel Formats

 

PNG 、 JPG 和 WebP 這類壓縮圖片格式可以有效減少 App 及傳輸時的檔案大小,當圖片讀取到記憶體當中時,會恢復未壓縮的原始狀態。借助 Android 的內建功能,可以降低圖片所佔用的記憶體 Heap 空間來改善記憶體使用較率。
Android 內建圖片機制採用 32 位元 pre 像素的格式,也就是 RGBA 各 8 位元的方式了表示一個像素,即使 JPG 不包含 alpha 係數,當讀入記憶體時每個像素還是會用掉 32 位元。為了解決這個問題, Android 提供了一些替代性的像素格式,供使用 BitmapFactory 產生 Bitmap 時使用:

  • RGB_565 : 16 bits/px
  • ARGB_4444 : 16 bits/px
  • ALPHA_8 : 8 bits/px

當然,這麼做的代價就是用畫質換取記憶體的空間,但只要使用得宜,就能降低 CPU 和 GPU 的使用量,進而減少 Heap 分散情形已改善效能。最後記得,如果你想要讓應用程式效能最佳化,就必須在記憶體使用大小、載入時間和畫質間取得完美的平衡。

52 Unlocking Location Context with the Android Places API

 

利用 Places API 取得使用者的位置,根據座標提供更有用的資訊,幫助使用者探索他們的周遭環境。
若要存取 place API,App 需包含 Google Play 並提供 API_KEY。
GeoDataApi 可以存取 Google 的資料庫,取得本地地方資訊與商家資訊。
PlaceDetectionApi 可以快速存取裝置的目前位置,並且可以報告裝置位於某個特定位置。

使用限制如下:
預設:每日每個應用程式每 24 小時期間能有 1,000 個存取要求。
計費:若啟用則需驗證身分,成功的話就會增加到 150,000 個要求。
大於 50 萬:Google 會主動聯繫~!!
若超過使用限制,則存取功能會失效。

53 Cast Ux Connection Logic

 

在使用 Google Cast 的時候,當使用者離開了原本的 wifi 區段並回去原本的地方,由於使用者並未 disconnect ,所以偵測是否在同個 wifi 區段並且重新連接,我們稱之為『 Reconnection Logic 』,這對於好的使用體驗來說非常的重要。
當播放影片的使用者 disconnect 時, cast 裝置則需要馬上停止播放,改為由 source device 進行播放。但是當多台裝置同時連接到同一個 cast 裝置時,當正在播放影片的人進行 disconnect ,則影片應該繼續播而不該中斷,因為還有其他人正在觀賞影片,我們稱之為『 Multisyndicapability 』。記住以上準則,你可以給使用者良好的 Cast 體驗。

54 Video actions and movie reviews

 

這篇主要在介紹 Google Search 背後龐大的知識網,以及開發者如何透過 html scheme 共同為使用者提供更好的搜尋體驗。

生活可能艱苦,人們會選擇看電視或電影讓生活更美好,但要找到好節目內容來觀看卻不容易,太多片斷性的資訊內容、閱覽模式等,讓觀眾無從選擇。

為了解決問題,Google knowledge graph 提供了結構式的內容架構,將幾十億筆的人、事、物互相連結,使得 Google 能夠回答所有簡單或困難的問題,例如查詢某位名人的年紀、評價某兩部電影、某部電影的播映時間甚至是你和某位明星的六度分隔數有幾人(註1)等等。

Google 在搜尋結果也優化了列表,提供推薦清單,讓搜尋結果更準確,一個點擊就能是正確答案,這部分也需要內容開發者的共同協助,提供更準確的 scheme tag,讓其他人可以輕易地搜尋到相關資訊。

相關文件:
https://g.co/SearchCriticReviews

註1: 六度分隔理論(Six Degrees of Separation,這個世界上平均只需要5個中間人就可以聯繫任何兩個互不相識的人。

55 Fit DevByte

 

健康對我們每個人至關重要,在生活中我們往往沒有意識到一整天其實做了很多關於健身的活動。像是當你走樓梯的時候,追公車的時候,甚至休閒時間打電動的時候。
Google Fit 能提供追蹤您所有活動資訊的功能,讓您知道做了甚麼鍛鍊身體的運動,像是武術、拳擊、舞蹈、足球、網球、高爾夫、攀岩甚至泛舟等等超過一百種以上的活動項目。
開發人員可以應用 Google Fit 這個追蹤活動功能,很大機會的開發出前所未見的應用程式。

56 High Performance Video for the Web

 

影片一開始是在倫敦維多利亞車站,在當下的 wifi 受到多人連結的頻寬限制,在這情況下如果要提供一個良好的 video 觀賞可能是件頭痛的事。

video 或 audio 可以提供許多設備播放,但通常連結是多變的頻寬也是受限的,所以提供了一個機制稱為「 DASH 」,在一般的 http 播放影片時會依照不同情況提供不同的位元率或格式,在不同的設備用戶可以選擇最佳的版本。

DASH 是什麼,他是 Dynamic, Adaptive, Streaming 及 HTTP ,而在網路做 DASH 最佳的方法是使用 shack player,要做 Dynamic 的視頻解決方案可能很複雜,而 shack player 使用簡單的 JavaScipt 就能提供最好的視頻。

首先,安裝 polyfills 為一般的瀏覽器,然後在上面創建 shack player,然後提供 DASH 的網址,接下來提供頻寬的分辦,只要幾行的 code 就可以做到這些。

而有後端只需要做 video 的編碼及準備串流檔案,而 shack player 還可以傳遞受保護的內容,使用 EME 做解密,shack player 還支持多國語言的內容,shack player 在 github 上有許多教學及功能說明可以提供了解

57 Memory Profiling 101

 

教你怎麼看 Memory,首先先來瞭解 Memory graph,淡藍色的部分是預估可以使用的記憶體,已配置的則為深藍色,另外一張可以知道 GC 回收的情況,太多的 GC 也會影響效能。首先先在 DDMS 點選 Heap Viewer,按下 Update Heap button 開始錄製,點選右側欄 Heap 分頁可以觀看詳細資訊,點一下 Cause GC 就會更新資料,這裏上半部你就可以看到您的物件,物件類型,以及各佔有多少記憶體大小,點擊該項目就可以在下半部看到 Number of allocs,這時候你就可以觀察記憶體狀況,如果 Activity 已經 Destory,但你所觀察的物件還在,那你可能要解決一下 Memory leak 的問題。在 Android Studio 也有對應的功能,叫做 Allocation tracker。您只要點選 Start allocation tracking 開始錄製,把玩一下您的 App,再來點選 Stop allocation tracking 停止錄製,然後就會顯示 Allocation 列表,點選細項會顯示 Call Stack,善加研究之,您就會發現問題點,然後修正您的程式。

58 The Performance Lifecycle

 

 

大多數開發者通常都會疏忽效能調校,直到發生了問題時才會意識到重要性。儘管如此,我們仍應該在開發週期中隨時注意這項工作。

基本上分為 3 個階段:收集資料、深入分析、展開行動。

在問題發生後,我們一開始可能找不出原因,這時候就需要利用各種工具收集相關資訊;在收集到資訊之後,又要如何解讀呢?這時就必須深入分析。步驟 1 跟 2 不是先後關係,而是互為因果,所以在你利用工具取得資料並且解讀後,可能又需要利用另外一個工具。例如利用 TraceView 查詢捲動時發生的各種事件,分析資料後發現記憶體對效能產生的影響,這時便需要轉而使用 Allocation Tracker 調查原因。最後我們進入最困難的階段,動手修復問題,值得注意的是,修復程式後,效能也不一定會恢復。另外為了不影響原本的專案運作,在修復問題前,最好事先擬定周全計畫。只要程式不穩定,我們應該保持這個週期程序,將各個部分調校到穩定為止。

59 Smaller PNG Files

 

PNG 是無失真影像壓縮格式,雖然畫質比較好但是檔案卻很大,如果直接從 server query PNG 原始圖檔會浪費使用者的網路頻寬,為了從 server side 拿到 PNG 圖檔,必須先將 PNG 作最佳化的處理,Script PNG 是一套針對 PNG 做壓縮處理的工具,它可以在畫質不受影響的前提下去執行不同的壓縮轉碼器。

然而在有些情況下其實不需要用到 PNG 檔案,例如:當你的圖片不需要透明效果的時候,JPEG 會是一個更好的選擇。如果你想要兼具透明效果以及良好的壓縮率則可以使用 WebP,Web P 是 google 開發的開放原始碼的影像格式,它支援透明度調整,不失真壓縮以及影像動畫,現在 Android 4.2.1 以上版本都已內建支援 WebP,要值得注意的是,WebP 跟先前提到的不失真壓縮處理都只能幫助在發布過程中減少檔案大小, 一但圖片載入到記憶體中就會解壓縮成為原來的格式,這代表著壓縮圖檔只對資料傳輸有幫助,對 CPU 與記憶體的使用率則完全沒有影響。

60 Pre-scaling Bitmaps

 

我們在 APP 中常用到 bitmap,但如果 bitmap 的記憶體用量大於畫面實際顯示的大小,那這些 bitmap 可能就會導致效能上的問題,要解決這種問題,調整 bitmap 大小是很好的辦法,Android 中就有提供許多縮放 bitmap 的 API,如 createScaledBitmap(),可以將圖片設為想要的大小,但需要現有的圖片才能運作,更理想的方法是在載入 bitmap 時就調整 bitmap 大小,此時可以使用 BitmapOptions 的 inSampleSize 這個參數,只要將此參數設定為大於 1 的值,則可以縮小圖片,例如設為 2,則傳回的圖片就會是原來的 1/2 大小,一般來說縮小的比例是 2 的次方,如果不是,則會用到 BitmapOptions 的 inScaled, inDensity, inTargetDensity 參數。
重點是如何取得圖片實際大小,我們必須先設定 bitmap 的 injustDecodeBounds 值,再為圖片檔案解碼,就可以得到圖片的寬跟高,最後再將圖片做縮放。
目前已有穩定的 library 可幫助處理這些問題,如 Glide, Picasso。

61 Android Development Patterns

 

嗯…Android Development patterns comming soon …XDDD

62 Re-using Bitmaps

 

透過物件池的概念解決使用大量 Bitmap 造成 APP 效能不佳的問題,當使用完物件不馬上釋放記憶體,而是將 Reference 記錄下來,之後需要同類型的物件時,只需要重複利用之前記錄的 Reference 而不需要重新向系統取得記憶體。如何將物件持的概念套用至 Bitmaps

  1. 設定 BitmapOptions.inBitmap 使用先前記錄的 Bitmaps Refernce
  2. 注意重複使用的 Bitmaps 大小是固定的,因此 SDK 18 以下會有 Bitmaps 大小的限制,19 以上則沒有限制
  3. 不同的像素格式使用各自的物件池
  4. 物件池中可以建立各種常用格式或大小的 Bitmaps

如果覺得自己做物件池很麻煩,也可以使用第三方的函式庫 Glide

63 Tools not Rules

 

不要盲目相信網路上關於效能改善的建議,有可能對方測試的裝置與你不同,有可能對方遇到的問題在你的 App 內並未造成影響,還有可能後來出的平台已經解決這個問題。

你應該先用你的應用程式跑一遍效能工具,然後只著重在會影響你的 App 的問題上,並定期重跑。

另外建立可評估效能的單元測試也是很好的方法,活用自動化工具搭配資料導向的程序,而非網路偏方,才是抓出效能問題的最佳解法。

64 Android Performance Patterns – Performance Anxiety

 

經實驗的結果表示,在 Android 平台上使用 ArrayList 並使用 index 的方式去存取資料是較有效率的,這篇的重點在於與其盲目的去相信網路上的效能偏方,不如自己來動手做實驗去測試如何效能為佳化。根據這部影片的其他 Reference 有說到,一個效能偏方不一定適用在所有地方,也不是所有地方一定要使用最佳化的方式,你可以透過 tool 去幫助你觀察效能瓶頸,根據有問題的地方再做改善即可。

65 Fun with ArrayMaps

 

Collections 的管理對 App 的效能有很大的影響,如經常使用的 HashMap,雖然非常好用但卻很佔用記憶體,因此提出效率更高的 ArrayMap。
ArrayMap 使用了兩個 small arrays,一個記錄 key 的 hash list,另一個按 key 的順序記錄 key-value list。

當存取 value 時, ArrayMap 會將 key 轉換為 hash 值,再對 hash array 使用 binary search 找到對應的 index,然後根據此 index 在另一個 array 中取得 key-value。
若在 key-value list 的 key 和前面輸入的查詢 key 不一致,就是發生了 collision,則利用 binary search 解決。

ArrayMap 使用的 memory 是連續的,所以資料量大時,逐一比對也會花較長時間。
因此在新增、刪除、查詢時,則需考量時間與空間的權衡,若考量速度則需選擇 HashMap,反之則為 ArrayMap。
而在 indexing compare 時,ArrayMap 也可直接存取 value,不需透過 iterlator。
當資料量為 0 時,HashMap 仍然會佔 memory,但 ArrayMap 則不會。

ArrayMap 適用條件:一千筆內的資料、包含 Map 結構的資料。

66 Back to school with the Classroom API

 

Google Classroom API 是個提供給老師與學生的課程管理 API,使用 Restful API 的設計讓開發者可以更彈性的使用,透過 API 可以:

  1. 新增課程,並設定課程的相關資訊,課程名稱、地點、描述
  2. 提供課程作業的功能
  3. 設定課程的狀態,Provisioned, Active, Archived, Declined, Upspecified
  4. 透過 Google Admin SDK 回傳的 user unique ID 或 email 操作各種 API
  5. 老師可以建立課程並使用 API 讓學生參與課程或發送課程邀請,而學生則可以接
    受課乘邀請並取得課程的相關內容
  6. 分享課程只要建立對應的 UI 並加上提供的 js resource 就可以完成
    詳細內容請參考 https://developers.google.com/classroom/

熱門新聞

Advertisement