今天简单的学习了一下android拍照的简单实现。 当然该程序是个小例子,非常简单,没有什么复杂的操作,但是可以学习到Android 拍照API流程。
1.在布局文件中添加一个 surfaceView (用来展示预览的图片)
2.根据 SurfaceView 获得 Holder
3.给固定器设置 SurfaceHolder.Callback ; 这个 Callback 有一系列的周期方法,
比如:surfaceCreated,surfaceChanged,surfaceDestroyed等方法.
① 在surfaceCreated 中 打开相机,设置预览效果 ;
② 在surfaceChanged中可以初始化相机( Camera );比如相机的参数: 像素, 大小,格式,开始预览,等等
③ 在surfaceDestroyed可以可以停止相机拍摄;释放相机资源
4. 相机自动对焦 的回调处理
Camera.autoFocus( AutoFocusCallback )
下面就看看该小例子的代码吧。
文件1.该应用的布局文件,res/layout/main.xml
<?xml version="1.0" encoding="utf-8"?> <!-- 帧布局 --> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent"> <!-- 用来展示画面 --> <SurfaceView android:id="@+id/surfaceView" android:layout_width="fill_parent" android:layout_height="fill_parent" /> <!-- 相对布局,该界面默认不显示出来,当触摸屏幕时候显示出来--> <RelativeLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:visibility="gone" android:id="@+id/buttonlayout"> <!-- 拍照按钮 --> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_alignParentBottom="true" android:layout_marginRight="5dp" android:text="@string/takepicture" android:onClick="takepicture" android:id="@+id/takePicture" /> <!-- 对焦按钮 --> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toLeftOf="@id/takePicture" android:layout_alignTop="@id/takePicture" android:layout_marginRight="20dp" android:text="@string/autofocus" android:onClick="autofocus" android:id="@+id/autofocus" /> </RelativeLayout> </FrameLayout>
文件2:布局文件所用到的资源文件,res/values/string.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="hello">Hello World, MainActivity!</string> <string name="app_name">拍照小应用</string> <string name="takepicture">拍照</string> <string name="autofocus">对焦</string> <string name="noSDcard">检测到手机没有存储卡!请插入手机存储卡再开启本应用</string> </resources>
文件3:该应用的主程序,PictureActivity.java
package cn.oyp.picture; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import android.app.Activity; import android.content.pm.ActivityInfo; import android.graphics.ImageFormat; import android.hardware.Camera; import android.hardware.Camera.AutoFocusCallback; import android.hardware.Camera.PictureCallback; import android.hardware.Camera.ShutterCallback; import android.os.Bundle; import android.os.Environment; import android.util.Log; import android.view.MotionEvent; import android.view.SurfaceHolder; import android.view.SurfaceHolder.Callback; import android.view.SurfaceView; import android.view.View; import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager; import android.widget.Toast; public class PictureActivity extends Activity { // 对焦和拍照按钮布局 private View buttonlayout; // 用来显示图片 private SurfaceView surfaceView; // 摄像头 private Camera camera; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 窗口特效为无标题 requestWindowFeature(Window.FEATURE_NO_TITLE); // 设置窗口全屏 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); // 设定屏幕显示为横向 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); setContentView(R.layout.main); buttonlayout = this.findViewById(R.id.buttonlayout); surfaceView = (SurfaceView) this.findViewById(R.id.surfaceView); // 获取的画面直接输出到屏幕上 surfaceView.getHolder() .setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); // 画面分辨率 surfaceView.getHolder().setFixedSize(176, 144); // 保持屏幕高亮 surfaceView.getHolder().setKeepScreenOn(true); // 监听 surfaceView何时创建 surfaceView.getHolder().addCallback(new Callback() { /** * 界面打开时该方法自动调用 * 打开相机,设置预览效果 ; */ @Override public void surfaceCreated(SurfaceHolder holder) { try { // 打开摄像头 camera = Camera.open(); // 摄像头参数 Camera.Parameters parameters = camera.getParameters(); // 将摄像头参数打印出来,各种机型的参数不一样,所以得根据具体机型来设置参数 // Log.i("MainActivity", parameters.flatten()); // 设置预览图片大小 parameters.setPreviewSize(800, 480); // 设置每秒钟捕获画面的频率 parameters.setPreviewFrameRate(5); // 设置图片格式 parameters.setPictureFormat(ImageFormat.JPEG); // 设置图片大小 parameters.setPictureSize(1024, 768); // 设置图片质量 parameters.setJpegQuality(80); // 将参数设置给摄像头 camera.setParameters(parameters); // 设置预览显示 camera.setPreviewDisplay(holder); // 开始预览 camera.startPreview(); } catch (Exception e) { e.printStackTrace(); // 释放摄像头 if (camera != null) { camera.release(); camera = null; } } } /** * 当预览界面的格式和大小发生改变时,该方法被调用 */ @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } /** * 当预览界面被关闭时,该方法被调用 * 停止相机拍摄;释放相机资源 */ @Override public void surfaceDestroyed(SurfaceHolder holder) { // 停止预览 camera.stopPreview(); // 释放摄像头 if (camera != null) { camera.release(); camera = null; } } }); } // 按下拍照按钮后,开始拍照 public void takepicture(View v) { if (camera != null) { camera.takePicture(new ShutterCallback() { /** * 在相机快门关闭时候的回调接口,通过这个接口来通知用户快门关闭的事件, * 普通相机在快门关闭的时候都会发出响声,根据需要可以在该回调接口中定义各种动作, 例如:使设备震动 */ @Override public void onShutter() { // just log ,do nothing Log.d("ShutterCallback", "...onShutter..."); } }, null, new PictureCallback() { // 当用户拍完一张照片的时候触发onPictureTaken,这时候对拍下的照片进行相应的处理操作 @Override public void onPictureTaken(byte[] data, Camera camera) { // 判断是否存在SD卡 if (Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED)) { try { // 将拍的照片保存到sd卡中 File jpgFile = new File(Environment .getExternalStorageDirectory(), System .currentTimeMillis() + ".jpg"); FileOutputStream outputStream = new FileOutputStream( jpgFile); outputStream.write(data); outputStream.close(); // 处理完照片后,又开始预览 camera.startPreview(); } catch (IOException e) { e.printStackTrace(); } } else { Toast.makeText(getApplicationContext(), R.string.noSDcard, Toast.LENGTH_LONG).show(); } } }); } } // 按下对焦按钮后,开始对焦 public void autofocus(View v) { if (camera != null) { // 相机自动对焦的回调处理 camera.autoFocus(new AutoFocusCallback() { @Override public void onAutoFocus(boolean success, Camera camera) { /* 对到焦点拍照 */ if (success) { // just log ,do nothing Log.d("AutoFocusCallback", "...onFocus..."); } } }); } } /** 当触摸屏幕的时候,将对焦和拍照按钮布局显示出来 */ @Override public boolean onTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { buttonlayout.setVisibility(ViewGroup.VISIBLE); return true; } return super.onTouchEvent(event); } }
文件4:该应用的描述文件 ,AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="cn.oyp.picture" android:versionCode="1" android:versionName="1.0"> <uses-sdk android:minSdkVersion="8" /> <!-- 摄像头权限 --> <uses-permission android:name="android.permission.CAMERA"/> <!-- 在SD卡中创建和删除文件权限 --> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <!-- 往SD卡中写入数据的权限 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name="PictureActivity" android:label="@string/app_name" android:screenOrientation="landscape"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
用的描述了解更多关于Android拍照的例子,可以参考以下几篇博文
http://blog.csdn.net/cfwdl/article/details/5746708
http://mjbb.iteye.com/blog/1018006
http://blog.csdn.net/hellogv/article/details/5962494
http://aokunsang.iteye.com/blog/1295813
==================================================================================================
作者:欧阳鹏 欢迎转载,与人分享是进步的源泉!
转载请保留原文地址:http://blog.csdn.net/ouyang_peng
==================================================================================================