(1)Surface
簡單翻譯:Surface是原始圖像緩衝區(raw buffer)的一個句柄,而原始圖像緩衝區是由屏幕圖像合成器(screen compositor)管理的。
就如在C語言編程一樣,通過一個文件的句柄,就可以操作文件。 同樣的,通過Surface就可以獲取raw buffer其中的內容。當得到一個Surface對象時,同時會得到一個Canvas(畫布)對象。這一點可以通過查看\frameworks\base\core\java\android\view\Surface.java文件可知道Surface類定義了一個Canvas成員變量
(2)Canvas
理解Canvas對象,可以把它當做畫布,Canvas的方法大多數是設置畫布的大小、形狀、畫布背景顏色等等,要想在畫布上面畫畫,一般要與Paint對象結合使用,顧名思義,Paint就是畫筆的風格,顏料的色彩之類的。如下:
- // 創建畫筆
- Paint paint = new Paint();
- paint.setColor(Color.RED);// 設置紅色
- canvas.drawCircle(60, 20, 10, paint);// 畫一個圓
(3)SurfaceView
你可以通過SurfaceHolder這個接口去訪問Surface,而執行getHolder()方法可以得到SurfaceHolder接口。當SurfaceView的窗口可見時,Surface就會被創建,當SurfaceView窗口隱藏時,Surface就會被銷燬。當然了,你也可以通過複寫surfaceCreated(SurfaceHolder) 和 surfaceDestroyed(SurfaceHolder) 這兩個方法來驗證一下Surface何時被創建與何時被銷燬。
SurfaceView與Surface的聯繫:簡單來說,Surface是管理顯示內容的數據(implementsParcelable),包括存儲數據的交換。而SurfaceView就是把這些數據顯示出來到屏幕上面。
(4)SurfaceHolder
SurfaceHolder是一個接口,其作用就像一個關於Surface的監聽器,SurfaceHolder控制surface的流程所使用的幾個方法:
- abstract void addCallback(SurfaceHolder.Callback callback) //Add a Callback interface for this holder
- abstract Canvas lockCanvas() //Start editing the pixels in the surface
- abstract Canvas lockCanvas(Rect dirty) //Just like lockCanvas() but allows specification of a dirty rectangle
- abstract void removeCallback(SurfaceHolder.Callback callback) //Removes a previously added Callback interface from this holder
- abstract void unlockCanvasAndPost(Canvas canvas) //Finish editing pixels in the surface
在SurfaceView中有一個方法getHolder,可以很方便地獲得SurfaceView所對應的Surface所對應的SurfaceHolder。
(5)SurfaceHolder.Callback
Class Overview:A client may implement this interface to receive information about changes to the surface. When used with aSurfaceView, the Surface being held is only available between calls tosurfaceCreated(SurfaceHolder) andsurfaceDestroyed(SurfaceHolder). The Callback is set with SurfaceHolder.addCallback method.
主要方法:
- public abstract void surfaceChanged(SurfaceHolder holder, int format, int width, int height) //invoked when surface changes
- public abstract void surfaceCreated(SurfaceHolder holder) //The SurfaceHolder whose surface is being created
- public abstract void surfaceDestroyed(SurfaceHolder holder) //The SurfaceHolder whose surface is being destroyed.
SurfaceHolder = SurfaceView.getHolder();
Surface = SurfaceHolder.getSurface();
Canvas =SurfaceHolder.LockCanvas(Rect dirty)
Canvas =Surface.lockCanvas(Rect dirty)
從設計模式的高度來看,Surface、SurfaceView和SurfaceHolder實質上就是廣爲人知的MVC,即Model-View-Controller。Model就是模型的意思,或者更簡單地說就是數據,也就是這裏的Surface;View即視圖,代表用戶交互界面,也就是這裏的SurfaceView;SurfaceHolder很明顯可以理解爲MVC中的Controller(控制器)。這樣看起來三者之間的關係就清楚了很多。
========================================================================================================
給大家來一個使用camera.takePicture拍照的案例,這個是使用android.hardware.Camera硬件方式的,使用的都是camera.class標準接口。代碼如下:
- package com.example.cameraandroid;
- import android.os.Bundle;
- import android.app.Activity;
- import java.io.File;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import android.content.Context;
- import android.content.Intent;
- import android.graphics.PixelFormat;
- import android.hardware.Camera;
- import android.hardware.Camera.Parameters;
- import android.hardware.Camera.PictureCallback; //拍照的回調接口
- import android.hardware.Camera.ShutterCallback; //快門的回調接口
- import android.media.AudioManager;
- import android.media.ToneGenerator;
- import android.net.Uri;
- import android.os.Environment;
- import android.os.StatFs;
- import android.util.Log;
- import android.view.Menu;
- import android.view.MenuItem; //MENU鍵功能項
- import android.view.SurfaceHolder;
- import android.view.SurfaceView;
- public class CameraAndroid extends Activity {
- private static final String TAG = "zhangcheng";
- private CameraPreview preview;
- private Camera camera;
- private ToneGenerator tone;
- private static final int OPTION_SNAPSHOT = 0; //MENU項的值
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- //setContentView(R.layout.activity_camera_android);
- preview = new CameraPreview(this); //自定義的view
- setContentView(preview);
- }
- public boolean onOptionsItemSelected(MenuItem item) { //activity的選項選擇函數
- Log.i(TAG,"onOptionsItemSelected");
- int itemId = item.getItemId(); //獲得自定義ID
- switch(itemId){
- case OPTION_SNAPSHOT:
- //拍攝照片
- camera.takePicture(shutterCallback, null, jpegCallback); //拍照動作
- break;
- }
- return true;
- }
- private PictureCallback jpegCallback = new PictureCallback(){
- @Override
- public void onPictureTaken(byte[] data, Camera camera) {
- Log.i(TAG,"jpegCallback");
- // TODO Auto-generated method stub
- Parameters ps = camera.getParameters();
- if(ps.getPictureFormat() == PixelFormat.JPEG){
- //存儲拍照獲得的圖片
- String path = save(data);
- //將圖片交給Image程序處理
- Uri uri = Uri.fromFile(new File(path));
- Intent intent = new Intent();
- intent.setAction("android.intent.action.VIEW");
- intent.setDataAndType(uri, "image/jpeg");
- startActivity(intent); //顯示剛纔拍的照片
- }
- }
- };
- private ShutterCallback shutterCallback = new ShutterCallback(){
- @Override
- public void onShutter() {
- Log.i(TAG,"shutterCallback");
- // TODO Auto-generated method stub
- if(tone == null)
- //發出提示用戶的聲音
- tone = new ToneGenerator(AudioManager.STREAM_MUSIC,ToneGenerator.MAX_VOLUME);
- tone.startTone(ToneGenerator.TONE_PROP_BEEP2);
- }
- };
- private String save(byte[] data){ //保存jpg到SD卡中
- String path = "/sdcard/"+System.currentTimeMillis()+".jpg";
- try{
- if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
- //判斷SD卡上是否有足夠的空間
- String storage = Environment.getExternalStorageDirectory().toString();
- StatFs fs = new StatFs(storage);
- long available = fs.getAvailableBlocks()*fs.getBlockSize();
- if(available<data.length){
- //空間不足直接返回空
- return null;
- }
- File file = new File(path);
- if(!file.exists())
- //創建文件
- file.createNewFile();
- FileOutputStream fos = new FileOutputStream(file);
- fos.write(data);
- fos.close();
- }
- }catch(Exception e){
- e.printStackTrace();
- return null;
- }
- return path;
- }
- class CameraPreview extends SurfaceView implements SurfaceHolder.Callback{ //完成自定義的CameraPreview
- SurfaceHolder mHolder;
- public CameraPreview(Context context) { //view必有帶Context的構造函數
- super(context);
- // TODO Auto-generated constructor stub
- mHolder = getHolder();
- mHolder.addCallback(this);
- mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
- }
- @Override
- public void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {
- Log.i(TAG,"surfaceChanged");
- // TODO Auto-generated method stub
- //已經獲得Surface的width和height,設置Camera的參數
- Camera.Parameters parameters = camera.getParameters();
- parameters.setPreviewSize(width,height);
- camera.setParameters(parameters); //設置完效果後必須有這個
- //開始預覽
- camera.startPreview();
- }
- @Override
- public void surfaceCreated(SurfaceHolder holder) {
- Log.i(TAG,"surfaceCreated");
- // TODO Auto-generated method stub
- camera = Camera.open();
- try {
- //設置顯示
- camera.setPreviewDisplay(holder);//使預覽在surfaceview上顯示出來
- } catch (IOException exception) {
- camera.release();
- camera = null;
- }
- }
- @Override
- public void surfaceDestroyed(SurfaceHolder holder) {
- Log.i(TAG,"surfaceDestroyed");
- // TODO Auto-generated method stub
- camera.stopPreview();
- //釋放Camera
- camera.release();
- camera = null;
- }
- }
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- // Inflate the menu; this adds items to the action bar if it is present.
- //getMenuInflater().inflate(R.menu.camera_android, menu);
- menu.add(0, OPTION_SNAPSHOT, 0, R.string.snapshot); //添加自定義meunitme項目
- return super.onCreateOptionsMenu(menu);
- }
- }
注意在androidmanifest.XML中加上硬件操作權限申明,如下:
- <uses-permission android:name="android.permission.CAMERA" />
- <uses-feature android:name="android.hardware.camera" />
- <uses-feature android:name="android.hardware.camera.autofocus" />
程序的運行結果就是:全屏預覽了一個攝像頭取景,如果按menu鍵,會激活“snapshot” 項,單擊它就可以拍照並預覽相片。
以上是採用camera.java的API實現的camera相機方式,其實camera應用相機方式還有另外一種:就是直接調用系統相機,本質就是採用intent直接跳轉到系統相機。關鍵代碼如下:intent.setAction("android.media.action.STILL_IMAGE_CAMERA"); //此action是mediastore類裏面的定義
原文地址:http://blog.chinaunix.net/u/23353/showart_1898839.html
參考原文:http://www.cmd100.com/bbs/forum.php?mod=viewthread&tid=148031
參考原文:http://www.cnblogs.com/hnrainll/archive/2012/06/04/2534935.html
參考原文:http://www.cnblogs.com/xuling/archive/2011/06/06/android.html
參考原文:http://www.linuxidc.com/Linux/2012-08/67619p3.htm
參考原文:http://blog.csdn.net/pathuang68/article/details/7351317