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

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