赞
踩
Android菜鸟第一次写原创博客,大神请轻喷,共同进步。
最近刚接触到如何实现一个简单的照相机功能,然后又将录音和录像功能加了进去。ps:录像功能相对复杂,自己实现起来比较困难,我就直接在程序里调用系统的录像功能了。以后在慢慢学习:)好,言归正传。
1、首先新建一个照相机项目;
2、我先新建了一个BaseActivity,用于设置相机屏幕全屏和获取屏幕宽高像素等功能;
代码:
- package xw.phonemanager.activity;
-
- import android.app.Activity;
- import android.os.Bundle;
- import android.util.DisplayMetrics;
- import android.view.Window;
- import android.view.WindowManager;
-
- public class BaseActivity extends Activity {
-
- public static float screenWidth, screenHeigth;
- // private ProgressDialog mDialog;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setFullScreen(); // 设置全屏
- getScreen(); //获取屏幕宽高值
- }
-
- // 设置全屏
- private void setFullScreen() {
- requestWindowFeature(Window.FEATURE_NO_TITLE);
- getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
- WindowManager.LayoutParams.FLAG_FULLSCREEN);
- }
- //获取屏幕宽高值
- private void getScreen() {
-
- DisplayMetrics metrics = new DisplayMetrics();
- getWindowManager().getDefaultDisplay().getMetrics(metrics);
-
- screenWidth = metrics.widthPixels;
- screenHeigth = metrics.heightPixels;
- }
-
- // public void showProgressDialog(String message){
- // }
-
- }
3、新建一个照相的Activity(名叫PhotographActivity)继承了
BaseActivity,同时实现了OnClickListener, SurfaceHolder.Callback, PictureCallback三个接口。这时eclipse会自动提示必须实现onClick(View v)、surfaceCreated(SurfaceHolder holder)、surfaceChanged(SurfaceHolder holder, int format, int width, int height)、surfaceDestroyed(SurfaceHolder holder)、onPictureTaken(byte[] data, Camera camera)这四个方法,具体功能请看代码注释;
4、新建一个布局文件photograph.xml,用于显示打开相机后预览状态屏幕上显示的东西,和常见的相机界面差不多,如图:
xml代码:
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent" >
-
- <SurfaceView
- android:id="@+id/camera"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:layout_alignParentTop="true" />
-
- <SeekBar
- android:id="@+id/seekbar_focal"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:layout_marginLeft="20dp"
- android:layout_alignParentRight="true"
- android:layout_marginRight="60dp"
- android:layout_alignParentTop="true"
- android:layout_marginTop="15dp" />
-
- <ImageView
- android:id="@+id/back_btn"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- android:layout_marginBottom="10dp"
- android:layout_alignParentRight="true"
- android:layout_marginRight="10dp"
- android:src="@drawable/back" />
-
- <ImageView
- android:id="@+id/flash_switch"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:layout_marginLeft="15dp"
- android:layout_alignParentBottom="true"
- android:layout_marginBottom="10dp"
- android:src="@drawable/light_auto" />
-
- <ImageView
- android:id="@+id/switch_camera"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignLeft="@+id/shot_btn"
- android:layout_alignTop="@+id/seekbar_focal"
- android:src="@drawable/showall"
- android:visibility="invisible"/>
-
- <ImageView
- android:id="@+id/shot_btn"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentRight="true"
- android:layout_marginRight="10dp"
- android:layout_centerVertical="true"
- android:src="@drawable/photo" />
-
- <Button
- android:id="@+id/record_start_btn"
- style="?android:attr/buttonStyleSmall"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- android:layout_marginBottom="10dp"
- android:layout_toRightOf="@id/flash_switch"
- android:layout_marginLeft="120dp"
- android:text="@string/record_start" />
-
- <Button
- android:id="@+id/record_stop_btn"
- style="?android:attr/buttonStyleSmall"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- android:layout_marginBottom="10dp"
- android:layout_toRightOf="@id/flash_switch"
- android:layout_marginLeft="120dp"
- android:text="@string/record_stop"
- android:visibility="invisible" />
-
- <Button
- android:id="@+id/video_btn"
- style="?android:attr/buttonStyleSmall"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- android:layout_marginBottom="10dp"
- android:layout_marginLeft="73dp"
- android:layout_toLeftOf="@id/back_btn"
- android:layout_marginRight="100dp"
- android:text="@string/video" />
-
- </RelativeLayout>
5、开始实现相机、录音和录像功能,请看代码和注释:
- package xw.activity.photograph;
-
- import java.io.BufferedOutputStream;
- import java.io.File;
- import java.io.FileNotFoundException;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.util.Calendar;
- import java.util.Locale;
-
- import xw.phonemanager.activity.BaseActivity;
- import xw.phonemanager.activity.MenuActivity;
- import xw.phonemanager.activity.R;
- import android.content.Intent;
- import android.content.pm.ActivityInfo;
- import android.graphics.Bitmap;
- import android.graphics.BitmapFactory;
- import android.graphics.PixelFormat;
- import android.hardware.Camera;
- import android.hardware.Camera.Parameters;
- import android.hardware.Camera.PictureCallback;
- import android.media.MediaRecorder;
- import android.net.Uri;
- import android.os.Bundle;
- import android.os.Environment;
- import android.provider.MediaStore;
- import android.text.format.DateFormat;
- import android.view.KeyEvent;
- import android.view.MotionEvent;
- import android.view.SurfaceHolder;
- import android.view.SurfaceView;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.view.View.OnTouchListener;
- import android.view.Window;
- import android.view.WindowManager;
- import android.widget.Button;
- import android.widget.ImageView;
- import android.widget.SeekBar;
- import android.widget.SeekBar.OnSeekBarChangeListener;
- import android.widget.Toast;
-
- public class PhotographActivity extends BaseActivity implements
- OnClickListener, SurfaceHolder.Callback, PictureCallback {
-
- SurfaceView cameraPrew;// 预览图对象
- ImageView shot;
- ImageView flash;
- ImageView back;
- ImageView switchCamera;
- Button recordStart;
- Button recordStop;
- Button VCR;
- SeekBar focus;
- Camera camera;// 相机对象
- Camera.Parameters parameters;// 相机参数对象
-
- MediaRecorder mRecorder; // MediaRecorder对象,用于实现录音和录像
-
- private int cameraNum; // 摄像头的数量
- private int cameraID;// 摄像头的编号
- private boolean canSwitchCam = false;
- private boolean noSD;
- private int maxZoom; // 最大变焦
- private String recFileName; // 录音音频文件名称
- // 设置了两个判断标识,当处于录音状态时不允许拍照或录像,均置为false
- private boolean isPhoto = true; // 是否可以照相
- private boolean isVideo = true; // 是否可以录像
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- setContentView(R.layout.photograph);
-
- Window window = getWindow();
- window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);// 屏幕高亮
- setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);// 强制横屏
- getWindow().setFormat(PixelFormat.TRANSPARENT);// 屏幕半透
-
- init();// 初始化
- }
-
- private void init() {
- checkSD();// 首先检测SD卡是否存在或可用,不可用则提示用户,避免浪费表情的尴尬:D
- cameraInit();
- prewInit();
- buttonInit();
- zoomInit();
- seekBarInit();
- }
-
- /**
- * 检查是否有SD卡
- */
- private void checkSD() {
- String SDtatus = Environment.getExternalStorageState();
- if (SDtatus == Environment.MEDIA_MOUNTED) {
- noSD = true;
- Toast.makeText(PhotographActivity.this, "没有SD卡或SD卡不可用",
- Toast.LENGTH_LONG).show();
- } else {
- noSD = false;
- }
- }
-
- /**
- * 相机初始化
- */
- private void cameraInit() {
- cameraNum = Camera.getNumberOfCameras();// 摄像头的个数
- if (camera != null) { // 若不为空,释放资源重新获取
- camera.release();
- }
- camera = Camera.open(); // 打开摄像头
-
- // 检测手机的摄像头个数,若不止一个则显示切换摄像头的图标,canSwitchCam置为true
- switchCamera = (ImageView) findViewById(R.id.switch_camera);
- if (cameraNum > 1) {
- switchCamera.setVisibility(View.VISIBLE);
- canSwitchCam = true;
- cameraID = 0;// 当前的摄像头ID设为0
- }
- // 相机实例获得相机参数集
- parameters = camera.getParameters();
-
- }
-
- /**
- * 预览初始化
- */
- private void prewInit() {
- cameraPrew = (SurfaceView) findViewById(R.id.camera);// 绑定SurfaceView并实例化
-
- cameraPrew.getHolder().setFixedSize((int) BaseActivity.screenWidth,
- (int) BaseActivity.screenHeigth);
- cameraPrew.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
- cameraPrew.getHolder().addCallback(this);
- // 给整个屏幕的SurfaceView设置一个触摸监听,实现全屏手动对焦
- cameraPrew.setOnTouchListener(new OnTouchListener() {
-
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- camera.autoFocus(null);// 点击屏幕即可对焦
- return false;
- }
- });
- }
-
- /**
- * 按键初始化,设置按键监听
- */
- private void buttonInit() {
- shot = (ImageView) findViewById(R.id.shot_btn);// 拍照键
- flash = (ImageView) findViewById(R.id.flash_switch);// 切换闪光灯键
- back = (ImageView) findViewById(R.id.back_btn);// 返回键
- recordStart = (Button) findViewById(R.id.record_start_btn);// 开始录音键
- recordStop = (Button) findViewById(R.id.record_stop_btn);// 结束录音键
- VCR = (Button) findViewById(R.id.video_btn);// 开始录像键
-
- // 设置监听
- shot.setOnClickListener(this);
- flash.setOnClickListener(this);
- back.setOnClickListener(this);
- switchCamera.setOnClickListener(this);
- recordStart.setOnClickListener(this);
- recordStop.setOnClickListener(this);
- VCR.setOnClickListener(this);
- }
-
- /**
- * 滑动条实现变焦,初始化
- */
- private void seekBarInit() {
- focus = (SeekBar) findViewById(R.id.seekbar_focal);
- focus.setProgress(0);
- focus.setMax(maxZoom);// 滑动条的最大值设为获得的相机可变焦值的最大值
- focus.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
-
- @Override
- public void onStopTrackingTouch(SeekBar seekBar) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void onStartTrackingTouch(SeekBar seekBar) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void onProgressChanged(SeekBar seekBar, int progress,
- boolean fromUser) {
- zoomChanged(progress);// 传递当前进度,变焦
- }
- });
- }
-
- private void zoomInit() {
- maxZoom = parameters.getMaxZoom();// 获得相机最大变焦范围
- }
-
- /**
- * 按键监听
- */
- @Override
- public void onClick(View v) {
- int id = v.getId();
- switch (id) {
- case R.id.shot_btn:
- if (isPhoto == true) {
- takPicture();
- } else {
- Toast.makeText(this, "无响应,正在录音", Toast.LENGTH_SHORT).show();
- }
- break;
- case R.id.flash_switch:
- flashSwitch();
- break;
- case R.id.back_btn:
- startActivity(new Intent(PhotographActivity.this,
- MenuActivity.class));
- finish();
- break;
- // 切换摄像头
- case R.id.switch_camera:
- if (canSwitchCam == true) {// 至少有两个才能切换
- if (camera != null) {
- camera.stopPreview();
- camera.release();
- Camera.open(++cameraID % cameraNum);// 在id:0~cameraNum之间切换
- }
- }
- break;
-
- case R.id.record_start_btn:
- if (noSD == true) { // 没有SD卡
- Toast.makeText(PhotographActivity.this, "没有SD卡或SD卡不可用",
- Toast.LENGTH_LONG).show();
- return;
- } else {
- startRec();// 开始录音
- }
- break;
-
- case R.id.record_stop_btn:
- stopRec();// 结束录音
- break;
-
- case R.id.video_btn:
- if (isVideo == true) {
- startVideo();// 开始录像
- } else {
- Toast.makeText(this, "无响应,正在录音", Toast.LENGTH_SHORT).show();
- }
- break;
- }
- }
-
- /**
- * 切换闪光灯状态,如果当前是开状态,点击切换为关状态, 再点击切换为自动状态,再点击又到开状态
- */
- private void flashSwitch() {
- if (parameters.getFlashMode() == Parameters.FLASH_MODE_AUTO) {
- flash.setImageResource(R.drawable.light_on);
- parameters.setFlashMode(Parameters.FLASH_MODE_ON);
- camera.setParameters(parameters);
- } else if (parameters.getFlashMode() == Parameters.FLASH_MODE_ON) {
- flash.setImageResource(R.drawable.light_off);
- parameters.setFlashMode(Parameters.FLASH_MODE_OFF);
- camera.setParameters(parameters);
- } else {
- flash.setImageResource(R.drawable.light_auto);
- parameters.setFlashMode(Parameters.FLASH_MODE_AUTO);
- camera.setParameters(parameters);
- }
- }
-
- // 变焦
- private void zoomChanged(int zoom) {
- parameters.setZoom(zoom);
- camera.setParameters(parameters);
- }
-
- // 照像
- public void takPicture() {
- camera.autoFocus(null);
- camera.takePicture(null, null, this);
- }
-
- @Override
- public void surfaceCreated(SurfaceHolder holder) {
- try {
- camera.setPreviewDisplay(cameraPrew.getHolder());// 获取相机预览
- } catch (IOException e) {
- e.printStackTrace();
- }
- camera.getParameters();// 获取相机参数实例
- camera.startPreview();
- }
-
- @Override
- public void surfaceChanged(SurfaceHolder holder, int format, int width,
- int height) {
- // TODO Auto-generated method stub
-
- }
-
- /**
- * 退出相机界面后,释放相机相关资源
- */
- @Override
- public void surfaceDestroyed(SurfaceHolder holder) {
- if (camera != null) {
- camera.stopPreview();
- camera.release();
- camera = null;
- }
- }
-
- /**
- * 拍照并保存,自动跳转到查看界面
- */
- @Override
- public void onPictureTaken(byte[] data, Camera camera) {
- if (noSD == true) { // 没有SD卡
- Toast.makeText(PhotographActivity.this, "没有SD卡或SD卡不可用",
- Toast.LENGTH_LONG).show();
- return;
- } else {
- Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
- String name = DateFormat.format("yyyyMMdd_hhmmss",
- Calendar.getInstance(Locale.CHINA))
- + ".jpg";// 自定义照片名字和格式
- File file = new File("sdcard/TianTian/photo/");
- file.mkdirs(); // 创建目录
- String fileName = "/mnt/sdcard/TianTian/photo/" + name;// 照片文件的绝对路径
- BufferedOutputStream bos = null;
- try {
- bos = new BufferedOutputStream(new FileOutputStream(fileName));
- bitmap.compress(Bitmap.CompressFormat.JPEG, 80, bos);// 通过缓冲流存入
-
- // 拍完之后跳转到查看刚拍的照片的一个Activity(ConfirmActivity),用户可以选择是否保留图片
- ConfirmActivity.photoName = fileName;
- Uri imgUri = Uri.fromFile(new File(fileName));
- Intent intent = new Intent();
- intent.setClass(PhotographActivity.this, ConfirmActivity.class);
- intent.setData(imgUri);
- this.camera.stopPreview();// 停止预览
- startActivity(intent);
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- } finally {
- try {
- bos.close();// 关闭流
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- }
-
- // 开始录音
- private void startRec() {
- // 录音时不能拍照和录像
- isPhoto = false;
- isVideo = false;
-
- mRecorder = new MediaRecorder();
- mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);// 设置录音员,从MIC获得声音
- mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);// 设置音频输出格式
- mRecorder.setAudioEncoder(MediaRecorder.VideoEncoder.DEFAULT);// 设置编码格式
-
- String path = Environment.getExternalStorageDirectory().getPath();
- String name = DateFormat.format("yyyyMMdd_hhmmss",
- Calendar.getInstance(Locale.CHINA))
- + ".3gp";
- File file = new File(path);
- file.mkdirs();
- recFileName = path + "/" + name;
- file = new File(recFileName);
- if (!file.exists()) {
- try {
- file.createNewFile();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- mRecorder.setOutputFile(recFileName);
- try {
- mRecorder.prepare();
- } catch (IllegalStateException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
- mRecorder.start(); // 录音开始
- Toast.makeText(this, "录音开始", Toast.LENGTH_SHORT).show();
-
- // “开始录音”后,将按钮换成“停止录音”获得焦点
- recordStart.setVisibility(View.GONE);
- recordStop.setVisibility(View.VISIBLE);
- }
-
- // 停止录音
- private void stopRec() {
-
- isPhoto = true;
- isVideo = true;
-
- mRecorder.stop();
- mRecorder.release();
- mRecorder = null;
- Toast.makeText(this, "录音结束", Toast.LENGTH_SHORT).show();
-
- // “停止录音”后,将按钮还原“开始录音”获得焦点
- recordStop.setVisibility(View.GONE);
- recordStart.setVisibility(View.VISIBLE);
- }
-
- /**
- * 调用系统录像机录像
- */
- private void startVideo() {
- camera.stopPreview();
- camera.release();
- camera = null;
- Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
- intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 0);
- startActivityForResult(intent, RESULT_FIRST_USER);
- finish();
- }
-
- /**
- * 重写onKeyDown方法,当在相机界面按返回键退到主菜单而不是直接退出程序
- */
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
- startActivity(new Intent(PhotographActivity.this,
- MenuActivity.class));
- finish();
- }
- return false;
- }
-
- }
- package xw.activity.photograph;
-
- import java.io.File;
-
- import xw.phonemanager.activity.BaseActivity;
- import xw.phonemanager.activity.R;
- import android.content.Intent;
- import android.content.pm.ActivityInfo;
- import android.net.Uri;
- import android.os.Bundle;
- import android.view.KeyEvent;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.widget.ImageView;
- import android.widget.Toast;
-
- public class ConfirmActivity extends BaseActivity {
-
- public static String photoName;
- ImageView photo;// 显示所拍的照
- ImageView save;// 保留
- ImageView delete;// 删除
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- setContentView(R.layout.confirm);
- setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);// 强制横屏
-
- photo = (ImageView) findViewById(R.id.photo_img);
- save = (ImageView) findViewById(R.id.photo_save);
- // 设置监听,点击后会自动回到相机界面
- save.setOnClickListener(new OnClickListener() {
-
- @Override
- public void onClick(View v) {
- Toast.makeText(ConfirmActivity.this, "照片已保存", Toast.LENGTH_LONG)
- .show();
- startActivity(new Intent(ConfirmActivity.this,
- PhotographActivity.class));
- finish();
- }
- });
-
- delete = (ImageView) findViewById(R.id.photo_delete);
- // 设置监听,点击后会自动回到相机界面
- delete.setOnClickListener(new OnClickListener() {
-
- @Override
- public void onClick(View v) {
- File file = new File(photoName);
- if (file.exists()) {
- file.delete();// 删除照片
- Toast.makeText(ConfirmActivity.this, "照片已删除",
- Toast.LENGTH_LONG).show();
- startActivity(new Intent(ConfirmActivity.this,
- PhotographActivity.class));
- finish();
- }
- }
- });
-
- showPic();// 显示所拍的照片
- }
-
- private void showPic() {
- Intent intent = getIntent();
- Uri originUri = intent.getData();
- photo.setImageURI(originUri);
- }
-
- /**
- * 重写onKeyDown方法,当在相机界面按返回键退到主菜单而不是直接退出程序
- */
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
- startActivity(new Intent(ConfirmActivity.this,
- PhotographActivity.class));
- finish();
- }
- return false;
-
- }
- }
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent" >
-
- <ImageView
- android:id="@+id/photo_img"
- android:layout_width="match_parent"
- android:layout_height="match_parent"/>
-
- <ImageView
- android:id="@+id/photo_delete"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentRight="true"
- android:layout_alignTop="@+id/photo_save"
- android:layout_marginRight="74dp"
- android:src="@drawable/photo_del" />
-
- <ImageView
- android:id="@+id/photo_save"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- android:layout_alignParentLeft="true"
- android:layout_marginBottom="32dp"
- android:layout_marginLeft="68dp"
- android:src="@drawable/photo_save" />
-
- </RelativeLayout>
学识鄙陋,未免贻笑大方,望见谅:)
谢谢。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。