鸿蒙操作系统开发入门经典
上QQ阅读APP看书,第一时间看更新

3.8 网络媒体与设备

3.8.1 网络管理

HarmonyOS网络管理模块主要提供以下功能。

  •  数据连接管理:网卡绑定,打开URL,数据链路参数查询。
  •  数据网络管理:指定数据网络传输,获取数据网络状态变更,数据网络状态查询。
  •  流量统计:获取蜂窝网络、所有网卡、指定应用或指定网卡的数据流量统计值。
  •  HTTP缓存:有效管理HTTP缓存,减少数据流量。
  •  创建本地套接字:实现本机不同进程间的通信,目前只支持流式套接字。

1.约束与限制

使用网络管理模块的相关功能时,需要请求相应的权限,如表3-13所示。

表3-13 需要请求相应的权限

1)场景介绍

应用使用当前的数据网络打开一个URL链接。

2)接口说明

应用使用当前网络打开一个URL链接,所使用的接口说明如表3-14所示。

表3-14 网络管理功能的主要接口

2.开发步骤

(1)调用NetManager.getInstance(Context)获取网络管理的实例对象。

(2)调用NetManager.getDefaultNet()获取默认的数据网络。

(3)调用NetHandle.openConnection()打开一个URL。

(4)通过URL链接实例访问网站,如代码示例3-71所示。

代码示例3-71 通过URL网址访问网站

3.8.2 设备的位置信息

移动终端设备已经深入人们日常生活的方方面面,如查看所在城市的天气、新闻轶事、出行打车、旅行导航、运动记录等。这些习以为常的活动,都离不开定位用户终端设备的位置。

当用户处于这些丰富的使用场景中时,系统的位置能力可以提供实时准确的位置数据。对于开发者来讲,设计基于位置体验的服务,也可以使应用的使用体验更贴近每个用户。

当应用在实现基于设备位置的功能时,如驾车导航、记录运动轨迹等,可以调用该模块的API,完成位置信息的获取。

1.基本概念

位置能力用于确定用户设备在哪里,系统使用位置坐标标示设备的位置,并用多种定位技术提供服务,如GNSS定位、基站定位、WLAN/蓝牙定位(基站定位、WLAN/蓝牙定位后续统称“网络定位技术”)。通过这些定位技术,无论用户设备在室内或户外,都可以准确地确定设备位置。

1)坐标

系统以1984年建立的世界大地坐标系统为参考,使用经度、纬度数据描述地球上的一个位置。

2) GNSS定位

基于全球导航卫星系统,包含GPS、GLONASS、北斗、Galileo等,通过导航卫星,由设备芯片提供的定位算法,用来确定设备的准确位置。定位过程具体使用哪些定位系统,取决于用户设备的硬件能力。

3)基站定位

根据设备当前驻网基站和相邻基站的位置,估算设备当前位置。此定位方式的定位结果精度相对较低,并且需要设备可以访问蜂窝网络。

4)WLAN、蓝牙定位

根据设备可搜索到的周围WLAN、蓝牙设备位置,估算设备当前位置。此定位方式的定位结果精度依赖设备周围可见的固定WLAN、蓝牙设备的分布,密度较高时,精度也相较于基站定位方式更高,同时也需要设备可以访问网络。

2.运作机制

位置能力作为系统为应用提供的一种基础服务,需要应用在所使用的业务场景,向系统主动发起请求,并在业务场景结束时,主动结束此请求,在此过程中系统会将实时的定位结果上报给应用。

3.约束与限制

使用设备的位置能力,需要用户进行确认并主动开启位置开关。如果位置开关没有开启,系统不会向任何应用提供位置服务。

设备位置信息属于用户敏感数据,所以即使用户已经开启位置开关,应用在获取设备位置前仍需向用户申请位置访问权限。在用户确认允许后,系统才会向应用提供位置服务。

4.获取设备的位置信息

1)场景介绍

开发者可以调用HarmonyOS位置相关接口,获取设备实时位置,或者最近的历史位置。

对于位置敏感的应用业务,建议获取设备实时位置信息。如果不需要设备的实时位置信息,并且希望尽可能地节省耗电,则开发者可以考虑获取最近的历史位置。

2)接口说明

获取设备的位置信息,所使用的接口说明如表3-15所示。

表3-15 获取设备的位置信息,所使用的接口说明

3)开发步骤

应用在使用系统能力前,需要检查是否已经获取用户授权访问设备位置信息。如未获得授权,可以向用户申请需要的位置权限,申请方式参考动态申请权限开发步骤。

系统提供的定位权限如下:

访问设备的位置信息,必须申请ohos.permission.LOCATION权限,并且获得用户授权。

如果应用在后台运行时也需要访问设备位置,除需要将应用声明为允许后台运行外,还必须申请ohos.permission.LOCATION_IN_BACKGROUND权限,这样应用在切入后台之后,系统可以继续上报位置信息。

开发者可以在应用config.json文件中声明所需要的权限,示例代码如下:

配置字段详细说明见权限开发指导。

实例化Locator对象,所有与基础定位能力相关的功能API都是通过Locator提供的。

其中入参需要提供当前应用程序的AbilityInfo信息,便于系统管理应用的定位请求。

实例化RequestParam对象,用于告知系统该向应用提供何种类型的位置服务,以及位置结果上报的频率。

方式一:

为了面向开发者提供贴近其使用场景的API使用方式,系统定义了几种常见的位置能力使用场景,并针对使用场景做了适当的优化处理,应用可以直接匹配使用,从而简化开发复杂度。系统当前支持的场景如表3-16所示。

表3-16 系统当前支持的场景

以导航场景为例,实例化方式如下:

方式二:

如果定义的现有场景类型不能满足所需的开发场景,则可使用系统提供的基本的定位优先级策略类型,如表3-17所示。

表3-17 系统提供的基本的定位优先级策略类型

以定位精度优先策略为例,实例化方式如下:

后两个入参用于限定系统向应用上报定位结果的频率,分别为位置上报的最短时间间隔和位置上报的最短距离间隔,开发者可以参考API具体说明进行开发。

实例化LocatorCallback对象,用于向系统提供位置上报的途径。

应用需要自行实现系统定义好的回调接口,并将其实例化。系统在定位成功并确定设备的实时位置结果时,会通过onLocationReport接口上报给应用。

应用程序可以在onLocationReport接口的实现中完成自己的业务逻辑,如代码示例3-72所示。

代码示例3-72 onLocationReport接口完成自己的业务逻辑

启动定位,代码如下:

如果应用不需要持续获取位置结果,则可以使用如下方式启动定位,系统会上报一次实时定位结果,然后自动结束应用的定位请求。应用不需要执行结束定位,代码如下:

(可选)结束定位,代码如下:

如果应用使用场景不需要获取实时的设备位置,可以获取系统缓存的最近一次历史定位结果,代码如下:

此接口的使用需要应用向用户申请ohos.permission.LOCATION权限。

5.地理编码转化成详细所在地信息

1)场景介绍

使用坐标描述一个位置,非常准确,但是并不直观,面向用户表达并不友好。

系统向开发者提供了地理编码转化能力(将坐标转化为地理编码信息),以及逆地理编码转化能力(将地理描述转化为具体坐标)。其中地理编码包含多个属性来描述位置,包括国家、行政区、街道、门牌号、地址描述等,这样的信息更便于用户理解。

2)接口说明

进行坐标和地理编码信息的相互转化,所使用的接口说明如表3-18所示。

表3-18 进行坐标和地理编码信息的相互转化,所使用的接口说明

3)开发步骤

GeoConvert需要访问后端服务,需要确保设备联网,以进行信息获取。

实例化GeoConvert对象,所有与(逆)地理编码转化能力相关的功能API都是通过GeoConvert提供的,代码如下:

如果需要根据自定义参数实例化GeoConvert对象,如语言、地区等,则可以使用GeoConvert(Localelocale)。

获取转化结果。

坐标转化地理位置信息,代码如下:

参考接口API说明,应用可以获得与此坐标相匹配的GeoAddress列表,应用可以根据实际使用需求,读取相应的参数数据。

位置描述转化为坐标,代码如下:

参考接口API说明,应用可以获得与位置描述相匹配的GeoAddress列表,其中包含对应的坐标数据,参考API使用。

如果需要查询的位置描述可能出现多地重名的请求,则可以通过设置一个经纬度范围,以便高效获取期望的准确结果,代码如下:

3.8.3 视频

HarmonyOS视频模块支持视频业务的开发和生态开放,开发者可以通过已开放的接口很容易地实现视频媒体的播放、操作和新功能开发。视频媒体的常见操作有视频编解码、视频合成、视频提取、视频播放及视频录制等。

视频播放包括播放控制、播放设置和播放查询,如播放的开始/停止、播放速度设置和是否循环播放等。视频播放类Player的主要接口如表3-19所示。

表3-19 视频播放类Player的主要接口

创建Player实例,可调用Player(Context context),创建本地播放器,用于在本设备播放。

构造数据源对象,并调用Player实例的setSource(Source source)方法,设置媒体源,播放本地视频,如代码示例3-73所示。

代码示例3-73 播放本地视频

播放网络视频,如代码示例3-74所示。

代码示例3-74 播放网络视频

调用prepare()方法,准备播放。

构造IPlayerCallback,IPlayerCallback需要实现onPlayBackComplete和onError(int errorType,interrorCode)两种方法,实现播放完成和播放异常时做相应的操作,如代码示例3-75所示。

代码示例3-75 播放视频回调

调用play()方法,开始播放。

调用pause()方法和play()方法,可以实现暂停和恢复播放。

调用rewindTo(long microseconds)方法实现播放中的拖曳功能。

调用getDuration()方法和getCurrentTime()方法,可以实现获取总播放时长及当前播放位置功能。

调用stop()方法,停止播放。

播放结束后,调用release()释放资源。

利用SurfaceProvider控件实现了一个视频播放的Demo,包括由开始、暂停和循环播放功能构建的播放页面,如代码示例3-76所示。

代码示例3-76 利用SurfaceProvider控件实现了一个视频播放的Demo

在Slice代码onStart方法中初始化,如代码示例3-77所示。

代码示例3-77 实现了一个视频播放

实现播放功能的代码如代码示例3-78所示。

代码示例3-78 实现播放功能

在Slice的其他生命周期对player进行资源管理,代码如下:

3.8.4 图像

HarmonyOS图像模块支持图像业务的开发,常见功能如图像解码、图像编码、基本的位图操作、图像编辑等。当然,也支持通过接口组合实现更复杂的图像处理逻辑。

1.基本概念

1)图像解码

图像解码就是将不同的存档格式图片(如JPEG、PNG等)解码为无压缩的位图格式,以方便在应用或者系统中进行相应处理。

2)PixelMap

PixelMap是图像解码后无压缩的位图格式,用于图像显示或者进一步处理。

3)渐进式解码

渐进式解码是在无法一次性提供完整图像文件数据的场景下,随着图像文件数据的逐步增加,通过多次增量解码逐步完成图像解码的模式。

4)预乘

预乘时,RGB各通道的值被替换为原始值乘以Alpha通道不透明的比例(0~1)后的值,方便后期直接合成叠加。不预乘指RGB各通道的数值是图像的原始值,与Alpha通道的值无关。

5)图像编码

图像编码就是将无压缩的位图格式,编码成不同格式的存档格式图片(JPEG、PNG等),以方便在应用或者系统中进行相应处理。

2.约束与限制

为及时释放本地资源,建议在图像解码的ImageSource对象、位图图像PixelMap对象或图像编码的ImagePacker对象使用完成后,主动调用ImageSource、PixelMap和ImagePacker的release()方法。

3.普通解码开发步骤

创建图像数据源ImageSource对象,可以通过SourceOptions指定数据源的格式信息,此格式信息仅为给解码器的提示,正确提供信息能帮助提高解码效率,如果不设置或设置不正确,则会自动检测正确的图像格式。不使用该选项时,可以将create接口传入的SourceOptions设置为null。

设置解码参数,解码获取PixelMap图像对象,解码过程中同时支持图像处理操作。设置desiredRegion支持按矩形区域裁剪,如果设置为全0,则不进行裁剪。设置desiredSize支持按尺寸缩放,如果设置为全0,则不进行缩放。设置rotateDegrees支持旋转角度,以图像中心点为圆心顺时针旋转。如果只需解码原始图像,不使用该选项时,则可将向createPixelMap传入的DecodingOptions设置为null。

解码完成并获取PixelMap对象后,可以进行后续处理,例如渲染显示等。

我们通过一个解析远程图片的例子,了解图像的解码过程,如代码示例3-79所示。

代码示例3-79 解析远程图片的例子

3.8.5 相机

HarmonyOS相机模块支持相机业务的开发,开发者可以通过已开放的接口实现相机硬件的访问、操作和新功能开发,最常见的操作如:预览、拍照、连拍和录像等。

1.基本概念

1)相机静态能力

用于描述相机固有能力的一系列参数,例如朝向、支持的分辨率等信息。

2)物理相机

物理相机就是独立的实体摄像头设备。物理相机ID是用于标识每个物理摄像头的唯一字符串。

3)逻辑相机

逻辑相机是由多个物理相机组合出来的抽象设备,逻辑相机通过同时控制多个物理相机设备来完成相机某些功能,如大光圈、变焦等功能。逻辑摄像机ID是一个唯一的字符串,用于标识多个物理摄像机的抽象能力。

4)帧捕获

相机启动后对帧的捕获动作统称为帧捕获。主要包含单帧捕获、多帧捕获、循环帧捕获。

5)单帧捕获

指的是相机启动后,在帧数据流中捕获一帧数据,常用于普通拍照。

6)多帧捕获

指的是相机启动后,在帧数据流中连续捕获多帧数据,常用于连拍。

7)循环帧捕获

指的是相机启动后,在帧数据流中一直捕获帧数据,常用于预览和录像。

2.约束与限制

在同一时刻只能有一个相机应用在运行。

相机模块内部有状态控制,开发者必须按照指导文档的流程进行接口的顺序调用,否则可能会出现调用失败等问题。

为了使所开发的相机应用拥有更好的兼容性,在创建相机对象或者进行参数设置前务必进行能力查询。

3.相机开发流程

相机模块的主要工作是给相机应用开发者提供基本的相机API,用于使用相机系统的功能,进行相机硬件的访问、操作和新功能开发。相机的开发流程如图3-91所示。

图3-91 相机开发流程

1)接口说明

相机模块为相机应用开发者提供了3个开发包,如表3-20所示。包括方法、枚举及常量/变量,方便开发者更容易地实现相机功能。详情可查阅对应的开发场景。

表3-20 相机模块为相机应用开发者提供了3个开发包

2)相机权限申请

在使用相机之前,需要申请相机的相关权限,保证应用拥有相机硬件及其他功能权限,应用权限的介绍可参考权限章节,相机涉及权限如表3-21所示。

表3-21 在使用相机之前,需要申请相机的相关权限

3)相机设备创建

CameraKit类是相机的入口API类,用于获取相机设备特性、打开相机,其接口如表3-22所示。

表3-22 CameraKit类是相机的入口API类

基于HarmonyOS实现一个相机应用,无论将来想应用到哪个或者哪些设备上,都必须先创建一个独立的相机设备,然后才能继续相机的其他操作。创建相机设备的建议步骤如下:

通过CameraKit.getInstance(Contextcontext)方法获取唯一的CameraKit对象,如代码示例3-80所示。

代码示例3-80 创建CameraKit对象

如果此步骤操作失败,则说明相机可能被占用或无法使用。如果被占用,则必须等到相机释放后才能重新获取CameraKit对象。

通过getCameraIds()方法,获取当前使用的设备所支持的逻辑相机列表。逻辑相机列表中存储了当前设备拥有的所有逻辑相机ID,如果列表不为空,则列表中的每个ID都支持独立创建相机对象。否则,说明正在使用的设备无可用的相机,不能继续后续的操作,如代码示例3-81所示。

代码示例3-81 获取当前使用的设备所支持的逻辑相机列表

还可以继续查询指定相机ID的静态信息,如表3-23和表3-24所示。

表3-23 CameraInfo的主要接口

表3-24 CameraAbility的主要接口

调用getDeviceLinkType(String physicalId)方法获取物理相机连接方式;

调用getCameraInfo(String cameraId)方法查询相机硬件朝向等信息;

调用getCameraAbility(String cameraId)方法查询相机能力信息(例如支持的分辨率列表等)。

通过createCamera(String cameraId,CameraStateCallback callback,EventHandler handler)方法,创建相机对象,此步骤执行成功意味着相机系统的硬件已经完成了上电。

第1个参数cameraIds可以是上一步获取的逻辑相机列表中的任何一个相机ID。

第2个和第3个参数负责相机创建和相机运行时的数据和状态检测,务必保证在整个相机运行周期内有效,如代码示例3-82所示。

代码示例3-82 相机设备的创建及完成回调

至此,相机设备的创建已经完成。相机设备创建成功会在CameraStateCallback中触发onCreated(Cameracamera)回调。在进入相机设备配置前,需要确保相机设备已经创建成功。否则会触发相机设备创建失败的回调,并返回错误码,进行错误处理后,重新执行相机设备的创建。

4)相机设备配置

创建相机设备成功后,在CameraStateCallback中会触发onCreated(Cameracamera)回调,并且返回Camera对象,用于执行相机设备的操作。

当一个新的相机设备成功创建后,首先需要对相机进行配置,调用configure (CameraConfig)方法实现配置。相机配置主要是设置预览、拍照、录像所用到的Surface(详见ohos.agp.graphics.Surface),如果不配置Surface,则相应的功能不能使用。

为了获取相机帧捕获结果的数据和进行状态检测,还需要在相机配置时调用setFrameStateCallback(FrameStateCallback,EventHandler)方法设置帧回调,如代码示例3-83所示。

代码示例3-83 对相机进行配置

相机配置成功后,在CameraStateCallback中会触发onConfigured(Camera camera)回调,然后才可以执行与相机帧捕获相关的操作,如表3-25所示。

表3-25 CameraConfig.Builder的主要接口

5)相机帧捕获

Camera操作类,包括相机预览、录像、拍照等功能接口,如表3-26所示。

表3-26 Camera的主要接口

6)启动预览(循环帧捕获)

用户一般先看见预览画面才执行拍照或者其他功能,所以对于一个普通的相机应用,预览是必不可少的。启动预览的建议步骤如下。

通过getFrameConfigBuilder(FRAME_CONFIG_PREVIEW)方法获取预览配置模板,常用帧配置项见表3-27,更多的帧配置项及详细使用方法可参考API说明的FrameConfig. Builder部分,如表3-27所示。

表3-27 常用帧配置项

通过triggerLoopingCapture(FrameConfig)方法实现循环帧捕获(如预览/录像),如代码示例3-84所示。

代码示例3-84 实现循环帧捕获

经过以上操作,相机应用已经可以正常进行实时预览了。在预览状态下,开发者还可以执行其他操作,例如当预览帧配置更改时,可以通过triggerLoopingCapture(FrameConfig)方法实现预览帧配置的更新,代码如下:

7)实现拍照(单帧捕获)

拍照功能属于相机应用的最重要功能之一,而且照片质量对用户至关重要。相机模块基于相机复杂的逻辑,从应用接口层到器件驱动层都已经做好了最适合用户的默认配置,这些默认配置尽可能地保证用户拍出的每张照片的质量。实现拍照的建议步骤如下。

通过getFrameConfigBuilder(FRAME_CONFIG_PICTURE)方法获取拍照配置模板,并且设置拍照帧配置,如表3-28所示。

表3-28 常用帧配置项

拍照前准备图像帧数据的接收,如代码示例3-85所示。

代码示例3-85 拍照前准备图像帧数据的接收

通过triggerSingleCapture(FrameConfig)方法实现单帧捕获(如拍照),如代码示例3-86所示。

代码示例3-86 实现单帧捕获(如拍照)

为了捕获到质量更高和效果更好的图片,还可以在帧结果中实时监测自动对焦和自动曝光的状态,一般而言,在自动对焦完成且自动曝光收敛后的瞬间是发起单帧捕获的最佳时机。

实现连拍(多帧捕获):连拍功能方便用户一次拍照获取多张照片,用于捕捉精彩瞬间。同普通拍照的实现流程一致,但连拍需要使用triggerMultiCapture(ListFrameConfigframeConfigs)方法。

启动录像(循环帧捕获):启动录像和启动预览类似,但需要另外配置录像Surface才能使用。录像前需要进行音视频模块的配置,如代码示例3-87所示。

代码示例3-87 进行音视频模块的配置

配置录像帧,启动录像,如代码示例3-88所示。

代码示例3-88 配置录像帧,启动录像

通过camera.stopLoopingCapture()方法停止循环帧捕获(录像)。

8)相机设备释放

使用完相机后,必须通过release()来关闭相机和释放资源,否则可能导致其他相机应用无法启动。一旦相机被释放,它所提供的操作就不能再被调用,否则会导致不可预期的结果,或者会引发状态异常。相机设备释放的示例如代码示例3-89所示。

代码示例3-89 设备释放

3.8.6 声频

HarmonyOS声频模块支持声频业务的开发,提供与声频相关的功能,主要包括声频播放、声频采集、音量管理和短音播放等。

在使用完AudioRenderer声频播放类和AudioCapturer声频采集类后,需要调用release()方法进行资源释放。

声频采集所使用的最终采样率与采样格式取决于输入设备,不同设备支持的格式及采样率范围不同,可以通过AudioManager类的getDevices接口查询。

在进行声频采集之前,需要申请话筒权限ohos.permission.MICROPHONE。

1)场景介绍

声频播放的主要工作是将声频数据转码为可听见的声频模拟信号并通过输出设备进行播放,同时对播放任务进行管理。声频播放类AudioRenderer的主要接口如表3-29所示。

表3-29 声频播放类AudioRenderer的主要接口

2)开发步骤

构造声频流参数的数据结构AudioStreamInfo,推荐使用AudioStreamInfo.Builder类来构造,模板如下,模板中所设置的值均为AudioStreamInfo.Builder类的默认值,根据声频流的具体规格设置具体参数。

使用创建的声频流构建声频播放的参数结构AudioRendererInfo,推荐使用AudioRen-dererInfo.Builder类来构造,模板如下,模板中所设置的值均为AudioRendererInfo.Builder类的默认值,根据声频播放的具体规格设置具体参数,如代码示例3-90所示。

代码示例3-90 本地声频播放案例封装