本文介绍App开发常用的一些设备操作,主要包括如何使用摄像头进行拍照、如何使用麦克风进行录音并结合摄像头进行录像、如何播放录制好的音频和视频、如何使用常见传感器实现业务功能、如何使用定位功能获取位置信息、如何利用短距离通信技术实现物联网等。
摄像头
本节介绍利用摄像头实现相机功能的办法,首先对表面视图SurfaceView的用法进行说明,演示如何运用相机类Camera结合表面视图完成拍照功能(含单拍和连拍)。然后对表面视图的升级版——纹理视图TextureView的用法进行阐述,并演示如何在新版Camera2架构中结合纹理视图完成拍照功能(含单拍和连拍)。最后介绍了与设备操作有关的运行时权限管理。
表面视图SurfaceView
Android的绘图机制是由UI线程在屏幕上绘图,一般情况下不允许其他线程直接做绘图操作。这个机制在处理简单页面时没什么问题,因为普通页面不会频繁且大面积地绘图,但是该机制在处理复杂多变的页面时会产生问题,比如时刻变化着的游戏界面、拍照或录像时不断变换着的预览界面就会导致UI线程资源堵塞,即界面卡死的状况。
表面视图SurfaceView是Android用来解决子线程绘图的特殊视图,拥有独立的绘图表面,即不与其宿主页面共享同一个绘图表面。由于拥有独立的绘图表面,因此表面视图的界面能够在一个独立线程中进行绘制,这个子线程为渲染线程。因为渲染线程不占用主线程资源,所以一方面可以实现复杂而高效的UI刷新,另一方面及时响应用户的输入事件。由于表面视图具备以上特性,因此可用于拍照和录像的预览界面,也可用于游戏的实时界面。
因为表面视图不在UI主线程绘图,无论是onDraw方法还是dispatchDraw方法都没有进行绘图操作,所以表面视图必然要通过其他途径绘图,这个途径便是内部类表面持有者SurfaceHolder外部调用SurfaceView对象的getHolder方法获得SurfaceHolder对象,然后进行预览界面的相关绘图操作。
从表面视图的转动效果可以看到,它与普通视图在处理上的区别主要有以下两点:
(1)表面视图允许开启多个线程同时进行绘图操作,而普通视图只有一个UI线程可以绘图。
(2)表面视图不会自动清空上次的绘图结果,即绘图操作是增量进行的,而普通视图在每次绘图前都会清空上次的绘图结果。
使用Camera拍照
在Android开发中,相机Camera是直接操作摄像头硬件的工具类,包括后置摄像头和前置摄像头,有以下常用方法。
- getNumberOfCameras:获取本设备的摄像头数目。
- open:打开摄像头,默认打开后置摄像头。如果有多个摄像头,那么open(0)表示打开后置摄像头,open(1)表示打开前置摄像头。
- getParameters:获取摄像头的拍照参数,返回Camera.Parameters对象。setParameters:设置摄像头的拍照参数。具体的拍照参数通过调用Camera.Parameters的下列方法进行设置。
- setPreviewSize:设置预览界面的尺寸。
- setPictureSize:设置保存图片的尺寸。
- setPictureFormat:设置图片格式。一般使用ImageFormat.JPEG表示JPG格式。
- setFocusMode:设置对焦模式。取值Camera.Parameters.FOCUS_MODE_AUTO只会自动对焦一次,取值FOCUS_MODE_CONTINUOUS_PICTURE则会连续对焦。
- setPreviewDisplay:设置预览界面的表面持有者,即SurfaceHolder对象。该方法必须在SurfaceHolder.Callback的surfaceCreated方法中调用。
- startPreview:开始预览。该方法必须在setPreviewDisplay方法之后调用。
- unlock:录像时需要对摄像头解锁,这样摄像头才能持续录像。该方法必须在startPreview方法之后调用。setDisplayOrientation:设置预览的角度。Android的0度在三点钟的水平位置,而手机屏幕是垂直位置,从水平位置到垂直位置需要旋转90度。
- autoFocus:设置对焦事件。参数自动对焦接口AutoFocusCallback的onAutoFocus方法在对焦完成时触发,在此提示用户对焦完毕可以拍照了。
- takePicture:开始拍照,并设置拍照相关事件。第一个参数为快门回调接口ShutterCallback,它的onShutter方法在按下快门时触发,通常可在此播放拍照声音,默认为“咔嚓”一声;第二个参数的PictureCallback表示原始图像的回调接口,通常无须处理直接传null;第三个参数的PictureCallback表示JPG图像的回调接口,压缩后的图像数据可在该接口中的onPictureTaken方法中获得。
- setZoomChangeListener:设置缩放比例变化事件。缩放变化监听器OnZoomChangeListener的onZoomChange方法在缩放比例发生变化时触发。
- setPreviewCallback:设置预览回调事件,通常在连拍时调用。预览回调接口PreviewCallback的onPreviewFrame方法在预览图像发生变化时触发。
- stopPreview:停止预览。
- lock:录像完毕对摄像头加锁。该方法在stopPreview方法之后调用。
- release:释放摄像头。因为摄像头不能重复打开,所以每次退出拍照时都要释放摄像头。
纹理视图TextureView
表面视图SurfaceView在一般情况下足够使用了,但是有一些限制。因为表面视图不是通过onDraw方法和dispatchDraw方法进行绘图,所以无法使用View的基本视图方法。例如,各种视图变化方法均无法奏效,包括透明度变化方法setAlpha、平移方法setTranslation、缩放方法setScale、旋转方法setRotation等,甚至连最基础的背景图设置方法setBackground都失效了。
为了解决表面视图的不足之处,Android在4.0之后引入了纹理视图TextureView。与表面视图相比,纹理视图并没有创建一个单独的绘图表面用来绘制,可以像普通视图一样执行变换操作,也可以正常设置背景图。
下面是TextureView的常用方法。
- lockCanvas:锁定并获取画布。
- unlockCanvasAndPost:解锁并刷新画布。
- setSurfaceTextureListener:设置表面纹理的监听器。该方法相当于SurfaceHolder的addCallback方法,用来监控表面纹理的状态变化事件。方法参数为SurfaceTextureListener监听器对象,需重写以下4个方法。
- onSurfaceTextureAvailable:在表面纹理可用时触发,可在此进行打开相机等操作。 onSurfaceTextureSizeChanged:在表面纹理尺寸变化时触发。 onSurfaceTextureDestroyed:在表面纹理销毁时触发。
- onSurfaceTextureUpdated:在表面纹理更新时触发。
- isAvailable:判断表面纹理是否可用。
- getSurfaceTexture:获取表面纹理。
使用Camera 2拍照
如同纹理视图是表面视图的升级版那样,Android在5.0之后推出了Camera的升级版——Camera 2。按照Android的官方说明,Camera 2支持以下5点新特性:
(1)支持每秒30帧的全高清连拍。
(2)支持在每帧之间使用不同的设置。
(3)支持原生格式的图像输出。
(4)支持零延迟快门和电影速拍。
(5)支持相机在其他方面的手动控制,比如设置噪音消除的级别。
Camera2在架构上做了大幅改造,原先的Camera类被拆分为多个管理类,主要有相机管理器CameraManager、相机设备CameraDevice、相机拍照会话CameraCaptureSession、图像读取器ImageReader。
传感器
本节介绍常见传感器的用法与相关应用场景,首先列举Android目前支持的传感器种类,然后对常用传感器分别进行说明,包括加速度传感器的用法和摇一摇的实现、磁场传感器的用法和指南针的实现,以及计步器、感光器、陀螺仪等其他传感器的基本用法。
传感器的种类
传感器Sensor是一系列感应器的总称,是Android设备用来感知周围环境和运动信息的工具。因为具体的感应信息依赖于相关硬件,所以虽然Android定义了众多感应器,但是并非每部手机都能支持这么多感应器,千元以下的低端手机往往只支持加速度等少数感应器。