工程師的工作不外乎要 debug, 最近又遇到一個 issue.
在 WVGA(width=800,
height=480) 的平台上, 執行應用程式, 該應用程式卻 allocate(width=533, height=320)的 graphic buffer. 造成畫面內容顯示不正確.
寫一個應用程式測試 Android平台的display metrics, 程式片段如下:
dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
Log.e("DM", "DM :
widthPixel "+dm.widthPixels);
Log.e("DM", "DM :
heightPixel "+dm.heightPixels);
Log.e("DM", "DM :
density "+dm.density);
Log.e("DM", "DM :
densityDpi "+dm.densityDpi);
Log.e("DM", "DM :
scaledDensity "+dm.scaledDensity);
Log.e("DM", "DM : xdpi "+dm.xdpi);
Log.e("DM", "DM : ydpi "+dm.ydpi);
發現在此平台上 可以得到兩個不同的結果. 造成結果不同的原因是在<uses-sdk android:minSdkVersion> 的設定. 這個設定位在 APK 的AndroidManifest.xml 中設定
android:minSdkVersion=3, 得到的log如下(DM 是我加的 Tag, 不用管它)
DM : widthPixel 320
DM : heightPixel 533
DM : density 1.5
DM : densityDpi 240
DM : scaledDensity 1.5
DM : xdpi 217.71428
DM : ydpi 218.49463
若是設定 android:minSdkVersion=4,
得到的log 是:
DM : widthPixel 480
DM : heightPixel 800
DM : density 1.5
DM : densityDpi 240
DM : scaledDensity 1.5
DM : xdpi 217.71428
DM : ydpi 218.49463
很明顯的 <uses-sdk
android:minSdkVersion=4> 得到的是正確的結果.
<uses-sdk> 這個 element 的作用是宣告應用程式的 API level, 這是 Android 設計來處理應用程式在不同版本的Android平台上執行時的相容性問題.
下表列出部分的 Android平台的版本和 API level 的對應關係
Platform version
|
API level
|
VERSION_CODE
|
Android 2.2.x
|
8
|
FROYO
|
Android 2.1.x
|
7
|
ECLAIR_MR1
|
Android 2.0.1
|
6
|
ECLAIR_0_1
|
Android 2.0
|
5
|
ECLAIR
|
Android 1.6
|
4
|
DONUT
|
Android 1.5
|
3
|
CUPCAKE
|
Android 1.1
|
2
|
BASE_1_1
|
Android 1.0
|
1
|
BASE
|
順帶補充資料, <uses-sdk> 這個 element 包含有 3個 attribute, 分別是
android:minSdkVersion
應用程式正常執行所需的最小 API level. 在應用程式安裝時,如果Android 平台 的 API level 小於這個 attribute 的數值, 則系統不會允許應用程式被安裝.
若是應用程式沒有指定則default 值是 1, 代表相容於所有的Android 版本.
如果應用程式有使用到 API level 3才支援的APIs 但又沒有指定這個屬性
則在 API level 小於3的Android 平台執行時, 此應用程式會 crash.
android:targetSdkVersion
這個 attribute 表示該應用程式已經在 targetsdkVersion所標示API level的平台上測試過. 另外, Android 平台有新的版本時, 應用程式開發者也應該在新的平台上測試應用程式且將 android:targetSdkVersion 屬性更新成該平台的 API level. 若是 應用程式的 android:targetSdkVersion 值小於Android 平台的 API level, 則平台運行該應用程式時不會做 compatibility 的調整.
android:maxSdkVersion
這個 attribute 的設定會決定應用程式是否可以安裝以及Android平台進行 OTA(Over The Air)更新後, 已經安裝的應用程式是否可以執行.
回到我們之前的問題,android:minSdkVersion=4, display metrics 可以得到正確的寬高是因為從 API level 4 (Android 1.6)開始, 才支持不同尺寸的顯示屏. 在此之前都只有320x480一種尺寸, 因此設置成android:minSdkVersion=3的應用程式 要在WVGA(480x800)的平台上運行, Android 平台會做 screen compatibility 調整,因此得到 (320x533)的不正確結果, 為了避免這種情況, 我們要Disable 這個功能.
關閉的方法, 只需要修改一行程式碼, 在檔案
/frameworks/base/services/java/com/android/server/PackageManagerService.java
找到 systemReady() 這是函式, 將其中一行:
PackageParser.setCompatibilityModeEnabled(compatibilityModeEnabled);
修改成
PackageParser.setCompatibilityModeEnabled(false);
如此可關閉 compatibility mode, 一律用 WVGA(480x800). 之後應用程式就可以正確allocate(width=800, height=480)的 graphic buffer.
Wow!I learn a lot from this article.
回覆刪除kuşadası
回覆刪除milas
çeşme
bağcılar
siirt
DLYZ3