本文來自於騰訊bugly開發者社區,未經做者贊成,請勿轉載,原文地址:http://dev.qq.com/topic/583ba1df25d735cd2797004djava
因爲Android系統的開放策略,Android手機呈現碎片化的趨勢,兼容性問題一直是Android App 開發者頭疼的難題。本文以Android相機預覽方向爲例,探索在Android機型適配上的一些思路。android
因爲Android系統的開放策略,Android手機呈現碎片化的趨勢,兼容性問題一直是Android App 開發者頭疼的難題。本文以Android相機預覽方向爲例,探索在Android機型適配上的一些思路。安全
先了解下Camera的框架,它是分層的結構。由上向下分別是微信
1)應用層 2)Camera系統的Java類 3)Camera的JNI代碼 4)Camera的本地框架 5)Camera服務部分 6)Camera HAL(Hardware Abstraction Layer)硬件抽象層架構
圖一Camera architectureapp
其中Camera HAL主要的接口文件爲CameraHardwareInterface.h ,須要各個系統根據本身的狀況實現。因爲設備底層硬件的變幻無窮,android框架不可能提供統一的硬件驅動以及接口實現,只能提供標準的接口,所以硬件提供商須要本身開發設備驅動,並去實現android框架提供的接口。框架
而實際上,因爲機器的硬件配置不一樣,廠商的底層實現不一樣,Andriod版本的不一樣,在一部手機上調試正常的程序,不必定能在其餘機型上正常運行。其中與攝像頭相關的適配問題包括攝像頭個數、preview size大小、預覽方向、閃光燈、對焦方式、幀率等等。ide
本文以相機預覽方向爲例,探討這個問題產生的緣由,以及一些可行的解決方法。工具
相機圖像數據都是來自於相機硬件的圖像傳感器(Image Sensor),這個Sensor被固定到手機以後是有一個默認的取景方向,且不會改變。好比MI3手機的屏幕「天然」方向和後置相機的圖像傳感器方向是如圖二所示的。測試
圖二MI3手機的屏幕「天然」方向和後置相機的圖像傳感器方向
在MI3手機上,對於一個橫屏應用來講,屏幕「天然」方向和後置相機的圖像傳感器方向一致,所以看到的圖像是正的,如圖三所示。而對於一個豎屏應用來講,屏幕「天然」方向和後置相機的圖像傳感器方向是不一致,從圖像傳感器的角度看,它看到的圖像是側過來的,如圖四所示,須要將相機預覽圖像順時針旋轉90度,才和屏幕「天然」方向一致。在Android系統中,提供camera.setDisplayOrientation(angle)方法,用來設置相機預覽圖像順時針旋轉的角度。
圖三MI3手機橫屏的相機應用
圖四MI3手機豎屏的相機應用
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的例子。
經過orientation屬性的含義能夠知道,咱們能夠用它和應用的方向來作相機預覽方向的適配,圖七是官方網站推薦的代碼。但並非全部手機的orientation值都靠譜,好比VIVO V1手機第一次獲取後置相機的CameraInfo的orientation值是90,而當執行了mCamera = Camera.open();以後再獲取CameraInfo的orientation值就是0,並且之後獲取的都是 0 ,除非重啓手機。不管是這款手機上的哪一個應用,只要執行了一次Camera.open()以後,其餘全部程序中獲取CameraInfo的orientation都是是0。所以按照此方法作適配不能解決全部手機上的問題。
圖七 Android官方推薦的相機預覽方向的適配作法
####3.1方案一:App端添加兼容性代碼
思路是在App端對特殊的手機添加兼容性代碼,以下所示。這樣能夠解決部分問題,但當版本發出後,又發現問題只能等版本升級修復;同時因爲手機型號,系統版本的不少組合,並且客戶端要維護一套很長的代碼。很天然的想到把相機預覽方向的角度作成後臺配置,就有了方案二。
if (is VIVO V1 mobile) { camera.setDisplayOrientation(90); } else if (is MotoXPro mobile) { camera.setDisplayOrientation(270); } else { Android官方推薦的相機預覽方向適配作法 }
爲了解決方案一的弊端,能夠將相機預覽方向順時針旋轉的角度抽取出來,做爲一個變量從server端下發。這樣能夠作到機型無關,版本發佈後,出現問題能夠經過Server端上線新的配置來解決。但新機型上問題的發現,確認,解決,上線均須要必定的人力耗費,並且有滯後性。還有沒有更好的解決方案呢?
if (get angle from server) { camera.setDisplayOrientation(angle); } else { Android官方推薦的相機預覽方向適配作法 }
公司一直提倡開發人員有產品思惟。從產品的角度說,用戶在使用相機應用時,他是知道相機預覽方向是正確的仍是錯誤的,咱們能夠給用戶一個旋轉相機預覽方向的按鈕,當用戶發現方向不對時,經過自助點擊按鈕解決問題。以下圖所示
圖八 發生問題時,引導用戶自助旋轉相機預覽方向
這樣即具備方案二的優勢,同時又能夠實時解決用戶的問題,不須要用戶等待咱們後臺下發正確的配置。進一步的,若是發現用戶點擊了旋轉按鈕,同時正確使用了相機功能,能夠將本機型對應的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);
在作相機相關的App時,須要考慮的適配問題還有不少,遠不止相機預覽方向這一種。總的思路就是能實時解決的就不滯後,能動態配置的就不要寫死在App端,有時能夠換個角度,考慮技術和產品相結合的方案。
更多精彩內容歡迎關注騰訊優測的微信公衆帳號:
騰訊優測是專業的移動雲測試平臺,爲應用、遊戲、H5混合應用的研發團隊提供產品質量檢測與問題解決服務。不只在線上平臺提供app自動化測試、雲真機遠程操控與調試、私有自動化測試工具XTest等多種質量檢測工具,更爲VIP客戶配備了專家團隊提供定製化綜合測試解決方案。