57. 【Android教程】相机:Camera

2024-05-09 04:44
文章标签 android 教程 相机 camera 57

本文主要是介绍57. 【Android教程】相机:Camera,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

相机现在已经不仅仅是手机必备神器了,甚至相机的拍照质量已经是很多人买手机的首选条件了。而对于相机而言主要有两大功能:拍照片和拍视频。Android 为此两种方式:

  • 相机 intent
  • 相机 API
    本节我们就一起来看看相机的具体用法。

1. 打开 Camera 的两大方式

目前市面上绝大多数的 Android 手机是有前后两个摄像头,当然有部分特殊机型会存在其他的情况,本节主要针对双摄像头设备做解析。
在前面有提到过,通常使用相机有两大方式:“Intent”和“API”。最大的差别就是“Intent”是跳转到系统提供的相机页面,而使用“API”是封闭在自己的 App 中使用相机。我们可以通过“Intent”直接打开系统提供的相机 Activity,在用户拍摄完成之后系统 Activity 会通知我们拍摄结果,然后拿到拍摄的图片或者视频。而直接通过 API 就需要我们去开发一整套相机的控制页面,自行完成照片 / 视频的拍摄进而直接拿到用户拍摄的结果。

2. Camera 的基本用法

我们分别看看这两种打开方式的使用方法:

2.1 使用 Intent 打开

通过使用 MediaStore 类提供的两个 Intnet 常量,可以直接将相机操作托管给 Android 系统而无需创建 Camera 实例:

  • ACTION_IMAGE_CAPTURE:
    拍摄照片
  • ACTION_VIDEO_CAPTURE:
    拍摄视频

2.2 使用 API 打开

采用 API 打开会让整个相机程序都封闭在自己的 APP 中完成,这里需要明确几个概念:

  1. Camera 类
    使用 API 之前需要创建 Camera 实例,然后通过 API 来初始化 Camera 进而拿到实时拍摄的画面

  2. SurfaceView
    用来渲染视频实时画面的 View

采用 Intent 打开相机的方法非常简单,接下来我们全程使用 Camera API 来实现一下相机功能。

3. Camera 使用示例

使用 API 来拍照会相对比较麻烦一点,首先需要获取权限,那么对于 Android 6.0 版本以上的系统除了要在 Manifest 里面加入 Camera 权限之外,还需要动态获取权限,这个可能大家在用一些比较老的教程示例时会踩坑。
获取到权限就可以打开 Camera 了,然后拿到 Camera 实例设置一个 SurfaceView 来渲染预览页面,在用户需要拍照的时候调用 Camera 的takePicture()方法获取当前帧,最后保存输出到文件中或者在新的 Activity 中展示,这样就算完成了一次拍照闭环。

3.1 Camera 拍照逻辑

首先看看整个拍照的代码如下:


package com.emercy.myapplication;import android.Manifest;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;public class MainActivity extends Activity {public static final String CAMERA_PATH = "path";public static final String CAMERA_IMG = "img";private SurfaceView mSurfaceView;private Button mTakePhoto;private Camera mCamera = null;private SurfaceHolder.Callback mCallback = new SurfaceHolder.Callback() {@Overridepublic void surfaceCreated(SurfaceHolder holder) {startPreview();}@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {stopPreview();}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);getPermission();bindViews();}/*** 获取权限*/private void getPermission() {if (Build.VERSION.SDK_INT > 22) {if (checkSelfPermission(android.Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {//先判断有没有权限 ,没有就在这里进行权限的申请requestPermissions(new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 100);} else {//说明已经获取到摄像头权限了Log.i("Camera", "已经获取了权限");}} else {//这个说明系统版本在6.0之下,不需要动态获取权限。Log.i("Camera", "这个说明系统版本在6.0之下,不需要动态获取权限。");}}private void bindViews() {mSurfaceView = (SurfaceView) findViewById(R.id.sfv_preview);mTakePhoto = (Button) findViewById(R.id.btn_take);mSurfaceView.getHolder().addCallback(mCallback);mTakePhoto.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {mCamera.takePicture(null, null, new Camera.PictureCallback() {@Overridepublic void onPictureTaken(byte[] data, Camera camera) {String path;if (TextUtils.isEmpty(path = savePhoto(data))) {Intent it = new Intent(MainActivity.this, PreviewActivity.class);it.putExtra(CAMERA_PATH, path);startActivity(it);} else {Toast.makeText(MainActivity.this, "拍照失败", Toast.LENGTH_SHORT).show();}}});}});}private String savePhoto(byte[] bytes) {try {File file = File.createTempFile(CAMERA_IMG, "");FileOutputStream fos = new FileOutputStream(file);fos.write(bytes);fos.flush();fos.close();return file.getAbsolutePath();} catch (IOException e) {e.printStackTrace();}return "";}private void startPreview() {mCamera = Camera.open();try {mCamera.setPreviewDisplay(mSurfaceView.getHolder());mCamera.setDisplayOrientation(90);   // 让相机旋转90度mCamera.startPreview();} catch (IOException e) {e.printStackTrace();}}private void stopPreview() {mCamera.stopPreview();mCamera.release();mCamera = null;}
}

里面涉及到的几个新概念大家需要注意,然后记得在SurfaceHolder.Callback()surfaceCreated()中启动预览,在surfaceDestroyed()方法中要停止预览,其他的基本上按照步骤来不会有什么问题。

3.2 相机布局

目前市面上有很多相机 App,各种布局千变万化,大家完全可以按照自己的喜好来进行设计。这里只做一个拍照预览和拍照按钮。

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><SurfaceViewandroid:id="@+id/sfv_preview"android:layout_width="match_parent"android:layout_height="match_parent" /><Buttonandroid:id="@+id/btn_take"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="bottom|center"android:text="拍照" /></FrameLayout>

3.3 照片回看页面

点击“拍照” Button 获取到当前画面之后,我们可以就可以按照自己的逻辑对图片进行操作了。比如可以通过 Http 上传、通过 Socket 发送给其他设备、保存到本地、或者传递给其他 App 等。本例子中将图片传递给另一个 Activity 专门用于查看图片,下面是 PhotoActivity 的代码:

package com.emercy.myapplication;import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;
import android.widget.ImageView;import java.io.File;import static com.emercy.myapplication.MainActivity.CAMERA_PATH;public class PhotoActivity extends Activity {@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);ImageView img = new ImageView(this);String path = getIntent().getStringExtra(CAMERA_PATH);if (path != null) {img.setImageURI(Uri.fromFile(new File(path)));}setContentView(img);}
}

通过 Intent 接收图片路径,然后展示在 ImageView 上,需要注意的是PhotoActivity 中是直接将 ImageView 作为参数直接设置给了 SetContentView(),这样相当于布局文件中只有一个 ImageView 的写法。

最后别忘了在 Manifest 当中添加权限:

    <uses-permission android:name="android.permission.CAMERA"/><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

编译运行效果如下:

点击拍照进入 PhotoActivity,展示的就是我们拍照的画面。

4. 小结

本节学习了一个手机上必不可少的设备,通过相机我们可以拍摄照片或者视频,Android 系统提供了两大打开方式:Intent 调用系统相机 Activitiy或者用 Camera API 自行实现拍照功能。第一种非常简单,将所有的相机操作都托管给系统,我们只关心最终用户拍摄的结果;而第二种就需要我们自己初始化 Camera 对象从而实现拍摄,在实际开发中如果你的功能是和拍摄强相关,需要一些定制化的拍摄体验,那么一定要使用第二种方式来自己实现 Camera,但是如果你只是一个简单的拍照获取图片,那么第一种会让你事半功倍。

这篇关于57. 【Android教程】相机:Camera的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/972426

相关文章

Nexus安装和启动的实现教程

《Nexus安装和启动的实现教程》:本文主要介绍Nexus安装和启动的实现教程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、Nexus下载二、Nexus安装和启动三、关闭Nexus总结一、Nexus下载官方下载链接:DownloadWindows系统根

CnPlugin是PL/SQL Developer工具插件使用教程

《CnPlugin是PL/SQLDeveloper工具插件使用教程》:本文主要介绍CnPlugin是PL/SQLDeveloper工具插件使用教程,具有很好的参考价值,希望对大家有所帮助,如有错... 目录PL/SQL Developer工具插件使用安装拷贝文件配置总结PL/SQL Developer工具插

Java中的登录技术保姆级详细教程

《Java中的登录技术保姆级详细教程》:本文主要介绍Java中登录技术保姆级详细教程的相关资料,在Java中我们可以使用各种技术和框架来实现这些功能,文中通过代码介绍的非常详细,需要的朋友可以参考... 目录1.登录思路2.登录标记1.会话技术2.会话跟踪1.Cookie技术2.Session技术3.令牌技

Android学习总结之Java和kotlin区别超详细分析

《Android学习总结之Java和kotlin区别超详细分析》Java和Kotlin都是用于Android开发的编程语言,它们各自具有独特的特点和优势,:本文主要介绍Android学习总结之Ja... 目录一、空安全机制真题 1:Kotlin 如何解决 Java 的 NullPointerExceptio

Python使用Code2flow将代码转化为流程图的操作教程

《Python使用Code2flow将代码转化为流程图的操作教程》Code2flow是一款开源工具,能够将代码自动转换为流程图,该工具对于代码审查、调试和理解大型代码库非常有用,在这篇博客中,我们将深... 目录引言1nVflRA、为什么选择 Code2flow?2、安装 Code2flow3、基本功能演示

Java Spring 中的监听器Listener详解与实战教程

《JavaSpring中的监听器Listener详解与实战教程》Spring提供了多种监听器机制,可以用于监听应用生命周期、会话生命周期和请求处理过程中的事件,:本文主要介绍JavaSprin... 目录一、监听器的作用1.1 应用生命周期管理1.2 会话管理1.3 请求处理监控二、创建监听器2.1 Ser

MySQL 安装配置超完整教程

《MySQL安装配置超完整教程》MySQL是一款广泛使用的开源关系型数据库管理系统(RDBMS),由瑞典MySQLAB公司开发,目前属于Oracle公司旗下产品,:本文主要介绍MySQL安装配置... 目录一、mysql 简介二、下载 MySQL三、安装 MySQL四、配置环境变量五、配置 MySQL5.1

MQTT SpringBoot整合实战教程

《MQTTSpringBoot整合实战教程》:本文主要介绍MQTTSpringBoot整合实战教程,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考... 目录MQTT-SpringBoot创建简单 SpringBoot 项目导入必须依赖增加MQTT相关配置编写

在Java中基于Geotools对PostGIS数据库的空间查询实践教程

《在Java中基于Geotools对PostGIS数据库的空间查询实践教程》本文将深入探讨这一实践,从连接配置到复杂空间查询操作,包括点查询、区域范围查询以及空间关系判断等,全方位展示如何在Java环... 目录前言一、相关技术背景介绍1、评价对象AOI2、数据处理流程二、对AOI空间范围查询实践1、空间查

Logback在SpringBoot中的详细配置教程

《Logback在SpringBoot中的详细配置教程》SpringBoot默认会加载classpath下的logback-spring.xml(推荐)或logback.xml作为Logback的配置... 目录1. Logback 配置文件2. 基础配置示例3. 关键配置项说明Appender(日志输出器