应用场景:

在Android开发过程中,有时需要调用手机自身设备的功能,本文侧重摄像头拍照功能的调用。

知识点介绍:

使用权限:调用手机自身设备功能(摄像头拍照功能),应该确保已经在AndroidManifest.xml中正确声明了对摄像头的使用及其它相关的feature。

<!--摄像头权限 -->
 <uses-permission android:name="android.permission.CAMERA" />
 <!--存储权限  SD卡读写权限 -->
 <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
 <!--Camera Feature 声明对camera feature的使用 -->
 <uses-feature android:name="android.hardware.camera" />
 <uses-feature
 android:name="android.hardware.camera.autofocus"
 android:required="false" />
 <!--视频、录音权限  请求音频捕获权限 -->
 <uses-permission android:name="android.permission.RECORD_VIDEO"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>

Class类:

1、 SurfaceView
视图(View)的继承类,这个视图里内嵌了一个专门用于绘制的Surface。你可以控制这个Surface的格式和尺寸。Surfaceview控制这个Surface的绘制位置。
2、 SurfaceHolder
SurfaceHolder是控制surface的一个抽象接口,你可以通过SurfaceHolder来控制surface的尺寸和格式,或者修改surface的像素,监视surface的变化等等,SurfaceHolder是SurfaceView的典型接口。
3、 SurfaceHolder.Callback
用户可以实现此接口接收surface变化的消息。当用在一个SurfaceView 中时,  它只在SurfaceHolder.Callback.surfaceCreated()和SurfaceHolder.Callback.surfaceDestroyed()之间有效。设置Callback的方法是SurfaceHolder.addCallback。

使用方式:

第一步:新建一个Android项目CameraTest,包含两个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:background="#FFFFFF"
 android:layout_height="match_parent"
 tools:context=".MainActivity" >
 <LinearLayout android:layout_height="wrap_content"
 android:layout_width="match_parent">
 <ImageView
 android:id="@+id/main_image"
 android:layout_height="wrap_content"
 android:src="@drawable/ic_launcher"
 android:layout_width="match_parent"/>
 </LinearLayout>
 <LinearLayout
 android:layout_height="wrap_content"
 android:layout_width="match_parent"
 android:layout_alignParentBottom="true"
 android:layout_marginBottom="20dp"
 android:orientation="horizontal">
 <Button android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:layout_weight="1"
 android:id="@+id/main_camera"
 android:text="拍照"/>
 <Button android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:layout_weight="1"
 android:text="退出"
 android:id="@+id/main_quit"/>
 </LinearLayout>
</RelativeLayout>

MainActivity.java

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;

import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;

public class MainActivity extends Activity {

 private Button cameraButton; //拍照按钮
 private Button quitButton; //退出按钮
 private ImageView imageView; //图片显示

 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 initViews();
 }

 private void initViews() {
 imageView = (ImageView) findViewById(R.id.main_image);
// 从本地取图片(在sdcard中获取文件)
 Bitmap bitmap = getLoacalBitmap("/sdcard/mhc.jpg");
 Log.e("msgTag", new File("/sdcard/mhc.jpg").exists()+"==========");
 imageView .setImageBitmap(bitmap); //设置Bitmap
 cameraButton = (Button) findViewById(R.id.main_camera);
 quitButton = (Button) findViewById(R.id.main_quit);
 MainOnClickListener mainOnClickListener = new MainOnClickListener();
 cameraButton.setOnClickListener(mainOnClickListener);
 quitButton.setOnClickListener(mainOnClickListener);
 }

 private class MainOnClickListener implements OnClickListener{

 @Override
 public void onClick(View v) {
 switch (v.getId()) {
 case R.id.main_camera:
 startActivity(new Intent(MainActivity.this, CameraActivity.class));
 break;
 case R.id.main_quit:
 MainActivity.this.finish();
 break;
 default:
 break;
 }
 }
 }

 /**
 * 根据文件路径获取所需要文件,并将该文件封装成Bitmap对象返回
 * @param fileUrl
 * @return
 */
 public static Bitmap getLoacalBitmap(String fileUrl) {
 try {
 FileInputStream fis = new FileInputStream(fileUrl);
 return BitmapFactory.decodeStream(fis); ///把流转化为Bitmap图片
 } catch (FileNotFoundException e) {
 e.printStackTrace();
 return null;
 }
 }
}

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:layout_height="match_parent"
 android:background="#FFFFFF"
 tools:context=".CameraActivity" >

 <LinearLayout
 android:layout_width="match_parent"
 android:layout_height="match_parent" >
 <SurfaceView
 android:id="@+id/camera_preview"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:layout_gravity="center_vertical|center_horizontal" />
 </LinearLayout>
 <LinearLayout
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:layout_alignParentBottom="true">
 <Button
 android:id="@+id/camera_save"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:text="拍照" />
 </LinearLayout>
</RelativeLayout> 

CameraActivity.java

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import android.graphics.ImageFormat;
import android.hardware.Camera;
import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class CameraActivity extends Activity {
 private String tag ="CameraActivity";
 private SurfaceView surfaceView;
 //Surface的控制器
 private SurfaceHolder surfaceHolder;
 private Camera camera;
 private Button saveButton;
 //拍照的回调接口
 private Camera.PictureCallback pictureCallback = new Camera.PictureCallback() {
 public void onPictureTaken(byte[] data, Camera camera) {
 new SavePictureTask().execute(data);
 camera.startPreview();
 }
 };

 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_camera);
 initViews();
 }

 private void initViews() {
 saveButton = (Button) findViewById(R.id.camera_save);
 surfaceView = (SurfaceView) findViewById(R.id.camera_preview);
 surfaceHolder = surfaceView.getHolder();
 // 给SurfaceView当前的持有者 SurfaceHolder 一个回调对象。
 //用户可以实现此接口接收surface变化的消息。当用在一个SurfaceView 中时,
 //它只在SurfaceHolder.Callback.surfaceCreated()和SurfaceHolder.Callback.surfaceDestroyed()之间有效。
 //设置Callback的方法是SurfaceHolder.addCallback.
 //实现过程一般继承SurfaceView并实现SurfaceHolder.Callback接口
 surfaceHolder.addCallback(surfaceCallback);
 // 设置surface不需要自己的维护缓存区
 surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
 saveButton.setOnClickListener(new OnClickListener() {

 @Override
 public void onClick(View v) {
 camera.takePicture(null, null, pictureCallback);
// Camera.takePicture(shutterCallback,rawCallback,pictureCallback );
// private ShutterCallback shutterCallback = new ShutterCallback(){
//  public void onShutter(){
//  /* 按快门瞬间会执行这里的代码 */
//  }
//  };
// private PictureCallback rawCallback = new PictureCallback(){
//  public void onPictureTaken(byte[] _data, Camera _camera){
//  /* 如需要处理 raw 则在这里 写代码 */
//  }
//  };
//  //当拍照后 存储JPG文件到 sd卡
//  PictureCallback pictureCallback=new PictureCallback(){
//  public void onPictureTaken(byte[] data,Camera camera) {
//  FileOutputStream outSteam=null;
//  try{
//  SimpleDateFormat format=new SimpleDateFormat("yyyyMMddHHmmss");
//  String times=format.format((new Date()));
//  outSteam=new FileOutputStream("/sdcard/"+times+"mhc.jpg");
//  outSteam.write(data);
//  outSteam.close();
//  }catch(FileNotFoundException e){
//  Log.d("Camera", "row");
//  } catch (IOException e) {
//  e.printStackTrace();
//  }
//  };
//  };
 }
 });
 }


 //SurfaceView当前的持有者的回调接口的实现
 SurfaceHolder.Callback surfaceCallback = new SurfaceHolder.Callback() {

 @Override
 public void surfaceCreated(SurfaceHolder holder) {
 camera = Camera.open();
 Log.e(tag, "摄像头Open完成");
 try {
 camera.setPreviewDisplay(holder);
 } catch (IOException e) {
 camera.release();
 camera = null;
 }
 }

 @Override
 public void surfaceChanged(SurfaceHolder holder, int format, int width,
 int height) {
 Camera.Parameters parameters = camera.getParameters();
 parameters.setPictureFormat(ImageFormat.JPEG);
 camera.setDisplayOrientation(0);
 camera.setParameters(parameters);
 camera.startPreview();
 }

 @Override
 public void surfaceDestroyed(SurfaceHolder holder) {
 camera.stopPreview();
 camera.release();
 camera = null;
 }
 };

 class SavePictureTask extends AsyncTask<byte[], String, String> {
 @Override
 protected String doInBackground(byte[]... params) {
 File picture = new File("/sdcard/mhc.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;
 }
 }
}

下载地址:Android实现摄像头拍照功能

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

02-08 14:41