天天看點

Android調用系統相機、自己定義相機、處理大圖檔

Android調用系統相機和自己定義相機執行個體

本博文主要是介紹了android上使用相機進行拍照并顯示的兩種方式,而且因為涉及到要把拍到的照片顯示出來,該樣例也會涉及到Android載入大圖檔時候的處理(避免OOM),還有簡要提一下有些人SurfaceView出現黑屏的原因。

Android應用拍照的兩種方式,以下為兩種形式的Demo展示出來的效果。

Android調用系統相機、自己定義相機、處理大圖檔
Android調用系統相機、自己定義相機、處理大圖檔

知識點:

一、調用系統自帶的相機應用

二、自己定義我們自己的拍照界面

三、關于計算機解析圖檔原理(怎樣正确載入圖檔到Android應用中)

所需權限:

一、調用系統照相機程式拍照(方式一)

1.定義所須要的權限

2.我們須要定義調用系統相機App的Intent,當然是通過設定IntentFilter中的Action來打開我們想要的activity了。

MediaStore.ACTION_IMAGE_CAPTURE - 這個Action将打開拍照的系統相機。傳回一個Image

MediaStore.ACTION_VIDEO_CAPTURE - 這個Action将打開錄像的系統相機。傳回一個Video

在MediaStore.ACTION_IMAGE_CAPTURE中,我們能夠看到這段話:

【The caller may pass an extra EXTRA_OUTPUT to control where this image will be 

written. If the EXTRA_OUTPUT is not present, then a small sized image is returned 

as a Bitmap object in the extra field. This is useful for applications that only 

need a small image. If the EXTRA_OUTPUT is present, then the full-sized image will 

be written to the Uri value of EXTRA_OUTPUT.】

3.API規定我們傳入拍照得到圖檔的存儲位置的Uri。否則Bimmap将以一個壓縮後的形式傳回到我們目前Activity.

intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri); // set the image file name

則會把拍照的圖檔存儲到我們傳入的Uri相應的File裡面。

4.我們調用startActivityForResult(intent)來啟動這樣一個系統相機app之後。然後在目前應用Activity的onActivityResult()中接受到傳回拍照成功或者失敗的消息,做相應處理。

5.“壓縮處理”(Android應用中載入大圖檔),并顯示到ImageView中。

二、自己定義照相機

1.檢查相機是否存在,并擷取相機Camera。

2.建立一個相機圖像預覽類:extends SurfaceView 并 implements SurfaceHolder (我定義:MySurfaceView)

3.把這個預覽類放入一個自己定義布局layout裡面,而且能夠在layout裡加入自己的其它button

4.設定相應的拍照button然後聽事件

5.捕獲照片和儲存圖檔

6.釋放掉我們使用的相機Camera,不然之後其它應用将無法使用它。

三、計算機解析圖檔的方式和Android中大圖檔Bitmap的壓縮顯示處理

這個問題有點老生長談了,平時我們常常遇到一些圖檔資源。我們把它載入到記憶體發現抛出記憶體不夠用的異常,即OOM。當然載入圖檔時出現的OOM情況有非常多種,比方單張圖檔沒有做壓縮,導緻圖檔占用記憶體過大而發生記憶體溢出。也有多張圖檔一次性載入進來。導緻的記憶體溢出。

通常單張大圖。我們載入進來往往會經過一個圖檔的壓縮處理的過程。而假設多張圖檔載入,我們可能就須要一些緩存機制。再加上一些算法來保證程式不出現OOM。

我們這裡想要講的知識點跟單張大圖比較有關系

首先,我們知道一個圖檔,它是由非常多像素點來表示的,而像素點的個數僅僅跟圖檔的分辨率有關。而跟圖檔所占的記憶體空間大小無關。比方我們的桌面桌面:1280 * 768 的分辨率,那麼它就有 1280 * 768 = 983040個像素點,這意味着什麼呢?我們知道我們要表示一個像素點的顔色。最常常我們須要RGB三種顔色來表示,而R:0~255,相當于兩個FF的位置,就是8位。這種話RGB合起來,一個像素點的表示就須要24位(這就是我們平衡聽到的24位圖),而加上透明度的8位,就是平時說的32位圖。那麼一張圖檔,它載入到記憶體中的話,它會占用多大的空間呢?

計算方法:(像素點 * 一個像素所占用的byte數) / 1024 / 1024 (MB) 

以1280 * 768 的分辨率。32位圖為例:所占記憶體大小: ((1280 * 768 * (32 / 8)) / 1024)/1024=3.75(MB)

說了這麼多,那麼我們再來說下Android系統的規定吧。Android系統嚴格規定了每一個應用所能配置設定的最大的記憶體為多少,我們知道有一個VM值(在我們建立模拟器的時候),這個VM值裡面便是我們所說的堆空間(Heap Size),當你的應用占用的空間已經超出我們定義的堆空間大小,那麼不好意思,OOM

這種話,我們明确了圖檔的大小占領原理,還有盡量不要超出這個堆空間,那麼OK,如今問題變得簡單了。假設我們有一種方式能夠在圖檔載入進來之前,知道圖檔的大小。然後改變它的長、寬,這種話,分辨率便變小了,這樣出來的乘積也就變小了。比方:我們的螢幕僅僅有320 * 240。 這時候你載入大分辨的圖檔進來最多也僅僅能顯示成這樣,是以我們常採用的是對圖檔進行壓縮處理。這裡有個概念叫壓縮比:

長:1024 / 320 = 3.2  約等于 3

寬:768 / 240 = 3.2 

那這樣我們假設把圖檔壓縮成這樣大小的,最後的圖檔載入進來的大小便是

((320 * 240 * (32 / 8)) / 1024)/1024=0.29(MB)

希望我這樣講完,大家都能聽懂了。我這裡先把照相機執行個體中出現的關于假設處理這塊圖檔的代碼先粘出來

關于堆空間:

堆(HEAP)是VM中占用記憶體最多的部分。一般是動态配置設定的。堆的大小不是一成不變的,通常有一個配置設定機制來控制它的大小。

比方初始的HEAP是4M大,當4M的空間被占用超過75%的時候,又一次配置設定堆為8M大。當8M被占用超過75%,配置設定堆為16M大。倒過來,當16M的堆利用不足30%的時候,縮減它的大小為8M大。

又一次設定堆的大小,尤其是壓縮,通常會涉及到記憶體的拷貝,是以變更堆的大小對效率有不良影響。

廢話少說以下就看代碼咯~~為了大家看起來友善點,代碼的結構可能不是非正常範!

源代碼下載下傳位址:​​javascript:void(0)​​

代碼部分: 

一、用系統的相機

button點選之後開啟系統相機Activity

生成File檔案,并得到Uri

二、用自己定義的相機

檢測相機裝置是否存在:

button按下之後的推斷:

自己定義的SurfaceView類:

自己定義相機Activity類:(為了避免當使用者按下Home鍵,之後再回到我們App中,SurfaceView變黑屏。我們須要将SurfaceView載入到FrameLayout中的代碼寫在onResume中)