Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android開發教程之調用攝像頭功能的方法詳解

Android開發教程之調用攝像頭功能的方法詳解

編輯:關於Android編程

本文實例講述了Android調用攝像頭功能的方法。分享給大家供大家參考,具體如下:

我們要調用攝像頭的拍照功能,顯然

第一步必須加入調用攝像頭硬件的權限,拍完照後我們要將圖片保存在SD卡中,必須加入SD卡讀寫權限,所以第一步,我們應該在Android清單文件中加入以下代碼

攝像頭權限:

<uses-permission android:name="android.permission.CAMERA"/>

SD卡讀寫權限:

<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

第二步,要將攝像頭捕獲的圖像實時地顯示在手機上

我們是用SurfaceView這個視圖組件來實現的,因此在main.xml中加入下列代碼

<SurfaceView
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  android:id="@+id/surfaceview"
 />

第三步,設置窗口的顯示方式

首先獲得當前窗口

Window window = getWindow();//得到窗口

接著設置沒有標題

requestWindowFeature(Window.FEATURE_NO_TITLE);//沒有標題

接著設置全屏
復制代碼 代碼如下:window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);//設置全屏

當然,我們在拍照過程中,屏幕必須一致處於高亮狀態,因此接著加入下面代碼
復制代碼 代碼如下:window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);//設置高亮

至此,我們將窗口的顯示方式規定死了,然後才能設置窗口上顯示的組件(順序非常重要)

setContentView(R.layout.main);

第四步,設置SurficeView顯示控件的屬性

找到surficeView

surfaceView = (SurfaceView) findViewById(R.id.surfaceview);

設置它的像素為800x600

surfaceView.getHolder().setFixedSize(800, 480);
//下面設置surfaceView不維護自己的緩沖區,而是等待屏幕的渲染引擎將內容推送到用戶面前
surfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

第五步,就是為surficeView加入回調方法(callBack)

surfaceView.getHolder().addCallback(new SurfaceCallback());

上面的回調類是我們自己定義的,代碼如下

private class SurfaceCallback implements SurfaceHolder.Callback{
@Override
public void surfaceCreated(SurfaceHolder holder) {
try {
camera = Camera.open();//打開硬件攝像頭,這裡導包得時候一定要注意是android.hardware.Camera
WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);//得到窗口管理器
Display display = wm.getDefaultDisplay();//得到當前屏幕
Camera.Parameters parameters = camera.getParameters();//得到攝像頭的參數
parameters.setPreviewSize(display.getWidth(), display.getHeight());//設置預覽照片的大小
parameters.setPreviewFrameRate(3);//設置每秒3幀
parameters.setPictureFormat(PixelFormat.JPEG);//設置照片的格式
parameters.setJpegQuality(85);//設置照片的質量
parameters.setPictureSize(display.getHeight(), display.getWidth());//設置照片的大小,默認是和   屏幕一樣大
camera.setParameters(parameters);
camera.setPreviewDisplay(surfaceView.getHolder());//通過SurfaceView顯示取景畫面
camera.startPreview();//開始預覽
isPreview = true;//設置是否預覽參數為真
} catch (IOException e) {
Log.e(TAG, e.toString());
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
if(camera!=null){
if(isPreview){//如果正在預覽
camera.stopPreview();
camera.release();
}
}
}
}

第六步,我們必須對按鍵事件進行監聽,如是拍照還是聚焦,代碼如下

public boolean onKeyDown(int keyCode, KeyEvent event) {//處理按鍵事件
if(camera!=null&&event.getRepeatCount()==0)//代表只按了一下
{
switch(keyCode){
case KeyEvent.KEYCODE_BACK://如果是搜索鍵
   camera.autoFocus(null);//自動對焦
 break;
  case KeyEvent.KEYCODE_DPAD_CENTER://如果是中間鍵
   camera.takePicture(null, null, new TakePictureCallback());//將拍到的照片給第三個對象中,這裡的TakePictureCallback()是自己定義的,在下面的代碼中
 break;
}
}
return true;//阻止事件往下傳遞,否則按搜索鍵會變成系統默認的
}

private final class TakePictureCallback implements PictureCallback{
public void onPictureTaken(byte[] data, Camera camera) {
try {
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
File file = new File(Environment.getExternalStorageDirectory(),System.currentTimeMillis()+".jpg");
FileOutputStream outputStream = new FileOutputStream(file);
bitmap.compress(CompressFormat.JPEG, 100, outputStream);
outputStream.close();
camera.stopPreview();
camera.startPreview();//處理完數據之後可以預覽
} catch (Exception e) {
Log.e(TAG, e.toString());
}
}
}

注意,代碼中有兩個回調類,一個是SurfaceCallback(),另外一個是TakePictureCallback(),初學者可能一時難以理解,通俗地講,前者是用來監視surficeView這個暫時存放圖片數據的顯示控件的,根據它的顯示情況調用不同的方法,包括surfaceCreated(),surfaceChanged(),surfaceDestroyed(),也就不難理解為什麼會有這三個回調方法了(注意,在surfaceDestroyed()方法中必須釋放攝像頭,詳細代碼參見上方)。TakePictureCallback()是為了監視是否拍照而設計的接口,期中也僅有一個方法,camera將拍照得到的數據傳入方法,我們便可以對拍照得到的數據進行進一步處理了。

至此,簡單的拍照功能介紹完畢!

package cn.camera.rxm;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Calendar;
import java.util.Locale;
import org.apache.commons.logging.Log;
import android.text.format.DateFormat;
import android.util.*;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.os.Bundle;
import android.os.Environment;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
//import android.widget.Toast;
public class MycamActivity extends Activity {
private Preview mPreview;
private Camera mCamera;
Bitmap CameraBitmap;
SurfaceHolder mHolder;
private static final int OPTION_SNAPSHOT = 0;
private static final int OPTION_STOPCAMERA = 1;
private View viewStart;
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    LayoutInflater flater = this.getLayoutInflater();
    viewStart = flater.inflate(R.layout.main, null);
    setContentView(viewStart);
    Button btn1 = (Button)findViewById(R.id.button1);
    btn1.setOnClickListener(
    new OnClickListener(){
    public void onClick(View v){
    mPreview = new Preview(getBaseContext());
    setContentView(mPreview);
    };
    }
    );
  }
  public boolean onCreateOptionsMenu(Menu menu){
//
menu.add(0, OPTION_SNAPSHOT, 0, R.string.take);
//
menu.add(0, OPTION_STOPCAMERA, 1, R.string.back);
//
return true;//super.onCreateOptionsMenu(menu);
}
public boolean onOptionsItemSelected(MenuItem item) {
//
int itemId = item.getItemId();
//
switch(itemId){
case OPTION_SNAPSHOT:
//拍攝照片
mCamera.takePicture(null, null, jpegCallback);
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mCamera.startPreview();
break;
case OPTION_STOPCAMERA:
mPreview = null;
setContentView(viewStart);
break;
}
return true;
}
private PictureCallback jpegCallback = new PictureCallback(){
//
public void onPictureTaken(byte[] data, Camera camera) {
try {
String name = new DateFormat().format("yyyyMMdd_hhmmss",
Calendar.getInstance(Locale.CHINA)) + ".jpg";
FileOutputStream fileout = new FileOutputStream("/mnt/sdcard/sdcard/DCIM/"+ name);
System.out.println(name);
fileout.write(data,0,data.length);
fileout.flush();
fileout.close();
} catch (IOException e) {
// TODO: handle exception
System.out.println(e);
}
}
};
class Preview extends SurfaceView implements SurfaceHolder.Callback
{
Preview(Context context)
{
super(context);
mHolder=getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder)
{
mCamera=Camera.open();
try
{
mCamera.setPreviewDisplay(holder);
}
catch(IOException exception)
{
mCamera.release();
mCamera=null;
}
}
public void surfaceDestroyed(SurfaceHolder holder)
{
mCamera.stopPreview();
mCamera.release();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// TODO Auto-generated method stub
Camera.Parameters parameters=mCamera.getParameters();
parameters.setPictureFormat(PixelFormat.JPEG);
parameters.setPreviewSize(1024, 1024);
mCamera.setParameters(parameters);
mCamera.setDisplayOrientation(90);
mCamera.startPreview();
}
}
}

更多關於Android相關內容感興趣的讀者可查看本站專題:《Android文件操作技巧匯總》、《Android編程開發之SD卡操作方法匯總》、《Android開發入門與進階教程》、《Android資源操作技巧匯總》、《Android視圖View技巧總結》及《Android控件用法總結》

希望本文所述對大家Android程序設計有所幫助。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved