以下內(nèi)容翻譯來源,Google官方開發(fā)文檔:https://developer.android.google.cn/guide/topics/media/camera.html
相關(guān)的類
- android.hardware.camera2
- Camera
- SurfaceView---這個(gè)類用于向用戶呈現(xiàn)實(shí)時(shí)相機(jī)預(yù)覽。
- MediaRecorder---這個(gè)類用于從攝像機(jī)錄制視頻。
- Intent---MediaStore.ACTION_IMAGE_CAPTURE或MediaStore.ACTION_VIDEO_CAPTURE可用于捕獲圖像或視頻,而無需直接使用Camera對(duì)象。
清單聲明
在使用Camera API開始開發(fā)應(yīng)用程序之前,應(yīng)確保您的清單具有適當(dāng)?shù)穆暶?,以允許使用相機(jī)硬件和其他相關(guān)功能。
-
相機(jī)權(quán)限 - 您的應(yīng)用程序必須請(qǐng)求使用設(shè)備相機(jī)的權(quán)限。
<uses-permission android:name="android.permission.CAMERA" />
注意:如果您通過調(diào)用現(xiàn)有的攝像頭應(yīng)用程序來使用攝像頭,則應(yīng)用程序不需要請(qǐng)求此權(quán)限。
-
相機(jī)功能 - 您的應(yīng)用程序還必須聲明使用相機(jī)功能,例如:
<uses-feature android:name="android.hardware.camera" />
-
存儲(chǔ)權(quán)限 - 如果應(yīng)用程序?qū)D像或視頻保存到設(shè)備的外部存儲(chǔ)設(shè)備(SD卡),則還必須在清單中指定此選項(xiàng)。
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
-
音頻錄制權(quán)限 - 對(duì)于使用視頻捕獲錄制音頻,應(yīng)用程序必須請(qǐng)求獲取音頻捕獲權(quán)限。
<uses-permission android:name="android.permission.RECORD_AUDIO" />
創(chuàng)建自定義攝像頭
為應(yīng)用程序創(chuàng)建自定義攝像頭界面的一般步驟如下:
- 檢測(cè)和訪問攝像機(jī) - 創(chuàng)建代碼以檢查攝像機(jī)是否存在并請(qǐng)求訪問。
- 創(chuàng)建預(yù)覽類 - 創(chuàng)建擴(kuò)展SurfaceView并實(shí)現(xiàn)SurfaceHolder界面的相機(jī)預(yù)覽類。這個(gè)類預(yù)覽來自相機(jī)的實(shí)時(shí)圖像。
- 構(gòu)建預(yù)覽布局 - 一旦你擁有相機(jī)預(yù)覽類,創(chuàng)建一個(gè)包含預(yù)覽和你想要的用戶界面控件的視圖布局。
- Capture的監(jiān)聽器 - 為您的接口控件連接偵聽器,以響應(yīng)用戶操作(例如按下按鈕)開始捕獲圖像或視頻。
- 捕獲和保存文件 - 設(shè)置用于捕獲圖片或視頻和保存輸出的代碼。
- 釋放相機(jī) - 使用相機(jī)后,應(yīng)用程序必須正確釋放它以供其他應(yīng)用程序使用。
相機(jī)硬件是一個(gè)共享資源,必須仔細(xì)管理,以便您的應(yīng)用程序不會(huì)與其他可能也想使用它的應(yīng)用程序沖突。以下部分討論如何檢測(cè)相機(jī)硬件,如何請(qǐng)求訪問相機(jī),如何捕獲圖片或視頻以及如何在應(yīng)用程序使用完成后釋放相機(jī)。
檢測(cè)相機(jī)硬件
如果您的應(yīng)用程序沒有特別要求使用清單聲明的攝像機(jī),則應(yīng)檢查相機(jī)在運(yùn)行時(shí)是否可用。要執(zhí)行此檢查,請(qǐng)使用PackageManager.hasSystemFeature()方法,如下面的示例代碼所示:
/** Check if this device has a camera */
private boolean checkCameraHardware(Context context) {
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
// this device has a camera
return true;
} else {
// no camera on this device
return false;
}
}
Android設(shè)備可以具有多個(gè)攝像機(jī),例如用于攝影的背面攝像機(jī)和用于視頻通話的前置攝像機(jī)。Android 2.3(API Level 9)及更高版本允許您使用Camera.getNumberOfCameras()方法檢查設(shè)備上可用的攝像機(jī)數(shù)量。
訪問相機(jī)
如果您確定運(yùn)行應(yīng)用程序的設(shè)備具有攝像頭,則必須通過獲取攝像頭實(shí)例來請(qǐng)求訪問它(除非您正在使用意圖來訪問一個(gè)攝像頭)。
要訪問主要攝像機(jī),請(qǐng)使用Camera.open()方法,并確保捕獲任何異常,如下面的代碼所示:
/** A safe way to get an instance of the Camera object. */
public static Camera getCameraInstance(){
Camera c = null;
try {
c = Camera.open(); // attempt to get a Camera instance
}
catch (Exception e){
// Camera is not available (in use or does not exist)
}
return c; // returns null if camera is unavailable
}
注意:使用Camera.open()時(shí)始終檢查異常。如果相機(jī)正在使用或不存在,則無法檢查異常,將導(dǎo)致您的應(yīng)用程序被系統(tǒng)關(guān)閉。
在運(yùn)行Android 2.3(API Level 9)或更高版本的設(shè)備上,您可以使用Camera.open(int)訪問特定的攝像機(jī)。上面的示例代碼將訪問具有多個(gè)攝像頭的設(shè)備上的第一個(gè)后置攝像頭
檢查相機(jī)功能
獲取對(duì)攝像機(jī)的訪問權(quán)限后,您可以使用Camera.getParameters()方法獲取有關(guān)其功能的更多信息,并檢查返回的Camera.Parameters對(duì)象以獲取支持的功能。使用API?? Level 9或更高版本時(shí),請(qǐng)使用Camera.getCameraInfo()確定相機(jī)是位于設(shè)備的正面還是背面,以及圖像的方向。
創(chuàng)建預(yù)覽類
為了讓用戶有效地拍攝照片或視頻,他們必須能夠看到設(shè)備相機(jī)看到的內(nèi)容。相機(jī)預(yù)覽類是SurfaceView,可以顯示來自相機(jī)的實(shí)時(shí)圖像數(shù)據(jù),因此用戶可以框架并捕獲圖片或視頻。
以下示例代碼演示了如何創(chuàng)建可包含在視圖布局中的基本攝像機(jī)預(yù)覽類。這個(gè)類實(shí)現(xiàn)了SurfaceHolder.Callback,以便捕獲用于創(chuàng)建和銷毀視圖的回調(diào)事件,這是分配攝像機(jī)預(yù)覽輸入所需要的。
/** A basic Camera preview class */
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
public CameraPreview(Context context, Camera camera) {
super(context);
mCamera = camera;
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, now tell the camera where to draw the preview.
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
Log.d(TAG, "Error setting camera preview: " + e.getMessage());
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// empty. Take care of releasing the Camera preview in your activity.
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
if (mHolder.getSurface() == null){
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e){
// ignore: tried to stop a non-existent preview
}
// set preview size and make any resize, rotate or
// reformatting changes here
// start preview with new settings
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e){
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
}
如果要為相機(jī)預(yù)覽設(shè)置特定大小,請(qǐng)?jiān)谏鲜鲎⑨屩兴龅膕urfaceChanged()方法中設(shè)置此大小。設(shè)置預(yù)覽大小時(shí),必須使用getSupportedPreviewSizes()的值。不要在setPreviewSize()方法中設(shè)置任意值。
注意:隨著Android 7.0(API級(jí)別24)及更高版本中多窗口功能的引入,即使在調(diào)用setDisplayOrientation()之后,也不能再假設(shè)預(yù)覽的縱橫比與您的活動(dòng)相同。根據(jù)窗口大小和寬高比,您可能必須使用信箱布局將寬相機(jī)預(yù)覽適配為縱向布局,反之亦然。
在布局中放置預(yù)覽
相機(jī)預(yù)覽類(例如上一部分中所示的示例)必須與用于拍攝圖片或視頻的其他用戶界面控件一起放置在活動(dòng)的布局中。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<FrameLayout
android:id="@+id/camera_preview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
/>
<Button
android:id="@+id/button_capture"
android:text="Capture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
/>
</LinearLayout>
在大多數(shù)設(shè)備上,相機(jī)預(yù)覽的默認(rèn)方向?yàn)闄M向。此示例布局指定水平(橫向)布局,以下代碼將應(yīng)用程序的方向固定為橫向。為了簡(jiǎn)化渲染相機(jī)預(yù)覽,您應(yīng)該將以下內(nèi)容添加到清單中,以將應(yīng)用程序的預(yù)覽活動(dòng)方向更改為橫向。
<activity android:name=".CameraActivity"
android:label="@string/app_name"
android:screenOrientation="landscape">
<!-- configure this activity to use landscape orientation -->
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
注意:相機(jī)預(yù)覽不必處于橫向模式。從Android 2.2(API級(jí)別8)開始,您可以使用setDisplayOrientation()方法設(shè)置預(yù)覽圖像的旋轉(zhuǎn)。為了在用戶重新定位手機(jī)時(shí)更改預(yù)覽方向,請(qǐng)?jiān)陬A(yù)覽類的surfaceChanged()方法中,首先使用Camera.stopPreview()停止預(yù)覽,更改方向,然后再次使用Camera.startPreview()啟動(dòng)預(yù)覽。
在相機(jī)視圖的活動(dòng)中,將預(yù)覽類添加到上面示例中所示的FrameLayout元素。您的相機(jī)活動(dòng)還必須確保在暫?;蜿P(guān)閉時(shí)釋放相機(jī)。以下示例顯示如何修改相機(jī)活動(dòng)以附加創(chuàng)建預(yù)覽類中顯示的預(yù)覽類。
public class CameraActivity extends Activity {
private Camera mCamera;
private CameraPreview mPreview;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Create an instance of Camera
mCamera = getCameraInstance();
// Create our Preview view and set it as the content of our activity.
mPreview = new CameraPreview(this, mCamera);
FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
preview.addView(mPreview);
}
}
注意:上面示例中的getCameraInstance()方法指的是訪問攝像機(jī)中顯示的示例方法。
捕獲圖片
一旦構(gòu)建了預(yù)覽類和顯示它的視圖布局,就可以開始使用應(yīng)用程序捕獲圖像。在應(yīng)用程序代碼中,您必須為用戶界面控件設(shè)置偵聽器,以通過拍攝圖片來響應(yīng)用戶操作。在應(yīng)用程序代碼中,您必須為用戶界面控件設(shè)置偵聽器,以通過拍攝圖片來響應(yīng)用戶操作。
為了檢索圖片,請(qǐng)使用Camera.takePicture()方法。此方法需要三個(gè)參數(shù),從相機(jī)接收數(shù)據(jù)。為了接收J(rèn)PEG格式的數(shù)據(jù),您必須實(shí)現(xiàn)一個(gè)Camera.PictureCallback接口來接收?qǐng)D像數(shù)據(jù)并將其寫入文件。以下代碼顯示了Camera.PictureCallback接口的基本實(shí)現(xiàn),用于保存從相機(jī)接收的圖像。
private PictureCallback mPicture = new PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
if (pictureFile == null){
Log.d(TAG, "Error creating media file, check storage permissions: " +
e.getMessage());
return;
}
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
} catch (FileNotFoundException e) {
Log.d(TAG, "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d(TAG, "Error accessing file: " + e.getMessage());
}
}
};
通過調(diào)用Camera.takePicture()方法觸發(fā)捕獲圖像。以下示例代碼顯示了如何從按鈕View.OnClickListener調(diào)用此方法。
// Add a listener to the Capture button
Button captureButton = (Button) findViewById(id.button_capture);
captureButton.setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
// get an image from the camera
mCamera.takePicture(null, null, mPicture);
}
}
);
警告:記住,當(dāng)您的應(yīng)用程序使用它時(shí),通過調(diào)用Camera.release()來釋放Camera對(duì)象!有關(guān)如何釋放相機(jī)的信息,請(qǐng)參閱釋放相機(jī)。
捕獲視頻
使用Android框架的視頻捕獲需要仔細(xì)管理Camera對(duì)象和與MediaRecorder類的協(xié)調(diào)。使用Camera錄制視頻時(shí),除了Camera.open()和Camera.release()調(diào)用外,還必須管理Camera.lock()和Camera.unlock()調(diào)用,以允許MediaRecorder訪問攝像機(jī)硬件。
注意:從Android 4.0(API級(jí)別14)開始,Camera.lock()和Camera.unlock()調(diào)用會(huì)自動(dòng)管理。
與使用設(shè)備相機(jī)拍攝照片不同,捕獲視頻需要非常特殊的通話順序。您必須遵循特定的執(zhí)行順序,才能使用您的應(yīng)用程序成功準(zhǔn)備和捕獲視頻,如下所述。
- 打開相機(jī) - 使用Camera.open()獲取相機(jī)對(duì)象的實(shí)例。
- 連接預(yù)覽 - 通過使用Camera.setPreviewDisplay()將SurfaceView連接到攝像機(jī),準(zhǔn)備實(shí)時(shí)的攝像機(jī)圖像預(yù)覽
- 開始預(yù)覽 - 調(diào)用Camera.startPreview()開始顯示實(shí)時(shí)攝像機(jī)圖像。
- 開始錄制視頻 - 必須完成以下步驟才能成功錄制視頻:
- 解鎖相機(jī) - 通過調(diào)用Camera.unlock()解鎖相機(jī)以供MediaRecorder使用。
- 配置MediaRecorder - 按以下順序調(diào)用以下MediaRecorder方法。有關(guān)更多信息,請(qǐng)參閱MediaRecorder參考文檔。
- setCamera() - 設(shè)置要用于視頻捕獲的攝像機(jī),使用應(yīng)用程序的當(dāng)前攝像機(jī)實(shí)例。
- setAudioSource() - 設(shè)置音頻源,使用MediaRecorder.AudioSource.CAMCORDER。
- setVideoSource() - 設(shè)置視頻源,使用MediaRecorder.VideoSource.CAMERA。
- 設(shè)置視頻輸出格式和編碼。對(duì)于Android 2.2(API Level 8)及更高版本,請(qǐng)使用MediaRecorder.setProfile方法,并使用CamcorderProfile.get()獲取配置文件實(shí)例。對(duì)于2.2之前的Android版本,必須設(shè)置視頻輸出格式和編碼參數(shù):
- setOutputFormat() - 設(shè)置輸出格式,指定默認(rèn)設(shè)置或MediaRecorder.OutputFormat.MPEG_4
- setAudioEncoder() - 設(shè)置聲音編碼類型,指定默認(rèn)設(shè)置或MediaRecorder.AudioEncoder.AMR_NB。
- setVideoEncoder() - 設(shè)置視頻編碼類型,指定默認(rèn)設(shè)置或MediaRecorder.VideoEncoder.MPEG_4_SP。
- 準(zhǔn)備MediaRecorder - 通過調(diào)用MediaRecorder.prepare()為提供的配置設(shè)置準(zhǔn)備MediaRecorder。
- 啟動(dòng)MediaRecorder - 通過調(diào)用MediaRecorder.start()開始錄制視頻
- 停止錄制視頻 - 按順序調(diào)用以下方法,以成功完成視頻錄制:
- 停止MediaRecorder - 停止通過調(diào)用MediaRecorder.stop()錄制視頻。
- 重置MediaRecorder - (可選)通過調(diào)用MediaRecorder.reset()從記錄器中刪除配置設(shè)置。
- 釋放MediaRecorder - 通過調(diào)用MediaRecorder.release()釋放MediaRecorder。
- 鎖定相機(jī) - 鎖定相機(jī),以便將來的MediaRecorder會(huì)話可以通過調(diào)用Camera.lock()來使用它。從Android 4.0(API級(jí)別14)開始,不需要此調(diào)用,除非MediaRecorder.prepare()調(diào)用失敗。
- 停止預(yù)覽 - 當(dāng)您的活動(dòng)使用相機(jī)完成后,使用Camera.stopPreview()停止預(yù)覽。
- 釋放相機(jī) - 釋放相機(jī),以便其他應(yīng)用程序可以通過調(diào)用Camera.release()來使用它。
注意:可以先使用MediaRecorder而不創(chuàng)建相機(jī)預(yù)覽,并跳過此過程的前幾個(gè)步驟。然而,由于用戶通常喜歡在開始記錄之前看到預(yù)覽,所以這里不討論該處理。
提示:如果您的應(yīng)用程序通常用于錄制視頻,請(qǐng)?jiān)陂_始預(yù)覽之前將setRecordingHint(boolean)設(shè)置為true。此設(shè)置可以幫助減少開始錄制所需的時(shí)間。
配置MediaRecorder
當(dāng)使用MediaRecorder類記錄視頻時(shí),必須按特定順序執(zhí)行配置步驟,然后調(diào)用MediaRecorder.prepare()方法來檢查和實(shí)現(xiàn)配置。以下示例代碼演示如何正確配置和準(zhǔn)備MediaRecorder類進(jìn)行視頻錄制。
private boolean prepareVideoRecorder(){
mCamera = getCameraInstance();
mMediaRecorder = new MediaRecorder();
// Step 1: Unlock and set camera to MediaRecorder
mCamera.unlock();
mMediaRecorder.setCamera(mCamera);
// Step 2: Set sources
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
// Step 3: Set a CamcorderProfile (requires API Level 8 or higher)
mMediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));
// Step 4: Set output file
mMediaRecorder.setOutputFile(getOutputMediaFile(MEDIA_TYPE_VIDEO).toString());
// Step 5: Set the preview output
mMediaRecorder.setPreviewDisplay(mPreview.getHolder().getSurface());
// Step 6: Prepare configured MediaRecorder
try {
mMediaRecorder.prepare();
} catch (IllegalStateException e) {
Log.d(TAG, "IllegalStateException preparing MediaRecorder: " + e.getMessage());
releaseMediaRecorder();
return false;
} catch (IOException e) {
Log.d(TAG, "IOException preparing MediaRecorder: " + e.getMessage());
releaseMediaRecorder();
return false;
}
return true;
}
在Android 2.2(API級(jí)別8)之前,您必須直接設(shè)置輸出格式和編碼格式參數(shù),而不是使用CamcorderProfile。這種方法在下面的代碼中演示:
// Step 3: Set output format and encoding (for versions prior to API Level 8)
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);
MediaRecorder的以下視頻錄制參數(shù)被賦予默認(rèn)設(shè)置,但是,您可能想要為應(yīng)用程序調(diào)整這些設(shè)置:
setVideoEncodingBitRate()
setVideoSize()
setVideoFrameRate()
setAudioEncodingBitRate()
setAudioChannels()
setAudioSamplingRate()
啟動(dòng)和停止MediaRecorder
當(dāng)使用MediaRecorder類啟動(dòng)和停止視頻錄制時(shí),必須遵循以下列出的特定順序。
- 使用Camera.unlock()解鎖相機(jī)
- 配置MediaRecorder,如上面的代碼示例所示
- 使用MediaRecorder.start()開始錄制
- 錄制視頻
- 使用MediaRecorder.stop()停止錄制
- 使用MediaRecorder.release()釋放媒體記錄器
- 使用Camera.lock()鎖定相機(jī)
以下示例代碼演示了如何連接一個(gè)按鈕,以使用相機(jī)和MediaRecorder類正確啟動(dòng)和停止視頻錄制。
注意:完成視頻錄制時(shí),請(qǐng)勿釋放相機(jī),否則將停止預(yù)覽。
private boolean isRecording = false;
// Add a listener to the Capture button
Button captureButton = (Button) findViewById(id.button_capture);
captureButton.setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
if (isRecording) {
// stop recording and release camera
mMediaRecorder.stop(); // stop the recording
releaseMediaRecorder(); // release the MediaRecorder object
mCamera.lock(); // take camera access back from MediaRecorder
// inform the user that recording has stopped
setCaptureButtonText("Capture");
isRecording = false;
} else {
// initialize video camera
if (prepareVideoRecorder()) {
// Camera is available and unlocked, MediaRecorder is prepared,
// now you can start recording
mMediaRecorder.start();
// inform the user that recording has started
setCaptureButtonText("Stop");
isRecording = true;
} else {
// prepare didn't work, release the camera
releaseMediaRecorder();
// inform user
}
}
}
}
);
注意:在上面的示例中,prepareVideoRecorder()方法引用配置MediaRecorder中顯示的示例代碼。此方法負(fù)責(zé)鎖定相機(jī),配置和準(zhǔn)備MediaRecorder實(shí)例。(詳見例子)
釋放相機(jī)
攝像機(jī)是由設(shè)備上的應(yīng)用程序共享的資源。您的應(yīng)用程序可以在獲取相機(jī)實(shí)例后使用相機(jī),并且您的應(yīng)用程序停止使用時(shí),以及應(yīng)用程序暫停后(Activity.onPause()),您必須特別小心釋放相機(jī)對(duì)象。如果應(yīng)用程序未正確釋放相機(jī),則隨后嘗試訪問相機(jī)(包括您自己的應(yīng)用程序)將會(huì)失敗,并可能導(dǎo)致您的或其他應(yīng)用程序關(guān)閉。
要釋放Camera對(duì)象的實(shí)例,請(qǐng)使用Camera.release()方法,如下面的示例代碼所示。
public class CameraActivity extends Activity {
private Camera mCamera;
private SurfaceView mPreview;
private MediaRecorder mMediaRecorder;
...
@Override
protected void onPause() {
super.onPause();
releaseMediaRecorder(); // if you are using MediaRecorder, release it first
releaseCamera(); // release the camera immediately on pause event
}
private void releaseMediaRecorder(){
if (mMediaRecorder != null) {
mMediaRecorder.reset(); // clear recorder configuration
mMediaRecorder.release(); // release the recorder object
mMediaRecorder = null;
mCamera.lock(); // lock camera for later use
}
}
private void releaseCamera(){
if (mCamera != null){
mCamera.release(); // release the camera for other applications
mCamera = null;
}
}
}
警告:如果您的應(yīng)用程序未正確釋放相機(jī),則隨后嘗試訪問相機(jī)(包括您自己的應(yīng)用程序)將會(huì)失敗,并可能導(dǎo)致您的或其他應(yīng)用程序關(guān)閉。
保存媒體文件
用戶創(chuàng)建的媒體文件(如圖片和視頻)應(yīng)保存到設(shè)備的外部存儲(chǔ)目錄(SD卡),以節(jié)省系統(tǒng)空間,并允許用戶在沒有設(shè)備的情況下訪問這些文件。在設(shè)備上保存媒體文件有許多可能的目錄位置,但是您應(yīng)該考慮作為開發(fā)人員只有兩個(gè)標(biāo)準(zhǔn)位置:
- Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) --此方法返回用于保存圖片和視頻的標(biāo)準(zhǔn),共享和推薦的位置。此目錄是共享(公共),因此其他應(yīng)用程序可以輕松地發(fā)現(xiàn),讀取,更改和刪除保存在此位置的文件。如果用戶卸載了您的應(yīng)用程序,則不會(huì)刪除保存到此位置的媒體文件。了避免干擾用戶現(xiàn)有的圖片和視頻,您應(yīng)該為此目錄中的應(yīng)用程序的媒體文件創(chuàng)建一個(gè)子目錄,如下面的代碼示例所示。此方法在Android 2.2(API級(jí)別8)中可用,適用于早期API版本中的等效調(diào)用,請(qǐng)參閱保存共享文件。
- Context.getExternalFilesDir(Environment.DIRECTORY_PICTURES) ---此方法返回用于保存與您的應(yīng)用程序相關(guān)聯(lián)的圖片和視頻的標(biāo)準(zhǔn)位置。如果您的應(yīng)用程序已卸載,則會(huì)刪除保存在此位置的所有文件。不對(duì)此位置中的文件強(qiáng)制執(zhí)行安全性,其他應(yīng)用程序可能會(huì)讀取,更改和刪除它們。
以下示例代碼演示了如何為媒體文件創(chuàng)建文件或Uri位置,當(dāng)使用Intent或作為構(gòu)建相機(jī)應(yīng)用程序的一部分調(diào)用設(shè)備的攝像機(jī)時(shí),可以使用該位置。
public static final int MEDIA_TYPE_IMAGE = 1;
public static final int MEDIA_TYPE_VIDEO = 2;
/** Create a file Uri for saving an image or video */
private static Uri getOutputMediaFileUri(int type){
return Uri.fromFile(getOutputMediaFile(type));
}
/** Create a File for saving an image or video */
private static File getOutputMediaFile(int type){
// To be safe, you should check that the SDCard is mounted
// using Environment.getExternalStorageState() before doing this.
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "MyCameraApp");
// This location works best if you want the created images to be shared
// between applications and persist after your app has been uninstalled.
// Create the storage directory if it does not exist
if (! mediaStorageDir.exists()){
if (! mediaStorageDir.mkdirs()){
Log.d("MyCameraApp", "failed to create directory");
return null;
}
}
// Create a media file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File mediaFile;
if (type == MEDIA_TYPE_IMAGE){
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"IMG_"+ timeStamp + ".jpg");
} else if(type == MEDIA_TYPE_VIDEO) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"VID_"+ timeStamp + ".mp4");
} else {
return null;
}
return mediaFile;
}
注意:Environment.getExternalStoragePublicDirectory()在Android 2.2(API級(jí)別8)或更高版本中可用。如果您要使用早期版本的Android定位設(shè)備,請(qǐng)改用Environment.getExternalStorageDirectory()。有關(guān)詳細(xì)信息,請(qǐng)參閱保存共享文件。
有關(guān)在Android設(shè)備上保存文件的詳細(xì)信息,請(qǐng)參閱數(shù)據(jù)存儲(chǔ)。
相機(jī)功能(用來設(shè)置更加詳細(xì)的視屏,例如各種比例和白平衡等。后期再補(bǔ)充詳細(xì))
Android支持您可以使用相機(jī)應(yīng)用程序控制的各種相機(jī)功能,例如圖片格式,閃光模式,對(duì)焦設(shè)置等。本節(jié)列出常見的攝像機(jī)功能,并簡(jiǎn)要討論如何使用它們。大多數(shù)攝像機(jī)功能可以使用通過Camera.Parameters對(duì)象訪問和設(shè)置。然而,有幾個(gè)重要的功能,需要的不僅是Camera.Parameters中的簡(jiǎn)單設(shè)置。這些功能將在以下部分中介紹:
- 測(cè)光和對(duì)焦區(qū)域
- 面部檢測(cè)
- 時(shí)間流逝視頻