今天简单的学习了一下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
==================================================================================================
分享到:
相关推荐
我的Android进阶之旅------>Android疯狂连连看游戏的实现 可以参考博客:http://blog.csdn.net/ouyang_peng/article/details/14115627
Android读写XML(上)——package说明.doc Android读写XML(下)——创建XML文档.doc ...Android基础教程之----动态更改屏幕方向的简单例子(LANDSCAPE与PORTRAIT)! .doc Android基础教程之----五大布局对象.doc
我的Android进阶之旅------>Android实现用Android手机控制PC端的关机和重启的功能(一)PC服务器端 (地址:http://blog.csdn.net/ouyang_peng/article/details/47004617) 我的Android进阶之旅------>Android实现用...
深入理解jvm虚拟机+Android进阶之光-附件资源
我的Android进阶之旅------>Android自定义View来实现解析lrc歌词并同步滚动、上下拖动、缩放歌词的功能 http://blog.csdn.net/ouyang_peng/article/details/50813419 1、实现歌词同步滚动的功能,即歌曲播放到哪句...
《Android高级进阶》是一本面向已有基础的Android开发者,旨在提升其技能和理解的书籍。这本书涵盖了Android开发中的高级主题和技术,对于那些希望在Android领域深入挖掘的工程师来说,是一份不可多得的资源。高清...
《Android高级进阶》是Android的进阶学习指南,主要为Android初中级开发者进阶所需的知识,高级开发者也可以从本书中发现很多共鸣点。《Android高级进阶》从8个方面对50个知识点进行分类讲解,包括基础篇、系统架构...
为了满足您的要求,我将基于Android高级进阶这一主题,提供一些该领域的通用知识点,希望能够帮助到您。 Android高级进阶通常包括如下几个方面的深入学习: 1. Android系统架构:深入理解Android系统底层架构,...
Android 高手进阶教程(二)之----Android Launcher 抽屉类 SlidingDrawer 的 使用 最近在研究 Lanucher ,看了源码,发现了 SlidingDrawer 这个类,也就是 所谓的"抽屉"类。它的用法很简单,要包括 handle ,和 content...
本书是一本Android进阶类书籍,书中各知识点由浅入深、环环相扣,最终这些知识点形成了一个体系结构。本书共分为11章。第1章介绍Android 5.0到Android 7.0的新特性。第2章介绍Material Design。第3章介绍View体系,...
Android知识体系图&面试&进阶(Version-1.0.1).xmind
《HenCoder Android开发进阶UI1-2Paint详解》的练习项目专注于深入理解并熟练运用Android中的Paint对象,以提升开发者在图形绘制方面的技能。在这个项目中,开发者将有机会实践各种Paint属性的设置和应用,从而掌握...
《Android平台开发之旅(第2版)》涵盖Android 3/4的新特性,立足实际的开发案例,介绍了Android平台开发的基础概念、实用技术和应用模式。主要内容包括应用程序框架、高级界面、数据库应用、网络通信与Web开发、无线...
右击目标工程,Build Path -> Configure Build Path -> Library选项下 -> Android 4.1 -> android.jar -> Source attachment --> Edit --> External Folder 选择这个文件目录C:\Program Files\Android\android-sdk\...
我的Android进阶之旅------>Android基于HTTP协议的多线程断点下载器的实现的源代码,原文地址:http://blog.csdn.net/ouyang_peng/article/details/10125409
我的Android进阶之旅------>Android基于HTTP协议的多线程断点下载器的实现的源代码,原文地址:http://blog.csdn.net/ouyang_peng/article/details/10125409 这个进行了优化