• Android 调用摄像头功能【拍照与视频】


    版权声明:本文为博主原创文章,未经博主同意不得转载。 https://blog.csdn.net/ma_hoking/article/details/28292973

    应用场景:

    在Android开发过程中,有时须要调用手机自身设备的功能,上篇文章主要側重摄像头拍照功能的调用。本篇文章将综合实现拍照与视频的操作。

    知识点介绍:

    该部分请阅读 【Android 调用摄像头功能】

    使用方式:

    第一步:

    新建一个Android项目CameraPhotoVedio,包括两个Activity: MainActivity、CameraActivity。

    第二步:
    【activity_main.xml】

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/shape_main"
        tools:context=".MainActivity" >
    
        <LinearLayout android:layout_height="wrap_content"
            android:layout_marginTop="50dp"
            android:layout_width="match_parent"
            android:orientation="vertical">
            <ImageView android:layout_height="wrap_content"
                android:layout_width="wrap_content"
                android:layout_gravity="center"
                android:src="@drawable/main"/>
        </LinearLayout>
        <LinearLayout android:layout_height="wrap_content"
            android:layout_marginTop="100dp"
            android:layout_width="match_parent"
            android:layout_alignParentBottom="true"
            android:orientation="vertical">
            <Button
                android:id="@+id/main_button"
                android:layout_height="50dp"
                android:layout_marginBottom="50dp"
                android:background="@drawable/shape_main"
                android:layout_width="match_parent"
                android:textColor="#FFFFFF"
                android:text="使用摄像头"/>
        </LinearLayout>
    </RelativeLayout>
    【MainActivity.java】

    import android.os.Bundle;
    import android.app.Activity;
    import android.content.Intent;
    import android.view.Menu;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    
    public class MainActivity extends Activity {
    
    	private Button button; //调用摄像头按钮
    	
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_main);
    		initViews();
    	}
    
    	private void initViews() {
    		button = (Button) findViewById(R.id.main_button);
    		button.setOnClickListener(new OnClickListener() {
    			
    			@Override
    			public void onClick(View v) {
    				startActivity(new Intent(getApplicationContext(), CameraActivity.class));
    			}
    		});
    	}
    }

    【activity_camera.xml】

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:background="#FFFFFF"
        android:layout_height="match_parent"
        tools:context=".CameraActivity" >
        <SurfaceView 
            android:layout_width="match_parent"
        	android:layout_height="match_parent"
        	android:id="@+id/camera_surfaceview"/>
    	<TextView android:layout_height="wrap_content"
    	    android:layout_width="wrap_content"
    	    android:text="计时区域"
    	    android:id="@+id/camera_time"/>
    	<LinearLayout android:layout_height="wrap_content"
    	    android:layout_width="match_parent"
    	    android:layout_alignParentBottom="true"
    	    android:orientation="horizontal">
    	    <Button android:layout_height="30dp"
    	        android:layout_width="match_parent"
    	        android:layout_marginBottom="20dp"
    	        android:layout_weight="1"
    	        android:background="@drawable/shape_main"
    	        android:id="@+id/camera_photo"
    	        android:layout_marginLeft="5dp"
    	        android:textColor="#FFFFFF"
    	        android:layout_marginRight="5dp"
    	        android:text="照片摄取"/>
    	    <Button android:layout_height="30dp"
    	        android:layout_marginBottom="20dp"
    	        android:layout_width="match_parent"
    	        android:layout_weight="1"
    	        android:background="@drawable/shape_main"
    	        android:id="@+id/camera_vedio"
    	        android:layout_marginLeft="5dp"
    	        android:textColor="#FFFFFF"
    	        android:layout_marginRight="5dp"
    	        android:text="视频摄取"/>
    	</LinearLayout>
    </RelativeLayout>

    【CameraActivity.java】

    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.util.Date;
    
    import com.example.cameraphotovideo.utils.FormatUtil;
    
    import android.graphics.ImageFormat;
    import android.hardware.Camera;
    import android.hardware.Camera.PictureCallback;
    import android.media.MediaRecorder;
    import android.os.AsyncTask;
    import android.os.Bundle;
    import android.os.Environment;
    import android.os.Handler;
    import android.app.Activity;
    import android.util.Log;
    import android.view.SurfaceHolder;
    import android.view.SurfaceHolder.Callback;
    import android.view.SurfaceView;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.TextView;
    
    public class CameraActivity extends Activity {
    
    	private String tag ="MaHaochen_______CameraActivity";
    	private SurfaceView surfaceView;
    	private SurfaceHolder surfaceHolder;
    	private Camera camera;
    	private MediaRecorder mediaRecorder;
    	private Button photoButton;  //拍照按钮
    	private Button vedioButton;  //摄像按钮 
    	private TextView timeTextView;
    	
    	protected boolean isPreview = false; //摄像区域是否准备良好
    	private boolean isRecording = true; // true表示没有录像,点击開始。false表示正在录像,点击暂停
    	private boolean bool;
    	
    	private int hour = 0;
    	private int minute = 0;     //计时专用
    	private int second = 0;
    	
    	private File mRecVedioPath;
    	private File mRecAudioFile;
    	
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_camera);
    		initCamera();
    		initViews();
    	}
    	//初始化摄像头
    	private void initCamera() {
    		mRecVedioPath = new File(Environment.getExternalStorageDirectory()
    				.getAbsolutePath() + "/mahc/video/temp/");
    		if (!mRecVedioPath.exists()) {
    			mRecVedioPath.mkdirs();
    		}
    		surfaceView = (SurfaceView) findViewById(R.id.camera_surfaceview);
    		SurfaceHolder cameraSurfaceHolder = surfaceView.getHolder();
    		cameraSurfaceHolder.addCallback(new Callback() {
    			
    			@Override
    			public void surfaceCreated(SurfaceHolder holder) {
    				try {
    				camera = Camera.open();
    				//设置Camera的角度/方向
    				camera.setDisplayOrientation(90);
    				Camera.Parameters parameters = camera.getParameters();
    				parameters.setPreviewFrameRate(5); // 每秒5帧
    				parameters.setPictureFormat(ImageFormat.JPEG);// 设置照片的输出格式
    				parameters.set("jpeg-quality", 85);// 照片质量
    				camera.setParameters(parameters);
    				camera.setPreviewDisplay(holder);
    				isPreview = true;
    				camera.startPreview();
    				} catch (IOException e) {
    					e.printStackTrace();
    				}
    				surfaceHolder = holder;
    			}
    			
    			@Override
    			public void surfaceChanged(SurfaceHolder holder, int format, int width,
    					int height) {
    				surfaceHolder = holder;
    			}
    			
    			@Override
    			public void surfaceDestroyed(SurfaceHolder holder) {
    				if (camera != null) {
    					if (isPreview) {
    						camera.stopPreview();
    						isPreview = false;
    					}
    					camera.release();
    					camera = null; // 记得释放Camera
    				}
    				surfaceView = null;
    				surfaceHolder = null;
    				mediaRecorder = null;
    			}
    		});
    		//开发时建议设置
    		//This method was deprecated in API level 11. this is ignored, this value is set automatically when needed. 
    		cameraSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    	}
    	
    	//初始化视图组件
    	private void initViews() {
    		timeTextView = (TextView) findViewById(R.id.camera_time);
    		timeTextView.setVisibility(View.GONE);
    		photoButton = (Button) findViewById(R.id.camera_photo);
    		vedioButton = (Button) findViewById(R.id.camera_vedio);
    		ButtonOnClickListener onClickListener = new ButtonOnClickListener();
    		photoButton.setOnClickListener(onClickListener);
    		vedioButton.setOnClickListener(onClickListener);
    	}
    	
    	class ButtonOnClickListener implements OnClickListener{
    
    		@Override
    		public void onClick(View v) {
    			switch (v.getId()) {
    			case R.id.camera_vedio:
    				//点击開始录像
    				if(isRecording){
    					if (isPreview) {
    						camera.stopPreview();
    						camera.release();
    						camera = null;
    					}
    					second = 0;
    					minute = 0;
    					hour = 0;
    					bool = true;
    					if(null==mediaRecorder){
    						mediaRecorder = new MediaRecorder();
    					}else {
    						mediaRecorder.reset();
    					}
    					//表面设置显示记录媒体(视频)的预览
    					mediaRecorder.setPreviewDisplay(surfaceHolder.getSurface());
    					//開始捕捉和编码数据到setOutputFile(指定的文件)
    					mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
    					//设置用于录制的音源
    					mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
    					//设置在录制过程中产生的输出文件的格式
    					mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
    					//设置视频编码器,用于录制
    					mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
    					//设置audio的编码格式
    					mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
    					//设置要捕获的视频的宽度和高度
    					mediaRecorder.setVideoSize(320, 240);
    					// 设置要捕获的视频帧速率
    					mediaRecorder.setVideoFrameRate(15);
    					try {
    						mRecAudioFile = File.createTempFile("Vedio", ".3gp",
    								mRecVedioPath);
    					} catch (IOException e) {
    						e.printStackTrace();
    					}
    					mediaRecorder.setOutputFile(mRecAudioFile.getAbsolutePath());
    					try {
    						mediaRecorder.prepare();
    						timeTextView.setVisibility(View.VISIBLE);
    						handler.postDelayed(task, 1000);
    						mediaRecorder.start();
    					} catch (Exception e) {
    						e.printStackTrace();
    					}
    					isRecording = !isRecording;
    					Log.e(tag, "=====開始录制视频=====");
    				}else {
    					//点击停止录像
    					bool = false;
    					mediaRecorder.stop();
    					timeTextView.setText(FormatUtil.format(hour)+":"+FormatUtil.format(minute)+":"+ FormatUtil.format(second));
    					mediaRecorder.release();
    					mediaRecorder = null;
    					FormatUtil.videoRename(mRecAudioFile);
    					Log.e(tag, "=====录制完毕,已保存=====");
    					isRecording = !isRecording;
    					try {
    						camera = Camera.open();
    						Camera.Parameters parameters = camera.getParameters();
    //						parameters.setPreviewFrameRate(5); // 每秒5帧
    						parameters.setPictureFormat(ImageFormat.JPEG);// 设置照片的输出格式
    						parameters.set("jpeg-quality", 85);// 照片质量
    						camera.setParameters(parameters);
    						camera.setPreviewDisplay(surfaceHolder);
    						camera.startPreview();
    						isPreview = true;
    					} catch (Exception e) {
    						e.printStackTrace();
    					}
    				}
    				break;
    
    			case R.id.camera_photo:
    				if (mediaRecorder != null) {
    					try {
    						bool = false;
    						mediaRecorder.stop();
    						timeTextView.setText(FormatUtil.format(hour) + ":" + FormatUtil.format(minute) + ":"
    								+ FormatUtil.format(second));
    						mediaRecorder.release();
    						mediaRecorder = null;
    						FormatUtil.videoRename(mRecAudioFile);
    					} catch (Exception e) {
    						e.printStackTrace();
    					}
    					isRecording = !isRecording;
    					Log.e(tag, "=====录制完毕,已保存=====");
    					try {
    						camera = Camera.open();
    						Camera.Parameters parameters = camera.getParameters();
    //						parameters.setPreviewFrameRate(5); // 每秒5帧
    						parameters.setPictureFormat(ImageFormat.JPEG);// 设置照片的输出格式
    						parameters.set("jpeg-quality", 85);// 照片质量
    						camera.setParameters(parameters);
    						camera.setPreviewDisplay(surfaceHolder);
    						camera.startPreview();
    						isPreview = true;
    					} catch (Exception e) {
    						e.printStackTrace();
    					}
    				}
    				if (camera != null) {
    					camera.autoFocus(null);
    					camera.takePicture(null, null, new PictureCallback() {
    						@Override
    						public void onPictureTaken(byte[] data, Camera camera) {
    							new SavePictureTask().execute(data);
    							camera.startPreview();
    							Log.e(tag,"=====拍照成功=====");
    						}
    					}); // 拍照
    				}
    				break;
    			default:
    				break;
    			}
    		}
    	}
    	/*
    	 * 定时器设置,实现计时
    	 */
    	private Handler handler = new Handler();
    	private Runnable task = new Runnable() {
    		public void run() {
    			if (bool) {
    				handler.postDelayed(this, 1000);
    				second++;
    				if (second >= 60) {
    					minute++;
    					second = second % 60;
    				}
    				if (minute >= 60) {
    					hour++;
    					minute = minute % 60;
    				}
    				timeTextView.setText(FormatUtil.format(hour) + ":" + FormatUtil.format(minute) + ":"
    						+ FormatUtil.format(second));
    			}
    		}
    	};
    	
    	
    	
    	class SavePictureTask extends AsyncTask<byte[], String, String> {
    		@Override
    		protected String doInBackground(byte[]... params) {
    			String path = Environment.getExternalStorageDirectory()
    					.getAbsolutePath() + "/mahc/image";
    			File out = new File(path);
    			if (!out.exists()) {
    				out.mkdirs();
    			}
    			File picture = new File(path+"/"+new Date().getTime()+".jpg");
    			try {
    				FileOutputStream fos = new FileOutputStream(picture.getPath());
    				fos.write(params[0]);
    				fos.close();
    			} catch (Exception e) {
    				e.printStackTrace();
    			}
    			Log.e(tag, "=====照片保存完毕=====");
    			CameraActivity.this.finish();
    			return null;
    		}
    	}
    }

    第三步:该项目须要一个工具类FormatUtil.java

    import java.io.File;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    import android.os.Environment;
    
    public class FormatUtil {
    
    	/**
    	 * 将缓存目录的数据转存到vedio文件下
    	 * @param recAudioFile
    	 */
    	public static void videoRename(File recAudioFile) {
    		String path = Environment.getExternalStorageDirectory()
    				.getAbsolutePath()+ "/mahc/video/"+ "0" + "/";
    		String fileName = new SimpleDateFormat("yyyyMMddHHmmss")
    				.format(new Date()) + ".3gp";
    		File out = new File(path);
    		if (!out.exists()) {
    			out.mkdirs();
    		}
    		out = new File(path, fileName);
    		if (recAudioFile.exists())
    			recAudioFile.renameTo(out);
    	}
    	
    	/**
    	 * 用以计时操作的相关方法
    	 * @param num
    	 * @return
    	 */
    	public static String format(int num){
    		String s = num + "";
    		if (s.length() == 1) {
    			s = "0" + s;
    		}
    		return s;
    	}
    }


    第四步:本项目须要处理界面的背景样式和按钮的背景,所以须要在res/drawable文件新建shape_main.xml。

    <?xml version="1.0" encoding="utf-8"?>
    <shape xmlns:android="http://schemas.android.com/apk/res/android">
        <gradient
            android:startColor="#FFCC99"
            android:endColor="#99CC66"
            android:centerColor="#0066CC"
            android:angle="45" />
    </shape>

    页面效果:

    效果截图



    下载地址:

    该资源正在审核中,敬请期待!                          点此下载资源!


  • 相关阅读:
    结队完成-连续最大子数组和
    一、数据库的基础简介
    十六、Shell之expect自动化交互程
    十五、Shell之数组
    十四、循环控制
    十三、Shell之select语句
    Linux系统产生随机数的6种方法
    十二、Shell之for循环
    十一、Shell之while&&until循环
    Shell补充之后台执行脚本程序
  • 原文地址:https://www.cnblogs.com/ldxsuanfa/p/10966514.html
  • Copyright © 2020-2023  润新知