前言
在很多場景中,都需要用到攝像頭去拍攝照片或視頻,在照片或視頻的基礎之上進行處理。但是Android系統源碼是開源的,很多設備廠商均可使用,並且定制比較混亂。一般而言,在需要用到攝像頭拍照或攝像的時候,均會直接調用系統現有的相機應用,去進行拍照或攝像,我們只取它拍攝的結果進行處理,這樣避免了不同設備的攝像頭的一些細節問題。本篇博客將介紹在Android應用中,如何調用系統現有的相機應用去拍攝照片與短片,並對其進行處理,最后均會以一個簡單的Demo來演示效果。
本篇博客的主要內容如下:
對於如何調用系統現有應用,之前就有講解,這里簡單再說一下。在開發的應用中調用系統現有應用,需要使用Intent指定開啟的應用的Action和Category,然后通過startActivity(Intent)或者startActivityForResult(Intent,int)開啟指定的Activity,如果使用startActivityForResult()方法開啟並需要返回值,再重寫onActivityResult(int,int,Intent)即可。
先來看看系統現有相機應用的AndroidManifest.xml清單文件定義的Activity:
1 <activity 2 android:name="com.android.camera.Camera" 3 android:clearTaskOnLaunch="true" 4 android:configChanges="orientation|keyboardHidden" 5 android:screenOrientation="landscape" 6 android:taskAffinity="android.task.camera" 7 android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen" > 8 <intent-filter> 9 <action android:name="android.intent.action.MAIN" /> 10 <categroy android:name="android.intent.category.DEFAULT" /> 11 <categroy android:name="android.intent.category.LAUNCHER" /> 12 </intent-filter> 13 <intent-filter> 14 <action android:name="android.media.action.IMAGE_CAPTURE" /> 15 <categroy android:name="android.intent.category.DEFAULT" /> 16 </intent-filter> 17 <intent-filter> 18 <action android:name="android.media.action.STILL_IMAGE_CAMERA" /> 19 <categroy android:name="android.intent.category.DEFAULT" /> 20 </intent-filter> 21 </activity> 22 <activity 23 android:name="com.android.camera.VideoCamera" 24 android:clearTaskOnLaunch="true" 25 android:configChanges="origientation|keyboardHidden" 26 android:label="@string/video_camera_label" 27 android:screenOrientation="landscape" 28 android:taskAffinity="android.task.camcorder" 29 android:theme="@android:style/theme.Black.NoTitleBar.Fullscreen" > 30 <intent-filter> 31 <action android:name="android.media.action.VIDEO_CAMERA" /> 32 <categroy android:name="android.intent.category.DEFAULT" /> 33 </intent-filter> 34 <intent-filter> 35 <action android:name="android.media.action.VIDEO_CAPTURE" /> 36 <categroy android:name="android.intent.category.DEFAULT" /> 37 </intent-filter> 38 </activity>
它定義了兩個Activity,com.android.camera.Camera表示照相機,com.android.camera.VideoCamera表示攝像機。從字面意思可以看出,為了捕獲系統相機返回的數據,一般需要使用一下兩個Action即可開啟照相機與攝像機:
- android.media.action.IMAGE_CAPTURE:Intent的Action類型,從現有的相機應用中請求一張圖片。
- android.media.action.VIDEO_CAPTURE:Intent的Action類型,從現有的相機應用中請求一段視頻。
上面兩個參數,均在MediaStore類中以靜態常量的形式定義好了,分別是:MediaStore.ACTION_IMAGE_CAPTURE(相機)
和MediaStore.ACTION_VIDEO_CAPTURE(攝像機)。
上面介紹到,開啟系統現有相機應用拍攝照片,需要用的MediaStore.ACTION_IMAGE_CAPTURE作為Intent的action開啟Activity即可。但是在使用系統現有相機用用的時候,默認會把圖片保存到系統圖庫的目錄下,如果需要指定圖片文件的保存路徑,需要額外在Intent中設置。
設置系統現有相機應用的拍攝照片的保存路徑,需要用Intent.putExtra()方法通過MediaStore.EXTRA_OUTPUT去設置Intent的額外數據,這里傳遞的是一個Uri參數,可以是一個文件路徑的Uri。
1 Intent intent=new Intent(); 2 // 指定開啟系統相機的Action 3 intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE); 4 intent.addCategory(Intent.CATEGORY_DEFAULT); 5 // 根據文件地址創建文件 6 File file=new File(FILE_PATH); 7 // 把文件地址轉換成Uri格式 8 Uri uri=Uri.fromFile(file); 9 // 設置系統相機拍攝照片完成后圖片文件的存放地址 10 intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
在新開啟的Activity中,如果需要獲取它的返回值,則需要使用startActivityForResult(Intent,int)方法開啟Activity,並重寫onActivityResult(int,int,Intent)獲取系統相機的返回數據,那么我們只需要在onActivityResult()中獲取到返回值即可。
系統相機拍攝的照片,如果不指定路徑,會保存在系統默認文件夾下,可以使用Intent.getExtra()方法得到,得到的是一個Uri地址,表示了一個內容提供者的地址。如果通過MediaStore.EXTRA_OUTPUT指定了保存路徑,那么通過Intent.getExtra()得到的將是一個空地址,但是既然是我們指定的地址,那么也不愁找不到它了。
上面講解了如何在開發的應用中使用系統相機拍攝照片並獲得它所涉及到的內容,下面通過一個簡單的Demo演示一下。在Demo中,有兩個Button分別以指定路徑的方式和不指定路徑的方式啟動系統相機,並獲取返回值顯示到ImageView中,Demo中注釋比較詳細,這里不再累述了。
布局代碼:activity_syscamera.xml

1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:orientation="vertical" > 6 7 <Button 8 android:id="@+id/btn_StartCamera" 9 android:layout_width="wrap_content" 10 android:layout_height="wrap_content" 11 android:text="系統相機拍照--指定路徑到SD卡" /> 12 <Button 13 android:id="@+id/btn_StartCameraInGallery" 14 android:layout_width="wrap_content" 15 android:layout_height="wrap_content" 16 android:text="系統相機拍照--默認圖庫" /> 17 <ImageView 18 android:id="@+id/iv_CameraImg" 19 android:layout_width="match_parent" 20 android:layout_height="match_parent" /> 21 22 </LinearLayout>
實現代碼:SysCameraActivity.java
1 package cn.bgxt.callsystemcamera; 2 3 import java.io.File; 4 5 import android.app.Activity; 6 import android.content.Intent; 7 import android.graphics.Bitmap; 8 import android.graphics.BitmapFactory; 9 import android.net.Uri; 10 import android.os.Bundle; 11 import android.provider.MediaStore; 12 import android.util.Log; 13 import android.view.View; 14 import android.widget.Button; 15 import android.widget.ImageView; 16 17 public class SysCameraActivity extends Activity { 18 private Button btn_StartCamera, btn_StartCameraInGallery; 19 private ImageView iv_CameraImg; 20 21 private static final String TAG = "main"; 22 private static final String FILE_PATH = "/sdcard/syscamera.jpg"; 23 24 @Override 25 protected void onCreate(Bundle savedInstanceState) { 26 super.onCreate(savedInstanceState); 27 setContentView(R.layout.activity_syscamera); 28 29 btn_StartCamera = (Button) findViewById(R.id.btn_StartCamera); 30 btn_StartCameraInGallery = (Button) findViewById(R.id.btn_StartCameraInGallery); 31 iv_CameraImg = (ImageView) findViewById(R.id.iv_CameraImg); 32 33 btn_StartCamera.setOnClickListener(click); 34 btn_StartCameraInGallery.setOnClickListener(click); 35 } 36 37 private View.OnClickListener click = new View.OnClickListener() { 38 39 @Override 40 public void onClick(View v) { 41 42 Intent intent = null; 43 switch (v.getId()) { 44 // 指定相機拍攝照片保存地址 45 case R.id.btn_StartCamera: 46 intent = new Intent(); 47 // 指定開啟系統相機的Action 48 intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE); 49 intent.addCategory(Intent.CATEGORY_DEFAULT); 50 // 根據文件地址創建文件 51 File file = new File(FILE_PATH); 52 if (file.exists()) { 53 file.delete(); 54 } 55 // 把文件地址轉換成Uri格式 56 Uri uri = Uri.fromFile(file); 57 // 設置系統相機拍攝照片完成后圖片文件的存放地址 58 intent.putExtra(MediaStore.EXTRA_OUTPUT, uri); 59 startActivityForResult(intent, 0); 60 break; 61 // 不指定相機拍攝照片保存地址 62 case R.id.btn_StartCameraInGallery: 63 intent = new Intent(); 64 // 指定開啟系統相機的Action 65 intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE); 66 intent.addCategory(Intent.CATEGORY_DEFAULT); 67 startActivityForResult(intent, 1); 68 break; 69 default: 70 break; 71 } 72 73 } 74 }; 75 76 @Override 77 protected void onActivityResult(int requestCode, int resultCode, Intent data) { 78 Log.i(TAG, "系統相機拍照完成,resultCode="+resultCode); 79 80 if (requestCode == 0) { 81 File file = new File(FILE_PATH); 82 Uri uri = Uri.fromFile(file); 83 iv_CameraImg.setImageURI(uri); 84 } else if (requestCode == 1) { 85 Log.i(TAG, "默認content地址:"+data.getData()); 86 iv_CameraImg.setImageURI(data.getData()); 87 } 88 } 89 }
效果展示:
這里只是簡單的演示了如何調用系統現有的相機應用獲取拍攝的圖片,沒有做圖片資源的回收,所以可能會有內存溢出的錯誤,重新啟動應用即可。
從系統現有的相機應用中獲取拍攝的視頻,與獲取拍攝的圖片過程大致相同,但是它除了可以通過putExtra()設置MediaStore.EXTRA_OUTPUT輸出路徑外,還可以設置其它值,這里簡單介紹一下:
- MediaStore.EXTRA_OUTPUT:設置媒體文件的保存路徑。
- MediaStore.EXTRA_VIDEO_QUALITY:設置視頻錄制的質量,0為低質量,1為高質量。
- MediaStore.EXTRA_DURATION_LIMIT:設置視頻最大允許錄制的時長,單位為毫秒。
- MediaStore.EXTRA_SIZE_LIMIT:指定視頻最大允許的尺寸,單位為byte。
系統現有相機拍攝視頻Demo
既然和拍攝照片的流程一樣,這里就不再累述了,直接上Demo。在Demo中通過一個Button啟動一個系統現有相機拍攝視頻,最后保存在SD卡上。
實現代碼:
1 package cn.bgxt.callsystemcamera; 2 3 import java.io.File; 4 5 import android.app.Activity; 6 import android.content.Intent; 7 import android.net.Uri; 8 import android.os.Bundle; 9 import android.provider.MediaStore; 10 import android.util.Log; 11 import android.view.View; 12 import android.widget.Button; 13 14 public class SysVideoCameraActivity extends Activity { 15 private Button btn_StartVideoCamera; 16 private static final String FILE_PATH = "/sdcard/sysvideocamera.3gp"; 17 private static final String TAG="main"; 18 @Override 19 protected void onCreate(Bundle savedInstanceState) { 20 super.onCreate(savedInstanceState); 21 setContentView(R.layout.activity_sysvideocamera); 22 23 btn_StartVideoCamera = (Button) findViewById(R.id.btn_StartVideoCamera); 24 btn_StartVideoCamera.setOnClickListener(click); 25 } 26 27 private View.OnClickListener click = new View.OnClickListener() { 28 29 @Override 30 public void onClick(View v) { 31 Intent intent = new Intent(); 32 intent.setAction("android.media.action.VIDEO_CAPTURE"); 33 intent.addCategory("android.intent.category.DEFAULT"); 34 File file = new File(FILE_PATH); 35 if(file.exists()){ 36 file.delete(); 37 } 38 Uri uri = Uri.fromFile(file); 39 intent.putExtra(MediaStore.EXTRA_OUTPUT, uri); 40 startActivityForResult(intent, 0); 41 } 42 }; 43 44 45 @Override 46 protected void onActivityResult(int requestCode, int resultCode, Intent data) { 47 Log.i(TAG, "拍攝完成,resultCode="+requestCode); 48 } 49 50 }
效果展示:
總結
到此就把如何使用系統現有相機應用拍攝照片與視頻都講解清楚了,在非相機相關的項目中,如果需要拍照的話,一般都是調用系統現有的相機應用,而不會直接調用Camera硬件去獲取圖像。