zoukankan      html  css  js  c++  java
  • 我的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

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

  • 相关阅读:
    Asp.Net Web API 2第八课——Web API 2中的属性路由
    Asp.Net Web API 2第七课——Web API异常处理
    Asp.Net Web API 2第六课——Web API路由和动作选择
    Asp.Net Web API 2第五课——Web API路由
    开始学习python
    BMI 小程序 购物车
    深浅copy 文件操作
    字典 dict 集合set
    基本数据类型 (str,int,bool,tuple,)
    python 运算符
  • 原文地址:https://www.cnblogs.com/riskyer/p/3341770.html
Copyright © 2011-2022 走看看