• 我的Android进阶之旅------>Android拍照小例子


    今天简单的学习了一下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

    ==================================================================================================

  • 相关阅读:
    Eclipse背景颜色设置
    SQL ROW_NUMBER() OVER函数的基本用法用法
    hdu 2844 Coins 多重背包问题
    VC++学习/MFC (1)
    java学习 (1)
    hdu 1506 City Game 二维的多重背包
    java学习(2)
    VC++学习/MFC (2)
    hdu 1506 Largest Rectangle in a Histogram
    hdu 1171 Big Event in HDU
  • 原文地址:https://www.cnblogs.com/riskyer/p/3341770.html
Copyright © 2020-2023  润新知