位置:首頁 > 手機開發 > Android開發教學 > Android Camera(攝像頭)

Android Camera(攝像頭)

通過以下兩種方式,可以在應用程序中使用攝像機

  1. 使用現有應用程序中Android攝像頭應用程序

  2. 直接使用應用程序提供的Android攝像頭API

使用現有應用程序的Android攝像頭應用程序

使用 MediaStore.ACTION_IMAGE_CAPTURE 啟動安裝在手機上的攝像頭應用程序。它的語法下麵給出:

Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);

除了以上,也可以通過 MediaStore 提供其它可用的意圖。它們列出如下

Sr.No 意圖類型和說明
1 ACTION_IMAGE_CAPTURE_SECURE
它返回照相機拍攝到的圖像,設備被固定
2 ACTION_VIDEO_CAPTURE
它調用已有的視頻應用程序在Android中捕獲視頻
3 EXTRA_SCREEN_ORIENTATION
它是用來在屏幕的方向設置:垂直或橫向
4 EXTRA_FULL_SCREEN
它被用來控製ViewImage的用戶接口
5 INTENT_ACTION_VIDEO_CAMERA
這個意圖是用來啟動攝像機在視頻模式
6 EXTRA_SIZE_LIMIT
它用於指定的視頻或圖像捕獲尺寸大小限製

現在使用startActivityForResult()函數推出活動,並等待它的結果。它的語法下麵給出:

startActivityForResult(intent,0)

這種方法已在活動 activity 類被定義。從主活動調用它。有在做同樣的工作的活動類中定義的方法,但是當它不是從活動要求,但在其他地方使用。它們被列在下麵:

Sr.No 活動功能說明
1 startActivityForResult(Intent intent, int requestCode, Bundle options)
它開始的活動,但可以利用它選擇額外的包
2 startActivityFromChild(Activity child, Intent intent, int requestCode)
啟動活動時,活動是任何其他活動的子活動
3 startActivityFromChild(Activity child, Intent intent, int requestCode, Bundle options)
它的工作與上述相同,但它可以在捆綁與它的形狀采取額外的值
4 startActivityFromFragment(Fragment fragment, Intent intent, int requestCode)
它啟動的碎片活動當前所在內部
5 startActivityFromFragment(Fragment fragment, Intent intent, int requestCode, Bundle options)
它不僅啟動從碎片的活性,但可以采用額外的值

不管用來啟動其活動功能,它們都返回結果。其結果可以通過覆蓋 onActivityResult 方法獲得。

例子

這裡有一個例子,說明如何啟動現有的攝像機應用程序捕獲的圖像和位圖的形式顯示結果

為了試驗這個例子,需要在支持攝像機的實際設備上運行此應用程序。

Steps 描述
1 使用Eclipse IDE創建Android應用程序,並將其命名為Camera。在創建這個項目,確保目標SDK編譯在Android SDK中的最新版本或使用更高級彆的API。
2 修改src/MainActivity.java 文件中添加意圖啟動活動代碼,由result方法來接受輸出。
3 修改所需的布局XML文件 res/layout/activity_main.xml 添加GUI組件。在這裡,我們隻添加ImageView和一個TextView
4 修改res/values/strings.xml 定義所需的常量值
5 運行應用程序並選擇運行Android設備,並在其上安裝的應用和驗證結果。

以下是修改後的主活動文件的內容:src/com.yiibai.camera/MainActivity.java.

package com.example.camera;


import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageView;

public class MainActivity extends Activity {

ImageView imgFavorite;

   @Override
   protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      imgFavorite = (ImageView)findViewById(R.id.imageView1);
      imgFavorite.setOnClickListener(new OnClickListener() {
         @Override
         public void onClick(View v) {
            open();
         }
      });
   }
   public void open(){
      Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
      startActivityForResult(intent, 0);
   }

   @Override
   protected void onActivityResult(int requestCode, int resultCode, Intent data) {
      // TODO Auto-generated method stub
      super.onActivityResult(requestCode, resultCode, data);
      Bitmap bp = (Bitmap) data.getExtras().get("data");
      imgFavorite.setImageBitmap(bp);
   }
   @Override
   public boolean onCreateOptionsMenu(Menu menu) {
      // Inflate the menu; this adds items to the action bar if it is present.
      getMenuInflater().inflate(R.menu.main, menu);
      return true;
   }
}

以下是文件 res/layout/activity_main.xml file 的內容:


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:paddingBottom="@dimen/activity_vertical_margin"
   android:paddingLeft="@dimen/activity_horizontal_margin"
   android:paddingRight="@dimen/activity_horizontal_margin"
   android:paddingTop="@dimen/activity_vertical_margin"
   tools:context=".MainActivity"> 

   <ImageView
   android:id="@+id/imageView1"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:layout_marginLeft="34dp"
   android:layout_marginTop="36dp"
   android:contentDescription="@string/hello_world"
   android:src="@drawable/ic_launcher" />

   <TextView
   android:id="@+id/textView1"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:layout_alignParentTop="true"
   android:layout_alignRight="@+id/imageView1"
   android:text="@string/tap"
   android:textAppearance="?android:attr/textAppearanceLarge" />

</RelativeLayout>

以下將是 res/values/strings.xml 的內容,以定義一個新的常量

<?xml version="1.0" encoding="utf-8"?>
<resources>
   <string name="app_name">Camera</string>
   <string name="action_settings">Settings</string>
   <string name="hello_world">Hello world!</string>
   <string name="tap">Tap the image to open the camera!!</string>
</resources>

以下是 AndroidManifest.xml 的默認內容:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
   package="com.yiibai.camera"
   android:versionCode="1"
   android:versionName="1.0" >

   <uses-sdk
      android:minSdkVersion="8"
      android:targetSdkVersion="17" />

   <application
      android:allowBackup="true"
      android:icon="@drawable/ic_launcher"
      android:label="@string/app_name"
      android:theme="@style/AppTheme" >
         <activity
            android:name="com.yiibai.camera.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
               <action android:name="android.intent.action.MAIN" />

               <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
   </application>

</manifest>

讓我們試著運行相機應用程序。假設已經連接實際的Android移動設備到計算機。顯示如下窗口,選擇要運行的Android應用程序的選項。

Anroid Camera Tutorial

選擇移動設備作為一個選項,然後檢查您的移動設備將顯示如下界麵:

Anroid Camera Tutorial

現在隻需輕點圖標的android的圖像,相機將被打開。隻需拍攝一張照片。捕獲後,兩個按鈕就會出現或者把它丟棄

Anroid Camera Tutorial

隻需按下抽動(綠色)按鈕,將被帶回應用程序使用Android圖標拍攝的圖像

Anroid Camera Tutorial

直接使用應用程序提供的Android攝像頭API

使用照相機API給攝像機整合在應用中

首先,需要使用靜態方法通過API calledCamera.open提供並初始化相機對象。它的語法如下:

Camera object = null;
object = Camera.open(); 

除了上述功能,也有這是下麵列出由Camera類提供的其它功能

Sr.No 方法 & 描述
1 getCameraInfo(int cameraId, Camera.CameraInfo cameraInfo)
它返回一個特定攝像機信息
2 getNumberOfCameras()
它返回限定的可用的設備上的照相機的整數
3 lock()
它被用來鎖定相機,所以冇有其他應用程序可以訪問它
4 release()
它被用來釋放在鏡頭鎖定,所以其他應用程序可以訪問它
5 open(int cameraId)
它是用來打開特定相機時,支持多個攝像機
6 enableShutterSound(boolean enabled)
它被用來使能/禁止圖像俘獲的默認快門聲音

現在,需要做一個獨立的類和SurfaceView擴展它並實現SurfaceHolder接口。

已經使用的兩種類具有以下目的

描述
Camera 它是用來控製攝像機和拍攝圖像或從相機拍攝的視頻
SurfaceView 這個類是用來展示實時攝像頭預覽給用戶

必須調用攝像機類的預覽方法來啟動攝像機的預覽給用戶

public class ShowCamera extends SurfaceView implements SurfaceHolder.Callback {
   
   private Camera theCamera;

   public void surfaceCreated(SurfaceHolder holder) {
      theCamera.setPreviewDisplay(holder);
      theCamera.startPreview();
   }
   public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3){
   }
   public void surfaceDestroyed(SurfaceHolder arg0) {
   }
}	

除了預覽,可以使用照相機API提供的其它功能中設置的攝像機的其它選項

Sr.No 方法 & 描述
1 startFaceDetection()
此功能啟動人臉檢測相機
2 stopFaceDetection()
它是用來阻止其通過上述功能啟用的臉部檢測
3 startSmoothZoom(int value)
這需要一個整數值,並調整攝像機的焦距非常順暢的值
4 stopSmoothZoom()
它是用來阻止攝像機的變焦
5 stopPreview()
它是用來阻止相機的預覽給用戶
6 takePicture(Camera.ShutterCallback shutter, Camera.PictureCallback raw, Camera.PictureCallback jpeg)
它被用來使能/禁止圖像拍攝的默認快門聲音

例子

下麵的例子演示了攝像機API的應用程序中的使用

為了試驗這個例子中,需要搭載最新的Android OS實際的移動設備,因為攝像機不支持模擬器

Steps 描述
1 使用Android Studio創建Android應用程序,並將其命名為:Camera。在創建這個項目,確保目標SDK和編譯在Android SDK的最新版本或使用更高級彆的API。
2 修改src/MainActivity.java文件引用添加攝像機的代碼,並獲得了XML的組件
3 創建一個新的文件ShowCamera.java使用SurfaceView擴展和實現SurfaceHolder接口。
4 修改所需的布局XML文件res/layout/activity_main.xml 添加GUI組件。在這裡我們隻添加FrameView,一個按鈕和一個ImageView。
5 修改 res/values/strings.xml 定義所需的常量值
6 修改 AndroidManifest.xml 如下圖所示,添加必要的權限攝像機
7 運行應用程序並選擇運行Android的設備,並在其上安裝的應用和驗證結果。

下麵是修改後的主活動文件 src/com.yiibai.camera1/MainActivity.java. 的內容。

package com.example.camera1;


import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.Toast;

public class MainActivity extends Activity {

   private Camera cameraObject;
   private ShowCamera showCamera;
   private ImageView pic;
   public static Camera isCameraAvailiable(){
      Camera object = null;
      try {
         object = Camera.open(); 
      }
      catch (Exception e){
      }
      return object; 
   }

   private PictureCallback capturedIt = new PictureCallback() {

      @Override
      public void onPictureTaken(byte[] data, Camera camera) {

      Bitmap bitmap = BitmapFactory.decodeByteArray(data , 0, data .length);
      if(bitmap==null){
         Toast.makeText(getApplicationContext(), "not taken", Toast.LENGTH_SHORT).show();
      }
      else
      {
         Toast.makeText(getApplicationContext(), "taken", Toast.LENGTH_SHORT).show();    	
      }
      cameraObject.release();
   }
};

   @Override
   protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      pic = (ImageView)findViewById(R.id.imageView1);
      cameraObject = isCameraAvailiable();
      showCamera = new ShowCamera(this, cameraObject);
      FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
      preview.addView(showCamera);
   }
   public void snapIt(View view){
      cameraObject.takePicture(null, null, capturedIt);
   }

   @Override
   public boolean onCreateOptionsMenu(Menu menu) {
      getMenuInflater().inflate(R.menu.main, menu);
      return true;
   }
}

創建新java文件:src/com.yiibai.camera1/ShowCamera.java. 並添加以下代碼 

package com.example.camera1;

import java.io.IOException;

import android.content.Context;
import android.hardware.Camera;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class ShowCamera extends SurfaceView implements SurfaceHolder.Callback {

   private SurfaceHolder holdMe;
   private Camera theCamera;

   public ShowCamera(Context context,Camera camera) {
      super(context);
      theCamera = camera;
      holdMe = getHolder();
      holdMe.addCallback(this);
   }

   @Override
   public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
   }

   @Override
   public void surfaceCreated(SurfaceHolder holder) {
      try   {
         theCamera.setPreviewDisplay(holder);
         theCamera.startPreview(); 
      } catch (IOException e) {
      }
   }

   @Override
   public void surfaceDestroyed(SurfaceHolder arg0) {
   }

}

修改 res/layout/activity_main.xml 的內容 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="fill_parent"
   android:layout_height="fill_parent"
   android:orientation="horizontal" >

   <LinearLayout
      android:layout_width="wrap_content"
      android:layout_height="match_parent"
      android:layout_weight="0.30"
      android:orientation="vertical" >
        
         <FrameLayout
            android:id="@+id/camera_preview"
            android:layout_width="fill_parent"
            android:layout_height="199dp" />

         <Button
            android:id="@+id/button_capture"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:onClick="snapIt"
            android:text="@string/Capture" />

         <ImageView
            android:id="@+id/imageView1"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:scaleType="fitXY"
            android:src="@drawable/ic_launcher" />
	  
   </LinearLayout>

< /LinearLayout>

修改 res/values/string.xml 的內容 

<?xml version="1.0" encoding="utf-8"?>
<resources>

   <string name="app_name">Camera1</string>
   <string name="action_settings">Settings</string>
   <string name="hello_world">Hello world!</string>
   <string name="Capture">Capture</string>
    
</resources>

修改AndroidManifest.xml 的內容,並添加必要的權限,如下圖所示。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
   package="com.yiibai.camera1"
   android:versionCode="1"
   android:versionName="1.0" >

   <uses-sdk
      android:minSdkVersion="8"
      android:targetSdkVersion="17" />
   <uses-permission android:name="android.permission.CAMERA"/>
   <uses-feature android:name="android.hardware.camera" />
   <uses-feature android:name="android.hardware.camera.autofocus" />

   <application
      android:allowBackup="true"
      android:icon="@drawable/ic_launcher"
      android:label="@string/app_name"
      android:theme="@style/AppTheme" >
         <activity
            android:name="com.yiibai.camera1.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
               <action android:name="android.intent.action.MAIN" />

               <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
         </activity>
   </application>

</manifest>

讓我們試著運行 Camera 應用程序。假設已經連接實際的Android移動設備到計算機。啟動應用程序之前會顯示如下窗口,選擇要運行的Android應用程序的選項。

Anroid Camera Tutorial

選擇移動設備作為一個選項,然後檢查移動設備將顯示如下界麵:

Anroid Camera Tutorial

相機將開始顯示在上半屏的預覽。隻需點擊捕捉按鈕。現在,可以存儲所拍攝的圖像,將其上傳到網上或者是放棄它。