2012年10月21日 星期日

[Reading] 心願清單 - chapter 1

以為還有時間慢慢說 瞬間卻再沒有機會

僥倖的把以為的不重要寄託在之後

能有下一次機會 是幸運是緣份

[Android] Avoid Memory leak

  • 當記憶體不足,system 就必須暫停你的 application,執行 garbage collection,通常暫停的時間很短暫讓 user 感覺不到,但若是在移動 scroll 或是遊戲戰鬥中,可以感覺到效能和回應的下降。
  • "leak" meaning you keep a reference to it thus preventing the GC from collecting it.
  • 在 Android 中,一個 Process 只能使用 16M 記憶體(模擬器為 8M?),若是超過變會引發 Out-of-Memory exception(OOM)。


容易占據大量記憶體的行為:
  • view layout
  • drawing method of a view
  • the logic code of a game


Context Leak
keeping a long-lived reference to a Context.

Context 最常用來載入和存取資源,在 app 中一般會有 Activity and Application 兩種 Context
  • setContentView(new TextView(this));
  • 表示 the entire View hierarchy and all its resources reference 到這個 activity,有可能會使得此 Context leak。

可用以下兩種方式避免 Context leak:
  • 不要將 Context 使用在自己的 scope 之外。
  • 使用 Application context。
    • This context will live as long as your application is alive and does not depend on the activities life cycle. 
    • If you plan on keeping long-lived objects that need a context, remember the application object. You can obtain it easily by calling Context.getApplicationContext() orActivity.getApplication().

In summary, to avoid context-related memory leaks, remember the following:
  • Do not keep long-lived references to a context-activity (a reference to an activity should have the same life cycle as the activity itself)
  • Try using the context-application instead of a context-activity
  • Avoid non-static inner classes in an activity if you don't control their life cycle, use a static inner class and make a weak reference to the activity inside. 
    • The solution to this issue is to use a static inner class with a WeakReference to the outer class, as done in ViewRoot and its W inner class for instance
  • A garbage collector is not an insurance against memory leaks


Bitmap Leak
  • 避免 Bitmap Leak 就必須使用 recycle 機制,適時的將不需要顯示的 Bitmap 物件回收。
  • 但還有另一種狀況: 產生 Bitmap 的時候,明明還有許多記憶體,卻發生了 OOM。
    • 假設現在產生了一個 13MB 的 Int array 物件,在使用完之後立即 recycle,照理說會空出 13MB 的空間,這時候繼續產生一個 10MB 的 Int array 物件不會有任何問題,反而生成一個 4MB 的 Bitmap 卻跳出OOM。
  • 在 Android 中,一個進程的記憶體可以由 2 個部門組成:Java 使用記憶體,C使用記憶體
    • 這兩個記憶體的和必需小於 16 MB,不然就會出現 OOM。
    • 而分配給 Java 使用的記憶體,縱使這塊記憶體被釋放了,也還是只能給Java的使用,所以就算釋放 Java 佔用的佔用了一個大塊記憶體,C 能使用的記憶體 = 16M - Java 某一瞬間占用的最大記憶體。 
    • 而 Bitmap 的生成是路程經過過程 malloc 進行記憶體分配的,佔用的是 C 的記憶體,這個也就說明了,上面所說的的 4MB Bitmap無法生成的原因,因為在 13MB 被Java用過後,剩下 C 能用的只有 3M 了。

補救方式
  • 使用 BitmapFactory.decodeStream() 產生Bitmap。
    • 儘量不要使用 setImageBitmap,setImageResource 或 BitmapFactory.decodeResource 來設置一張大圖,因為這些函數在完成 decode 後,最終都是通過 java 層的 createBitmap 來完成的,需要消耗更多記憶體。
    • 因此,改用先通過 BitmapFactory.decodeStream 方法,創建出一個 bitmap,再將其設為 ImageView 的 source,decodeStream 最大的秘密在於其直接調用 JNI >> nativeDecodeAsset() 來完成 decode,
    • 無需再使用 java 層的 createBitmap,從而節省了 java 層的空間。
    • decodeStream 直接拿的圖片來讀取位元組碼了,不會根據機器的各種解析度來自動適應,使用了 decodeStream 之後,需要在 hdpi 和 mdpi,ldpi 中配置相應的圖片資源,否則在不同解析度機器上都是同樣大小(圖元點數量),顯示出來的大小就不對了。
  • 設定圖片的 Config 參數,可以跟有效減少載入的記憶體。
    • BitmapFactory.Options inSampleSize:值越大解析度越小,佔用memory也越小。
  • 在 onPause/onStop/onDestory 時, 將沒用到的 Bitmap release(用recyle())
BitmapFactory.Options opts = new BitmapFactory.Options();
// Options 只保存图片尺寸大小,不保存图片到内存
// 缩放的比例,缩放是很难按准备的比例进行缩放的,其值表明缩放的倍数
// SDK 中建议其值是2的指数值,值越大会导致图片不清晰
opts.inSampleSize = 4;
Bitmap bmp = BitmapFactory.decodeResource(getResources(), mImageIds[position],opts);                              
 ...               
//回收
bmp.recycle();


* Reference
- Tracking Memory Allocations | Android Developers
- Avoiding memory leaks | Android Developers Blog
- (转)内存溢出的解决办法 Android - 攀升·Uranus - C++博客
- Android開發——解決載入大圖片時記憶體溢出的問題 @ 資訊園 :: 痞客邦 PIXNET ::
- GiveMePasS’s Android惡補筆記: 如何改善Bitmap所帶來的Out of Memory(OOM)問題
- Re: [問題] Bitmap OutOfMemory 永遠的痛 - 看板 AndroidDev - 批踢踢實業坊
- Andorid , Object-C and Java Programming Learning: [Android]Android Out Of Memory(OOM) 的詳細研究

2012年10月20日 星期六

[Android] Dialog error - Unable to add window token null is not for an application

Error Message

Unable to add window token null is not for an application


Occurred when 

使用 getApplication() 去建立 dialog,必須使用 Activity (extends Context) 才行。


* Reference
- AlertDialog显示错误 Unable to add window token null is not for an application - Trinea @Java @Android 体验 技术 营销 - ITeye技术网站

[javascript] Different result of String.length for browsers

javascript 中使用 String.length
  • chrome, FF
    • 換行視為 \n => 1 字元
  • IE
    • 換行視為 \r\n => 2 字元

Solution
在 IE 中,先將 \r\n replace 為 \n 再取得 length。

2012年10月16日 星期二

[Android] layout qualifier

ex: In API 3.1

layout resource...
  • only in layout-w720dp -> crash
  • only in layout-xlarge -> ok (3.2 also ok)

cannot use layout-xlarge-w720dp!

[JPA] @Embedable and @Column

C extends P

If C and P are Embedable...

得 Override getA() method

否則 A 不會 mapping 到 等於沒有寫 @Column 的意思


[Spring] URL decode

Springframework will do URL decoder.


2012年10月11日 星期四

[Hardware] RAM, SSD

RAM Disk
  • 通常是利用軟體的方式,將動態記憶體(Dynamic Random Access Memory,DRAM)模擬成硬碟裝置的一種技術。
  • 斷電時資料會隨之清空、流失,讀寫速度爆快,壽命又很長的存放空間。
    • 資料存放位置就是記憶體,所以斷電後記憶體內的資料就會消失,因此並不算是個穩定的存取空間,只能把它當作是一個超高速暫存空間利用。
  • 不像傳統硬碟採用馬達與磁片等機械裝置,而是靠電子訊號傳輸,因此在分類上也算是固態硬碟。
  • 不像NADA Flash般有寫入次數限制。再加上依靠電子訊號傳輸,沒有機械損耗疑慮,因此壽命比起傳統硬碟或SSD都來得長了許多。只要記憶體不過分加壓超頻,再加上記憶體大多是終身保固的情況下,要說RAM Disk永遠不會壞也是可以的。
  • 效能會受到軟體、記憶體時脈、晶片組的記憶體通道數而有所不同。
  • 扣除軟體差異,記憶體時脈越高則效能越好,而四通道平台又比雙通道來得快一些。


HDD (Hard Disk Drive)
  • 由馬達、磁片與讀寫頭等機械裝置所構成的,因此會有磨損問題


SSD (Solid State Disk)
  • 從前還沒發明積體電路、電晶體的時候,電腦是由真空管所組成,電子在傳遞時,並不是百分之百地經過固體傳導,而是會流過一段真空的路徑。
  • 現今的電晶體其實也就是將矽做成能讓電子在裡頭流動的、交錯複雜的晶體管線,而成份全部都由固體所構成,因此叫做「固態硬碟」也十分名符其實。
  • 與傳統硬碟的要差別在於裡頭完全沒有機械構造,不會有吵雜的馬達運轉聲與磁頭讀取聲,因此有耐震、安靜等特性,而且對比傳統硬碟需要較高電流以啟動馬達運轉,SSD就節能多了。

記憶體顆粒
  • 如果你打開過固態硬碟,可以發現裡面沒馬達、沒碟片、也沒磁頭,就只有一顆一顆像是電腦上插著的記憶體模組般的黑色顆粒一樣,這種晶片稱為NAND Flash。
  • SSD其實它就跟他的近親「USB隨身碟」一樣,是將資料儲存在快閃記憶體中,不過這些顆粒並不像 RAM 一樣,斷電或是重新開機以後,資料就會消失,而是會將內容資料儲存起來。
  • 視顆粒差異,有著幾萬次到十萬次資料寫入限制。

NAND又區分為兩種儲存形式:
  • SLC
    • 是單層式儲存,一個單元只能儲存一個位元,可以表示0及1。
    • 壽命較長,約10萬次左右
    • 存取速度也比 MLC 快
    • 雖然SLC在性能上比MLC優良不少,不過受限於成本過高,常常都是mlc產品的兩倍價格以上。
  • MLC
    • 可以一次儲存2個位元,分別可表示為00、01、10、11,因此儲存密度比SLC高,當然成本也比較低。
    • 壽命較短,只有一萬次的存取次數。
    • 目前由於MLC製成精進,也應用了多通道技術,讓MLC的讀寫速度得以跟上SLC,市場主流產品多是以MLC為主,SSD的價格也不像以往那樣高不可攀了。

控制晶片是SSD的大腦
  • 除了記憶體顆粒以外,SSD中最重要的零組件是控制晶片,控制晶片決定了一顆SSD支援的功能,在控制晶片中主要負責三項工作,分別是:
    • 自動錯誤校正
    • 故障區塊管理
    • 平均抹寫儲存區塊。
  • 目前主要的控制晶片廠牌有Sandforce、Marvell、Samsung、JMicron等。

韌體好壞決定效能穩定性
  • 韌體是SSD效能的靈魂,雖然市售的SSD很多都是採用相同控制器,不過生產廠商調校韌體的功力卻大大影響了效能及穩定性。
  • 所以常常聽到玩家會為了有更好的效能而購買大廠牌的SSD,這也是因為雖然控制器廠商就那幾家,但通常大廠的韌體也寫得比較好,不僅可以修正一些影響速度的bug,也可以增加更多實用的功能,幫助SSD能取得更好的表現。
  • 此外,傳統硬碟買來以後,除非遇到重大缺失,不然其實不太需要更新韌體,不過SSD有沒有更新韌體,表現就會差很多喔。


* Reference
- 比 SSD 更快,RAM Disk 攻略:4種應用、4個實測、軟體效能大車拼
- SSD調教實戰(1):原理篇

2012年10月10日 星期三

[Android] ListView Tips

In order to avoid blending and make the rendering faster while scrolling/flinging, the ListView widget uses a ’scrolling cache’ mechanism.
  • ListView 背景預設為透明色,所以會看到 window 預設的背景色,深灰色 (#FF191919)
  • 為了滑動效能,the Android framework reuses the cache color hint.
  • 若 scrolling cache is true,那麼當 color hint is set,the framework 複製 ListView 中的每個 child 為 bimap 並且設該 hint value.
    • the framework copies each child of the list in a Bitmap filled with the hint value. ListView then blits these bitmaps directly on screen and because these bitmaps are known to be opaque, no blending is required. (?)
    • This mechanism consists on taking an opaque screenshot of all visible child Views (in other words, it draws the content of each itemview in a Bitmap) and directly draws those screenshots when necessary. 
  • 因為預設的 cache color hint is #191919,所以在滑動時會看到 item 的黑色背景。
    • The color used to make those screenshots opaque is the one given by the cache color hint.
    • If your ListView turns opaque (black for instance) when scrolling that because you need to set the cache color hint to the actual color of your ListView background.
若不想看到這黑色(cache color hint)背景(也就是關閉此優化方式),可以在 xml 設置 android:cacheColorHint="#00000000" 即可。


CharArrayBuffer
Cursor#getString() 每次呼叫都會建立 String objects,而且這些 objects 當 user scroll ListView 時就會被回收,所以為避免這樣的建立與回收物件,CharArrayBuffer 儲存 cursor 中的 data,然後直接從 CharArrayBuffer 中存取,reuse。


Using a color as part of your list selector may entirely fill your ListView.
This problem comes from the fact a ColorDrawable does not respect its bounds: it entirely fills the clip rect of the Canvas in which it is drawn into.

Solution
Use a Drawable that respect its bounds such as a GradientDrawable or a NinePatchDrawable.

 
   
* Reference
- AndroidDevBlog » ListView Tips & Tricks #2: Sectioning your ListView
- AndroidDevBlog » ListView Tips & Tricks #3: Create fancy ListViews
- Why is my list black? An Android optimization | Android Developers Blog

[Android] background of android.R.style.Theme_Holo_Light_Dialog

Situation

在 Activity 中設定 android.R.style.Theme_Holo_Light_Dialog

並將此 theme 的背景設為半透明

(Using custom style extends android.R.style.Theme_Holo_Light_Dialog)

開啟畫面時 預設會 focus 在 editText 而跳出 soft keyboard

dialog background 會由半透明變成全黑

But! 相同方式 若是在 AndroidManifest.xml 中設定 theme

即使跳出 soft keyboard 背景也不會變黑?!


Record

soft keyboard is a dialog on window top.

而預設的 soft keyboard dialog style 的背景是黑色的

是否是因為此背景使得 Activity 也轉為黑色背景?


* Reference
- How is the soft keyboard in Android drawn? - Stack Overflow

[Android] Dialog style attributes


@null


true


false


true


@color/transparent


false


* Reference
- android 自定义Dialog背景透明及显示位置设置 - J健 - 博客园

[Android] setContentView of Dialog

Error Message

android.util.AndroidRuntimeException: requestFeature() must be called before adding content

Solution

一定要在 dialog.setContentView() 呼叫 dialog.show()。


* Reference
- android alertdialog布局 dialog布局 - - ITeye技术网站

[AndroidView] Clickable widget in ListView item

Occurred when

如果是 button 則會接收走 click item event,使得 ListView 沒有接收到 click item event; 但若是 TextView 則不會有此現象。


Solution

在 button 設定以下屬性

android:focusable="false"


* Reference
- android - ListView and Buttons inside ListView - Stack Overflow
- [转]ListView事件的研究 - 雪夜&流星 - 博客园

[AndroidDev] Screen Compatibility Mode

Notice:
如果你所開發的 app,是小於 Android 3.0 且已經能在 tablet 上正常顯示,應該關閉此功能以維持 the best user experience。

Definition:
  • 為了幫助不能在大螢幕上正常顯示 layout 的 app 的模式。
  • 但!! Screen compatibility mode 不是作為解決顯示在 larger screen 的根本方法,因為他是放大 layout 因此使得畫面變模糊。


有以下兩種版本:

Version 1 (Android 1.6 - 3.1)
  • 系統以 normal size 來畫 layout,剩餘沒填滿的地方,則都填入黑色。
  • 僅適用於 screen size 320dp x 480dp。
  • To disable this version of screen compatibility mode, you simply need to set 
    • android:minSdkVersion or android:targetSdkVersion to "4" or higher, or
    • android:resizeable = "true".
Version 2 (Android 3.2 and greater)
  • 系統以 normal size 來畫 layout,再放大 layout 填滿 screen,所以可能會顯得模糊。
  • 如果 app 沒有宣告 <supports-screens android:largeScreens="true" />,那在 system bar 會出現選項(an icon with outward-pointing arrows)讓 user 選擇是否開啟此功能;但若 app 有宣告,user 則不能選擇。

Disabling Screen Compatibility Mode

讓 user 自行選擇是否使用(>= Android 3.2):
  • set both android:minSdkVersion and android:targetSdkVersion to "10" or lower and does not explicitly declare support for large screens using the <supports-screens> element.
  • set either android:minSdkVersion or android:tagetSdkVersion to "11" or higher and explicitly declares that it does not support large screens, using the <supports-screens> element.

Easiest:
表示支援所有大小的 screen,系統會 resize layout 每個 screen。


Easy but has other effects:
In your manifest's <uses-sdk> element, set android:targetSdkVersion to "11" or higher:

表示你的 app 支援 Android 3.0 與能正常執行於 larger screen size。

Caution:
When running on Android 3.0 and greater, this also has the effect of enabling the Holographic theme for you UI, adding the Action Bar to your activities, and removing the Options Menu button in the system bar.
If screen compatibility mode is still enabled after you change this, check your manifest's and be sure that there are no attributes set "false".


Enabling Screen Compatibility Mode

  • 如果是開發 Android 3.2 (API level 13) or higher 的 app 可以用 <supports-screens> 決定是否使用次功能。
  • 設定 android:minSdkVersion or android:targetSdkVersion to "11" or higher,user 則不能使用。(?)
If either of these are true and your application does not resize properly for larger screens, you can choose to enable screen compatibility mode in one of the following ways:

表示你 app 支援的 the maximum "smallest screen width" 是 320 dp,也就是說當 device screen 的 smallest screen width 大於 320 dp,user 就能使用 screen compatibility mode。

強制開啟此功能
If your application is functionally broken when resized for large screens and you want to force users into screen compatibility mode (rather than simply providing the option), you can use the android:largestWidthLimitDp attribute:


<supports-screens> 設為 true,表示你的 app 支援該大小的 screen,不使用此功能。


* Reference
- Screen Compatibility Mode
- Screen Compatibility Mode

[Java] final in Inner Class

final in Local Inner Class
建立在 Method 中的 inner class。
Local inner class 所在的 Method 回傳值(return)後,Method 中的變數將會被銷毀,因此在 Method 中,被 Local inner class 所用到的變數會被複製一份來使用,此時,如果該變數不是 final,則複製的變數就可能因為更改而不同步,造成錯亂,因此 Local inner class 所用到的 local variables 必須標記為 final。

final in Anonymous Inner Class
匿名式 Anonymous inner class 所用到的 local variables 也必須須標記為 final,因為 Anonymous Inner Class 在實體化時,會將使用到的 local variables 直接複製並且生成為自己的 private 變數,同樣的,出現拷貝時,就會有同步的問題,因此該變數也必須被標記為 final。


* Reference
- InnerClass 的解析 @ 來喝杯JAVA咖啡 :: 痞客邦 PIXNET ::

2012年10月9日 星期二

[Android] Restart activity after backing from it

Message

Launch timeout has expired, giving up wake lock!

Activity idle timeout for ActivityRecord


Occurred when

當想要開啟的 activity 尚未 destroy 時,則會出現此 warning 且 activity 在 destroy 後不會再次被開啟。



* Reference
- Launch timeout has expired, giving up wake lock! - Google 網上論壇
- android - Launch timeout has expired, giving up wake lock! Activity idle timeout for HistoryRecord. Is this something to worry about? - Stack Overflow

[AndroidTool] HierarachyViewer unable to debug device

Error Message

Unable to get view server protocol version from device
Unable to debug device

Caused by:

因為大部份手機不允許使用 HierarachyViewer,以保護手機上 app 的安全,因此必須在開發機或 emulators 上使用。


* Reference
- android - Why is hierarchyviewer not working for Samsung Galaxy TAB 7.0? - Stack Overflow

Unstructured Supplementary Service Data (USSD)

Introduction
  • 是用戶端(手機)在 GSM 系統上與系統服務商伺服器溝通的一種協定,使用者透過手機撥號程式輸入特定 USSD 指令之後,可以取得系統服務商提供的服務。
    • ex: 查詢預付卡餘額,在手機上按 *#06# 會跳出 IMEI 碼。
  • 部分手機廠商使用自定USSD指令對手機做特殊設定或操作。
    • ex: 恢復為出廠設定、開啟工程模式等。
  • Format:
    • 每一個USSD字串都要以「*」字元開始再以「#」結束。


Compared with SMS

UUSD 和 SMS 都是 GSM 系統用來傳送數據的服務。
  • 操作方式
    • UUSD
      • 發送 USSD 和撥一組電話號碼非常類似,因此不需要依靠手機提供特定的介面。
    • SMS
      • 不同的手機會有不同的操作方式。
  • 傳送方式
    • UUSD
      • 建立一條固定且快速的通道,並沒有任何儲存媒介。
      • 是 Session-oriented 的處理方式,當客戶送出 USSD 需求,此時會有一個 session 建立連結,而且這個 Session 會一直保留直到客戶接收或者 AP time-out 才釋放,因此不需要預留訊息頻道。
      • 指令可以儲存在電話簿或使用快速撥號鍵,當需要重複發送時非常快速且方便。
      • 不保證訊息一定能傳送到目的端,不論由手機發出的申請需求或是應用程式提供的服務傳送。
    • SMS
      • store and forward 的機制,也就是所發出的簡訊會先被儲存在簡訊中心,以便於在適當時機將訊息送達手機上。
      • 是 Transaction-oriented 的方式,先儲存再傳送,所以若傳送失敗則可以由系統自行重送。
  • 處理時間 
    • USSD 1:SMS 7
  • 設計
    • UUSD
      • 為了讓 GSM 網路能提供一種發送指令的方式,所以 USSD 的目的地是後端的應用程式。
    • SMS 
      • 提供了除了通話之外的另一種用戶和用戶之間的溝通方式。
  • USSD 比喻成網頁的瀏覽,而 SMS 則類似 e-mail 的功能。
  • USSD 支援無縫漫遊 (seamless roaming),SMS 則否。


* Reference
- 研究:USSD指令可遠端破壞Android手機資料與SIM卡 | 即時新聞 | iThome online
- USSD功能_小林子_新浪博客
- USSD_百度百科
- USSD1-3ns
- ACE

2012年10月8日 星期一

Supporting Multiple Screens - 換算

算式
  • px = dp * (dpi / 160)
  • dp = px /(dpi/160)
  • dpi type = squrt(xx + yy) / inch
  • sqrt(xx + yy) / dpi type = inch

Examples:
  • not2 5.5" 1280*720 pixels
    • 267 dpi -> xhdpi
  • Amazon Kindle Fire HD 7" 16GB 7" 1280 x 800 pixels
  • Google Nexus 7 16GB 7" 1280 x 800 pixels
    • 191 dpi -> hdpi
  • ASUS Eee Pad Transformer Prime TF201 32GB 10.1" 1280 x 800 pixels
  • SAMSUNG GALAXY Note 10.1 Wi-Fi 10.1" 1280 x 800 pixels
    • 132 dp -> mdpi


dpi
  • ldpi: ~ 120 dpi
  • mdpi: 120 dpi ~ 160 dpi
  • hdpi: 160 dpi ~ 240 dpi
  • xhdpi: 240 dpi ~ 320 dpi

dp to screen size examples:
  • 480 dp
    • 480 mdpi
      • 480 px -> 4" ~ 3"
    • 720 hdpi
      • 1080 px -> 9.5" ~ 6.3"
    • 960 xhdpi
    • 1920 px -> 11.3" ~ 8.4"
  • 600 dp, about 7"
    • 600 mdpi
      • 600 px -> 7" ~ 5.3"
    • 900 hdpi
      • 1350 px -> 11.9" ~ 7.9"
    • 1920 xhdpi
      • 3840 px -> 22.6" ~ 16.9"

[AndroidDev] Supporting Multiple Screens

Android system 用以下方式使得你 App 不因螢幕密度有所改變 (density independence):
  • Scales dp units as appropriate for the current screen density
    • Use wrap_content, fill_parent, or dp units when specifying dimensions in an XML layout file
    • Do not use hard coded pixel values in your application code
    • Do not use AbsoluteLayout (it's deprecated)
  • Scales drawable resources to the appropriate size, based on the current screen density, if necessary.
    • Supply alternative bitmap drawables for different screen densities
=> Android System 依據 screen size/density 調整 layout;依據 screen density 調整 bitmap drawables。


How to Support Multiple Screens
  • Explicitly declare in the manifest which screen sizes your application supports
    • 宣告 <supports -screens="-screens"> 以避免你的 app 被從 google play 下載到不合的裝置。
    • 但當運作在較大的螢幕上時會影響 screen compatibility mode 的運作。
  • Provide different layouts for different screen sizes
    • 提供不同 layout for 不同螢幕大小,利用空間及便於 user 操作。
    • ex: small, normal, large, and xlarge。
    • 但是在 Android 3.2 (API level 13) 以上 screen size groups are deprecated,應改使用 sw-dp configuration qualifier。
  • Provide different bitmap drawables for different screen densities
    • 提供不同大小的圖片資源。
    • ex: ldpi (low), mdpi (medium), hdpi (high), and xhdpi (extra high)。
    • 假如只提供預設大小 (drawable, mdpi),那麼圖片在 hdpi 被放大,ldpi 縮小。

系統選擇 resources 的方式

  • The system uses the appropriate alternative resource
    • 依據螢幕 size and density 和你所提供的 resources 及所設定的 qualifier 對應出最適合的 resources,無則使用預設放大縮小(ex: drawable)。
    • 但在使用預設前,系統會先找是否能使用其他 density resources 的可能。
    • ex: 若需要 ldpi,但只有 hdpi and mdpi,那麼系統會優先選擇 hdpi 的,因為改變較小,hdpi * 0.5 < mdpi * 0.75。 
  • Eliminate resource files that contradict the device configuration. 
    • 依 qulifier 篩選,刪去不合者,但 Screen pixel density 不合時並不會刪去,Android 會選擇最適合 螢幕密度的(most closely matches the device screen density)。 
    • 有以下 qulifier: 
      • MCC and MNC 
      • Language and region 
      • smallestWidth(Added in API level 13.) 
      • Available width(Added in API level 13.) 
      • Available height(Added in API level 13.) 
      • Screen size(Added in API level 4) 
      • Screen aspect
        • long: Long screens, such as WQVGA, WVGA, FWVGA 
        • notlong: Not long screens, such as QVGA, HVGA, and VGA 
      • Screen orientation 
      • UI mode(Added in API level 8, television added in API 13) 
      • Night mode( Added in API level 8.) 
      • Screen pixel density (dpi) 
      • Touchscreen type Keyboard availability 
        • Primary text input method 
        • Navigation key availability 
        • Primary non-touch navigation method 
      • Platform Version (API level) 
Note: 
  • 選擇 size qualifiers 時,系統會選擇較小 screen size 的資源,
    • ex: large screen size 使用 normal screen size resources。 
  • 但如果只有較大 screen size resources 可用時,則會 crash
    • ex: normal screen size,但只有 large size resource。 
Tip: 
如果不想要被放大縮小,則可將圖片放入 nodpi;沒有 qualifier,是預設仍會放大縮小。


New qualifiers in Android 3.2 
  • 在 Android 3.0 時,要提供給 tablet 使用的 layout 可放入 res/layout-xlarge/,但這樣如果想在 7" 上也使用 tablet layout,則大部份都會不合條件,7" tablet 會和 5" handset 一同屬於 large group,這樣開發者變無法藉 screen size group 讓 7" tablet 能使用不同的 layout,因此在 Android 3.2 有了新的 qualifier,swdp
  • qualifiers 上指定的 size 應該為你畫面呈現時所需要的空間 (activity's window, include action bar),因為 Android System 可能會佔掉些空間 (such as the system bar at the bottom of the screen or the status bar at the top),所以系統是扣除 system UI 後的大小才是有效範圍
利用 qualifier 使用不同資源:
  • Create a new directory in your project's res/ directory and name it using the format:
    • <resources_name>-<qualifier>
      • <resources_name> is the standard resource name.
        • ex: drawable, layout, 
      • <qualifier> is a configuration qualifier.
        • ex:  hdpi, xlarge..
    • 可同時使用多個,用 dash (-) 做為分隔即可。
  • 在該指定的 directory 下放入相對應的 configuration-specific resources,resource 命名需和 default resources 相同,系統才能替代。


Scaling Bitmap objects created at runtime
  • a Bitmap object 系統視其為 mdpi,並且會使用 "auto-scaling"。
    • 若是想建立符合 screen density 的 bitmap,使用 setDensity() 指定是 DisplayMetrics#DENSITY_HIGH, DisplayMetrics#DENSITY_LOW...etc。
    • 如果是透過 BitmapFactory 建立 bitmap (ex: from a file or a stream),使用 BitmapFactory.Options 去設定屬性,做為系統是否 scale it 的參考,ex:
      • inDensity: 設定 bitmap density。
      • inScaled: 指定 bitmap 是否縮放以符合 screen size。如果設為 false,則表示關閉 pre-scaling 功能,那麼系統則會 auto-scale it at draw time。
  • auto-scale 會比 pre-scaling 花費較多 CPU 資源但較節省 memory 空間。
Note:
In Android 3.0 and above, there should be no perceivable difference between pre-scaled and auto-scaled bitmaps, due to improvements in the graphics framework.


To summarize, you should be sure that your application layout: 
  • Fits on small screens (so users can actually use your application) 
  • Is optimized for bigger screens to take advantage of the additional screen space 
  • Is optimized for both landscape and portrait orientations 



* Reference
- Supporting Multiple Screens | Android Developers
- Providing Resources | Android Developers