最近在学习FM模块,FM是一个值得学习的模块,可以从上层看到底层。上层就是FM的按扭操作和界面显示,从而调用到FM底层驱动来实现广播收听的功能。

看看FM启动流程:如下图:

Android FM模块学习之一 FM启动流程0

 

先进入FMRadio.java类,onCreate初始化一些数据,画出FM界面,启动fm在onStart()方法里启动FMRadioService.java (调用bindToService(this, osc)方法)。

Android FM模块学习之一 FM启动流程1

注册下fm设置(在设置后发送一个设置广播,更新FMRadio类的状态)。Android FM模块学习之一 FM启动流程2

加载初始化数据,获取频率地址

newPresetStation("",FmSharedPreferences.getTunedFrequency());

Android FM模块学习之一 FM启动流程3

在bindToService(this,osc)方法中,先启动StartService(同一个Service只onCreate一次),再启动bindservice(这样有个好处按返回键service不会走onDestroy方法)bindservice通过onBind回传一个IBinder对象到FMRadio类的内部类ServiceConnection的onServiceConnected方法中,调用enableRadio()方法。

Android FM模块学习之一 FM启动流程4 

 

在enableRaido方法中调用FMRadio.java的isAntennaAvailable()方法进行耳机判断,天线判断是否可用,通过一个插入拔出广播接收来控制的(FMRadio中的registerHeadsetListener()方法)action(Intent.ACTION_HEADSET_PLUG) 

mHeadsetPlugged =(intent.getIntExtra("state", 0) == 1); 等于1说明耳机可用,等于0可用。

 

调用FmRadio方法FmOn  (mService.fmOn())

界面可用enableRadioOnOffUI()

 

private void enableRadio() {
      mIsScaning = false;
      mIsSeeking = false;
      mIsSearching = false;
      boolean bStatus = false;
      if (isHdmiOn()) {
          showDialog(DIALOG_CMD_FAILED_HDMI_ON);
      }else {
        <span style="font-family:KaiTi_GB2312;">  </span>if (mService != null) {
             try {
                if((false == mService.isFmOn()) && isAntennaAvailable()) {
                    bStatus = mService.fmOn();
                    if(bStatus) {
                       tuneRadio(FmSharedPreferences.getTunedFrequency());
                       enableRadioOnOffUI();
                    }else {Log.e(LOGTAG, "mService.fmOn failed");
                       mCommandFailed = CMD_FMON;
                       if(isCallActive()) {
                          enableRadioOnOffUI();
                          showDialog(DIALOG_CMD_FAILED_CALL_ON);
                       }else {
                          showDialog(DIALOG_CMD_FAILED);
                       }
                    }
                }else {enableRadioOnOffUI();
                }
             }catch (RemoteException e) {
                e.printStackTrace();
             }
          }
      }
   }

在FMRadioService.java的fmOn()方法中初始化FmReceiver的引用mReceiver = newFmReceiver(FMRADIO_DEVICE_FD_STRING, fmCallbacks);

取出设置保存的地区频率的属性

FmConfig config =FmSharedPreferences.getFMConfiguration();

真正接受fm声音在

bStatus =mReceiver.enable(FmSharedPreferences.getFMConfiguration());

 

isSpeakerEnabled()扬声器可用,用户设置扬声器

 

设置铃声路径

boolean state =mReceiver.setAnalogMode(analogMode); analogMode模拟设置低功率

 

bStatus = setLowPowerMode(false);

电话不在闲置状太下

int state = getCallState();

fmActionOnCallState(state);

 

启动FM  startFM();设置耳机等可以接受fm声音

AudioSystem.setForceUse(AudioSystem.FOR_MEDIA,AudioSystem.FORCE_NONE);

Fm设备可用

AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_FM,

                                    AudioSystem.DEVICE_STATE_AVAILABLE, "");

 

注册远程组的处理

 bStatus = mReceiver.registerRdsGroupProcessing(FmReceiver.FM_RX_RDS_GRP_RT_EBL|

                                                          FmReceiver.FM_RX_RDS_GRP_PS_EBL|

                                                          FmReceiver.FM_RX_RDS_GRP_AF_EBL|

                                                           FmReceiver.FM_RX_RDS_GRP_PS_SIMPLE_EBL);

 

可用自动跳转到选着的频率

bStatus =enableAutoAF(FmSharedPreferences.getAutoAFSwitch());

 

将内置天线设为0

FmTransceiver.java
FmReceiverJNI.setControlNative (sFd, V4L2_CID_PRIVATE_TAVARUA_ANTENNA,iAntenna)

mReceiver.setInternalAntenna(false)

 

总结:该代码流程对各大厂商来说,已经有很大差异,但是总体流程差异不大,仅做参考,有错误之处,欢迎各路大神指点~~~

posted on 2015-01-25 22:37  King_Li  阅读(889)  评论(0编辑  收藏  举报