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搜索




  • 相关阅读:
    [LeetCode]2. Add Two Numbers链表相加
    Integration between Dynamics 365 and Dynamics 365 Finance and Operation
    向视图列添加自定义图标和提示信息 -- PowerApps / Dynamics365
    Update the Power Apps portals solution
    Migrate portal configuration
    Use variable to setup related components visible
    Loyalty management on Retail of Dynamic 365
    Modern Fluent UI controls in Power Apps
    Change screen size and orientation of a canvas app in Power App
    Communication Plan for Power Platform
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/5023180.html
Copyright © 2011-2022 走看看