【Android项目】本地FM收音机开发及源码简析

【Android项目】本地FM收音机开发及源码简析

 

目录

1.概述

2.收音机的基本原理

3.收音机其他信息 RDS功能

4.Android开发FM收音机源码解析

5.App层如何设计本地FM应用

6. 总结

 

1.概述


本地FM(收音机)应用不同于现在的网络FM(喜马拉雅,考拉等),是由Android手机硬件的调谐芯片,通过接收和解调电台发出的电磁波的调频(FM)或调幅(AM)信号,从而播放和展示相应的节目信息。所以本地收音机应用一般不需要联网,其核心依赖于硬件调谐芯片。所以不是所有的手机都能收听本地收音机,但大部分的手机都支持。

 

 

2.收音机的基本原理


收音机的核心原理就是:电台播音员播出音频经过设备处理成电信号并搭载无线电波进行调制频率或者调制振幅后发射出来,收音机听过天线获取到电波信号,经过解调还原出电信号并且通过信号放大等操作输出到喇叭将电信号还原为为音频信号。

上面说到两种调制方式: AM(调幅)/ FM(调频);

那么为什么需要进行调制?

因为正常情况下人能够听到的声音频率是20--20Khz之间。声波在控制的传输介质为空气,但是衰减很大,传输距离很短,几十米左右。所以直接用声波进行传输是不现实的。但是无线电波在空中传输的介质是电磁场,并且传输距离长。所以将声波转化为电信号之后和无线电波进行调制,则拥有了长距离传输的特性。

AM(调幅)方式:信号波的信号调制在载波上,改变了载波的振幅。频率在503---1060KHz之间

FM(调频)方式:信号波的信号调制在载波上,改变了载波的频率。调频范围为76-108MHz,在我国为87.5-108MHz、日本为76-90MHz。

 

【Android项目】本地FM收音机开发及源码简析_第1张图片

 

 

 

收音机这边接收信号并进行解调放大通过喇叭还原音频。

 

3.收音机其他信息 RDS功能


RDS全称“Radio Data System” 无线数据广播系统;上面我们只讲了信号波的传送,如果只有信号波,电台显示的信息会非常单调。只能展示当前的频率。但是电台除了这些还有电台的名称,节目信息,介绍等相关信息。这时,就需要就靠RDS的来完成了,它是在调频广播发射信号中利用副载波把电台名称等信息发送以数字的形式发送出去。收音机这边通过具有RDS功能的调谐芯片将信息进行解析出来,并且展示。

所以,使用RDS的前提是:电台和收音机调谐芯片都必须同时支持RDS的功能;但目前只有少部分的电台支持RDS。

RDS有两个核心的功能:AF和TA;

AF是指当当前台的信号低于某个值得时候自动搜索该台的其他信号好的频道并且进行自动切换。以达到更好的用户体验。

TA功能是一个强制性播放的功能,如果发生重大事故,紧急通告等交通信息,会强制性切换到该频率进行播放。

具体RDS功能可以搜索【FM收音机_RDS功能概述及编码】深入了解。

 

 

4.Android开发FM收音机源码解析


首先我们来看一下层级结构

硬件driver(由芯片厂家提供) -> HAL(遵循HAL接口协议) -> C动态库(JNI调用)-> Framework(RadioManager) -> Application(逻辑与界面)。

RadioManager这个类在系统API中是hide的,如果想在AndroidStudio中编译是需要做处理的,可自行查阅,但获取framework.jar应该都是必须的。

下面我用一张时序图来展示,咱们先不讨论在Application层面如果设计框架,先看一下如果我们在App中调用了tune(...)方法去播放某一个电台,从framework及其以下经过了那一些的流程。

【Android项目】本地FM收音机开发及源码简析_第2张图片

以上时序图是基于8.0的源码绘制的,其实9.0的源码和8.0收音机的差别还挺多的。demo的结构变得多,源码中App的收音机demo是在目录:

android-8.0.0_r1\packages\apps\Car\Radio\src\com\android\car\radio\

上面的时序图似乎少了点什么?

HAL好像直接就和Framework交互了,中间不应该还有jni吗;所以我们找到目录

android-8.0.0_r1\frameworks\base\core\jni\android_hardware_Radio.cpp

我们知道jni起到的衔接java和c的作用,其实就是java中的方法和c中的方法进行一一相互映射,或者在jni中对应java的方法,并且对c的方法处理逻辑。

那么我们来看一下这几个类的方法

RadioTMoudle.java中的方法:

【Android项目】本地FM收音机开发及源码简析_第3张图片

 

再看下android_hardware_Radio.cpp中对应

 

我们看到了什么?

RadioTMoudle.java中方法都在android_hardware_Radio.cpp中,只不过方法名都加上了固定的前缀,这只是jni的特色。说明这两个文件能够对应的上。

【Android项目】本地FM收音机开发及源码简析_第4张图片

我们接着看,比如说

(void *)android_hardware_Radio_tune方法看看执行了什么

【Android项目】本地FM收音机开发及源码简析_第5张图片

 

再看看ITuner.hal文件中的tune方法

【Android项目】本地FM收音机开发及源码简析_第6张图片

似乎,接轨了。

 

 

 

5.App层如何设计本地FM应用


上面,我们简单的说完了Tuner底层的调用流程。那么问题来了,我一个做FM本地应用开发的,这些Framework都做好了。跟我有啥关系?其实不然,了解这些原理,能够在我们调试的时候更方便界定问题,难道底层就不会出错吗,对吧。而且,在定制的系统上,如果收音机定制的话,底层是会根据需求进行修改的,所以也是不稳定的。

那么如果设计应用层的框架结构呢。

答案:根据需求来。。。

假设我的需求是这样的,好吧,不是假设,实际上我的项目需求就是这样的。

【Android项目】本地FM收音机开发及源码简析_第7张图片

 

别说话,看图。

【Android项目】本地FM收音机开发及源码简析_第8张图片

 

简述下需求:

1- 主界面(Launcher)下方有个控制面板,可以对收音机进行操作。

2- 点击控制面板空白区域可以打开收音机的页面。收音机界面可以操作和显示,并收藏。 状态和外面控制面板保持一致

3- 外部可扩展的控制,盘控控制,语音控制等;

4- 遵循音频焦点策略

 

 

分析:

1- 控制面板的显示:采用widget桌面小部件的方式显示。和应用FM交互通过广播。

2- 点击空白区域打开,启动Activity界面。界面上进行操作,但是需要考虑,如果直接通过控制面板操作,则是不需要启动Activity也能播放。所以必须要有一个CoreService核 心服务在后台运行,不需要依赖界面。

3- 外部控制也应该是和Servicre进行交互。需要考虑其扩展性

4- 监听焦点获取与丢失并且进行逻辑处理。

 

设计:

经过上的分析,我们整理以下几个核心的点

CoreService 一个真正操作的核心服务

Activity 主界面

Widget 控制面板

代码设计模式:这个可以看自己,这里使用MVP模式。那么就会有两个Presenter:

RaidoPresenter 收音机核心操作(包含音频处理)

FavoritePresenter 收藏操作

其他外部控制,只需要设计数据交互模式即可。

 

最终:

来一草图

【Android项目】本地FM收音机开发及源码简析_第9张图片

算了,我自己都看不清楚,用我的灵魂之手从新画个。

【Android项目】本地FM收音机开发及源码简析_第10张图片

 

是不是清晰多了。这图就很明了了,应该很清晰。别说话,看图。

 

 

6. 总结


本篇文章比较简单了介绍了,Android本地收音机的开发的一些知识,关于这方面的资料。在网上还是比较少,通过自己的项目经验,在此输出此文,个人能力有限,难免可能有错误.

 

 

 

 

你可能感兴趣的:(Android-随笔知识)