Android实现摄像头拍照功能

 更新时间:2018年04月27日 11:33:19   作者:Hoking  
这篇文章主要为大家详细介绍了Android实现摄像头拍照功能,本文侧重摄像头拍照功能的调用,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

应用场景:

在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实现摄像头拍照功能

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

相关文章

  • DatePicker日期滚动选择使用详解

    DatePicker日期滚动选择使用详解

    这篇文章主要为大家详细介绍了DatePicker日期滚动选择的使用方法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-09-09
  • android 解决ViewPager加载大量图片内存溢出问题

    android 解决ViewPager加载大量图片内存溢出问题

    本篇文章是介绍 android 解决ViewPager加载大量图片内存溢出问题,并附有代码实例,希望能帮到有需要的小伙伴
    2016-07-07
  • Android实现文件下载

    Android实现文件下载

    这篇文章主要为大家详细介绍了Android实现文件下载,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-07-07
  • 准确测量 Android 应用中 Activity 和 Fragment 的启动时间的详细过程

    准确测量 Android 应用中 Activity 和 Fragmen

    在 Android 应用开发中,了解每个 Activity 和 Fragment 的启动时间对于性能优化至关重要,本文将介绍几种方法来准确测量 Activity 和 Fragment 的启动时间,并提供实际操作步骤,以帮助提升应用的响应速度和用户体验,需要的朋友可以参考下
    2024-07-07
  • Android实现透明度可变的标题栏效果

    Android实现透明度可变的标题栏效果

    这篇文章主要介绍了Android实现透明度可变的标题栏效果的相关资料,具有一定的参考价值,需要的朋友可以参考下
    2016-02-02
  • Android 接收微信、QQ其他应用打开第三方分享功能

    Android 接收微信、QQ其他应用打开第三方分享功能

    这篇文章主要介绍了Android 接收微信、QQ其他应用打开,第三方分享 ,思路很简单通过在AndroidManifest.xml注册ACTION事件,在用于接收分享的Activity里面加接收代码,感兴趣的朋友可以一起学习下
    2022-11-11
  • Android Bitmap压缩方法的选择详解

    Android Bitmap压缩方法的选择详解

    这篇文章主要介绍了Android Bitmap压缩方法的选择的相关资料,需要的朋友可以参考下
    2016-09-09
  • Android实现颜色选取圆盘

    Android实现颜色选取圆盘

    这篇文章主要为大家详细介绍了Android实现颜色选取圆盘,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-06-06
  • Android 贝塞尔曲线绘制一个波浪球

    Android 贝塞尔曲线绘制一个波浪球

    当 flutter 的现有组件无法满足产品要求的UI效果时,我们就需要通过自绘组件的方式来进行实现了。本文章就来介绍如何用贝塞尔曲线实现一个带文本的波浪球,需要的可以参考一下
    2022-05-05
  • AndroidQ(10)黑暗模式适配的实现

    AndroidQ(10)黑暗模式适配的实现

    这篇文章主要介绍了AndroidQ(10)黑暗模式适配的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-06-06

最新评论