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

简介: 今天简单的学习了一下android拍照的简单实现。 当然该程序是个小例子,非常简单,没有什么复杂的操作,但是可以学习到Android 拍照API流程。 1.在布局文件中添加一个 surfaceView (用来展示预览的图片) 2.

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

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

相关文章
|
6月前
|
API Android开发 计算机视觉
视觉智能平台有android人脸识别拍照demo?
视觉智能平台有android人脸识别拍照demo么?
65 0
|
7月前
|
编解码 网络协议 Android开发
Android平台RTMP|RTSP直播播放器功能进阶探讨
很多开发者在跟我聊天的时候,经常问我,为什么一个RTMP或RTSP播放器,你们需要设计那么多的接口,真的有必要吗?带着这样的疑惑,我们今天聊聊Android平台RTMP、RTSP播放器常规功能,如软硬解码设置、实时音量调节、实时快照、实时录像、视频view翻转和旋转、画面填充模式设定、解码后YUV、RGB数据回调等:
104 0
|
8月前
|
存储 数据可视化 Android开发
Android 实现拍照功能,并将图片保存到本地存储
Android 实现拍照功能,并将图片保存到本地存储
453 0
|
12月前
|
Web App开发 编解码 前端开发
Android | 音视频方向进阶路线及资源合集
但是系统相机和系统控件VideoView的局限性都是可定制型太差,系统相机的图像分辨率,视频码率以及VideoView的进度条等.
156 0
|
Java Android开发 Kotlin
一些实用的Android进阶小技巧
主要是利用application获取唯一的全局实例context,使得我们在任何场景都可以获取context
75 0
一些实用的Android进阶小技巧
|
存储 XML API
Android调用相机拍照录视频录音以及存储,7.0以上及以下都可使用。
Android调用相机拍照录视频录音以及存储,7.0以上及以下都可使用。
297 0
|
前端开发 Android开发
Android进阶之绘制-自定义View完全掌握(四)
Android进阶之绘制-自定义View完全掌握(四)
87 0
Android进阶之绘制-自定义View完全掌握(四)
|
编解码 Android开发
Android进阶之绘制-自定义View完全掌握(三)
Android进阶之绘制-自定义View完全掌握(三)
134 0
Android进阶之绘制-自定义View完全掌握(三)