概述:
Android framework提供了對各種設備的相機和相機特性的支持, 這讓我們在APP中可以捕捉圖片和視頻. 該文檔描述了一個快速簡單的方法來創建一個拍照和錄像功能, 並概述了一個先進的方法來創建自定義的相機體驗.
建議:
在開始讓APP使用Android設備的相機之前, 我們應該考慮一些關於APP打算如何使用這個硬件的問題:
相機需求: 對於我們要開發的APP來說, 相機功能真的如此重要以至於放棄在沒有相機硬件的設備上的安裝嗎? 如果是的話, 那麼應該在manifest中聲明相機需求.
快速圖片還是自定義相機: 我們的APP將會如何使用相機呢? 只是需要拍一張快速圖片或者視頻剪輯? 還是APP本身提供了一種新的使用相機的方式? 如果是前者, 則應該考慮使用已經存在的相機APP. 如果是後者, 則需要自己創建一個相機APP.
儲存: APP生成的圖片或者視頻是打算只是對自己的APP可用, 還是需要分享, 可以被其他的APP訪問呢? 在APP被卸載之後, 圖片和視頻是否還可用呢?
基礎:
Android framework支持通過android.hardware.camera2API或者相機Intent抓取圖片和視頻. 這裏是對應的類:
android.hardware.camera2: 這個包是用來控制設備相機的基礎API. 它可以用來拍攝照片或者視頻.
Camera: 該類是已經過時的控制設備相機的API.
SurfaceView: 該類是用來展示一個直播相機預覽給用戶的.
MediaRecorder: 該類是用來從相機拍攝視頻用的.
Intent: 一個action類型爲MediaStore.ACTION_IMAGE_CAPTURE或者MediaStore.ACTION_VIDEO_CAPTURE的intent, 可以用來拍照或者拍視頻, 它並不需要直接使用Camera對象.
Manifest聲明:
開始開發使用相機的APP之前, 我們應該確定manifest中已經聲明瞭合適的權限來使用相機硬件和相關的功能.
1. Camera Permission: 必選項, 設備相機使用權限.
<uses-permission android:name="android.permission.CAMERA"/>
注意, 如果我們通過一個intent來使用相機, 那麼則不需要這個權限.
2. Camera Features – APP也必須聲明使用相機功能. 比如:
<uses-feature android:name="android.hardware.camera"/>
增加camerafeatures到我們的manifest會讓Google Play阻止APP安裝到那些沒有相機或者不支持指定的相機功能的設備上. 如果APP可以使用相機或者相機功能但是並不是必須功能, 那麼應該通過android:required來指定, 並設置其爲false:
<uses-feature android:name="android.hardware.camera" android:required="false" />
3. Storage Permission – 如果APP保存圖片或者視頻到設備的外部存儲(SD卡), 那麼必須聲明該權限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
4. Audio Recording Permission – 如果需要在拍攝的時候錄音,那麼必須聲明這個權限:
<uses-permission android:name="android.permission.RECORD_AUDIO" />
5. Location Permission – 如果APP需要爲圖片標記GPS定位信息, 那麼必須使用該權限:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
使用現成的相機APP:
在我們的APP中如果想要快速簡單的使用相機拍照或者視頻功能的話, 最便捷的方法就是使用一個Intent來調用一個現成的Android相機APP. 一個相機intent可以通過已存在的相機APP來發起拍照或者拍攝視頻的需求, 然後將控制權返回給我們的APP. 這一小節將描述如何使用該技術來實現拍照和攝像.
通過intent來調用一個camera的步驟通常是醬嬸兒的:
1. 構造一個Camera intent – 創建一個請求一個圖片或者視頻的Intent, 需要使用這兩種類型: MediaStore.ACTION_IMAGE_CAPTURE , 表示想用已經存在的相機APP拍照; MediaStore.ACTION_VIDEO_CAPTURE,表示想用已經存在的相機拍攝視頻.
2. 啓動Camera Intent – 使用startActivityForResult()方法來執行camera Intent. 然後Camera應用的用戶接口將會出現在設備屏幕上, 讓用戶可以拍照或者視頻.
3. 接收Intent結果– 設置一個onActivityResult()方法來接收回調和camera intent返回的數據. 當用戶結束拍攝之後, 系統將會調用這個方法.
圖片抓取Intent:
使用camera intent來拍照是一種快速的最少代碼的可以實現拍照功能的方法. 一個圖片抓取intent可以包含下面的額外信息:
l MediaStore.EXTRA_OUTPUT – 這個設置項需要一個Uri對象, 它指定了一個我們想要保存圖片的路徑和文件名. 這個設置項是可選的, 但是強烈建議使用. 如果沒有指定這個值, 那麼相機應用將會使用默認文件名保存圖片到默認的路徑, 這些信息在返回的intent的getData()方法中.
下面的栗子演示瞭如何構造一個圖片抓取intent並執行它. 其中的getOutputMediaFileUri()方法可以在”保存媒體文件”章節找到. 該方法可能在下一篇文章中.
private static final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 100; private Uri fileUri; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // create Intent to take a picture and return control to the calling application Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE); // create a file to save the image intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri); // set the image file name // start the image capture Intent startActivityForResult(intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE); }
當startActivityForResult()方法執行後, 用戶可以看到一個camera應用的接口. 當用戶拍照之後(或者取消了操作), 用戶接口返回到我們自己的APP, 這時候我們必須實現onActivityResult()方法來接收intent的結果, 並繼續APP的操作.
視頻抓取intent:
使用camera intent抓取視頻同樣是實現該功能最便捷的方法. 一個視頻抓取intent可以支持這些額外的信息:
MediaStore.EXTRA_OUTPUT – 這個設置項需要一個Uri來指定保存視頻的路徑和文件名. 這個設置項是可選的但是強烈建議使用. 如果沒指定這個值的話, 那麼Camera應用會將視頻保存在默認的路徑, 文件名也是默認的, 然後通過Intent.getData()返回數據.
MediaStore.EXTRA_VIDEO_QUALITY – 這個值可以爲0, 表示最低質量, 最小文件尺寸. 或者爲1表示最高質量和最大文件尺寸.
MediaStore.EXTRA_DURATION_LIMIT- 該值用來限制想要錄製的視頻的時長, 單位是秒.
MediaStore.EXTRA_SIZE_LIMIT – 該值用來限制錄製視頻的文件大小, 單位是bytes.
下面的代碼演示瞭如何構造一個視頻抓取intent並執行它. 同上, getOutputMediaFileUri()方法在”保存媒體文件”中實現, 這個小節會在下一篇blog中出現.
private static final int CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE = 200; private Uri fileUri; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); //create new Intent Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE); fileUri = getOutputMediaFileUri(MEDIA_TYPE_VIDEO); // create a file to save the video intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri); // set the image file name intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1); // set the video image quality to high // start the Video Capture Intent startActivityForResult(intent, CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE); }
當startActivityForResult()方法執行後, 用戶可以看到一個camera應用的接口. 當用戶拍攝視頻結束之後(或者取消了操作), 用戶接口返回到我們自己的APP, 這時候我們必須實現onActivityResult()方法來接收intent的結果, 並繼續APP的操作.
接收cameraintent結果:
一旦構造並且執行了一個圖片或者視頻的camera intent, 我們的APP就必須配置接收intent的結果. 這小節將展示如何從camera intent獲取結果, 這樣我們的APP就可以處理抓取到的圖片或者視頻了. 爲了接收intent結果, 我們必須在啓動intent的activity中重寫onActivityResult()方法. 下面的栗子演示瞭如何重寫onActivityResult()方法來從intent中獲取結果:
private static final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 100; private static final int CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE = 200; @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE) { if (resultCode == RESULT_OK) { // Image captured and saved to fileUri specified in the Intent Toast.makeText(this, "Image saved to:\n" + data.getData(), Toast.LENGTH_LONG).show(); } else if (resultCode == RESULT_CANCELED) { // User cancelled the image capture } else { // Image capture failed, advise user } } if (requestCode == CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE) { if (resultCode == RESULT_OK) { // Video captured and saved to fileUri specified in the Intent Toast.makeText(this, "Video saved to:\n" + data.getData(), Toast.LENGTH_LONG).show(); } else if (resultCode == RESULT_CANCELED) { // User cancelled the video capture } else { // Video capture failed, advise user } } }
一旦我們的activity收到了成功的結果, 那麼抓取的圖片和視頻就可以從指定的路徑獲取到了.
總結:
使用相機是很多APP的基本功能, 多數的即時通訊工具都帶有這個功能, 現在幾乎所有的APP都有這個功能, 因爲我們總是要拍攝一張圖片作爲頭像.
調用系統的拍攝APP很容易, 只需要構造intent然後在處理返回數據就可以了. 邏輯清晰簡單. 不多贅述.
參考: https://developer.android.com/guide/topics/media/camera.html