Sunday, March 11, 2012

談談Android的螢幕解析度

撰寫時間︰2012/03/12 13:15
更新時間︰2012/03/23 11:54
文章更新次數︰3

一、前言
Android手機有多種解析度,
視覺或美工在設計版面時,
倒底該怎麼做,
才能讓每種不同規格的Android手機,
表現出其最大效能?

二、文章開始
讓我們先從Android的圖形資源檔說起。

左邊這張圖是Android置放圖片的資料夾,
如果以手機來說,
至少可以分成4種資料夾,
分別為drawable、drawable-hdpi、drawable-mdpi和drawable-ldpi。


因為這樣的資料夾分類,
讓每種解析度的手機,
能聰明的依照它們自己的螢幕密度(density),
找到他們需要的圖檔應該要在哪個目錄取得
關於這4個資料夾的使用方式,
以及該放什麼圖片進去,
我會在稍後提及。

註︰

需要先在AndroidMenifest.xml裡將Any density設為true,
手機才會依自己的螢幕密度(density)去找適當的drawable資料夾,
否則會一律從drawable這個預設目錄去取得圖形資源。
(如果又沒有設drawable資料夾,
則會從其它的圖形資料夾下找到該圖形資源,
然後依照density的比例去自動縮放。

如果你現在看不懂我說的,
無妨。
因為等一下我還會再說明。)

Android官方技術文件中提供目前Android的解度析有以上這些規格(但實際上有更多)
要如何理解這張表格,
小鰻當時也花了很久的時間在摸索,
當然,要怎麼知道手機的density,
Google很多人都有教了,
不在此特做說明。

以欄位來看,
第1欄屬於ldpi的手機規格至少有︰
QVGA(240x320)、WQVGA400、WQVGA432、WVGA800、WVGA854...。

 Android Design Guide建議我們在處理每種解析度的圖片問題時,
可以使用底下2種方式︰
1.先從mdpi的規格去製圖,然後再使用photoshop之類的圖片編修軟體,向上調整尺寸和向下調整。
2.從最大尺寸去製圖(假設你想開發手機App,可以從Galaxy Nexus的density320開始繪製),然後再向下縮小。

Android的最基本尺寸規格是Medium Density(160) - mdpi
任何其它的Android尺寸,
都是由mdpi去向上或向下延伸換算出來的,
因此我個人是比較推薦使用第1種 - 從mdpi去調整圖形大小的方法來製圖。

photoshop是Google很推薦的繪製工具,
因為使用這套軟體,
可以自由的拉大和縮小圖形也不會失真(以專案檔的方式來說的話)。

如同我前面所說,
如果要設計手機版面,
至少會有4種drawable資料夾,
這裡解釋一下這4個資料夾的用法。

1.drawable
drawable資料夾相當於drawable - nodpi,
如果手機從這個資料夾抓出圖片,
那麼系統繪製圖片的方式,
是"圖片有多大就畫多大",
以1:1的方式去繪製。

所以,如果使用這個資料夾,
通常還要在程式裡做很多螢幕解析度的換算,
不然會遇到圖片在小手機,
根本完全跑版、超出手機螢幕大小的問題。

2.drawable - mdpi
mdpi(density160)是Android標準的規格尺寸,
任何其它dpi,都是從mdpi去演算及延伸的,
強列建議先由mdpi去排版製圖,
然後再去調整其它的解析度。

3.drawable - hdpi
前面說到,
Android的標準尺寸是mdpi(density160),
而hdpi則是density240,
240(hdpi density) /160(mdpi density) = 1.5。
這樣的比例換算下來,
螢幕顆粒密度比原本的mdpi還要精密,
因此,
你會發現圖片在mdpi中看是正常大小,
但到hdpi的手機來看,
圖片被明顯縮小了。

因此,
這個資料夾裡的圖片,
你必須畫得比drawable - mdpi的圖檔還大。
大幾倍?
答案是...150%

這個值就是剛才240/160=1.5算出來的值,
你必須將mdpi的那張圖,
用photoshop放大150%另存新檔,
放在drawable - hdpi來用,
才能顯示跟drawable - mdpi一樣的畫面大小。

3.drawable - ldpi
ldpi的Density為120,
120/160 = 0.75,
因此,
使用photoshop將剛才mdpi的尺寸,
縮小成75%
放進drawable - ldpi目錄,
將能讓呈現出來的畫面,
跟mdpi的畫面一樣。

如果要製作不同解析度的icon,你需要對每一種dpi去客製化,才能在每種手機上呈現一樣的結果。


如果你問我︰
「天啊!
我一定要花那麼多的工夫在製做不同尺寸的解析度嗎?」
這個答案是可選擇的。

why?
如果你今天開發的App,
畫面只繪製mdpi,
那有沒有辦法在ldpi和hdpi正常顯示呢?
答案是...可以。

把drawable目錄刪掉,
剩下其它3個目錄(drawable - ldpi、drawable - mdpi、drawable - hdpi),
且將繪好的mdpi圖形,
丟進drawable - mdpi,
如果程式發現現在使用的手機,
是ldpi或hdpi時,
系統會自動去換算放大或縮小,
也不會讓原本設計給mdpi的圖片尺寸,
在hdpi或ldpi中跑版。
但...這就牽扯到視覺(美工)人員最在意的品質問題。

品質是視覺(美工)人員的生命,
他們的職責就是替產出的作品負責,
畫面上的每1 mm,
都是比自己的小孩還要親的小孩。
當然,
也是有視覺(美工)人員是比較...隨遇而安的心態啦...。

讓系統去自動縮放圖片大小
壞處有下︰

1.如果手機解析度比mdpi還大(如hdpi),
那麼這張圖將被拉大,
畫面將沒那麼精美了。

 2.如果手機解析度比mdpi還小(如ldpi),
那麼這張圖將被縮小,
看起來似乎沒什麼問題,
但你要知道,
使用者手上拿的這種ldpi手機,
通常都是效能極差的Android手機(我們稱它為Android低階機,講好聽叫入門機),
以台灣來說,
通常都是電信業者綁門號,
 0元就能帶回家的Android手機。

這種品質的手機,
你在開發時,
會發現它的所有硬體支援度都比中高階的Android手機還差。
如果iPhone開發工程師已經在開發下一款產品時,
老闆為了要旗下的產品支援所有Android手機,
你會發現你還在調校這些低階手機。

現在,
你把mdpi大小的圖片塞進這隻效能極差的ldpi手機中,
因為效能極差,
沒多久,
你就會遇到記憶體不足(我前面的文章有提到)的問題!

三、結論
無論你是視覺(美工)人員或者是Android程式設計師,
不管是螢幕畫面還是手機效能,
最好都還是替不同的螢幕解析度去客製化不同的圖片大小,
一來控制畫面品質,
二來也能確保程式穩定度。

這些細心,
每一種規格的Android手機使用者都能依各自的可用資源看到你呈現出來的產品,
何樂而不為?

四、備註
我開發過的手機和平板規格︰
1.Nexus one(800x480, density 240)
2.Nexus S(800x480, density 240)
3.Galaxy Nexus(1280x720, density 320)
4.HTC Hero(480x320, density 160)
5.Sony Arc(854x480, density 240)
6.遠傳小精靈(320x240, density 120)
7.HTC野火機1代(320x240, density 120)
8.Samsung SII(800x480, density 240)
9.HTC Flyer平板(1024x600, density 160)
10.Samsung Tab 7.7(1024x600, density 170)
11.HTC Desire(800x480, density 240)
12.HTC Incredible(800x480, density 240)
13.HTc Sensation(960x540, density....)
還有更多...

以上如果規格或Density有錯,
煩請告知。
感謝

其它導讀︰
1.處理多螢幕解析度問題-PartII(外文)

Tuesday, March 6, 2012

Android刷機工具 Odin



刷Kernal的方式
如果kernal是.zip,使用recovery mode刷入;如果Kernal是.tar,則用Odin,不要勾選Re-partition(不分區),放入PDA中直接刷!

小技巧

  1. 刷Rom前、後最好都雙Wipe(進入Recovery mode執行Wipe Data和Wipe cache partition)
  2. 先刷完Rom後再刷kernal
  3. 通常kernal都是放進PDA裡刷


Monday, March 5, 2012

[技術公報]Android App打破50MB的上傳限制了

Android Apps Break the 50MB Barrier


Android applications have historically been limited to a maximum size of 50MB. This works for most apps, and smaller is usually better — every megabyte you add makes it harder for your users to download and get started. However, some types of apps, like high-quality 3D interactive games, require more local resources.
Android app先前將最大檔案容量限制在50MB,這個方案在許多的App上運作的很好 - 因為你所編譯並產出的每megabyte都會讓你的使用者需要花時間下載後才能啟動。然而,有一些類型的App,像是高畫質的3D互動遊戲,卻需要更大量的本地端資源。

So today, we’re expanding the Android app size limit to 4GB.
因此,我們今天將Android App的容量限制提高至4GB

The size of your APK file will still be limited to 50MB to ensure secure on-device storage, but you can now attach expansion files to your APK.
APK檔容量其實仍然限制在50MB,這是為了確保裝置儲存的安全性。但是你現在還可以添加擴充檔至您的APK中。
  • Each app can have two expansion files, each one up to 2GB, in whatever format you choose.每個App有2個擴充檔,每一個擴充檔最高是2GB,沒有檔案格式上的限制
  • Android Market will host the files to save you the hassle and cost of file serving.
    Android市集會將這2個充檔保留在Android Server中,一方面省去了你開發上的麻煩,也節省你的開發成本。
  • Users will see the total size of your app and all of the downloads before they install/purchase.
    使用者會在他們安裝/購買前,看到你App的總量和總下載次數。
On most newer devices, when users download your app from Android Market, the expansion files will be downloaded automatically, and the refund period won’t start until the entire download completes. On older devices, your app will download the expansion files the first time it runs, via a downloader library which we’ve provided below.
在大多數新型裝置中,當使用者從Android市集下載了您的App,擴充檔也會跟著被自動下載,此時,15分鐘的退費期間將不會被算在內,15分鐘的限制將會在全部的檔案都下載完成後才會開始計算。然而,在一些舊有的裝置中,你的App會在下載並執行App的第1次啟動後,才開始透過我們底下提供的downloader函式庫下載擴充檔。

While you can use the two expansion files any way you wish, we recommend that one serve as the initial download and be rarely if ever updated; the second can be smaller and serve as a “patch carrier,” getting versioned with each major release.
雖然您可以依照你希望的方式來使用這2個擴充檔,我們仍建議您將其中一個擴充檔用在初始化下載,若是要更新App,盡量不要用它。另一個擴充槽則可設計成被置放較小的檔案,提供"更新補丁(patch carrier)",用來做每個版本主要更新的內容。

Helpful Resources有用的資源

In order to make expansion file downloading as easy as possible for developers, we're providing sample code and libraries in the Android SDK Manager.
為了能簡單且有效的讓開發者使用擴充檔這個資源,我們在Android SDK Manager提供了簡單的範例程式和函式庫。
  • In the Google Market Licensing package, an updated License Verification Library (LVL). This minor update mostly adds the ability to obtain expansion file details from the licensing server.
    在Google市集的許可套件中,一個更新的許可驗証函式庫(LVL)。能過這個小更新取得擴充檔的詳細資訊。
  • From the Google Market APK Expansion package, the downloader service example. The library makes it relatively simple to implement a downloader service in your application that follows many of our best practices, including resuming downloads and displaying a progress notification.
    從Google市集APK擴充套件來的downloader服務範例。函式庫非常容易從downloader服務去實作,因為這是從我們很多很棒的實作中去完成的 - 功能包含了續傳下載和訊息通知欄的下載進度顯示。
Because many developers may not be used to working with one or two large files for all of their secondary content, the example code also includes support for using a Zip file as the secondary file. The Zip example implements a reasonable patching strategy that allows for the main expansion file to “patch” the APK and the patch file to “patch” both the APK and the main expansion file by searching for asset files in all three places, in the order patch->main->APK. 
由於許多的開發者也許不會用他們次要的擴充檔來放置1~2個大型檔案,因此範例程式用zip格式來做次要檔的放置。zip範例的實作是合理的策略,允許主要的擴充檔以"patch" APK的方式來擴充,(恕刪)...........順序是ptch-->main-->APK。

Expansion File Basics擴充檔基本概念

Expansion files have a specific naming convention and are located in a specific place for each app. As expansion files are uploaded to the publisher site, they are assigned a version code based upon the version of the APK that they are associated with. The naming convention and location are as follows:
擴充檔在每一個app中,都擁有特定的命名慣例和置放的位置。擴充檔被更新至publisher網站,也被指定到相關連的某個version code以上的apk中。命名慣例和位置依照︰
Location: <shared-storage>/Android/obb/<package-name>/
Filename: [main|patch].<expansion-version>.<package-name>.obb
Example: /sdcard/Android/obb/com.example.myapp/main.5.com.example.myapp.obb
Expansion files are stored in shared storage. Unlike APK files, they can be read by any application.
擴充檔被儲存在分享空間。它們不像APK檔,因此可以被任何的APP自由的讀取。

Downloading and Using the Expansion Files下載並使用擴充檔

When the primary activity for the app is created, it should check to make sure the expansion files are available. The downloader library provides helper functions (for example the “Helpers” class in the code below) to make this easy.
當主要activity被建立後,應該要檢查並確保是否有可用的擴充檔。downloader函式庫提供了一個helper功能(範例程式中被命名為"Helper"類,下方的程式中也可看到),讓開發者方便使用。

boolean expansionFilesDelivered() {
 // get filename where main == true and version == 3
String fileName = Helpers.getExpansionAPKFileName(this, true, 3);
// does the file exist with FILE_SIZE?
      if (!Helpers.doesFileExist(this, fileName, FILE_SIZE, false))
                return false;
        }
        return true;
    }
}






















If the file does not exist, fire up the downloader service with  DownloaderClientMarshaller.startDownloadServiceIfRequired(). The downloader will perform an LVL check against the server. This check will deliver the names of the files, file sizes, and the file URLs.
如果擴充檔沒有放在SD卡的指定位置,可以使用DownloaderClientMarshaller.startDownloadServiceIfRequired()來啟動downloader服務。downloader會針對server執行LVL檢驗,檢驗會傳遞檔案名稱、檔案大小和檔案的URLs。

Once that check has been completed, it will begin downloading the files. You don’t have to use our download solution, but you might want to because we:
一旦檢查機制完成,就會開始下載檔案。也許你不需要使用我們提供的下載方案,但是您可能還是會用到,因為我們提供了︰
  • Include a notification UI that provides progress and estimated completion time in layouts customized for ICS and pre-ICS devices
     訊息通知介面,能在ICS和ICS版本之前的裝置提供了進度條和下載時間估算。
  • Resume large files safely
    提供安全性的續傳檔案。
  • Handle redirection with appropriate limits
    重新定位apk的適量限制。
  • Run in the background as a service
    提供背景服務下載。
  • Pause and resume downloads when WiFi is not available
    當WiFi失效時,提供暫停和續傳的功能。
Enjoy! We can’t wait to see what kinds of things developers do with this! For more information about how to use expansion files with your app, read the APK Expansion Files developer guide.
好好享用吧!我們迫不及待想看到開發者使用這些功能!更多擴充檔的資訊,請閱讀開發者導引的APK Expansion Files單元。

[This post wasn’t actually written by anyone, but bashed out by a posse of engineering and product-management people. Heavy bashers included Dan Galpin, Ilya Firman, Andy Stadler, Michael Siliski, and Ellie Powers.]