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

时间:2022-02-01 15:48:38

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

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