现在手机动不动就能拍月亮,拍黑洞,拍太阳。而,且,它,们,都,是,安,卓,机。
哈哈,这篇文章关于安卓和摄像头的那些事。
归档到多媒体。
Camera
概述
官方都只给了这么一段简单的话,那我好像也多说不出啥。
反正大概就是“我对摄像头的支持很好,提供了很多简单的API给你用”这种感觉。
👇是API文档的传送门:
Android provides full access to the device camera hardware so you can build a wide range of camera or vision-based apps. Or if you just need a way for the user to capture a photo, you can simply request an existing camera app to capture a photo and return it to you.
Android框架支持通过Camera APl或Camera intent来抓取图像和视频
- Camera此类是控制设备相机的主要API,此类用于在创建相机应用时获取图片和视频。
- SurfaceView此类为用户提供camera的实时图像预览 。
- MediaRecorder此类用于从camera录制视频。
- Intent 一个MediaStore.ACTION IMAGE CAPTURE或MediaStore.ACTION_VIDEO_CAPTURE的intent,可以使用它来抓取图像或视频,而不用操作Camera对象。
权限
CameraPermission
你的应用必须请求使用设备相机的取限
<uses-permission android:name="android.permission.CAMERA"/>
CameraFeatures
你的应用必须也要声明要使用的相机特性:
<uses-feature android:name="android.hardware.Camera"/>
如果你的应用要使用相机或相机的一些特性,但又不是必须的,你应该在manifest中指定这些需求,但把android:required属性置为false
<uses-feature android:name="android.hardware.Camera" android:required="false"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
AudioRecording Permission
在使用视频捕获设备来录制音频时,你的应用必须请求音频捕获权限
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
使用现有的相机
一个不用写代码来获取图片和视频的快速方法是使用intent来调用现有的Android camera应用。
一个camera intent调用现存的相机应用抓取图片或视频剪辑然启返回的你的应用。
调用一个相机intent,主要有以下步骤:
- 组建一个相机Intent-创建一个请求图片或视频的Intent,使用以下intent类型中的一个:
- MediaStore.ACTION IMAGE CAPTURE:从已存在的相机应用中请求一个图片。
- MediaStore.ACTION-VIDEO-CAPTURE:从已存在的相机应用中请求一个视频。
- 启动这个相机Intent,使用startActivityForResult()方法来执行相机intent,在你启动intent后,相机应用的界面会出现在设备屏幕上,然后用户就可以用它来获取图片或视频
- 接收Intent结果,在你的应用中设置一个onActivityResult(方法来接收从相机intent来的回调和数据,当用户获取了一个图或视频之后(或取消了操作),系统就会调用此方法。
图像获取Intent
使用相机intent获取图像是使用最少代码获取图像的捷运。
一个图像获取intent包含以下额外信息:
MediaStore.EXTRA-OUTPUT——此设置需要一个Uri对象,这个对象指定了一个保存图像的路径和文件名,此设置是可选的,但是强烈建议使用之。如果你没有指定此值,相机应用就会把图像以默认的名字保存到默认的位置。:
private static final int CAPTURE IMAGE_ACTIVITY REQUEST CODE _100;
private Uri fileUri;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedinstanceState);setContentView(R.layout.main);
//创建一个获取图像的
IntentIntent intent = new Intent(MediaStore.ACTION IMAGE CAPTURE);
//创建一个文件来保存图
fileUri = getoutputMediafileUri(MEDIA TYPE-IMAGE);
//设置图像文件名
intent.putExtra(MediaStore.EXTRA OUTPUT, fileUril;
//开始图像获取
IntentstartActivityForResult(intent, CAPTURE IMAGE ACTIVITY REQUEST CODE);
}
public static final int MEDIA_TYPE_IMAGE = 1, MEDIA_TYPE_VIDEO = 2;
private static Uri getOutputMediaFileUri(int type) {
return Uri.fromFile(getOutputMediaFile(type));
}
private static File getOutputMediaFile(lint type) {
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "MyCameraApp");
if (!mediaStorageDir.exists() {
if (!mediaStorageDir.mkdirs()) {
return null;
}
}
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File mediaFile = null;
if (type == MEDIA_TYPE_IMAGE) {
KmediaFile = new File(mediaStorageDir.getPath() + File.separator + IMG_ + timeStamp + ".jpg");
} else if (type == MEDIA_TYPE_VIDEO) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator + VID + timlstamp + ".mp4" );
} else {
return null;
}
return mediaFile;
}
- 当startActivityForResult()方法被执行,看到一个相机应用的界面
- 当用户获取了一个图像(或取消了操作),用户界面返回到你的应用,
- 你必须拦截onActivityResult()方法来接收intent的结果然后再继续执行你的应用。
拍照实现
关于FileUriExposedException异常可以参考👇
https://blog.csdn.net/nishigesb123/article/details/89514737
需要的权限见上文权限部分内容。
源码:
package com.example.a4_25camera;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.StrictMode;
import android.provider.MediaStore;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import java.io.File;
public class MainActivity extends AppCompatActivity {
//图片类型
private static final int MEDIA_TYPE_IMAGE = 1;
//视频类型
private static final int MEDIA_TYPE_VIDEO = 2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
}
}
//拍照
public void photo(View v) {
Intent intent = new Intent();
intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, getOutputMediaFileUri(MEDIA_TYPE_IMAGE));
startActivityForResult(intent, MEDIA_TYPE_IMAGE);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (resultCode) {
case RESULT_OK:
if (MEDIA_TYPE_IMAGE == requestCode) {
System.out.println(file);
} else if (MEDIA_TYPE_VIDEO == requestCode) {
;
}
break;
}
}
//临时先定义一下
File file = null;
//参数为类型
private Uri getOutputMediaFileUri(int type) {
file = getOutputMediaFile(type);
return Uri.fromFile(file);
}
//获取File
private File getOutputMediaFile(int type) {
File file = null;
//定义目录,两种类型目录应该不一样
String rootPath = null;
switch (type) {
//如果是图片
case MEDIA_TYPE_IMAGE:
rootPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getPath();
file = new File(rootPath + File.separator + System.currentTimeMillis() + ".jpg");
break;
//如果是视频
case MEDIA_TYPE_VIDEO:
rootPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES).getPath();
file = new File(rootPath + File.separator + System.currentTimeMillis() + ".mp4");
break;
}
return file;
}
}
测试效果:
视频获取intent
使用相机intent获取视频是使用最少代码使得你的应用获取视频的捷径。
一个视频获取intent可以包含以下额外信息:
- MediaStore.EXTRA_OUTPUT:此设置需要一个保存视频的路径和文件名的Uri。此设置是可选的但强烈推荐,如果你不指定此值,相机应用就杷请求到的图像以默认的文件名保存到默认的文件夹下,这些信息保存在返回的intent的Intent.getData()字段中。
- MediaStore.EXTRA_ VIDEO_QUALITY:此值在最低质量最小文件R寸时是0,在最高质量最大文件尺寸时是1。
- MediaStore. EXTRA_ DURATION_LIMIT:此值设置获取视频的长度,以秒为单位。
- MediaStore.EXTRA_SIZE_ LIMIT:此值设置获取视频文件的大小,以字节为单位。
private static final int CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE_200;
private Uri fileUri;
@Override
public void onCreate(Bundle savedinstanceState) {
super.onCreate(savedinstanceState);
setContentView(R.layout.main);
Intent intent = new Intent(MediaStore_ACTION_VIDEO_CAPTURE);
fileUri = getOutputMediaFileUri(MEDIA_TYPE_VIDEO);
intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);
startActivityForResult(intent, CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE);
}
视频录制实现
接之前案例源码的基础上进行修改。
package com.example.a4_25camera;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.StrictMode;
import android.provider.MediaStore;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import java.io.File;
public class MainActivity extends AppCompatActivity {
//图片类型
private static final int MEDIA_TYPE_IMAGE = 1;
//视频类型
private static final int MEDIA_TYPE_VIDEO = 2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
}
}
//拍照
public void photo(View v) {
Intent intent = new Intent();
intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, getOutputMediaFileUri(MEDIA_TYPE_IMAGE));
startActivityForResult(intent, MEDIA_TYPE_IMAGE);
}
//录屏
public void video(View v) {
Intent intent = new Intent();
intent.setAction(MediaStore.ACTION_VIDEO_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, getOutputMediaFileUri(MEDIA_TYPE_VIDEO));
intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);
startActivityForResult(intent, MEDIA_TYPE_VIDEO);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (resultCode) {
case RESULT_OK:
if (MEDIA_TYPE_IMAGE == requestCode) {
System.out.println(file);
} else if (MEDIA_TYPE_VIDEO == requestCode) {
System.out.println(file);
System.out.println(data.getData());
}
break;
}
}
//临时先定义一下
File file = null;
//参数为类型
private Uri getOutputMediaFileUri(int type) {
file = getOutputMediaFile(type);
return Uri.fromFile(file);
}
//获取File
private File getOutputMediaFile(int type) {
File file = null;
//定义目录,两种类型目录应该不一样
String rootPath = null;
switch (type) {
//如果是图片
case MEDIA_TYPE_IMAGE:
rootPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getPath();
file = new File(rootPath + File.separator + System.currentTimeMillis() + ".jpg");
break;
//如果是视频
case MEDIA_TYPE_VIDEO:
rootPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES).getPath();
file = new File(rootPath + File.separator + System.currentTimeMillis() + ".mp4");
break;
}
return file;
}
}
效果如👇