Android学习十---Android Camera
Android camera用来拍照和拍摄视频的先看一下最后实现的效果图
最后的效果图
一、准备
在你的应用程序上使用android拍照设备,需要考虑以下几个方面
1. 是否是一定需要camera
如果需要,那么就无法安装在没有摄像头的设备。
需要在mainfest 中声明
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
2. 是想用怎样的方式来使用相机
可以有两种方式
2.1 简单的拍照 使用已经存在camera apps
2.2 需要更多定制的功能,创建一个camera app
3. 存储方式
是只能在本应用程序里使用还是可以被其他程序使用。
二、相关类
android.hardware.camera2
包中包含控制设备相机的基本类
Camera
过时不用的相机控制类
SurfaceView
提供实时的相机预览
MediaRecorder
用来记录video
Intent
使用
MediaStore.ACTION_IMAGE_CAPTURE
MediaStore.ACTION_VIDEO_CAPTURE
两个Intent类型来捕获图像和视频
三、Manifest声明
camera许可
<uses-permission android:name="android.permission.CAMERA" />
camera特征
<uses-feature android:name="android.hardware.camera" />
存储许可
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
音视频录制
<uses-permission android:name="android.permission.RECORD_AUDIO" />
位置许可
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
四、使用已经存在的camera apps
使用方式是用Intent,使用Intent能够使用最少的代码来获取图片
流程主要是
创建一个camera Intent,Intent的类型包括,MediaStore.ACTION_IMAGE_CAPTURE
,
启动一个camera Intent,使用startActivityForResult()方法来执行一个camera intent,在启动Intent后,camera应用界面能够显示在设备屏幕来供使用MediaStore.ACTION_VIDEO_CAPTURE
接受Intent的结果,使用onActivityResult()方法来接受Intent的回调和数据。当用户结束拍照后,系统调用这一方法。
下列代码显示如何创建一个camera intent并执行
private static final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 100;
private Uri fileUri; @Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main); // create Intent to take a picture and return control to the calling application
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE); // create a file to save the image
intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri); // set the image file name // start the image capture Intent
startActivityForResult(intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);
}
接收camera intent的结果,主要是重载onActivityResult。
private static final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 100;
private static final int CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE = 200; @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
// Image captured and saved to fileUri specified in the Intent
Toast.makeText(this, "Image saved to:\n" +
data.getData(), Toast.LENGTH_LONG).show();
} else if (resultCode == RESULT_CANCELED) {
// User cancelled the image capture
} else {
// Image capture failed, advise user
}
}
}
!一但程序接受到一个成功的结果,那么应用程序就可以获取在指定路径下的图片。
五、创建一个Camera App
官方建议使用新的android.hardware.camera2,使用旧的Camera API会出现deprecated的警告。
一般创建一个定制Camera接口的步骤包括
1.检测和获取camera
/** Check if this device has a camera */
private boolean checkCameraHardware(Context context) {
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
// this device has a camera
return true;
} else {
// no camera on this device
return false;
}
}
/** A safe way to get an instance of the Camera object. */
public static Camera getCameraInstance(){
Camera c = null;
try {
c = Camera.open(); // attempt to get a Camera instance
}
catch (Exception e){
// Camera is not available (in use or does not exist)
}
return c; // returns null if camera is unavailable
}
2.创建一个预览类
/** A basic Camera preview class */
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera; public CameraPreview(Context context, Camera camera) {
super(context);
mCamera = camera; // Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
} public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, now tell the camera where to draw the preview.
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
Log.d(TAG, "Error setting camera preview: " + e.getMessage());
}
} public void surfaceDestroyed(SurfaceHolder holder) {
// empty. Take care of releasing the Camera preview in your activity.
} public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it. if (mHolder.getSurface() == null){
// preview surface does not exist
return;
} // stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e){
// ignore: tried to stop a non-existent preview
} // set preview size and make any resize, rotate or
// reformatting changes here // start preview with new settings
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview(); } catch (Exception e){
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
}
3.创建一个预览的布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<FrameLayout
android:id="@+id/camera_preview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
/> <Button
android:id="@+id/button_capture"
android:text="Capture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
/>
</LinearLayout>
public class CameraActivity extends Activity { private Camera mCamera;
private CameraPreview mPreview; @Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main); // Create an instance of Camera
mCamera = getCameraInstance(); // Create our Preview view and set it as the content of our activity.
mPreview = new CameraPreview(this, mCamera);
FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
preview.addView(mPreview);
}
}
4.开始监听捕获事件
private PictureCallback mPicture = new PictureCallback() { @Override
public void onPictureTaken(byte[] data, Camera camera) { File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
if (pictureFile == null){
Log.d(TAG, "Error creating media file, check storage permissions: " +
e.getMessage());
return;
} try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
} catch (FileNotFoundException e) {
Log.d(TAG, "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d(TAG, "Error accessing file: " + e.getMessage());
}
}
};
5.捕获并保存文件
// Add a listener to the Capture button
Button captureButton = (Button) findViewById(id.button_capture);
captureButton.setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
// get an image from the camera
mCamera.takePicture(null, null, mPicture);
}
}
);
保存图片到SD卡中
private PictureCallback mPicture = new PictureCallback() { /** Create a File for saving an image or video */ @Override
public void onPictureTaken(byte[] data, Camera camera) { File pictureFile = getOutputMediaFile();
if (pictureFile == null) {
Log.d(TAG,"Error creating media file, check storage permissions: ");
return;
} try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
} catch (FileNotFoundException e) {
Log.d(TAG, "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d(TAG, "Error accessing file: " + e.getMessage());
}
camera.startPreview(); } }; private File getOutputMediaFile() {
// To be safe, you should check that the SDCard is mounted
// using Environment.getExternalStorageState() before doing this. File mediaStorageDir = new File(
Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
"MyCameraApp");
// This location works best if you want the created images to be shared
// between applications and persist after your app has been uninstalled. // Create the storage directory if it does not exist
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
Log.d("MyCameraApp", "failed to create directory");
return null;
}
}
// Create a media file name
File mediaFile;
String timeStamp = String.format("%d.jpg", System.currentTimeMillis());
mediaFile = new File(mediaStorageDir.getPath() + File.separator
+ "IMG_" + timeStamp + ".jpg");
return mediaFile;
}
6.释放相机
public class CameraActivity extends Activity {
private Camera mCamera;
private SurfaceView mPreview;
private MediaRecorder mMediaRecorder; ... @Override
protected void onPause() {
super.onPause();
releaseMediaRecorder(); // if you are using MediaRecorder, release it first
releaseCamera(); // release the camera immediately on pause event
} private void releaseCamera(){
if (mCamera != null){
mCamera.release(); // release the camera for other applications
mCamera = null;
}
}
}
caution:
相机是一个共享资源,所以每次使用完毕后要记得调用Camera.release()来释放,否则后续想要获取相机的应用都会被关闭。
六、注意问题
6.1 拍完成照片后,停在拍照完成的界面,无法继续拍摄
在onPictureTaken的实现最后添加一个启动预览camera.startPreview();
private PictureCallback mPicture = new PictureCallback() { /** Create a File for saving an image or video */ @Override
public void onPictureTaken(byte[] data, Camera camera) { File pictureFile = getOutputMediaFile();
if (pictureFile == null) {
Log.d(TAG,"Error creating media file, check storage permissions: ");
return;
} try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
} catch (FileNotFoundException e) {
Log.d(TAG, "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d(TAG, "Error accessing file: " + e.getMessage());
}
camera.startPreview(); } };
代码:
https://github.com/dawnminghuang/android_camera
参考资料
http://developer.android.com/guide/topics/media/camera.html
Android学习十---Android Camera的更多相关文章
- [置顶] Android学习系列-Android中解析xml(7)
Android学习系列-Android中解析xml(7) 一,概述 1,一个是DOM,它是生成一个树,有了树以后你搜索.查找都可以做. 2,另一种是基于流的,就是解析器从头到尾解析一遍xml文件. ...
- android 学习十四 探索安全性和权限
1.部署安全性:应用程序必须使用数字证书才能安装到设备上. 2.执行期间的安全性: 2.1 使用独立进程 2.2 使用固定唯一用户ID 2.3 申明性权限模型 3数字证书 ...
- Android学习十二---在android上实现图像匹配
一.效果图及功能描述 效果图 点击ShowImg后 点击match,然后点击showmatch,可以不断点击showmatch. 主要功能描述:显示在SD卡上已经存在的图片test.jpg,根据图片在 ...
- android学习十四(android的接收短信)
收发短信是每一个手机主要的操作,android手机当然也能够接收短信了. android系统提供了一系列的API,使得我们能够在自己的应用程序里接收和发送短信. 事实上接收短信主要是利用我们前面学过的 ...
- Android学习十二:自定义控件学习
自定义控件: 1.定义控件的属性,atts.xml 2.代码实现自定义控件的控制 3.引用该控件 首先定义相关的属性 <?xml version="1.0" encoding ...
- android学习十二(android的Content Provider(内容提供器)的使用)
文件存储和SharePreference存储以及数据存储一般为了安全,最好用于当前应用程序中訪问和存储数据.内容提供器(Content Provider)主要用于在不同的应用程序之间实现数据共享的功能 ...
- android学习十 ActionBar
1.api level大于等于11 支持,或者使用兼容库,但兼容库的问题很多. 2.一个操作栏属于一个活动,并具有其生命周期 3.操作栏分3类:a.选项卡操作栏,b.列表操作栏,c.标准操作栏 4.获 ...
- Android学习——在Android中使用OpenCV的第一个程序
刚開始学习Android,因为之前比較熟悉OpenCV,于是就想先在Android上执行OpenCV试试 =============================================== ...
- 【Android学习】android:layout_weight的用法实例
对于android:layout_weight的用法,用下面的例子来说明: <LinearLayout xmlns:android="http://schemas.android.co ...
随机推荐
- JS中怎样判断undefined
- maven仓库镜像配置
<!-- 阿里云仓库 --> <mirror> <id>alimaven</id> <mirrorOf>central</mirror ...
- mybatis之高级结果映射
先贴一句官方文档内容 如果世界总是这么简单就好了. 正如官方文档所说:如果一切都是这么简单,那该多好啊,但是实际上,我们面对的是复杂的对象,就是对象里有对象,有列表对象,总之五花八门的对象.这个时候我 ...
- yum 安装出错--"Couldn't resolve host 'mirrors.aliyun.com'"
1.yum 安装出错 [root@iz25m0z7ik3z ~]#yum install mysql [root@iZ25m0z7ik3Z ~]#yum install mysql Loaded pl ...
- highCharts+Struts2生成柱状图
这篇文章主要结合Struts2+json+Highcharts实现动态数据的显示.为了节省时间,就不写数据库了.在action中用一个集合来模拟从数据库取到的数据.模拟数据为三个学生在不同时间成绩的变 ...
- Android基础新手教程——3.1 基于监听的事件处理机制
Android基础新手教程--3.1.1 基于监听的事件处理机制 标签(空格分隔): Android基础新手教程 本节引言: 第二章我们学习的是Android的UI控件,我们能够利用这些控件构成一个精 ...
- HDU 4970(杭电多校#9 1011题)Killing Monsters(瞎搞)
题目地址:HDU 4970 先进行预处理.在每一个炮塔的火力范围边界标记一个点. 然后对每一个点的伤害值扫一遍就能算出来. 然后在算出每一个点到终点的总伤害值,并保存下来,也是扫一遍就可以. 最后在询 ...
- 边缘检测sobel算子
sobel算子 - sophia_hxw - 博客园http://www.cnblogs.com/sophia-hxw/p/6088035.html #1,个人理解 网上查了很多资料,都说sobel算 ...
- VC++Debug避免F11步进不想要的函数中
It's often useful to avoid stepping into some common code like constructors or overloaded operators. ...
- Camlistore名词解释
Terminology 名词解释 To stay sane and communicate effectively we try hard to use consistent terminology ...