(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);// 画一个圆Surface本身的作用类似一个句柄,得到了这个句柄就可以得到其中的Canvas、原生缓冲器以及其它方面的内容。Surface实现了Parcelable接口,(implements Parcelable),也就是说Surface对象可以把显示内容的数据写入到 Parcel 中,并且能够从Parcel读回数据。
你可以通过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.(6)附上上述所说几种的联系
========================================================================================================
给大家来一个使用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