Camerahtml
版本:Android 4.0 r1java
在本文中android
須要考慮的問題安全
概述session
Manifest聲明app
捕獲圖像的intentide
關鍵類
參閱
Android框架包含了對多種攝像頭和攝像特性的支持,應用程序能夠進行圖片和視頻的捕獲。本文討論了一種快速、簡便的捕獲圖像和視頻的方法,並簡述了一種更高級的可爲用戶建立自定義攝像功能的方法。
須要考慮的問題
在讓應用程序使用Android設備的攝像頭以前,應該考慮一些指望如何使用此硬件的問題。
概述
經過 Camera API或攝像頭意圖 Intent ,Android框架爲圖像和視頻捕獲提供支持。下面列出了有關的類:
此類是控制攝像頭的主要API。在建立攝像頭應用程序時,此類用於拍攝照片或視頻。
此類用於向用戶提供攝像頭實時預覽功能。
此類用於從攝像頭錄製視頻。
動做類型爲MediaStore.ACTION_IMAGE_CAPTURE
或MediaStore.ACTION_VIDEO_CAPTURE
的意圖, 可在不直接使用Camera
對象的狀況下捕獲圖像和視頻。
Manifest聲明
開始開發攝像頭API的應用以前,應該確保已經在manifest中正確聲明瞭對攝像頭的使用及其它相關的feature。
<uses-permission android:name = "android.permission.CAMERA" />
注意:若是是 經過意圖 來使用攝像頭的,應用程序就沒必要請求本權限。
<uses-feature android:name = "android.hardware.camera" />
關於攝像頭feature的清單,參閱manifest Feature參考。
在manifest中加入camera feature,將會使得Android Market在沒有攝像頭或不支持指定feature的設備上禁止安裝該應用程序。關於Android Market基於feature過濾的使用詳情,請參閱 Android Market和基於Feature的過濾。
若是應用程序可能用到攝像頭或攝像頭feature,但卻不是必需的,則應在manifest中指定包含android:required 屬性的feature,並將該屬性設爲false:
<uses-feature android:name = "android.hardware.camera" android:required = "false" />
存儲權限——若是應用程序要把圖像或視頻保存到設備的外部存儲上(SD卡),則還必須在>manifest中指定以下權限。
<uses-permission android:name = "android.permission.WRITE_EXTERNAL_STORAGE" />
錄音權限——要用音頻捕獲來錄音,應用程序必須請求音頻捕獲權限。
<uses-permission android:name = "android.permission.RECORD_AUDIO" />
使用內置的攝像頭應用程序
有一種快捷的方法可讓應用程序不用額外編寫不少代碼就能實現拍照或攝像,這就是用意圖 Intent 來調用內置的Android攝像頭應用程序。攝像頭intent會請求經過內置攝像應用來捕獲圖像或視頻,並把控制權返回給應用程序。本節展現瞭如何用這種方法來捕獲圖像。
一般按如下步驟來提交一個攝像頭intent:
捕獲圖像的intent
若是但願程序以最少的代碼實現拍照功能,利用攝像頭intent捕獲圖像是一條捷徑。圖像捕捉intent還能夠包含如下附加信息:
MediaStore.EXTRA_OUTPUT——本設置須要一個 Uri對象,用於指定存放圖片的路徑和文件名。本設置是可選項,但強烈建議使用。若是未指定本設置值,那麼攝像應用將會把所請求的圖片以默認文件名和路徑進行保存,並將數據置入intent的 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);
//建立拍照 Intent並將控制權返回給調用的程序
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE);
//建立保存圖片的文件
intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
//設置圖片文件名
//啓動圖像捕獲Intent
startActivityForResult(intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);
}
startActivityForResult() 方法執行完畢後,用戶將看到內置攝像頭應用程序的界面。用戶拍照完畢(或取消操做)後,用戶界面返回應用程序,這時必須截獲 onActivityResult() 方法來接收intent的返回結果並執行後續操做。關於如何接收完整的intent,請參閱 接收攝像頭Intent的結果。
捕獲視頻的intent
若是但願程序以最少的代碼實現攝像功能,利用攝像頭intent捕獲視頻是一條捷徑。視頻捕捉intent能夠包含如下附帶信息:
如下例子演示瞭如何構建並執行一個視頻捕獲intent。本例中的getOutputMediaFileUri()方法引自 保存媒體文件中的例程代碼。
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);
//建立新的Intent
intent new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
fileUri = getOutputMediaFileUri(MEDIA_TYPE_VIDEO);
//建立保存視頻的文件
intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
//設置視頻文件名
intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY,1);
//設置視頻的品質爲高
//啓動視頻捕獲Intent
startActivityForResult(intent, CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE);
}
startActivityForResult() 方法執行完畢後,用戶將看到一個改動過的攝像程序界面。用戶攝像完畢(或取消操做)後,用戶界面返回應用程序,這時必須截獲 onActivityResult() 方法來接收intent的返回結果並執行後續操做。關於如何接收完整的intent,請參閱下一節。
接收攝像頭的結果
一旦已構建並運行了圖像或視頻的攝像頭intent,應用程序就必須進行設置,以接收intent返回的結果。本節展現瞭如何 截獲攝像頭intent的回調方法,以便應用程序對捕獲到的圖片及視頻進行進一步的處理。
要接收intent的返回結果,必須覆蓋啓動intent的activity中的 onActivityResult()方法。如下例子演示瞭如何覆蓋 onActivityResult()來獲取上述章節例程中的 圖像捕獲intent或 視頻捕獲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) {
//捕獲的圖像保存到Intent指定的fileUri
Toast..makeText(this,"Image saved to:\n"+
data.getData(),Toast.LENGTH_LONG).show();
}
else if (resultCode==RESULT_CANCELED) {
//用戶取消了圖像捕獲
else {
//圖像捕獲失敗,提示用戶
}
}
if(requestCode==CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE) {
if (resultCode==RESULT_OK) {
//捕獲的視頻保存到Intent指定的fileUri
Toast.makeText(this,"Video saved to:\n" +
data.getData();
Toast.LENGTH_LONG).show();
}
else if (resultCode == RESULT_CANCELED) {
//用戶取消了視頻捕獲
}
else {
//視頻捕獲失敗,提示用戶
}
}
}
一旦activity接收到成功的結果,就說明捕獲到的圖像或視頻已保存到指定位置了,應用程序就可對其進行訪問。
建立攝像頭應用程序
有些開發人員可能須要自定義外觀的攝像頭用戶界面,或者須要提供特殊的功能。相比 使用intent 而言,建立定製的攝像activity須要編寫更多的代碼,不過也能向用戶提供更吸引人的使用感覺。
一般按照如下步驟建立一個定製的攝像界面:
攝像頭硬件是一個共享資源,必須對其進行精心管理,所以須要使用它的應用程序之間不能發生衝突。下一節將會討論如何檢測攝像頭硬件、如何請求訪問攝像頭、使用完畢如何釋放。
警告:應用程序用完攝像頭後,請記得調用 Camera.release() 釋放Camera對象!若是某應用程序未能正確釋放攝像頭,全部後續訪問攝像頭的嘗試(包括此應用程序自身)都將會失敗,並可能致使程序被強行關閉。
檢測攝像頭硬件
若是應用程序未利用manifest聲明對攝像頭需求進行特別指明,則應該在運行時檢查一下攝像頭是否可用。可用 PackageManager.hasSystemFeature() 方法來進行這種檢查,代碼示例以下:
private boolean checkCameraHardware(Context context) {
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
//攝像頭存在
return true;
}
else {
//攝像頭不存在
return false;
}
}
Android設備可能擁有多個攝像頭,好比後置攝像頭用於拍照、前置攝像頭用於攝像。Android 2.3 (API Level 9)以上版本容許利用 Camera.getNumberOfCameras()方法來檢查設備可用攝像頭的數量。
訪問攝像頭
若是在運行程序的設備上已經檢測到了攝像頭,則必須經過獲取一個 Camera的實例來請求對其訪問(除非使用了 用於訪問攝像頭的intent)。
可用Camera.open()方法來訪問主攝像頭,並確保捕獲所有的異常,示例代碼以下:
public static Camera getCameraInstance(){
Camera c=null;
try {
c=Camera.open();//試圖獲取Camera實例
}
catch(Exceptione){
//攝像頭不可用(正被佔用或不存在)
}
returnc;//不可用則返回null
}
警告:每次使用Camera.open()時都要檢查異常。若是攝像頭被佔用或者不存在,未檢查異常將會致使應用程序被系統強行關閉。
在運行Android 2.3 (API Level 9)以上版本的設備上,能夠用 Camera.open(int)訪問指定的攝像頭。在擁有多於一個攝像頭的設備上,以上示例代碼將會訪問第一個也即朝後的那個攝像頭。
檢查攝像頭feature
一旦得到了攝像頭的訪問權,就能夠經過 Camera.getParameters()方法來獲取更多信息,檢查返回的 Camera.Parameters對象可查看攝像頭所支持的feature。若是正在使用API Level 9以上版本,可用 Camera.getCameraInfo()來肯定攝像頭朝前仍是朝後以及圖像的方向。
建立預覽類
爲了方便拍照或攝像,用戶必須能看到攝像頭所拍攝的畫面。攝像頭預覽類就是一種可以顯示攝像頭實時數據的 SurfaceView,用戶能夠調整並捕獲圖片和視頻。
如下示例代碼演示瞭如何建立一個基本的攝像頭預覽類,它可被嵌入一個 View佈局中。爲了截獲view建立和銷燬時的回調事件,此類實現了 SurfaceHolder.Callback,這在指定攝像頭預覽的輸入時須要用到。
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback{
private SurfaceHolder mHolder;
private Camera mCamera;
public CameraPreview Context context,Camera camera {
super (context);
mCamera =camera;
// 安裝一個SurfaceHolder.Callback,
// 這樣建立和銷燬底層surface時可以得到通知。
mHolder = getHolder();
mHolder.addCallback(this);
//已過時的設置,但版本低於3.0的Android還須要用到。
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated( SurfaceHolder holder) {
// surface已被建立,如今把預覽畫面的位置通知攝像頭
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
}catch (IOException e) {
Log.d(TAG, "Error setting camera preview: " + e.getMessage());
}
}
public void surfaceDestroyed(SurfaceHolderholder){
//空代碼。注意在activity中釋放攝像頭預覽對象
}
public void surfaceChanged (SurfaceHolder holder, int format,int w,int h) {
// 若是預覽沒法更改或旋轉,注意此處的事件
// 確保在縮放或重排時中止預覽
if (mHolder.getSurface()==null){
// 預覽surface不存在
return;
}
// 更改時中止預覽
try{
mCamera.stopPreview();
}catch(Exception e){
// 忽略:試圖中止不存在的預覽
}
// 在此進行縮放、旋轉和從新組織格式
// 以新的設置啓動預覽
try{
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
}catch(Exception e){
Log.d(TAG, "Error starting camera preview: "+e.getMessage());
}
}
}
將預覽畫面置入layout
上節例程所述的攝像預覽類必須被放入一個activity的layout中,連同其它用戶界面控件一塊兒,實現拍照或攝像功能。本節展現瞭如何爲預覽建立一個簡單的layout和activity。
如下layout代碼提供了一個很是簡單的view,用於顯示一個攝像預覽畫面。在此例中,FrameLayout元素用於容納攝像預覽類。利用此類layout,能夠把附加的圖片信息或控件疊加到實時預覽畫面上。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayoutxmlns: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>
在大多數設備上,缺省的攝像預覽方向是橫向的。此例中的layout指定了橫向(landscape)佈局,下面的代碼還把應用程序的方向也改成了橫向。爲了簡化攝像預覽畫面的刷新,應該在manifest中增長以下內容,把應用程序的預覽activity也改成橫向顯示。
<activityandroid:name=".CameraActivity"
android:label="@string/app_name"
android:screenOrientation="landscape">
<!-- configure this activity to use landscape orientation -->
<intent-filter>
<actionandroid:name="android.intent.action.MAIN"/>
<categoryandroid:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
注意:攝像預覽畫面並非必定要橫向顯示。自Android 2.2 (API Level 8) 開始,能夠利用setDisplayOrientation()方法來旋轉預覽畫面。爲了讓預覽方向跟隨手機方向的變化而改變,能夠在預覽類的surfaceChanged()方法中實現,先用Camera.stopPreview()中止預覽,改變方向後再用Camera.startPreview()開啓預覽。
在攝像view 的activity中,請把預覽類添加到上述的FrameLayout元素中。當攝像頭暫停使用或者關閉時,攝像activity還必須確保將其釋放。如下例子展現瞭如何修改攝像activity,加入建立預覽類所述的預覽類。
publicclassCameraActivityextendsActivity{
privateCamera mCamera;
privateCameraPreview mPreview;
@Override
publicvoid onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 建立Camera實例
mCamera = getCameraInstance();
// 建立Preview view並將其設爲activity中的內容
mPreview =newCameraPreview(this, mCamera);
FrameLayout preview =(FrameLayout) findViewById(id.camera_preview);
preview.addView(mPreview);
}
}
注意:上例中的getCameraInstance()方法引用了訪問攝像頭中的方法示例。
捕獲圖像
一旦建立了預覽類和顯示它的view layout,就能夠開始在程序中捕獲圖片了。必須在程序代碼中爲用戶界面控件設置listener,使其可響應用戶操做進行拍照。
能夠經過Camera.takePicture()方法來獲取圖片,此方法用到三個參數並從攝像頭接收數據。若是要以JPEG的格式接收數據,必須實現Camera.PictureCallback接口,以接收圖片數據並寫入文件。如下代碼展現了Camera.PictureCallback接口的簡單例子,實現了從攝像頭接收圖片並保存。
privatePictureCallback mPicture =newPictureCallback(){
@Override
publicvoid 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 =newFileOutputStream(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());
}
}
};
經過調用Camera.takePicture()方法,觸發器捕獲了一張圖片。如下例程展現瞭如何在按鈕View.OnClickListener的中調用此方法。
// 在Capture按鈕中加入listener
Button captureButton =(Button) findViewById(id.button_capture);
captureButton.setOnClickListener(
newView.OnClickListener(){
@Override
publicvoid onClick(View v){
// 從攝像頭獲取圖片
mCamera.takePicture(null,null, mPicture);
}
}
);
注意:下文例程中的mPicture成員將會引用上述代碼。
警告:當應用程序使用完攝像頭以後,請記得調用Camera.release()釋放Camera對象!關於如何釋放攝像頭的詳情,請參閱釋放攝像頭。
捕獲視頻
Android框架的視頻捕捉須要對Camera對象進行仔細的管理,還要與MediaRecorder類一塊兒協同工做。使用Camera錄製視頻時,必須管理好Camera.lock()與Camera.unlock()的調用,使得MediaRecorder可以順利訪問攝像頭硬件,而且還要進行Camera.open()和Camera.release()調用。
注意:自Android 4.0 (API level 14) 開始,Camera.lock()和Camera.unlock()調用由系統自動管理。
與用攝像頭拍照不一樣,視頻捕獲必需十分精確地按順序進行調用。必須按照特定的順序來執行,應用程序才能成功地準備並捕獲視頻,詳細步驟以下。
警告:必須按照以下順序調用 MediaRecorder 的下列配置方法。不然應用程序將會引起錯誤,錄像也將失敗。
注意:也能夠沒必要先建立攝像頭預覽就使用 MediaRecorder,並跳過本節開始的幾步。不過,由於用戶通常都但願在開始錄像前看到預覽畫面,這裏就不討論那類過程了。
配置MediaRecorder
在使用MediaRecorder類進行錄像時,必須先按照特定順序進行配置,而後調用MediaRecorder.prepare()方法檢查並執行這些配置。如下例程演示瞭如何爲錄像正確配置並準備MediaRecorder類。
privateboolean prepareVideoRecorder(){
mCamera = getCameraInstance();
mMediaRecorder =newMediaRecorder();
// 第1步:解鎖並將攝像頭指向MediaRecorder
mCamera.unlock();
mMediaRecorder.setCamera(mCamera);
// 第2步:指定源
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
// 第3步:指定CamcorderProfile(須要API Level 8以上版本)
mMediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));
// 第4步:指定輸出文件
mMediaRecorder.setOutputFile(getOutputMediaFile(MEDIA_TYPE_VIDEO).toString());
// 第5步:指定預覽輸出
mMediaRecorder.setPreviewDisplay(mPreview.getHolder().getSurface());
// 第6步:根據以上配置準備MediaRecorder
try{
mMediaRecorder.prepare();
}catch(IllegalStateException e){
Log.d(TAG,"IllegalStateException preparing MediaRecorder: "+ e.getMessage());
releaseMediaRecorder();
returnfalse;
}catch(IOException e){
Log.d(TAG,"IOException preparing MediaRecorder: "+ e.getMessage());
releaseMediaRecorder();
returnfalse;
}
returntrue;
}
若是是Android 2.2 (API Level 8) 以前的版本,則必須直接指定輸出格式和編碼格式,而不是使用CamcorderProfile。如下代碼演示了這種方式:
// 第3步:設置輸出格式和編碼格式(針對低於API Level 8版本)
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
mMediaRecorder.setVideoEncoder(MediaRecorder. VideoEncoder.DEFAULT);
MediaRecorder中如下有關視頻錄製的參數都給出了缺省值,固然也能夠在應用程序中修改這些設置:
開始和中止MediaRecorder
使用MediaRecorder類開始和中止視頻錄製時,必須遵循如下特定順序。
如下例程演示瞭如何觸發按鈕並用camera和MediaRecorder類正確地開始和中止視頻錄製。
注意:視頻錄製完畢後請不要釋放camera,不然預覽將會中止。
privateboolean isRecording =false;
// 爲Capture按鈕加入listener
Button captureButton =(Button) findViewById(id.button_capture);
captureButton.setOnClickListener(
newView.OnClickListener(){
@Override
publicvoid onClick(View v){
if(isRecording){
// 中止錄像並釋放camera
mMediaRecorder.stop(); // 中止錄像
releaseMediaRecorder();// 釋放MediaRecorder對象
mCamera.lock(); // 將控制權從MediaRecorder 交回camera
// 通知用戶錄像已中止
setCaptureButtonText("Capture");
isRecording =false;
}else{
// 初始化視頻camera
if(prepareVideoRecorder()){
// Camera已可用並解鎖,MediaRecorder已就緒,
// 如今能夠開始錄像
mMediaRecorder.start();
// 通知用戶錄像已開始
setCaptureButtonText("Stop");
isRecording =true;
}else{
// 準備未能完成,釋放camera
releaseMediaRecorder();
// 通知用戶
}
}
}
}
);
注意:在上例中,prepareVideoRecorder()方法引用了配置MediaRecorder.中的示例代碼。此方法實現了鎖定camera、配置和準備MediaRecorder實例。
釋放攝像頭
攝像頭是設備上全部應用程序共享使用的資源。應用程序能夠在得到Camera實例後使用攝像頭,中止使用後請務必注意釋放攝像頭對象,應用程序暫停時(Activity.onPause())也是如此。若是某應用程序未能正確地釋放攝像頭,則全部後續訪問攝像頭的嘗試(包括該應用程序自身)都將會失敗,並可能致使應用程序被強行關閉。
用Camera.release()方法能夠釋放Camera對象的實例,代碼示例以下。
publicclassCameraActivityextendsActivity{
privateCamera mCamera;
privateSurfaceView mPreview;
privateMediaRecorder mMediaRecorder;
...
@Override
protected void onPause(){
super.onPause();
releaseMediaRecorder();// 若是正在使用MediaRecorder,首先須要釋放它。
releaseCamera(); // 在暫停事件中當即釋放攝像頭
}
privatevoid releaseMediaRecorder(){
if(mMediaRecorder !=null){
mMediaRecorder.reset(); // 清除recorder配置
mMediaRecorder.release();// 釋放recorder對象
mMediaRecorder =null;
mCamera.lock(); // 爲後續使用鎖定攝像頭
}
}
privatevoid releaseCamera(){
if(mCamera !=null){
mCamera.release(); // 爲其它應用釋放攝像頭
mCamera =null;
}
}
}
警告:若是某應用程序未能正確釋放攝像頭,全部後續訪問攝像頭的嘗試(包括該應用程序自身)都將會失敗,並可能會致使應用程序被強行關閉。
保存媒體文件
諸如圖片和視頻這些由用戶建立的媒體文件,應該保存到設備外部存儲的目錄中(SD卡)去,以節省系統空間,並使用戶離開設備時也能訪問這些文件。設備上有不少可用於存儲媒體文件的目錄,但做爲開發人員只應考慮兩個標準的位置:
· Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)——本方法返回標準的、共享的、系統建議的存放位置,用於存放圖片和視頻文件。本目錄是共享的(public),所以其它應用程序能夠很容易地查找、讀取、修改、刪除存於此處的文件。即便應用程序被用戶卸載,存於此處的媒體文件也不會被刪除。爲了不與已有的圖片和視頻相沖突,應該在此目錄下爲本身的媒體文件建立一個子目錄,以下代碼所示。本方法自Android 2.2 (API Level 8) 起啓用,更早API版本的也有相似的調用,請參閱保存共享文件。
· Context.getExternalFilesDir(Environment.DIRECTORY_PICTURES)——本方法返回一個標準的、用於存放圖片和視頻的位置,該存放位置與應用程序相關聯。若是應用程序被卸載,則存於此處的文件將會被刪除。對存於此處的文件不會增長訪問權限控制,其它應用程序也能夠讀取、修改、刪除文件。
如下例程演示瞭如何爲媒體文件建立一個File或Uri存放位置,經過Intent調用攝像頭時可使用該文件,建立攝像應用時也可使用它。
publicstaticfinalint MEDIA_TYPE_IMAGE =1;
publicstaticfinalint MEDIA_TYPE_VIDEO =2;
privatestaticUri getOutputMediaFileUri(int type){
returnUri.fromFile(getOutputMediaFile(type));
}
privatestaticUri getOutputMediaFile(int type){
// 安全起見,在使用前應該
// 用Environment.getExternalStorageState()檢查SD卡是否已裝入
File mediaStorageDir =newFile(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES),"MyCameraApp");
// 若是指望圖片在應用程序卸載後還存在、且能被其它應用程序共享,
// 則此保存位置最合適
// 若是不存在的話,則建立存儲目錄
if(! mediaStorageDir.exists()){
if(! mediaStorageDir.mkdirs()){
Log.d("MyCameraApp","failed to create directory");
returnnull;
}
}
// 建立媒體文件名
String timeStamp =newSimpleDateFormat("yyyyMMdd_HHmmss").format(newDate());
File mediaFile;
if(type == MEDIA_TYPE_IMAGE){
mediaFile =newFile(mediaStorageDir.getPath()+File.separator +
"IMG_"+ timeStamp +".jpg");
}elseif(type == MEDIA_TYPE_VIDEO){
mediaFile =newFile(mediaStorageDir.getPath()+File.separator +
"VID_"+ timeStamp +".mp4");
}else{
returnnull;
}
return mediaFile;
}
注意:Environment.getExternalStoragePublicDirectory()自Android 2.2 (API Level 8) 版本啓用。若是目標設備使用較早期版本的Android,請用Environment.getExternalStorageDirectory()代替。詳情請參閱保存共享文件。
關於在Android設備上保存文件的詳細信息,請參閱數據存儲。