【Android应用开发技术:媒体开发】录像

作者:郭孝星

微博:郭孝星的新浪微博

邮箱:[email protected]

博客:http://blog.csdn.net/allenwells

Github:https://github.com/AllenWells

一 启用相机

1.1 请求相机权限

<manifest ... >
    <uses-feature android:name="android.hardware.camera"
                  android:required="true" />
    ...
</manifest>

如果我们的App使用相机,但相机并不是应用的正常运行所必不可少的组件,可以将android:required 设置为false。这样的话,Google Play也会允许没有相机的设备下载该应用。当然在有必要在使用相机之前通过调用以下方法:

hasSystemFeature(PackageManager.FEATURE_CAMERA);

来检查设备上是否有相机。如果没有,我们应该禁用和相机相关的功能。

1.2 创建Intent对象

利用一个描述了做什么的Intent对象,Android可以将某些执行任务委托给其他应用。整个过程包含三部分:

  • Intent本身
  • 一个函数调用来启动外部的 Activity
  • 当焦点返回到你的Activity时,处理返回图像数据的代码。

举例

发送一个Intent来录制视频

static final int REQUEST_VIDEO_CAPTURE = 1;
private void dispatchTakeVideoIntent()
{
    Intent takeVideoIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);

//注意在调用startActivityForResult()方法之前,先调用resolveActivity(),这个方法会返回能处理该Intent的第一个Activity,即即检查有没有能处理这个Intent的Activity。执行这个检查是必要的,因为如果你调用startActivityForResult()时,没有应用能处理该Intent,应用将会崩溃。所以只要返回结果不为null,使用该Intent就是安全的。

    if (takeVideoIntent.resolveActivity(getPackageManager()) != null)
    {
        startActivityForResult(takeVideoIntent, REQUEST_VIDEO_CAPTURE);
    }
}

1.3 查看视频

Android的相机程序会把指向视频存储地址的Uri添加到Intent中,并传送给onActivityResult())方法。

举例

获取该视频并显示到一个VideoView当中。

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == REQUEST_VIDEO_CAPTURE && resultCode == RESULT_OK) {
        Uri videoUri = intent.getData();
        mVideoView.setVideoURI(videoUri);
    }
}

二 控制相机

2.1 打开相机对象

获取一个Camera对象是直接控制相机的第一步。正如Android自带的相机程序一样,访问相机推荐的方式是在onCreate())方法里面另起一个线程来打开相机。这种办法可以避免因为启动时间较长导致UI线程被阻塞。还有一种更好的方法,可以把打开相机的操作延迟到onResume())方法里面去执行,这样使得代码更容易重用,并且保持控制流程简单。

private boolean safeCameraOpen(int id) {
    boolean qOpened = false;
    try {
        releaseCameraAndPreview();
        mCamera = Camera.open(id);
        qOpened = (mCamera != null);
    } catch (Exception e) {
        Log.e(getString(R.string.app_name), "failed to open Camera");
        e.printStackTrace();
    }
    return qOpened;
}
private void releaseCameraAndPreview() {
    mPreview.setCamera(null);
    if (mCamera != null) {
        mCamera.release();
        mCamera = null;
    }
}

2.2 创建相机预览界面

拍照通常需要向用户提供一个预览界面来显示待拍摄的事物,我们可以使用SurfaceView来展现照相机采集的图像。

//为了显示一个预览界面,我们需要创建一个Preview类。这个类需要实现 android.view.SurfaceHolder.Callback接口,用这个接口把相机硬件获取的数据传递给程序,该Preview类必须在图像实时预览开始之前传递给Camera对象。

class Preview extends ViewGroup implements SurfaceHolder.Callback {
    SurfaceView mSurfaceView;
    SurfaceHolder mHolder;    Preview(Context context) {
        super(context);
        mSurfaceView = new SurfaceView(context);
        addView(mSurfaceView);
        // Install a SurfaceHolder.Callback so we get notified when the
        // underlying surface is created and destroyed.
        mHolder = mSurfaceView.getHolder();
        mHolder.addCallback(this);
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }
...
}

Preview创建后,接下来我们就可以设置和启动Preview。Camera实例与它相关的Preview必须以特定的顺序来创建,其中Camera对象首先被创建。

举例

将初始化Canera的动作封装起来

public void setCamera(Camera camera) {
    if (mCamera == camera) { return; }
    stopPreviewAndFreeCamera();
    mCamera = camera;
    if (mCamera != null) {
        List<Size> localSizes = mCamera.getParameters().getSupportedPreviewSizes();
        mSupportedPreviewSizes = localSizes;
        requestLayout();
        try {
            mCamera.setPreviewDisplay(mHolder);
        } catch (IOException e) {
            e.printStackTrace();
        }
        // Important: Call startPreview() to start updating the preview
        // surface. Preview must be started before you can take a picture.
        mCamera.startPreview();
    }
}

2.3 修改相机设置

相机设置可以改变拍照的方式。

举例

改变预览大小,如下所示:

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
    // Now that the size is known, set up the camera parameters and begin
    // the preview.
    Camera.Parameters parameters = mCamera.getParameters();
    parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
    requestLayout();
    mCamera.setParameters(parameters);
    // Important: Call startPreview() to start updating the preview surface.
    // Preview must be started before you can take a picture.
    mCamera.startPreview();
}

大多数相机程序会锁定预览为横屏状态,因为该方向是相机传感器的自然方向。当然这一设定并不会阻止拍竖屏的照片,因为设备的方向信息会被记录在EXIF头中。setCameraDisplayOrientation())方法可以让你在不影响照片拍摄过程的情况下,改变预览的方向。然而,对于Android API Level 14及以下版本的系统,在改变方向之前,必须先停止预览,然后再去重启它。

2.4 拍摄照片

预览开始之后,可以进行照片的拍摄。

拍摄照片:调用Camera.takePicture(),将创建的Camera.PictureCallback与Camera.ShutterCallback对象传递到该方法内。

连续拍摄照片:调用Camera.takePicture(),创建一个Camera.PreviewCallback并实现onPreviewFrame()方法。我们可以拍摄选中的预览帧,或是为调用takePicture())建立一个延迟。

在拍摄好图片后,你必须在用户拍下一张图片之前重启预览。

举例

利用快门来实现重启,如下所示:

@Override
public void onClick(View v) {
    switch(mPreviewState) {
    case K_STATE_FROZEN:
        mCamera.startPreview();
        mPreviewState = K_STATE_PREVIEW;
        break;
    default:
        mCamera.takePicture( null, rawCallback, null);
        mPreviewState = K_STATE_BUSY;
    } // switch
    shutterBtnConfig();
}

2.5 停止预览并释放相机

当程序使用相机完毕后,有必要做清理的动作。特别地,必须释放Camera对象,不然可能会引起其他应用崩溃,包括我们自己应用的新实例。在预览的Surface被销毁之后,可以做停止预览并释放相机的动作。

public void surfaceDestroyed(SurfaceHolder holder) {
    // Surface will be destroyed when we return, so stop the preview.
    if (mCamera != null) {
        // Call stopPreview() to stop updating the preview surface.
        mCamera.stopPreview();
    }
}
/**
 * When this function returns, mCamera will be null.
 */
private void stopPreviewAndFreeCamera() {
    if (mCamera != null) {
        // Call stopPreview() to stop updating the preview surface.
        mCamera.stopPreview();        // Important: Call release() to release the camera for use by other
        // applications. Applications should release the camera immediately
        // during onPause() and re-open() it during onResume()).
        mCamera.release();
        mCamera = null;
    }
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-12-15 18:09:59

【Android应用开发技术:媒体开发】录像的相关文章

本人讲课时录制的Android应用开发技术教学视频

网盘地址:http://yun.baidu.com/pcloud/album/info?query_uk=1963923831&album_id=3523786484935252365 本人讲课时录制的视频,采用webex录制,视频文件内容相对较小30-50兆左右,1个视频文件平均大概有1个小时左右的时间,每个例子基本上从建立项目开始边做边讲. 由于讲课范围是Android应用开发技术,视频没涉及搭建环境,基础控件的使用等基础内容. 主要内容包括: 后台服务. 服务的绑定.服务和线程.远程服务和

【Android应用开发技术:用户界面】章节列表

作者:郭孝星 微博:郭孝星的新浪微博 邮箱:[email protected] 博客:http://blog.csdn.net/allenwells Github:https://github.com/AllenWells [Android应用开发技术:用户界面]章节列表 [Android应用开发技术:用户界面]用户界面基本原理 [Android应用开发技术:用户界面]设备适配 [Android应用开发技术:用户界面]用户界面布局技巧 [Android应用开发技术:用户界面]View基本原理 [

【Android应用开发技术:图像处理】Bitmap显示性能优化分析

作者:郭孝星 微博:郭孝星的新浪微博 邮箱:[email protected] 博客:http://blog.csdn.net/allenwells Github:https://github.com/AllenWells [Android应用开发技术:图像处理]章节列表 Bitmap经常会消耗大量内存而导致程序崩溃,常见的异常如下所示:java.lang.OutofMemoryError:bitmap size extends VM budget,因此为了保证程序的稳定性,我们应该小心处理程序

【Android应用开发技术:用户界面】界面设计中易混淆的概念汇总

作者:郭孝星 微博:郭孝星的新浪微博 邮箱:[email protected] 博客:http://blog.csdn.net/allenwells Github:https://github.com/AllenWells [Android应用开发技术:用户界面]章节列表 一 px.dp.sp px:即像素,每个px对应屏幕上的一个点. dp:即设备独立像素,一种基于屏幕密度的抽象单位,在每英寸160点的显示器上:1 dp = 1 px. sp:即比例像素,主要用来处理字体大小,可以根据用户字体

【Android应用开发技术:用户界面】9Patch图片设计

作者:郭孝星 微博:郭孝星的新浪微博 邮箱:[email protected] 博客:http://blog.csdn.net/allenwells Github:https://github.com/AllenWells [Android应用开发技术:用户界面]章节列表 9Patch图片是一种特殊的PNG图片,该图片以.9.png为后缀名,它在原始图片四周各添加一个宽度为1像素的线条,这4条线决定了该图片的缩放规则和内容显示格则. 一 9Patch图片的显示规则 9Patch图片left边和t

【Android应用开发技术:网络通信】网络服务可发现基本原理

作者:郭孝星 微博:郭孝星的新浪微博 邮箱:[email protected] 博客:http://blog.csdn.net/allenwells Github:https://github.com/AllenWells [Android应用开发技术:网络通信]章节列表 网络服务发现(Network Service Discovery)是一种在局域网内可以辨识并使用其他设备上提供的服务的技术,这种技术在端对端应用(例如:文件共享.联机游戏)中提供很好的帮助. NSD是基于Apple的Bonjo

【Android应用开发技术:用户界面】布局管理器

作者:郭孝星 微博:郭孝星的新浪微博 邮箱:[email protected] 博客:http://blog.csdn.net/allenwells Github:https://github.com/AllenWells [Android应用开发技术:用户界面]章节列表 布局管理继承于ViewGroup.它用来管理Android应用用户界面里各组件,它的使用使得Android应用的图形用户界面具有良好的平台无关性. 常见的布局方式例如以下所看到的: 线性布局 表格布局 帧布局 相对布局 网络布

【Android应用开发技术:媒体开发】打印

作者:郭孝星 微博:郭孝星的新浪微博 邮箱:[email protected] 博客:http://blog.csdn.net/allenwells Github:https://github.com/AllenWells 在Android 4.4以及更高版本的系统中,提供了直接从Android应用程序打印图片和文字的服务,包括打印图片.HTML页面以及创建自定义打印文档等. 一 打印图片 Android Support Library中的PrintHelper提供了一种打印图片的简单方法,该类

【Android应用开发技术:媒体开发】音频

作者:郭孝星 微博:郭孝星的新浪微博 邮箱:[email protected] 博客:http://blog.csdn.net/allenwells Github:https://github.com/AllenWells Android为播放音乐.闹铃.通知铃.来电声音.系统声音.打电话声音和DTMF频道都分别维护了一个隔离的音频流,这是我们能够控制不同音频的前提,这其中大多数的音频流都是被系统限制的,不能胡乱使用. 一 音频控制 默认情况下,按下音量控制键会调节当前被激活的音频流,如果我们的