【Android】20.3 拍照和视频录制
分类:C#、Android、VS2015;
创建日期:2016-03-13
一、简介
Android提供的Camera有两个典型的版本,一个是在Android 5.0以前提供的,称为Camera;另一个是从Android 5.0开始提供的,称为Camera2。
这里仅演示使用系统Camera程序实现拍照的基本用法。
二、Camera基本概念
用Camera实现拍照和摄像功能时,有以下两种实现办法:
一是直接利用Intent启动系统自带的Camera App打开相机实现拍照和摄像功能,然后通过Android.Provider命名空间下的.MediaStore类获取拍照或摄像结果保存的文件路径。这是最简单的实现办法,对于一般的需求基本上就能满足要求了。
二是使用Camera API自定义相机,实现专用的拍照和摄像功能。
1、确定是否需要在AndroidMainfest.xml中声明使用照相机.
(1)Camera权限和Camera特性
如果你是调用系统Camera程序,不必声明该权限和特性。
如果你是构造自定义的Camera程序,则必须在AndroidMainfest.xml中声明使用照相机的权限,例如:
<uses-permission android:name="android.permission.CAMERA" />
你还必须在AndroidMainfest.xml中声明照相机特性,例如:
<uses-feature android:name="android.hardware.camera" />
如果你的程序可能需要使用照相机,但并不是一定要使用,那么可以设置android:required属性,比如:
<uses-feature android:name="android.hardware.camera" android:required="false" />
(2)存储权限
如果需要在扩展存储设备上(如sd卡)存储你的照片或者拍摄的视频,那么必须声明如下权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
(3)音频录制权限
如果需要录制音频或者视频,必须在AndroidMainfest.xml文件中设置如下权限:
<uses-permission android:name="android.permission.RECORD_AUDIO" />
2、使用系统Camera程序
这是一种可以让你的程序以最少的编码,然后可以快速使用照相机的方法,此方式通过一个Intent来调用系统的Camera程序,让系统的Camera应用程序去拍摄照片或者录制视频,而且可以返回拍摄或者录制的结果给你自己的应用程序。
(1)基本用法
(a)构造一个Camera Intent -- 创建一个拍摄照片或者视频的Intent,可以使用如下两种方法:
向系统Camera程序请求拍摄图片。例如:
Intent intent = new Intent(MediaStore.ActionImageCapture);
向系统Camera程序请求录制视频。例如:
Intent intent = new Intent(MediaStore.ActionVideoCapture);
(b)开启Camera intent -- 通过调用startActivityForResult()来执行Camera intent, 在你调用这个方法之后,系统Camera程序就是出现在用户界面,然后用户就可以拍摄照片或者视频了。
(c)接收Intent 结果 -- 在你的应用程序里面建立一个OnActivityResult()方法来接收来自系统Camera程序的执行结果。当用户拍摄了照片或者视频(也许取消了拍摄操作),系统就会调用这个方法。
(2)图片拍摄Intent
使用系统Camera来拍摄图片,是一种以最快的速度,最少的代码,让你的程序能够拍照的方法。一个图片拍摄的intent可以包含如下扩展信息:
(a)MediaStore.ExtraOutput -- 指定一个Uri对象,系统Camera程序会把拍摄的图片存储到指定位置。这个设置一般是强烈推荐的。如果你不指定这个Uri路径,那么系统Camera程序会把图片以一个默认的名字存储在一个默认的位置。我们可以通过返回的intent,然后用Intent.GetData()方法来获取这个值。
例如:
private File file;
string dirPath;
string filePath;
……
Intent imageIntent = new Intent(MediaStore.ActionImageCapture);
filePath = dirPath + $"/PP{System.DateTime.Now:yyyyMMdd_hhmmss}.jpg";
file = new File(filePath);
imageIntent.PutExtra(MediaStore.ExtraOutput, Uri.FromFile(file));
StartActivityForResult(imageIntent, 100, savedInstanceState);
当StartActivityForResult()方法执行之后,用户就会看到系统的Camera界面。当用户完成拍摄照片(或者取消拍摄)之后,用户界面就会返回你自己的应用程序。那么你必须拦截OnActivityResult方法,以便接收执行结果和继续你自己代码的逻辑。
(3)视频录制intent
使用系统Camera来录制视频,是一种以最快的速度,最少的代码,让你的程序能够录制视频的方法。一个视频录制的intent可以包含如下扩展信息:
MediaStore.ExtraOutput -- 指定一个Uri对象,系统Camera程序会把录制的视频存储到指定位置。这个设置一般是强烈推荐的。如果你不指定这个Uri路径,那么系统Camera程序会把视频以一个默认的名字存储在默认的位置。可以通过返回的intent,然后用Intent.GetData()方法来获取这个值。
MediaStore.ExtraVideoQuality -- 视频质量,0(低质量,比较小的文件来存储视频), 1(高质量,比较大的文件来存储视频)
MediaStore.ExtraDurationLimit -- 设置一个值来限制视频的录制时间,单位为秒。
MediaStore.ExtraSizeLimit -- 设置一个值来限制视频大小,byte为单位。
当StartActivityForResult()方法执行之后,用户就会看到系统的Camera界面。当用户完成录制视频(或者取消拍摄)之后,用户界面就会返回你自己的应用程序,接下来你就通过重写的OnActivityResult()方法接收执行结果。
(4)接收Camera返回的结果
一旦你执行了拍摄图片或者视频的intent之后,就可以重写OnActivityResult()方法接收执行结果了。得到结果后,存储在指定位置的图片或者视频就能被我们的程序使用了。
3、构造自定义的Camera程序
调用系统Camera App实现拍照和摄像功能虽然能够满足我们的简单需求,但是毕竟自由度降低了,而且拍照的界面就是系统提供的样子。
如果你希望自定义比较漂亮的界面,可以自己定制Camera应用程序制自定义的Camera程序可能比调用系统的Camera需要更多的代码,但是这能给你的用户带来不一样的用户体验。比如Camera 360软件等,就需要根据SDK提供的Camera API来编写自己的程序。
注意:Android已经弃用了5.0之前的版本中提供的Android.Hardware.Camera类,而是改为用Camera2实现,具体用法请参看相关资料。
二、模拟器设置
由于手机自带摄像头,因此可直接使用相机功能。但是,如果你希望在模拟器中测试你的程序,在模拟器中可利用前置相机(Front Camera)来模拟。
下图是Android 4.4.2(Api 19)的模拟器参数设置界面:
将此界面中的【Front Camera】设置为“Emulated”以后,模拟器就会用一个随机移动的矩形来模拟相机的拍照和摄像效果。
下图是Android 6.0(Api 23)的模拟器参数设置界面:
三、示例
在模拟器中运行时,打开相机后,单击下方的圆形按钮即可拍照,拍照的结果保存到SD卡中指定的文件夹下,所拍的图片也会立即在ImageView控件中显示出来,而且还能单独通过Android系统自带的【图库】程序查看拍照的结果。
1、运行截图
下图左侧为初始界面,右侧为单击【拍照】后的拍照界面。
下图左侧为单击圆形拍照按钮后的结果,右侧为对号后显示的文件保存位置。
下面左图为单击【视频录制】后的结果,右图为录制完成后的结果。
2、设计步骤
(1)权限要求
本例子需要在AndroidManifest.xml中添加下面的权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
如果已经有对应的权限就不用再添加了,如果没有就双击Properties文件夹勾选这个权限,让系统自动将其添加到AndroidManifest.xml文件中,或者自己直接将其添加到AndroidManifest.xml文件中。
(2)添加ch2003Main.axml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<Button
android:id="@+id/ch2003_btn1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="拍照" />
<Button
android:id="@+id/ch2003_btn2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="视频录制" />
<TextView
android:text=""
android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/ch2003_textView1" />
<ImageView
android:src="@android:drawable/ic_menu_gallery"
android:layout_width="fill_parent"
android:layout_height="300dp"
android:id="@+id/ch2003_imageView1"
android:adjustViewBounds="true" />
<VideoView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/ch2003_videoView1" />
</LinearLayout>
(3)添加ch2003BitmapHelpers.cs
该文件会自动缩放图片以适应屏幕大小,这是为了解决内存不够时直接加载大图片可能会导致应用程序崩溃的情况。
using Android.Widget;
using Android.Graphics.Drawables;
using Android.Graphics; namespace MyDemos.SrcDemos
{
public static class ch2003BitmapHelpers
{
public static void RecycleBitmap(ImageView imageView)
{
if (imageView == null)
{
return;
} Drawable toRecycle = imageView.Drawable;
if (toRecycle != null)
{
((BitmapDrawable)toRecycle).Bitmap.Recycle();
}
} public static Bitmap LoadAndResizeBitmap(string fileName, int width, int height)
{
BitmapFactory.Options options = new BitmapFactory.Options
{
InPurgeable = true,
InJustDecodeBounds = true
};
BitmapFactory.DecodeFile(fileName, options);
int outHeight = options.OutHeight;
int outWidth = options.OutWidth;
int inSampleSize = 1;
if (outHeight > height || outWidth > width)
{
if(outWidth > outHeight)
{
inSampleSize = outHeight / height;
}
else
{
inSampleSize = outWidth / width;
}
}
options.InSampleSize = inSampleSize;
options.InJustDecodeBounds = false;
Bitmap resizedBitmap = BitmapFactory.DecodeFile(fileName, options);
return resizedBitmap;
}
}
}
(4)添加ch2003MainActivity.cs
using System.Collections.Generic;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Widget;
using Android.Provider;
using Android.Content.PM;
using Android.Graphics; using Android.Net;
using Java.IO; namespace MyDemos.SrcDemos
{
[Activity(Label = "ch2003MainActivity")]
[IntentFilter(new[] { Intent.ActionMain },
Categories = new[] { Intent.CategoryDefault, ch.MyDemosCategory })]
public class ch2003MainActivity : Activity
{
private File file;
string dirPath;
string filePath;
private ImageView imageView1;
private VideoView videoView1;
private TextView textView1;
private MediaType mediaType; protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState); SetContentView(Resource.Layout.ch2003Main);
textView1 = FindViewById<TextView>(Resource.Id.ch2003_textView1);
imageView1 = FindViewById<ImageView>(Resource.Id.ch2003_imageView1);
videoView1 = FindViewById<VideoView>(Resource.Id.ch2003_videoView1);
Button btn1 = FindViewById<Button>(Resource.Id.ch2003_btn1);
Button btn2 = FindViewById<Button>(Resource.Id.ch2003_btn2); //判断相机是否可用(是否有一个App正在准备拍照)
if (IsThereAnAppToTakePictures())
{
dirPath = $"{Environment.ExternalStorageDirectory.Path}/{Environment.DirectoryPictures}/MyDemosPictures";
if (!System.IO.Directory.Exists(dirPath))
{
System.IO.Directory.CreateDirectory(dirPath);
}
btn1.Click += delegate
{
//拍照
mediaType = MediaType.Image;
Intent imageIntent = new Intent(MediaStore.ActionImageCapture);
filePath = dirPath + $"/PP{System.DateTime.Now:yyyyMMdd_hhmmss}.jpg";
file = new File(filePath);
imageIntent.PutExtra(MediaStore.ExtraOutput, Uri.FromFile(file));
StartActivityForResult(imageIntent, 100);
};
btn2.Click += delegate
{
//视频录制
mediaType = MediaType.Video;
Intent videoIntent = new Intent(MediaStore.ActionVideoCapture);
filePath = dirPath + $"/PP{System.DateTime.Now:yyyyMMdd_hhmmss}.mp4";
file = new File(filePath);
videoIntent.PutExtra(MediaStore.ExtraOutput, Uri.FromFile(file));
videoIntent.PutExtra(MediaStore.ExtraVideoQuality, 1);
StartActivityForResult(videoIntent, 200);
};
}
else
{
//如果相机不可用,禁用按钮
btn1.Text = "相机不可用,无法拍照";
btn2.Text = "相机不可用,无法录制视频";
btn1.Enabled = btn2.Enabled = false;
}
} /// <summary>
/// 判断相机是否可用(是否有一个App正在准备拍照)
/// </summary>
/// <returns></returns>
private bool IsThereAnAppToTakePictures()
{
Intent intent = new Intent(MediaStore.ActionImageCapture);
IList<ResolveInfo> availableActivities = PackageManager.QueryIntentActivities(intent, PackageInfoFlags.MatchDefaultOnly);
return availableActivities != null && availableActivities.Count > 0;
} protected override void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data); // 使其可以在图库中可用,即浏览图库时能看到相机拍摄的照片
Intent mediaScanIntent = new Intent(Intent.ActionMediaScannerScanFile);
Uri contentUri = Uri.FromFile(file);
mediaScanIntent.SetData(contentUri);
SendBroadcast(mediaScanIntent); if(mediaType== MediaType.Image)
{
imageView1.Visibility = Android.Views.ViewStates.Visible;
videoView1.Visibility = Android.Views.ViewStates.Gone;
//辅助程序(ch2003BitmapHelpers.cs)会自动缩放该图片以适应屏幕大小。
int width = Resources.DisplayMetrics.WidthPixels;
int height = imageView1.Height;
using (Bitmap bitmap = ch2003BitmapHelpers.LoadAndResizeBitmap(filePath, width, height))
{
ch2003BitmapHelpers.RecycleBitmap(imageView1);
imageView1.SetImageBitmap(bitmap);
imageView1.RefreshDrawableState();
}
textView1.Text = "拍照结果:\n" + filePath;
}
else
{
imageView1.Visibility = Android.Views.ViewStates.Gone;
videoView1.Visibility = Android.Views.ViewStates.Visible;
videoView1.SetVideoURI(Uri.Parse(filePath));
videoView1.SetMediaController(new MediaController(this));
videoView1.Start();
textView1.Text = "视频录制结果:\n" + filePath;
}
}
}
}
【Android】20.3 拍照和视频录制的更多相关文章
- iOS开发系列--音频播放、录音、视频播放、拍照、视频录制
--iOS多媒体 概览 随着移动互联网的发展,如今的手机早已不是打电话.发短信那么简单了,播放音乐.视频.录音.拍照等都是很常用的功能.在iOS中对于多媒体的支持是非常强大的,无论是音视频播放.录制, ...
- iOS开发----音频播放、录音、视频播放、拍照、视频录制
随着移动互联网的发展,如今的手机早已不是打电话.发短信那么简单了,播放音乐.视频.录音.拍照等都是很常用的功能.在iOS中对于多媒体的支持是非常强大的,无论是音视频播放.录制,还是对麦克风.摄像头的操 ...
- 音频播放、录音、视频播放、拍照、视频录制-b
随着移动互联网的发展,如今的手机早已不是打电话.发短信那么简单了,播放音乐.视频.录音.拍照等都是很常用的功能.在iOS中对于多媒体的支持是非常强大的,无论是音视频播放.录制,还是对麦克风.摄像头的操 ...
- iOS音频播放、录音、视频播放、拍照、视频录制
随着移动互联网的发展,如今的手机早已不是打电话.发短信那么简单了,播放音乐.视频.录音.拍照等都是很常用的功能.在iOS中对于多媒体的支持是非常强大的,无论是音视频播放.录制,还是对麦克风.摄像头的操 ...
- android调用系统相机进行视频录制并保存到指定目录
最近在做视频录制上传,调用的是系统的相机. 在做之前查了一些资料,发现好多人遇到保存到指定目录不成功的现象.自己写的时候就注意这些,最后发现他们遇到的问题我这边根本没有.可能是他们写法有问题吧. 下边 ...
- Android截图命令screencap与视频录制命令screenrecord
Android截图命令screencap 查看帮助命令 bixiaopeng@bixiaopeng ~$ adb shell screencap -v screencap: invalid optio ...
- C#视频拍照、视频录制项目示例
1.AForge 2.WPFMediaKit 3.ffmpeg
- 【Android】20.0 第20章 音频、视频、拍照、语音合成
分类:C#.Android.VS2015: 创建日期:2016-03-11 一.简介 Android提供了常见的多媒体文件编码.解码机制,你可以直接调用Android提供的API,实现相册.播放器.录 ...
- 本人讲课时录制的Android应用开发技术教学视频
网盘地址:http://yun.baidu.com/pcloud/album/info?query_uk=1963923831&album_id=3523786484935252365 本人讲 ...
随机推荐
- Python网络爬虫 - 下载图片
下载博客园的logo from urllib.request import urlretrieve from urllib.request import urlopen from bs4 import ...
- php之快速入门学习-15(php函数)
PHP 函数 PHP 的真正威力源自于它的函数. 在 PHP 中,提供了超过 1000 个内建的函数. PHP 内建函数 如需查看所有数组函数的完整参考手册和实例,请访问我们的 PHP 参考手册. P ...
- CSDN日报20170310——《假如我是一行代码》
[程序人生]假如我是一行代码 作者:henry-hacker 我们不止一次在生活中听到"假如我如何如何,我会如何如何"的句式.而这种句式说出来的一般意义无非就是让我们站在还有一个角 ...
- SettingsMyEclipse
迁移时间--2017年5月20日10:39:42 Author:Marydon-----------------------------------MyEclipse单独设置项---------- ...
- map函数原理
# -*- coding: utf-8 -*- #python 27 #xiaodeng #map函数 #map函数会对一个序列对象中的每一个元素应用被传入的函数,并返回一个包含了所有函数调用结果的一 ...
- Java多线程中run(), start(), join(), wait(), yield(), sleep()的使用
Run 每个Thread中需要实现的方法, 如果直接调用的话, 会是和单线程一样的效果, 要另起线程需要使用start(). start 新起线程调用run(). 主线程不等待直接往下执行 Yield ...
- openvpn服务端一键生成windows,macos客户端配置文件
#!/bin/bash #获取参数 while getopts "n:" opt; do case $opt in n) client_name=$OPTARG ;; \?) ;; ...
- NYOJ——————数的长度(斯特林公式的应用)
数的长度 时间限制:3000 ms | 内存限制:65535 KB 难度:1 描述 N!阶乘是一个非常大的数,大家都知道计算公式是N!=N*(N-1)······*2*1.现在你的任务是计算出 ...
- 【LeetCode】130. Surrounded Regions (2 solutions)
Surrounded Regions Given a 2D board containing 'X' and 'O', capture all regions surrounded by 'X'. A ...
- Microsoft Office2003打开office2007文件的补丁
Microsoft office2003打开office2007,不需要安装2007,只需要装一个补丁即可 搜索:office2003打开office2007文件的补丁