zoukankan      html  css  js  c++  java
  • Android FM学习中的模块 FM启动过程

       最近的研究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()


    <span style="font-size:18px;">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()) && <strong>isAntennaAvailable()</strong>) {
                        bStatus = mService.fmOn();
                        if(bStatus) {
                           tuneRadio(FmSharedPreferences.getTunedFrequency());
                          <strong> enableRadioOnOffUI();</strong>
                        }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();
                 }
              }
          }
       }</span>
    

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

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

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

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

     

    /*
       * Turn ON FM: Powers up FM hardware, and initializes the FM module
       *                                                                                 .
       * @return true if fm Enable api was invoked successfully, false if the api failed.
       */
       private boolean fmOn() {
          boolean bStatus=false;
          mWakeLock.acquire(10*1000);
          if ( TelephonyManager.CALL_STATE_IDLE != getCallState() ) {
             return bStatus;
          }
         if(mReceiver == null)
          {
             try {
               <strong> mReceiver = new FmReceiver(FMRADIO_DEVICE_FD_STRING, fmCallbacks);</strong>
             }
             catch (InstantiationException e)
             {
                throw new RuntimeException("FmReceiver service not available!");
             }
          }
         if (mReceiver != null)
          {
             if (isFmOn())
             {
                /* FM Is already on,*/
                bStatus = true;
                Log.d(LOGTAG, "mReceiver.already enabled");
             }
             else
             { // This sets up the FM radio device
                FmConfig config = FmSharedPreferences.getFMConfiguration();
                Log.d(LOGTAG, "fmOn: RadioBand   :"+ config.getRadioBand());
                Log.d(LOGTAG, "fmOn: Emphasis    :"+ config.getEmphasis());
                Log.d(LOGTAG, "fmOn: ChSpacing   :"+ config.getChSpacing());
                Log.d(LOGTAG, "fmOn: RdsStd      :"+ config.getRdsStd());
                Log.d(LOGTAG, "fmOn: LowerLimit  :"+ config.getLowerLimit());
                Log.d(LOGTAG, "fmOn: UpperLimit  :"+ config.getUpperLimit());
               <strong> bStatus = mReceiver.enable(FmSharedPreferences.getFMConfiguration());</strong>
                if (isSpeakerEnabled()) {
                    setAudioPath(false);
                } else {setAudioPath(true);
                }
                Log.d(LOGTAG, "mReceiver.enable done, Status :" +  bStatus);
             }
    
             if (bStatus == true)
             {
                /* Put the hardware into normal mode */
               <strong> bStatus = setLowPowerMode(false);</strong>
                Log.d(LOGTAG, "setLowPowerMode done, Status :" +  bStatus);
                 AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
                if( (audioManager != null) &&(false == mPlaybackInProgress) )
                {
                   Log.d(LOGTAG, "mAudioManager.setFmRadioOn = true 
    " );
                   //audioManager.setParameters("FMRadioOn="+mAudioDevice);
                   <strong>int state =  getCallState();</strong>
                   if ( TelephonyManager.CALL_STATE_IDLE != getCallState() )
                   {
                     <strong>fmActionOnCallState(state);</strong>
                   } else {
                      <span style="color:#00CCCC;"><strong> startFM();</strong> </span>// enable FM Audio only when Call is IDLE
                   }
                   Log.d(LOGTAG, "mAudioManager.setFmRadioOn done 
    " );
                }if (mReceiver != null) {//<span style="font-family:KaiTi_GB2312;font-size:18px;">注冊远程组的处理</span>
    <span style="font-family:KaiTi_GB2312;">             </span> <strong>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);</strong>
                    Log.d(LOGTAG, "registerRdsGroupProcessing done, Status :" +  bStatus);
                }
                <strong>bStatus = enableAutoAF(FmSharedPreferences.getAutoAFSwitch());</strong>//<span style="font-family:KaiTi_GB2312;font-size:18px;">可用自己主动跳转到选着的频率</span>
                Log.d(LOGTAG, "enableAutoAF done, Status :" +  bStatus);
                /* There is no internal Antenna*/
                <strong>bStatus = mReceiver.setInternalAntenna(false);/</strong>/<span style="font-family:KaiTi_GB2312;font-size:18px;">将内置天线设为0</span>
                Log.d(LOGTAG, "setInternalAntenna done, Status :" +  bStatus);
    
                /* Read back to verify the internal Antenna mode*/
                readInternalAntennaAvailable();
    
                startNotification();
                bStatus = true;
             }
             else
             {mReceiver = null; // as enable failed no need to disable
                                  // failure of enable can be because handle
                                  // already open which gets effected if
                                  // we disable
                stop();
             }
          }
          return(bStatus);
       }

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

       private boolean setAudioPath(boolean analogMode) {
    
            if (mReceiver == null) {
                  return false;
            }
            if (isAnalogModeEnabled() == analogMode) {
                    Log.d(LOGTAG,"Analog Path already is set to "+analogMode);
                    return false;
            }
            if (!isAnalogModeSupported()) {
                    Log.d(LOGTAG,"Analog Path is not supported ");
                    return false;
            }
            if (SystemProperties.getBoolean("hw.fm.digitalpath",false)) {
                    return false;
            }
    
            boolean state =<strong> mReceiver.setAnalogMode(analogMode);</strong>
            if (false == state) {
                Log.d(LOGTAG, "Error in toggling analog/digital path " + analogMode);
                return false;
            }
            misAnalogPathEnabled = analogMode;
            return true;
       }

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

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

                      fmActionOnCallState(state);


    启动FM  startFM();

    private void startFM(){
           Log.d(LOGTAG, "In startFM");
           if(true == mAppShutdown) { // not to send intent to AudioManager in Shutdown
               return;
           }
           if (isCallActive()) { // when Call is active never let audio playback
               mResumeAfterCall = true;
               return;
           }
           mResumeAfterCall = false;
           if ( true == mPlaybackInProgress ) // no need to resend event
               return;
           AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
           int granted = audioManager.requestAudioFocus(mAudioFocusListener, AudioManager.STREAM_MUSIC,
                  AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
           if(granted != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
              Log.d(LOGTAG, "audio focuss couldnot be granted");
              return;
           }
           
           Log.d(LOGTAG,"FM registering for registerMediaButtonEventReceiver");
           mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
           ComponentName fmRadio = new ComponentName(this.getPackageName(),
                                      FMMediaButtonIntentReceiver.class.getName());
           mAudioManager.registerMediaButtonEventReceiver(fmRadio);
           mStoppedOnFocusLoss = false;
    
           if (!isSpeakerEnabled() && !mA2dpDeviceSupportInHal &&  (true == mA2dpDeviceState.isDeviceAvailable()) &&
               !isAnalogModeEnabled()
                && (true == startA2dpPlayback())) {
                mOverA2DP=true;
                Log.d(LOGTAG, "Audio source set it as A2DP");
              <strong>  AudioSystem.setForceUse(AudioSystem.FOR_MEDIA, AudioSystem.FORCE_BT_A2DP);</strong>
           } else {
               Log.d(LOGTAG, "FMRadio: Requesting to start FM");
               //reason for resending the Speaker option is we are sending
               //ACTION_FM=1 to AudioManager, the previous state of Speaker we set
               //need not be retained by the Audio Manager.
               <strong>AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_FM,
                                   AudioSystem.DEVICE_STATE_AVAILABLE, "");</strong>//<span style="font-family:KaiTi_GB2312;font-size:18px;">Fm设备</span>
               if (isSpeakerEnabled()) {
                   mSpeakerPhoneOn = true;
                   Log.d(LOGTAG, "Audio source set it as speaker");
                  <strong> AudioSystem.setForceUse(AudioSystem.FOR_MEDIA, AudioSystem.FORCE_SPEAKER);</strong>
               } else {
                   Log.d(LOGTAG, "Audio source set it as headset");
                  <strong> AudioSystem.setForceUse(AudioSystem.FOR_MEDIA, AudioSystem.FORCE_NONE);</strong>
               }
    
           }
           sendRecordServiceIntent(RECORD_START);
           mPlaybackInProgress = true;
       }

    设置耳机等能够接受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)

    <span style="font-size:18px;"> /*==============================================================
       FUNCTION:  setInternalAntenna
       ==============================================================*/
       /**
       *    Returns true if successful, false otherwise
       *
       *    <p>
       *    This method sets internal antenna type to true/false
       *
       *    @param intAntenna true is Internal antenna is present
       *
       *    <p>
       *    @return    true/false
       */
     public boolean setInternalAntenna(boolean intAnt)
       {
    
           int iAntenna ;
    
           if (intAnt)
              iAntenna = 1;
           else
              iAntenna = 0;
    
    
           int re = <strong>FmReceiverJNI.setControlNative (sFd, V4L2_CID_PRIVATE_TAVARUA_ANTENNA, iAntenna);</strong>
    
           if (re == 0)
             return true;
    
           return false;
       }</span>

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




  • 相关阅读:
    scrapy 中间件
    索引
    理解平均负载
    jquery1
    网络编程
    模块
    进程
    图书管理系统用ajax删除书籍
    mysql
    jquery
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/5023180.html
Copyright © 2011-2022 走看看