1. 程式人生 > >【騰訊優測乾貨分享】Android 相機預覽方向及其適配探索

【騰訊優測乾貨分享】Android 相機預覽方向及其適配探索

由於Android系統的開放策略,Android手機呈現碎片化的趨勢,相容性問題一直是Android App 開發者頭疼的難題。本文以Android相機預覽方向為例,探索在Android機型適配上的一些思路。

1. android相機簡介

由於Android系統的開放策略,Android手機呈現碎片化的趨勢,相容性問題一直是Android App 開發者頭疼的難題。本文以Android相機預覽方向為例,探索在Android機型適配上的一些思路。

1.1 相機架構

先了解下Camera的框架,它是分層的結構。由上向下分別是

1)應用層
2)Camera系統的Java類
3)Camera的JNI程式碼
4)Camera的本地框架
5)Camera服務部分
6)Camera HAL(Hardware Abstraction Layer)硬體抽象層

圖一Camera architecture

其中Camera HAL主要的介面檔案為CameraHardwareInterface.h ,需要各個系統根據自己的情況實現。由於裝置底層硬體的千變萬化,android框架不可能提供統一的硬體驅動以及介面實現,只能提供標準的介面,因此硬體提供商需要自己開發裝置驅動,並去實現android框架提供的介面。

而實際上,由於機器的硬體配置不同,廠商的底層實現不同,Andriod版本的不同,在一部手機上除錯正常的程式,不一定能在其他機型上正常執行。其中與攝像頭相關的適配問題包括攝像頭個數、preview size大小、預覽方向、閃光燈、對焦方式、幀率等等。

本文以相機預覽方向為例,探討這個問題產生的原因,以及一些可行的解決方法。

2. 相機預覽方向適配問題的產生

2.1相機的安裝方向

相機影象資料都是來自於相機硬體的影象感測器(Image Sensor),這個Sensor被固定到手機之後是有一個預設的取景方向,且不會改變。比如MI3手機的螢幕“自然”方向和後置相機的影象感測器方向是如圖二所示的。

圖二MI3手機的螢幕“自然”方向和後置相機的影象感測器方向

在MI3手機上,對於一個橫屏應用來說,螢幕“自然”方向和後置相機的影象感測器方向一致,因此看到的影象是正的,如圖三所示。而對於一個豎屏應用來說,螢幕“自然”方向和後置相機的影象感測器方向是不一致,從影象感測器的角度看,它看到的影象是側過來的,如圖四所示,需要將相機預覽影象順時針旋轉90度,才和螢幕“自然”方向一致。在Android系統中,提供camera.setDisplayOrientation(angle)方法,用來設定相機預覽影象順時針旋轉的角度。

圖三MI3手機橫屏的相機應用

圖四MI3手機豎屏的相機應用

2.2相機的安裝方向如何獲取?

Android官方提供orientation這個屬性來讀取,官方定義如圖五所示:orientation表示相機影象的方向。它的值是相機影象順時針旋轉到裝置自然方向一致時的角度。例如假設裝置是豎屏的。後置相機感測器是橫屏安裝的。當你面向螢幕時,如果後置相機感測器頂邊的和裝置自然方向的右邊是平行的,則後置相機的orientation是90。如果前置相機感測器頂邊和裝置自然方向的右邊是平行的,則前置相機的orientation是270。

int android.hardware.Camera.CameraInfo.orientation
public int orientation

Added in API level 9

The orientation of the camera image. The value is the angle that the camera image needs to be rotated clockwise so it shows correctly on the display in its natural orientation. It should be 0, 90, 180, or 270.

For example, suppose a device has a naturally tall screen. The back-facing camera sensor is mounted in landscape. You are looking at the screen. If the top side of the camera sensor is aligned with the right edge of the screen in natural orientation, the value should be 90. If the top side of a front-facing camera sensor is aligned with the right of the screen, the value should be 270.

圖五camerainfo.orientation定義

以MI3為例,通過程式呼叫取到的後置相機的orientation是90,前置相機的orientation是270。我理解的orientation是相機採集的影象順時針旋轉到螢幕自然方向的角度。圖六所示是MI3手機的後置相機和前置相機對準同一個小人,後置前置相機採集到的影象及前置相機預覽的影象。需要特別說明的是,對於前置相機來說,相機預覽的影象是相機採集到的影象的映象, 關注圖六中小人頭髮在前置採集到的影象和預覽的影象中頭髮的不同。因此在MI3手機上做豎屏應用時,對於後置相機的預覽方向,只需要旋轉後置相機的orientation,即90度即可和螢幕方向保持一致;對於前置相機的預覽方向,由於系統對前置相機採集到的影象做了映象,因此需要旋轉270-180,也是90度即可和螢幕方向保持一致。

圖六MI3手機上orientation的例子。

2.3官方推薦的相機預覽方向適配做法

通過orientation屬性的含義可以知道,我們可以用它和應用的方向來做相機預覽方向的適配,圖七是官方網站推薦的程式碼。但並不是所有手機的orientation值都靠譜,比如VIVO V1手機第一次獲取後置相機的CameraInfo的orientation值是90,而當執行了mCamera = Camera.open();之後再獲取CameraInfo的orientation值就是0,而且以後獲取的都是 0 ,除非重啟手機。無論是這款手機上的哪個應用,只要執行了一次Camera.open()之後,其他所有程式中獲取CameraInfo的orientation都是是0。因此按照此方法做適配不能解決所有手機上的問題。

圖七 Android官方推薦的相機預覽方向的適配做法

3. 相機預覽方向適配

3.1方案一:App端新增相容性程式碼

思路是在App端對特殊的手機新增相容性程式碼,如下所示。這樣可以解決部分問題,但當版本發出後,又發現問題只能等版本升級修復;同時由於手機型號,系統版本的很多組合,而且客戶端要維護一套很長的程式碼。很自然的想到把相機預覽方向的角度做成後臺配置,就有了方案二。

if (is VIVO V1 mobile) {
    camera.setDisplayOrientation(90);
} else if (is MotoXPro mobile) {
    camera.setDisplayOrientation(270);
} else {
    Android官方推薦的相機預覽方向適配做法
}

3.2方案二:Server端動態配置

為了解決方案一的弊端,可以將相機預覽方向順時針旋轉的角度抽取出來,作為一個變數從server端下發。這樣可以做到機型無關,版本釋出後,出現問題可以通過Server端上線新的配置來解決。但新機型上問題的發現,確認,解決,上線均需要一定的人力耗費,而且有滯後性。還有沒有更好的解決方案呢?

if (get angle from server) {
    camera.setDisplayOrientation(angle);
} else {
    Android官方推薦的相機預覽方向適配做法
}

3.3方案三:Server端動態配置與使用者自助引導相結合

公司一直提倡開發人員有產品思維。從產品的角度說,使用者在使用相機應用時,他是知道相機預覽方向是正確的還是錯誤的,我們可以給使用者一個旋轉相機預覽方向的按鈕,當用戶發現方向不對時,通過自助點選按鈕解決問題。如下圖所示

圖八 發生問題時,引導使用者自助旋轉相機預覽方向

這樣即具有方案二的優點,同時又可以實時解決使用者的問題,不需要使用者等待我們後臺下發正確的配置。進一步的,如果發現使用者點選了旋轉按鈕,同時正確使用了相機功能,可以將本機型對應的angle上報給Server端。Server端可以自動或輔助人工以更新配置。對於QQ安全中心APP來說,在人臉驗證過程需要開啟前置相機,如果使用者本次人臉驗證點選了旋轉預覽方向按鈕,同時又通過了人臉驗證,我們可以認為使用者正確使用了相機功能,Server端可以自動更新使用者上報的angle,使和該使用者同機型的其他使用者都受益。

if (get angle from server) {
    camera.setDisplayOrientation(angle);
} else {
    Android官方推薦的相機預覽方向適配做法
}
...
if (user click rotate icon) {
    angle = angle + 90;
    camera.setDisplayOrientation(angle);
}
...
report(angle);

4 結語

在做相機相關的App時,需要考慮的適配問題還有很多,遠不止相機預覽方向這一種。總的思路就是能實時解決的就不滯後,能動態配置的就不要寫死在App端,有時可以換個角度,考慮技術和產品相結合的方案。

更多精彩內容歡迎關注騰訊優測的微信公眾賬號:

騰訊優測是專業的移動雲測試平臺,為應用、遊戲、H5混合應用的研發團隊提供產品質量檢測與問題解決服務。不僅在線上平臺提供app自動化測試、雲真機遠端操控與除錯、私有自動化測試工具XTest等多種質量檢測工具,更為VIP客戶配備了專家團隊提供定製化綜合測試解決方案。