zoukankan      html  css  js  c++  java
  • Android FM模块学习之一 FM启动流程

    转自:http://blog.csdn.net/tfslovexizi/article/details/41283743

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

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

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

    注册下fm设置(在设置后发送一个设置广播,更新FMRadio类的状态)。

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

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

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

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

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

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

    界面可用enableRadioOnOffUI()

    1. <span style="font-size:18px;">private void enableRadio() {  
    2.       mIsScaning = false;  
    3.       mIsSeeking = false;  
    4.       mIsSearching = false;  
    5.       boolean bStatus = false;  
    6.       if (isHdmiOn()) {  
    7.           showDialog(DIALOG_CMD_FAILED_HDMI_ON);  
    8.       }else {  
    9.         <span style="font-family:KaiTi_GB2312;">  </span>if (mService != null) {  
    10.              try {  
    11.                 if((false == mService.isFmOn()) && <strong>isAntennaAvailable()</strong>) {  
    12.                     bStatus = mService.fmOn();  
    13.                     if(bStatus) {  
    14.                        tuneRadio(FmSharedPreferences.getTunedFrequency());  
    15.                       <strong> enableRadioOnOffUI();</strong>  
    16.                     }else {Log.e(LOGTAG, "mService.fmOn failed");  
    17.                        mCommandFailed = CMD_FMON;  
    18.                        if(isCallActive()) {  
    19.                           enableRadioOnOffUI();  
    20.                           showDialog(DIALOG_CMD_FAILED_CALL_ON);  
    21.                        }else {  
    22.                           showDialog(DIALOG_CMD_FAILED);  
    23.                        }  
    24.                     }  
    25.                 }else {enableRadioOnOffUI();  
    26.                 }  
    27.              }catch (RemoteException e) {  
    28.                 e.printStackTrace();  
    29.              }  
    30.           }  
    31.       }  
    32.    }</span>  

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

    取出设置保存的地区频率的属性  FmConfig config =FmSharedPreferences.getFMConfiguration();

    真正接受fm声音在  bStatus =mReceiver.enable(FmSharedPreferences.getFMConfiguration());

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

    1. /* 
    2.    * Turn ON FM: Powers up FM hardware, and initializes the FM module 
    3.    *                                                                                 . 
    4.    * @return true if fm Enable api was invoked successfully, false if the api failed. 
    5.    */  
    6.    private boolean fmOn() {  
    7.       boolean bStatus=false;  
    8.       mWakeLock.acquire(10*1000);  
    9.       if ( TelephonyManager.CALL_STATE_IDLE != getCallState() ) {  
    10.          return bStatus;  
    11.       }  
    12.      if(mReceiver == null)  
    13.       {  
    14.          try {  
    15.            <strong> mReceiver = new FmReceiver(FMRADIO_DEVICE_FD_STRING, fmCallbacks);</strong>  
    16.          }  
    17.          catch (InstantiationException e)  
    18.          {  
    19.             throw new RuntimeException("FmReceiver service not available!");  
    20.          }  
    21.       }  
    22.      if (mReceiver != null)  
    23.       {  
    24.          if (isFmOn())  
    25.          {  
    26.             /* FM Is already on,*/  
    27.             bStatus = true;  
    28.             Log.d(LOGTAG, "mReceiver.already enabled");  
    29.          }  
    30.          else  
    31.          { // This sets up the FM radio device  
    32.             FmConfig config = FmSharedPreferences.getFMConfiguration();  
    33.             Log.d(LOGTAG, "fmOn: RadioBand   :"+ config.getRadioBand());  
    34.             Log.d(LOGTAG, "fmOn: Emphasis    :"+ config.getEmphasis());  
    35.             Log.d(LOGTAG, "fmOn: ChSpacing   :"+ config.getChSpacing());  
    36.             Log.d(LOGTAG, "fmOn: RdsStd      :"+ config.getRdsStd());  
    37.             Log.d(LOGTAG, "fmOn: LowerLimit  :"+ config.getLowerLimit());  
    38.             Log.d(LOGTAG, "fmOn: UpperLimit  :"+ config.getUpperLimit());  
    39.            <strong> bStatus = mReceiver.enable(FmSharedPreferences.getFMConfiguration());</strong>  
    40.             if (isSpeakerEnabled()) {  
    41.                 setAudioPath(false);  
    42.             } else {setAudioPath(true);  
    43.             }  
    44.             Log.d(LOGTAG, "mReceiver.enable done, Status :" +  bStatus);  
    45.          }  
    46.   
    47.          if (bStatus == true)  
    48.          {  
    49.             /* Put the hardware into normal mode */  
    50.            <strong> bStatus = setLowPowerMode(false);</strong>  
    51.             Log.d(LOGTAG, "setLowPowerMode done, Status :" +  bStatus);  
    52.              AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);  
    53.             if( (audioManager != null) &&(false == mPlaybackInProgress) )  
    54.             {  
    55.                Log.d(LOGTAG, "mAudioManager.setFmRadioOn = true  " );  
    56.                //audioManager.setParameters("FMRadioOn="+mAudioDevice);  
    57.                <strong>int state =  getCallState();</strong>  
    58.                if ( TelephonyManager.CALL_STATE_IDLE != getCallState() )  
    59.                {  
    60.                  <strong>fmActionOnCallState(state);</strong>  
    61.                } else {  
    62.                   <span style="color:#00CCCC;"><strong> startFM();</strong> </span>// enable FM Audio only when Call is IDLE  
    63.                }  
    64.                Log.d(LOGTAG, "mAudioManager.setFmRadioOn done  " );  
    65.             }if (mReceiver != null) {//<span style="font-family:KaiTi_GB2312;font-size:18px;">注册远程组的处理</span>  
    66. <span style="font-family:KaiTi_GB2312;">             </span> <strong>bStatus = mReceiver.registerRdsGroupProcessing(FmReceiver.FM_RX_RDS_GRP_RT_EBL|  
    67.                                                            FmReceiver.FM_RX_RDS_GRP_PS_EBL|  
    68.                                                            FmReceiver.FM_RX_RDS_GRP_AF_EBL|  
    69.                                                            FmReceiver.FM_RX_RDS_GRP_PS_SIMPLE_EBL);</strong>  
    70.                 Log.d(LOGTAG, "registerRdsGroupProcessing done, Status :" +  bStatus);  
    71.             }  
    72.             <strong>bStatus = enableAutoAF(FmSharedPreferences.getAutoAFSwitch());</strong>//<span style="font-family:KaiTi_GB2312;font-size:18px;">可用自动跳转到选着的频率</span>  
    73.             Log.d(LOGTAG, "enableAutoAF done, Status :" +  bStatus);  
    74.             /* There is no internal Antenna*/  
    75.             <strong>bStatus = mReceiver.setInternalAntenna(false);/</strong>/<span style="font-family:KaiTi_GB2312;font-size:18px;">将内置天线设为0</span>  
    76.             Log.d(LOGTAG, "setInternalAntenna done, Status :" +  bStatus);  
    77.   
    78.             /* Read back to verify the internal Antenna mode*/  
    79.             readInternalAntennaAvailable();  
    80.   
    81.             startNotification();  
    82.             bStatus = true;  
    83.          }  
    84.          else  
    85.          {mReceiver = null; // as enable failed no need to disable  
    86.                               // failure of enable can be because handle  
    87.                               // already open which gets effected if  
    88.                               // we disable  
    89.             stop();  
    90.          }  
    91.       }  
    92.       return(bStatus);  
    93.    }  

    设置铃声路径  boolean state =mReceiver.setAnalogMode(analogMode);

    1. private boolean setAudioPath(boolean analogMode) {  
    2.   
    3.      if (mReceiver == null) {  
    4.            return false;  
    5.      }  
    6.      if (isAnalogModeEnabled() == analogMode) {  
    7.              Log.d(LOGTAG,"Analog Path already is set to "+analogMode);  
    8.              return false;  
    9.      }  
    10.      if (!isAnalogModeSupported()) {  
    11.              Log.d(LOGTAG,"Analog Path is not supported ");  
    12.              return false;  
    13.      }  
    14.      if (SystemProperties.getBoolean("hw.fm.digitalpath",false)) {  
    15.              return false;  
    16.      }  
    17.   
    18.      boolean state =<strong> mReceiver.setAnalogMode(analogMode);</strong>  
    19.      if (false == state) {  
    20.          Log.d(LOGTAG, "Error in toggling analog/digital path " + analogMode);  
    21.          return false;  
    22.      }  
    23.      misAnalogPathEnabled = analogMode;  
    24.      return true;  
    25. }  

    analogMode模拟设置低功率  bStatus = setLowPowerMode(false);

    电话不在闲置状太下 int state = getCallState();

                      fmActionOnCallState(state);

    启动FM  startFM();

    1. private void startFM(){  
    2.        Log.d(LOGTAG, "In startFM");  
    3.        if(true == mAppShutdown) { // not to send intent to AudioManager in Shutdown  
    4.            return;  
    5.        }  
    6.        if (isCallActive()) { // when Call is active never let audio playback  
    7.            mResumeAfterCall = true;  
    8.            return;  
    9.        }  
    10.        mResumeAfterCall = false;  
    11.        if ( true == mPlaybackInProgress ) // no need to resend event  
    12.            return;  
    13.        AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);  
    14.        int granted = audioManager.requestAudioFocus(mAudioFocusListener, AudioManager.STREAM_MUSIC,  
    15.               AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);  
    16.        if(granted != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {  
    17.           Log.d(LOGTAG, "audio focuss couldnot be granted");  
    18.           return;  
    19.        }  
    20.          
    21.        Log.d(LOGTAG,"FM registering for registerMediaButtonEventReceiver");  
    22.        mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);  
    23.        ComponentName fmRadio = new ComponentName(this.getPackageName(),  
    24.                                   FMMediaButtonIntentReceiver.class.getName());  
    25.        mAudioManager.registerMediaButtonEventReceiver(fmRadio);  
    26.        mStoppedOnFocusLoss = false;  
    27.   
    28.        if (!isSpeakerEnabled() && !mA2dpDeviceSupportInHal &&  (true == mA2dpDeviceState.isDeviceAvailable()) &&  
    29.            !isAnalogModeEnabled()  
    30.             && (true == startA2dpPlayback())) {  
    31.             mOverA2DP=true;  
    32.             Log.d(LOGTAG, "Audio source set it as A2DP");  
    33.           <strong>  AudioSystem.setForceUse(AudioSystem.FOR_MEDIA, AudioSystem.FORCE_BT_A2DP);</strong>  
    34.        } else {  
    35.            Log.d(LOGTAG, "FMRadio: Requesting to start FM");  
    36.            //reason for resending the Speaker option is we are sending  
    37.            //ACTION_FM=1 to AudioManager, the previous state of Speaker we set  
    38.            //need not be retained by the Audio Manager.  
    39.            <strong>AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_FM,  
    40.                                AudioSystem.DEVICE_STATE_AVAILABLE, "");</strong>//<span style="font-family:KaiTi_GB2312;font-size:18px;">Fm设备</span>  
    41.            if (isSpeakerEnabled()) {  
    42.                mSpeakerPhoneOn = true;  
    43.                Log.d(LOGTAG, "Audio source set it as speaker");  
    44.               <strong> AudioSystem.setForceUse(AudioSystem.FOR_MEDIA, AudioSystem.FORCE_SPEAKER);</strong>  
    45.            } else {  
    46.                Log.d(LOGTAG, "Audio source set it as headset");  
    47.               <strong> AudioSystem.setForceUse(AudioSystem.FOR_MEDIA, AudioSystem.FORCE_NONE);</strong>  
    48.            }  
    49.   
    50.        }  
    51.        sendRecordServiceIntent(RECORD_START);  
    52.        mPlaybackInProgress = true;  
    53.    }  


    设置耳机等可以接受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  

    mReceiver.setInternalAntenna(false)
    FmReceiverJNI.setControlNative (sFd, V4L2_CID_PRIVATE_TAVARUA_ANTENNA,iAntenna)

    1. <span style="font-size:18px;"> /*============================================================== 
    2.    FUNCTION:  setInternalAntenna 
    3.    ==============================================================*/  
    4.    /** 
    5.    *    Returns true if successful, false otherwise 
    6.    * 
    7.    *    <p> 
    8.    *    This method sets internal antenna type to true/false 
    9.    * 
    10.    *    @param intAntenna true is Internal antenna is present 
    11.    * 
    12.    *    <p> 
    13.    *    @return    true/false 
    14.    */  
    15.  public boolean setInternalAntenna(boolean intAnt)  
    16.    {  
    17.   
    18.        int iAntenna ;  
    19.   
    20.        if (intAnt)  
    21.           iAntenna = 1;  
    22.        else  
    23.           iAntenna = 0;  
    24.   
    25.   
    26.        int re = <strong>FmReceiverJNI.setControlNative (sFd, V4L2_CID_PRIVATE_TAVARUA_ANTENNA, iAntenna);</strong>  
    27.   
    28.        if (re == 0)  
    29.          return true;  
    30.   
    31.        return false;  
    32.    }</span>  


    好,到此为止,FM的启动工作基本上就完成了。接下来就需要去搜索频道了,后续会继续分析FM搜索

  • 相关阅读:
    BUAA OO 2019 第三单元作业总结
    OpenJML入门
    BUAA OO 2019 第二单元作业总结
    BUAA OO 2019 第一单元作业总结
    Spring MVC原理
    Spring AOP原理
    Spring DI原理
    Spring IOC原理分析
    观察者模式
    装饰模式
  • 原文地址:https://www.cnblogs.com/mochaMM/p/5151842.html
Copyright © 2011-2022 走看看