摘要:通過(guò)可以將和連接起來(lái),當(dāng)和連接后,獲得的預(yù)覽幀數(shù)據(jù)就可以通過(guò)顯示在屏幕上了。預(yù)覽幀數(shù)據(jù)傳遞給,實(shí)現(xiàn)預(yù)覽圖像的顯示。這里預(yù)覽幀數(shù)據(jù)對(duì)應(yīng)的預(yù)覽圖像暫且稱(chēng)作相機(jī)預(yù)覽圖像。拍攝幀數(shù)據(jù)可以生成位圖文件,最終保存成或者等格式的圖片。
歡迎大家前往騰訊云+社區(qū),獲取更多騰訊海量技術(shù)實(shí)踐干貨哦~
本文由QQ空間開(kāi)發(fā)團(tuán)隊(duì)發(fā)表于云+社區(qū)專(zhuān)欄
最近我負(fù)責(zé)開(kāi)發(fā)了一個(gè)跟Android相機(jī)有關(guān)的需求,新功能允許用戶(hù)使用手機(jī)攝像頭,快速拍攝特定尺寸(1:1或3:4)的照片,并支持在拍攝出的照片上做貼紙相關(guān)的操作。由于之前沒(méi)有接觸過(guò)Android相機(jī)開(kāi)發(fā),所以在整個(gè)開(kāi)發(fā)過(guò)程中踩了不少坑,費(fèi)了不少時(shí)間和精力。這篇文章總結(jié)了Android相機(jī)開(kāi)發(fā)的相關(guān)知識(shí)、流程,以及容易遇到的坑,希望能幫助今后可能會(huì)接觸Android相機(jī)開(kāi)發(fā)的朋友快速上手,節(jié)省時(shí)間,少走彎路。
一.Android中開(kāi)發(fā)相機(jī)應(yīng)用的兩種方式Android系統(tǒng)提供了兩種使用手機(jī)相機(jī)資源實(shí)現(xiàn)拍攝功能的方法,一種是直接通過(guò)Intent調(diào)用系統(tǒng)相機(jī)組件,這種方法快速方便,適用于直接獲得照片的場(chǎng)景,如上傳相冊(cè),微博、朋友圈發(fā)照片等。另一種是使用相機(jī)API來(lái)定制自定義相機(jī),這種方法適用于需要定制相機(jī)界面或者開(kāi)發(fā)特殊相機(jī)功能的場(chǎng)景,如需要對(duì)照片做裁剪、濾鏡處理,添加貼紙,表情,地點(diǎn)標(biāo)簽等。這篇文章主要是從如何使用相機(jī)API來(lái)定制自定義相機(jī)這個(gè)方向展開(kāi)的。
二.相機(jī)API中關(guān)鍵類(lèi)解析通過(guò)相機(jī)API實(shí)現(xiàn)拍攝功能涉及以下幾個(gè)關(guān)鍵類(lèi)和接口:
Camera:最主要的類(lèi),用于管理和操作camera資源。它提供了完整的相機(jī)底層接口,支持相機(jī)資源切換,設(shè)置預(yù)覽/拍攝尺寸,設(shè)定光圈、曝光、聚焦等相關(guān)參數(shù),獲取預(yù)覽/拍攝幀數(shù)據(jù)等功能,主要方法有以下這些:
open():獲取camera實(shí)例。
setPreviewDisplay(SurfaceHolder):綁定繪制預(yù)覽圖像的surface。surface是指向屏幕窗口原始圖像緩沖區(qū)(raw buffer)的一個(gè)句柄,通過(guò)它可以獲得這塊屏幕上對(duì)應(yīng)的canvas,進(jìn)而完成在屏幕上繪制View的工作。通過(guò)surfaceHolder可以將Camera和surface連接起來(lái),當(dāng)camera和surface連接后,camera獲得的預(yù)覽幀數(shù)據(jù)就可以通過(guò)surface顯示在屏幕上了。
setPrameters設(shè)置相機(jī)參數(shù),包括前后攝像頭,閃光燈模式、聚焦模式、預(yù)覽和拍照尺寸等。
startPreview():開(kāi)始預(yù)覽,將camera底層硬件傳來(lái)的預(yù)覽幀數(shù)據(jù)顯示在綁定的surface上。
stopPreview():停止預(yù)覽,關(guān)閉camra底層的幀數(shù)據(jù)傳遞以及surface上的繪制。
release():釋放Camera實(shí)例
takePicture(Camera.ShutterCallback shutter, Camera.PictureCallback raw, Camera.PictureCallback jpeg):這個(gè)是實(shí)現(xiàn)相機(jī)拍照的主要方法,包含了三個(gè)回調(diào)參數(shù)。shutter是快門(mén)按下時(shí)的回調(diào),raw是獲取拍照原始數(shù)據(jù)的回調(diào),jpeg是獲取經(jīng)過(guò)壓縮成jpg格式的圖像數(shù)據(jù)的回調(diào)。
SurfaceView:用于繪制相機(jī)預(yù)覽圖像的類(lèi),提供給用戶(hù)實(shí)時(shí)的預(yù)覽圖像。普通的view以及派生類(lèi)都是共享同一個(gè)surface的,所有的繪制都必須在UI線(xiàn)程中進(jìn)行。而surfaceview是一種比較特殊的view,它并不與其他普通view共享surface,而是在內(nèi)部持有了一個(gè)獨(dú)立的surface,surfaceview負(fù)責(zé)管理這個(gè)surface的格式、尺寸以及顯示位置。由于UI線(xiàn)程還要同時(shí)處理其他交互邏輯,因此對(duì)view的更新速度和幀率無(wú)法保證,而surfaceview由于持有一個(gè)獨(dú)立的surface,因而可以在獨(dú)立的線(xiàn)程中進(jìn)行繪制,因此可以提供更高的幀率。自定義相機(jī)的預(yù)覽圖像由于對(duì)更新速度和幀率要求比較高,所以比較適合用surfaceview來(lái)顯示。
SurfaceHolder:surfaceholder是控制surface的一個(gè)抽象接口,它能夠控制surface的尺寸和格式,修改surface的像素,監(jiān)視surface的變化等等,surfaceholder的典型應(yīng)用就是用于surfaceview中。surfaceview通過(guò)getHolder()方法獲得surfaceholder 實(shí)例,通過(guò)后者管理監(jiān)聽(tīng)surface 的狀態(tài)。
SurfaceHolder.Callback接口:負(fù)責(zé)監(jiān)聽(tīng)surface狀態(tài)變化的接口,有三個(gè)方法:
surfaceCreated(SurfaceHolder holder):在surface創(chuàng)建后立即被調(diào)用。在開(kāi)發(fā)自定義相機(jī)時(shí),可以通過(guò)重載這個(gè)函數(shù)調(diào)用camera.open()、camera.setPreviewDisplay(),來(lái)實(shí)現(xiàn)獲取相機(jī)資源、連接camera和surface等操作。
surfaceChanged(SurfaceHolder holder, int format, int width, int height):在surface發(fā)生format或size變化時(shí)調(diào)用。在開(kāi)發(fā)自定義相機(jī)時(shí),可以通過(guò)重載這個(gè)函數(shù)調(diào)用camera.startPreview來(lái)開(kāi)啟相機(jī)預(yù)覽,使得camera預(yù)覽幀數(shù)據(jù)可以傳遞給surface,從而實(shí)時(shí)顯示相機(jī)預(yù)覽圖像。
surfaceDestroyed(SurfaceHolder holder):在surface銷(xiāo)毀之前被調(diào)用。在開(kāi)發(fā)自定義相機(jī)時(shí),可以通過(guò)重載這個(gè)函數(shù)調(diào)用camera.stopPreview(),camera.release()來(lái)實(shí)現(xiàn)停止相機(jī)預(yù)覽及釋放相機(jī)資源等操作。
三.自定義相機(jī)的開(kāi)發(fā)過(guò)程定制一個(gè)自定義相機(jī)應(yīng)用,通常需要完成以下步驟,其流程圖如圖1所示:
檢測(cè)并訪(fǎng)問(wèn)相機(jī)資源 檢查手機(jī)是否存在相機(jī)資源,如果存在,請(qǐng)求訪(fǎng)問(wèn)相機(jī)資源。
創(chuàng)建預(yù)覽類(lèi) 創(chuàng)建繼承自SurfaceView并實(shí)現(xiàn)SurfaceHolder接口的拍攝預(yù)覽類(lèi)。此類(lèi)能夠顯示相機(jī)的實(shí)時(shí)預(yù)覽圖像。
建立預(yù)覽布局 有了拍攝預(yù)覽類(lèi),即可創(chuàng)建一個(gè)布局文件,將預(yù)覽畫(huà)面與設(shè)計(jì)好的用戶(hù)界面控件融合在一起。
設(shè)置拍照監(jiān)聽(tīng)器 給用戶(hù)界面控件綁定監(jiān)聽(tīng)器,使其能響應(yīng)用戶(hù)操作(如按下按鈕), 開(kāi)始拍照過(guò)程。
拍照并保存文件 將拍攝獲得的圖像轉(zhuǎn)換成位圖文件,最終輸出保存成各種常用格式的圖片。
釋放相機(jī)資源 相機(jī)是一個(gè)共享資源,必須對(duì)其生命周期進(jìn)行細(xì)心的管理。當(dāng)相機(jī)使用完畢后,應(yīng)用程序必須正確地將其釋放,以免其它程序訪(fǎng)問(wèn)使用時(shí),發(fā)生沖突。
圖1 定制自定義相機(jī)的過(guò)程
對(duì)應(yīng)到代碼編寫(xiě)上可以分成三個(gè)步驟:
第一步:在AndroidManifest.xml中添加Camera相關(guān)功能使用的權(quán)限,具體聲明有以下這些:
第二步:編寫(xiě)相機(jī)操作功能類(lèi)CameraOperationHelper。采用單例模式來(lái)統(tǒng)一管理相機(jī)資源,封裝相機(jī)API的直接調(diào)用,并提供用于跟自定義相機(jī)Activity做UI交互的回調(diào)接口,其功能函數(shù)如下,主要有創(chuàng)建釋放相機(jī),連接開(kāi)始關(guān)閉預(yù)覽界面,拍照,自動(dòng)對(duì)焦,切換前后攝像頭,切換閃光燈模式等,具體實(shí)現(xiàn)可以參考官方API文檔。
第三步:編寫(xiě)自定義相機(jī)Activity,主要是定制相機(jī)界面,實(shí)現(xiàn)UI交互邏輯,如按鈕點(diǎn)擊事件處理,icon資源切換,鏡頭尺寸切換動(dòng)畫(huà)等。這里需要聲明一個(gè)SurfaceView對(duì)象來(lái)實(shí)時(shí)顯示相機(jī)預(yù)覽畫(huà)面。通過(guò)SurfaceHolder及其Callback接口來(lái)一同管理屏幕surface和相機(jī)資源的連接,相機(jī)預(yù)覽圖像的顯示/關(guān)閉。
四. 開(kāi)發(fā)過(guò)程遇到的一些坑下面再講講我在開(kāi)發(fā)自定義相機(jī)時(shí)踩過(guò)的一些坑:
1. Activity設(shè)為豎屏?xí)r,SurfaceView預(yù)覽圖像顛倒90度。說(shuō)明這個(gè)問(wèn)題之前,先介紹下Android手機(jī)上幾個(gè)方向的概念:
屏幕方向:在Android系統(tǒng)中,屏幕的左上角是坐標(biāo)系統(tǒng)的原點(diǎn)(0,0)坐標(biāo)。原點(diǎn)向右延伸是X軸正方向,原點(diǎn)向下延伸是Y軸正方向。
相機(jī)傳感器方向:手機(jī)相機(jī)的圖像數(shù)據(jù)都是來(lái)自于攝像頭硬件的圖像傳感器,這個(gè)傳感器在被固定到手機(jī)上后有一個(gè)默認(rèn)的取景方向,如下圖2所示,坐標(biāo)原點(diǎn)位于手機(jī)橫放時(shí)的左上角,即與橫屏應(yīng)用的屏幕X方向一致。換句話(huà)說(shuō),與豎屏應(yīng)用的屏幕X方向呈90度角。
圖2 相機(jī)傳感器方向示意圖
相機(jī)的預(yù)覽方向:由于手機(jī)屏幕可以360度旋轉(zhuǎn),為了保證用戶(hù)無(wú)論怎么旋轉(zhuǎn)手機(jī)都能看到“正確”的預(yù)覽畫(huà)面(這個(gè)“正確”是指顯示在UI預(yù)覽界面的畫(huà)面與人眼看到的眼前的畫(huà)面是一致的),Android系統(tǒng)底層根據(jù)當(dāng)前手機(jī)屏幕的方向?qū)D像傳感器采集到的數(shù)據(jù)進(jìn)行了旋轉(zhuǎn)處理,然后才送給顯示系統(tǒng),因此可以保證預(yù)覽畫(huà)面始終“正確”。在相機(jī)API中可以通過(guò)setDisplayOrientation()設(shè)置相機(jī)預(yù)覽方向。在默認(rèn)情況下,這個(gè)值為0,與圖像傳感器一致。因此對(duì)于橫屏應(yīng)用來(lái)說(shuō),由于屏幕方向和預(yù)覽方向一致,預(yù)覽圖像不會(huì)顛倒90度。但是對(duì)于豎屏應(yīng)用,屏幕方向和預(yù)覽方向垂直,所以會(huì)出現(xiàn)顛倒90度現(xiàn)象。為了得到正確的預(yù)覽畫(huà)面,必須通過(guò)API將相機(jī)的預(yù)覽方向旋轉(zhuǎn)90,保持與屏幕方向一致,如圖3所示。
圖3 相機(jī)預(yù)覽方向示意圖
(紅色箭頭為預(yù)覽方向,藍(lán)色方向?yàn)槠聊环较颍?/p>
相機(jī)的拍照方向:當(dāng)點(diǎn)擊拍照按鈕,拍攝的照片是由圖像傳感器采集到的數(shù)據(jù)直接存儲(chǔ)到SDCard上產(chǎn)生的,因此,相機(jī)的拍照方向與傳感器方向是一致的。
2. SurfaceView預(yù)覽圖像、拍攝照片拉伸變形說(shuō)明這個(gè)問(wèn)題之前,同樣先說(shuō)一下幾個(gè)跟相機(jī)有關(guān)的尺寸。
SurfaceView尺寸:即自定義相機(jī)應(yīng)用中用于顯示相機(jī)預(yù)覽圖像的View的尺寸,當(dāng)它鋪滿(mǎn)全屏?xí)r就是屏幕的大小。這里surfaceview顯示的預(yù)覽圖像暫且稱(chēng)作手機(jī)預(yù)覽圖像。
Previewsize:相機(jī)硬件提供的預(yù)覽幀數(shù)據(jù)尺寸。預(yù)覽幀數(shù)據(jù)傳遞給SurfaceView,實(shí)現(xiàn)預(yù)覽圖像的顯示。這里預(yù)覽幀數(shù)據(jù)對(duì)應(yīng)的預(yù)覽圖像暫且稱(chēng)作相機(jī)預(yù)覽圖像。
Picturesize:相機(jī)硬件提供的拍攝幀數(shù)據(jù)尺寸。拍攝幀數(shù)據(jù)可以生成位圖文件,最終保存成.jpg或者.png等格式的圖片。這里拍攝幀數(shù)據(jù)對(duì)應(yīng)的圖像稱(chēng)作相機(jī)拍攝圖像。圖4說(shuō)明了以上幾種圖像及照片之間的關(guān)系。手機(jī)預(yù)覽圖像是直接提供給用戶(hù)看的圖像,它由相機(jī)預(yù)覽圖像生成,拍攝照片的數(shù)據(jù)則來(lái)自于相機(jī)拍攝圖像。
圖4 幾種圖像之間的關(guān)系
下面說(shuō)下我在開(kāi)發(fā)過(guò)程中遇到的三種拉伸變形現(xiàn)象:
1、手機(jī)預(yù)覽畫(huà)面中物體被拉伸變形。
2、拍攝照片中物體被拉伸變形。
3、點(diǎn)擊拍照瞬間,手機(jī)預(yù)覽畫(huà)面會(huì)停頓下,此時(shí)的圖像是拉伸變形的,然后預(yù)覽畫(huà)面恢復(fù)后圖像又正常了。
現(xiàn)象1的原因是SurfaceView和Previewsize的長(zhǎng)寬比率不一致。因?yàn)槭謾C(jī)預(yù)覽視圖的圖像是由相機(jī)預(yù)覽圖像根據(jù)SurfaceView大小縮放得來(lái)的,當(dāng)長(zhǎng)寬比不一致時(shí)必然會(huì)導(dǎo)致圖像變形。后兩個(gè)現(xiàn)象的原因則是Previewsize和Picturesize的長(zhǎng)寬比率不一致所致,查了相關(guān)的資料,發(fā)現(xiàn)其具體原因跟某些手機(jī)相機(jī)硬件的底層實(shí)現(xiàn)有關(guān)??傊疄榱吮苊庖陨蠋追N變形現(xiàn)象的發(fā)生,在開(kāi)發(fā)時(shí)最好將SurfaceView、PreviewSize、PictureSize三個(gè)尺寸保證長(zhǎng)寬比例一致。具體實(shí)現(xiàn)可以先通過(guò)camera.getSupportedPreviewSizes()和camera.getSupportedPictureSizes()獲得相機(jī)硬件支持的所有預(yù)覽和拍攝尺寸,然后在里面篩選出和SurfaceView的長(zhǎng)寬比一致并且大小合適的尺寸,通過(guò)camera.setPrameters來(lái)更新設(shè)置。注意:市場(chǎng)上手機(jī)相機(jī)硬件支持的尺寸一般都是主流的4:3或者16:9,所以SurfaceView尺寸不能太奇葩,最好也設(shè)置成這樣的長(zhǎng)寬比。
3. 各種crash前兩個(gè)Crash的原因是:相機(jī)硬件在聚焦和拍照前必須要保證已經(jīng)連接到surface,并且開(kāi)啟相機(jī)預(yù)覽,surface有收到預(yù)覽數(shù)據(jù)。如果在還沒(méi)有執(zhí)行camera. setPreviewDisplay或者未調(diào)用camera. startPreview之前,就調(diào)用camera.autofocus或camera.takepicture,就會(huì)出現(xiàn)這個(gè)運(yùn)行時(shí)異常。對(duì)應(yīng)到自定義相機(jī)的代碼中,要注意在拍照按鈕事件響應(yīng)中執(zhí)行camera.autofocus或camera.takepicture前,一定要檢驗(yàn)camera有沒(méi)有設(shè)置預(yù)覽Surfaceview并開(kāi)啟了相機(jī)預(yù)覽。這里有個(gè)方法可以判斷預(yù)覽狀態(tài):Camera.setPreviewCallback是預(yù)覽幀數(shù)據(jù)的回調(diào)函數(shù),它會(huì)在SurfaceView收到相機(jī)的預(yù)覽幀數(shù)據(jù)時(shí)被調(diào)用,因此在里面可以設(shè)置是否允許對(duì)焦和拍照的標(biāo)志位。
還有一點(diǎn)要注意,camera.takePicture()在執(zhí)行過(guò)程中會(huì)執(zhí)行camera.stopPreview來(lái)獲取拍攝幀數(shù)據(jù),表現(xiàn)為預(yù)覽畫(huà)面卡住,而如果此時(shí)用戶(hù)點(diǎn)擊了按鈕的話(huà),也就是調(diào)用camera.takepicture,也會(huì)出現(xiàn)上面的crash,因此在開(kāi)發(fā)時(shí),可能還需要屏蔽拍照按鈕的連續(xù)點(diǎn)擊。
第三個(gè)crash則涉及圖像的裁剪,由于要支持1:1或者4:3尺寸鏡頭,所以會(huì)需要對(duì)預(yù)覽視圖進(jìn)行裁剪,由于是豎屏應(yīng)用,所以裁剪區(qū)域的坐標(biāo)系跟相機(jī)傳感器方向是成90度角的,表現(xiàn)在裁剪里就是,屏幕上的x方向,對(duì)應(yīng)在拍攝圖像上是高度方向,而屏幕上的y方向,對(duì)應(yīng)到拍攝圖像上則是寬度方向。因此在計(jì)算時(shí)要一定注意坐標(biāo)系的轉(zhuǎn)換以及越界保護(hù)。
4. 前置攝像頭的鏡像效果Android相機(jī)硬件有個(gè)特殊設(shè)定,就是對(duì)于前置攝像頭,在展示預(yù)覽視圖時(shí)采用類(lèi)似鏡面的效果,顯示的是攝像頭成像的鏡像。而拍攝出的照片則仍采用攝像頭成像??吹竭@里,大家可能會(huì)有些懷疑,不妨現(xiàn)在就試試自己Android手機(jī)上的前置攝像頭,對(duì)比下預(yù)覽圖像和拍攝出照片的區(qū)別。這是由于底層相機(jī)在傳遞前置攝像頭預(yù)覽數(shù)據(jù)時(shí)做了水平翻轉(zhuǎn)變換,即將x方向鏡像翻轉(zhuǎn)180度。這個(gè)變化對(duì)之前豎屏預(yù)覽的方向也會(huì)造成影響,本來(lái)對(duì)于后置攝像頭旋轉(zhuǎn)90度即可使預(yù)覽視圖正確,而對(duì)前置攝像頭,如果也旋轉(zhuǎn)90度的話(huà),看到的預(yù)覽圖像則是上下顛倒的(因?yàn)閤方向翻轉(zhuǎn)了180度),因此必須再旋轉(zhuǎn)180度,才能顯示正確,如圖5所示,大家可以結(jié)合之前相機(jī)預(yù)覽方向的示意圖一起理解。
圖5 前置攝像頭的預(yù)覽方向示意圖
此外,由于拍攝圖像并沒(méi)有做水平翻轉(zhuǎn),所以對(duì)于前置攝像頭拍出來(lái)的照片,用戶(hù)會(huì)發(fā)現(xiàn)跟預(yù)覽時(shí)所見(jiàn)的是左右翻轉(zhuǎn)的。這個(gè)在一定程度上會(huì)影響用戶(hù)體驗(yàn)。為了解決這個(gè)問(wèn)題,可以對(duì)前置攝像頭拍攝的圖像在生成位圖文件時(shí)增加一個(gè)水平翻轉(zhuǎn)矩陣變換。
5. 鎖屏下相機(jī)資源的釋放問(wèn)題為了節(jié)省手機(jī)電量,不浪費(fèi)相機(jī)資源,在開(kāi)發(fā)的自定義相機(jī)里,如果預(yù)覽圖像已不需要顯示,如按Home鍵盤(pán)切換后臺(tái)或者鎖屏后,此時(shí)就應(yīng)該關(guān)閉預(yù)覽并把相機(jī)資源釋放掉。參考官方API文檔,當(dāng)surfaceView變成可見(jiàn)時(shí),會(huì)創(chuàng)建surface并觸發(fā)surfaceHolder.callback接口中surfaceCreated回調(diào)函數(shù)。而surfaceview變成不可見(jiàn)時(shí),則會(huì)銷(xiāo)毀surface,并觸發(fā)surfacedestroyed回調(diào)函數(shù)。我們可以在對(duì)應(yīng)的回調(diào)函數(shù)里,處理相機(jī)的相關(guān)操作,如連接surface、開(kāi)啟/關(guān)閉預(yù)覽。 至于相機(jī)資源釋放,則可以放在Acticity的onpause里執(zhí)行。相應(yīng)的,要重新恢復(fù)預(yù)覽圖像時(shí),可以把相機(jī)資源申請(qǐng)和初始化放在Acticity的onResume里執(zhí)行,然后通過(guò)創(chuàng)建surfaceview,將camera和surface相連并開(kāi)啟預(yù)覽。
但是在開(kāi)發(fā)過(guò)程中發(fā)現(xiàn),對(duì)于按HOME鍵切后臺(tái)場(chǎng)景,程序可以正常運(yùn)行。對(duì)于鎖屏場(chǎng)景,則在重新申請(qǐng)相機(jī)資源時(shí)會(huì)發(fā)生crash,說(shuō)相機(jī)資源訪(fǎng)問(wèn)失敗。那么原因是什么呢?我在代碼里增加了調(diào)試log, 檢查了代碼的執(zhí)行順序,結(jié)果如下:
在自定義相機(jī)頁(yè)面按HOME鍵時(shí)的執(zhí)行流程:
程序運(yùn)行->按HOME鍵
Activity調(diào)用的順序是onPause->onStop
SurfaceView調(diào)用了surfaceDestroyed方法
然后再切回程序
Activity調(diào)用的順序是onRestart->onStart->onResume
SurfaceView調(diào)用了surfaceCreated->surfaceChanged方法
而對(duì)于鎖屏,其執(zhí)行流程則是:
Activity只調(diào)用onPause方法
解鎖后Activity調(diào)用onResume方法
SurfaceView中surfaceholder.callback的所有方法都沒(méi)有執(zhí)行
問(wèn)題找到了,由于鎖屏?xí)r,callback的回調(diào)方法沒(méi)有執(zhí)行,導(dǎo)致相機(jī)和預(yù)覽的連接還沒(méi)有斷開(kāi),相機(jī)資源就被釋放了,所以導(dǎo)致在重新申請(qǐng)相機(jī)資源時(shí),系統(tǒng)報(bào)crash。根據(jù)上面的文檔,推測(cè)是鎖屏下系統(tǒng)并沒(méi)有改變surfaceview的可見(jiàn)性,于是我嘗試在onPause和onResume時(shí)通過(guò)手動(dòng)設(shè)置surfaceview的visibile屬性,結(jié)果發(fā)現(xiàn)可以正常觸發(fā)回調(diào)函數(shù)了。由于在切后臺(tái)或者鎖屏?xí)r,用戶(hù)本來(lái)就應(yīng)該看不到surfaceview,因此這種手動(dòng)更改surfaceview的可見(jiàn)性的方法,并不會(huì)對(duì)用戶(hù)的體驗(yàn)造成影響。
問(wèn)答
Android - 如何修復(fù)權(quán)限異常?
相關(guān)閱讀
深入理解Autorelease Pool
ComponentKit框架解析之一—初識(shí)CK
Android 內(nèi)存泄漏分析心得
【每日課程推薦】機(jī)器學(xué)習(xí)實(shí)戰(zhàn)!快速入門(mén)在線(xiàn)廣告業(yè)務(wù)及CTR相應(yīng)知識(shí)
此文已由作者授權(quán)騰訊云+社區(qū)發(fā)布,更多原文請(qǐng)點(diǎn)擊
搜索關(guān)注公眾號(hào)「云加社區(qū)」,第一時(shí)間獲取技術(shù)干貨,關(guān)注后回復(fù)1024 送你一份技術(shù)課程大禮包!
海量技術(shù)實(shí)踐經(jīng)驗(yàn),盡在云加社區(qū)!
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/77203.html
摘要:前言阿里巴巴機(jī)器智能實(shí)驗(yàn)室線(xiàn)下智能團(tuán)隊(duì)從年底開(kāi)始涉及線(xiàn)下智能領(lǐng)域,從算法工程產(chǎn)品化業(yè)務(wù)落地多個(gè)方面入手,與合作伙伴們一起取得了一些小小的成績(jī)。目前,該套工具作為推薦的量化工具廣泛應(yīng)用在阿里集團(tuán)內(nèi)多個(gè)線(xiàn)下業(yè)務(wù)場(chǎng)景中。 showImg(https://segmentfault.com/img/remote/1460000019246850); 阿里妹導(dǎo)讀:AI 技術(shù)已經(jīng)從互聯(lián)網(wǎng)走向零售、...
摘要:在移動(dòng)端頁(yè)面使用上傳文件或者圖片時(shí),和安卓的展現(xiàn)方式有很多不一樣。 在移動(dòng)端頁(yè)面使用上傳文件或者圖片時(shí),IOS和安卓的展現(xiàn)方式有很多不一樣。 input 有 captrure屬性,取值:camera:相機(jī);camcorder:攝像;microphone:錄音 在安卓想要調(diào)用相機(jī)需要添加capture屬性,于是我在IOS和Android上進(jìn)行了三端測(cè)試! 結(jié)果如下: 1. 安卓: 【...
摘要:在移動(dòng)端頁(yè)面使用上傳文件或者圖片時(shí),和安卓的展現(xiàn)方式有很多不一樣。 在移動(dòng)端頁(yè)面使用上傳文件或者圖片時(shí),IOS和安卓的展現(xiàn)方式有很多不一樣。 input 有 captrure屬性,取值:camera:相機(jī);camcorder:攝像;microphone:錄音 在安卓想要調(diào)用相機(jī)需要添加capture屬性,于是我在IOS和Android上進(jìn)行了三端測(cè)試! 結(jié)果如下: 1. 安卓: 【...
閱讀 3914·2023-04-26 02:07
閱讀 3701·2021-10-27 14:14
閱讀 2923·2021-10-14 09:49
閱讀 1651·2019-08-30 15:43
閱讀 2650·2019-08-29 18:33
閱讀 2395·2019-08-29 17:01
閱讀 942·2019-08-29 15:11
閱讀 617·2019-08-29 11:06