Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android FM模塊學習之二 FM搜索頻率流程

Android FM模塊學習之二 FM搜索頻率流程

編輯:關於Android編程

上一篇大概分析了一下FM啟動流程,若不了解Fm啟動流程的,可以去打開前面的鏈接先了解FM啟動流程,接下來我們簡單分析一下FM的搜索頻率流程。

在了解源碼之前,我們先看一下流程圖:

\

其實從圖中可以看到,實現搜索頻率的功能是在底層CPP文件,java層只操作和更新一些界面(GUI),Java調用JNI實現功能。Java app基本核心,通過方法回調實現a類和b類方法,b類調a類方法信息交互相互控制融為一體。App實現一些JNI接口最終實現核心功能是cpp文件,最後通過Service類(耗時操作)調用New一個線程循環不斷的獲取cpp裡的信息,去更新UI界面活動狀態。

搜索流程簡單分析<喎?/kf/ware/vc/" target="_blank" class="keylink">vc3Ryb25nPqO6teO798vRy/ewtMWlo6zNqLn9u6W197e9t6ijrNfuuvO197W9Rk1SZWNlaXZlckpOScDg1tC1xLe9t6jKtc/WuabE3KGjzai5/UZNUnhFdmVudExpc3RuZXLA4LK7ts+78cihY3BwseTGtbXExrXCyqOsw7+78cih0ru0zsa1wsoo1rG1vca1wsrL0cv3zeqzyc2j1rm199PDKb7Nu9i190ZNUmFkaW9TZXJ2aWNlxNqyv0ZtUnhFdkNhbGxiYWNrc0FkYXB0b3K1xLe9t6jU2rvYtfe1vUZNUmFkaW/A4NbQt723qKOsvavGtcLKtObI60ZtU2hhcmVkUHJlZmVyZW5jZXPA4HhtbM7EtbXW0KOst6LLzUhhbmRsZXK4/NDCVUmjrLy0v8y2yMXMo6y21Luwv/KjrNfz09K8/c231tC85M/Uyr61xMa1wsrSu9bCzPi2r6GjPC9wPgo8cD4gICC908/CwLTP6s+4tPrC67fWzvajujxicj4KPC9wPgo8cD4gICAgRk1SYWRpb9bQtcSyy7Wly9HL97mmxNyjrG9uT3B0aW9uc0l0ZW1TZWxlY3RlZChNZW51SXRlbSBpdGVtKbzgzP3W0NffaW5pdGlhdGVTZWFyY2gobVNjYW5QdHlJbmRleCk7t723qKGjPC9wPgo8cD48aW1nIHNyYz0="/uploadfile/Collfiles/20141121/2014112108585517.jpg" alt="\">


\


\

調用FMRadioService的scan()方法(mService.scan(pty))進行掃描頻率

\

updateSearchProgress()裡加了同步方法對象鎖

\

調用了private Dialog createProgressDialog(int id)對話框進行搜索信息

標准耳機FmSharedPreferences.isRBDSStd()

private Dialog createProgressDialog(int id) {
      String msgStr = "";
      String titleStr = "";
      String []items;
      double frequency = mTunedStation.getFrequency() / 1000.0;
      boolean bSearchActive = false;

      if (isSeekActive()) {
          msgStr = getString(R.string.msg_seeking);
          bSearchActive = true;
      }else if (isScanActive()) {
          if(FmSharedPreferences.isRBDSStd()) {//標准耳機
                items = getResources().
                         getStringArray(R.array.search_category_rbds_entries);
          }else { // if(FmSharedPreferences.isRDSStd())
                items = getResources().
                         getStringArray(R.array.search_category_rds_entries);
          }String ptyStr = "";
          if (items.length > mScanPtyIndex)
              ptyStr = items[mScanPtyIndex];
          if (!TextUtils.isEmpty(ptyStr)) {
             msgStr = getString(R.string.msg_scanning_pty, ptyStr);
          }else {
             Log.d(LOGTAG, "pty is null\n");
             msgStr = getString(R.string.msg_scanning);
          }
          titleStr = getString(R.string.msg_search_title, ("" + frequency));
          bSearchActive=true;
      }else if (isSearchActive()) {
         msgStr = getString(R.string.msg_searching);
         titleStr = getString(R.string.msg_searching_title);
         bSearchActive = true;
      }
      if (bSearchActive) {mProgressDialog = new ProgressDialog(FMRadio.this);
          if (mProgressDialog != null) {
              mProgressDialog.setTitle(titleStr);
              mProgressDialog.setMessage(msgStr);
              mProgressDialog.setIcon(R.drawable.ic_launcher_fmradio);
              mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
              mProgressDialog.setCanceledOnTouchOutside(false);
              mProgressDialog.setButton(DialogInterface.BUTTON_POSITIVE,
                                   getText(R.string.button_text_stop),
               new DialogInterface.OnClickListener() {
                  public void onClick(DialogInterface dialog, int whichButton) {
                      cancelSearch();
                  }
              });
              mProgressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() { public void onCancel(DialogInterface dialog) {
                   cancelSearch();
                }
              });
              mProgressDialog.setOnKeyListener(new OnKeyListener() {
                public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
                    Log.d(LOGTAG, "OnKeyListener event received in ProgressDialog" + keyCode);
                    switch (keyCode) {
                        case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
                        case 126: //KeyEvent.KEYCODE_MEDIA_PLAY:
                        case 127: //KeyEvent.KEYCODE_MEDIA_PAUSE:
                        case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
                        case KeyEvent.KEYCODE_MEDIA_NEXT:
                        case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
                        case KeyEvent.KEYCODE_MEDIA_REWIND:
                        case KeyEvent.KEYCODE_MEDIA_STOP:
                            return true;
                    } return false;
                }
            });
          }
          Message msg = new Message();
          msg.what = TIMEOUT_PROGRESS_DLG;
          mSearchProgressHandler.sendMessageDelayed(msg, SHOWBUSY_TIMEOUT);
      }
      return mProgressDialog;
   }
調用FMRadioService類中的Scan()方法掃描

調用 FMReceiver的searchStations()方法進行掃描

public boolean scan(int pty)
   {
      boolean bCommandSent=false;
      if (mReceiver != null)
      {
         Log.d(LOGTAG, "scan:  PTY: " + pty);
         if(FmSharedPreferences.isRBDSStd())
         {
            /* RBDS : Validate PTY value?? */
            if( ((pty  > 0) && (pty  <= 23)) || ((pty  >= 29) && (pty  <= 31)) )
            {bCommandSent = mReceiver.searchStations(FmReceiver.FM_RX_SRCHRDS_MODE_SCAN_PTY,
                                                       FmReceiver.FM_RX_DWELL_PERIOD_2S,
                                                       FmReceiver.FM_RX_SEARCHDIR_UP,
                                                       pty,
                                                       0);
            }
            else
            {
               bCommandSent = mReceiver.searchStations(FmReceiver.FM_RX_SRCH_MODE_SCAN,
                                                FmReceiver.FM_RX_DWELL_PERIOD_2S,
                                                FmReceiver.FM_RX_SEARCHDIR_UP);
            }}
         else
         {
            /* RDS : Validate PTY value?? */
            if( (pty  > 0) && (pty  <= 31) )
            {
               bCommandSent = mReceiver.searchStations(FmReceiver.FM_RX_SRCHRDS_MODE_SCAN_PTY,
                                                          FmReceiver.FM_RX_DWELL_PERIOD_2S,
                                                          FmReceiver.FM_RX_SEARCHDIR_UP,
                                                          pty,
                                                          0);
            }
            else{
               bCommandSent = mReceiver.searchStations(FmReceiver.FM_RX_SRCH_MODE_SCAN,
                                                FmReceiver.FM_RX_DWELL_PERIOD_2S,
                                                FmReceiver.FM_RX_SEARCHDIR_UP);
            }
         }
      }
      return bCommandSent;
   }

FmReceiver類的public boolean searchStations (int mode,int dwellPeriod,intdirection,int pty,Int pi) 方法

獲得FMState狀態

int state = getFMState();

/ * 驗證參數* /

調用setSearchState(subSrchLevel_ScanInProg);

re = mControl.searchStations(sFd, mode,dwellPeriod, direction, pty, pi);

public boolean searchStations (int mode,
                                  int dwellPeriod,
                                  int direction){

      int state = getFMState();//獲得FMState狀態
      boolean bStatus = true;
      int re;

      /* Check current state of FM device */
      if (state == FMState_Turned_Off || state == FMState_Srch_InProg) {
          Log.d(TAG, "searchStations: Device currently busy in executing another command.");
          return false;
      }

      Log.d (TAG, "Basic search...");
      /* Validate the arguments */
      if ( (mode != FM_RX_SRCH_MODE_SEEK) &&
           (mode != FM_RX_SRCH_MODE_SCAN))
      {
         Log.d (TAG, "Invalid search mode: " + mode );
         bStatus = false;
      }
      if ( (dwellPeriod < FM_RX_DWELL_PERIOD_0S ) ||
           (dwellPeriod > FM_RX_DWELL_PERIOD_7S))
      {
         Log.d (TAG, "Invalid dwelling time: " + dwellPeriod);
         bStatus = false;
      }
      if ( (direction != FM_RX_SEARCHDIR_DOWN) &&
           (direction != FM_RX_SEARCHDIR_UP))
      {
         Log.d (TAG, "Invalid search direction: " + direction);
         bStatus = false;
      }
      if (bStatus)
      {
         Log.d (TAG, "searchStations: mode " + mode + "direction:  " + direction);

         if (mode == FM_RX_SRCH_MODE_SEEK)
             setSearchState(subSrchLevel_SeekInPrg);
         else if (mode == FM_RX_SRCH_MODE_SCAN)
             setSearchState(subSrchLevel_ScanInProg);
         Log.v(TAG, "searchStations: CURRENT-STATE : FMRxOn ---> NEW-STATE : SearchInProg");

         re = mControl.searchStations(sFd, mode, dwellPeriod, direction, 0, 0);
         if (re != 0) {
             Log.e(TAG, "search station failed");
             if (getFMState() == FMState_Srch_InProg)
                 setSearchState(subSrchLevel_SrchComplete);
             return false;
         }         state = getFMState();
         if (state == FMState_Turned_Off) {
             Log.d(TAG, "searchStations: CURRENT-STATE : FMState_Off (unexpected)");
             return false;
         }
      }
      return bStatus;
   }

設置FM搜索電源狀態

static void setSearchState(int state)
   {
      mSearchState = state;
      switch(mSearchState) {
         case subSrchLevel_SeekInPrg:
         case subSrchLevel_ScanInProg:
         case subSrchLevel_SrchListInProg:
            setFMPowerState(FMState_Srch_InProg);
            break;
         case subSrchLevel_SrchComplete:
            /* Update the state of the FM device */
            mSearchState = subSrchLevel_NoSearch;
            setFMPowerState(FMState_Rx_Turned_On);
            break;
         case subSrchLevel_SrchAbort:
            break;
         default:
            mSearchState = subSrchLevel_NoSearch;
            break;
      }
   }
setFMPowerState(FMState_Rx_Turned_On); 是調用FmTransceiver類發射器類,FM電源狀態

/*==============================================================
   FUNCTION:  setFMPowerState
   ==============================================================*/
   /**
   *    Sets the FM power state
   *
   *    

* This method sets the FM power state. * *

*/ static void setFMPowerState(int state) { FMState = state; }

調用FMRxControls.java類的

/ * 配置各種搜索參數,開始搜索* /

public int searchStations (int fd, int mode,int dwell, int dir, int pty, int pi)

設置一些參數

FmReceiverJNI.setControlNative();

設置的搜索模式

設置掃描居住的時間

設置的企業

設置PI

/* configure various search parameters and start search */
   public int searchStations (int fd, int mode, int dwell,
                               int dir, int pty, int pi){
      int re = 0;


      Log.d(TAG, "Mode is " + mode + " Dwell is " + dwell);
      Log.d(TAG, "dir is "  + dir + " PTY is " + pty);
      Log.d(TAG, "pi is " + pi + " id " +  V4L2_CID_PRIVATE_TAVARUA_SRCHMODE);



      re = FmReceiverJNI.setControlNative (fd, V4L2_CID_PRIVATE_TAVARUA_SRCHMODE, mode);
      if (re != 0) {
          Log.e(TAG, "setting of search mode failed");
          return re;
      }
      re = FmReceiverJNI.setControlNative (fd, V4L2_CID_PRIVATE_TAVARUA_SCANDWELL, dwell);
      if (re != 0) {
          Log.e(TAG, "setting of scan dwell time failed");
          return re;
      }
      if (pty != 0)
      {  re = FmReceiverJNI.setControlNative (fd, V4L2_CID_PRIVATE_TAVARUA_SRCH_PTY, pty);
         if (re != 0) {
             Log.e(TAG, "setting of PTY failed");
             return re;
         }
      }

      if (pi != 0)
      {
         re = FmReceiverJNI.setControlNative (fd, V4L2_CID_PRIVATE_TAVARUA_SRCH_PI, pi);
         if (re != 0) {
             Log.e(TAG, "setting of PI failed");
             return re;
         }
      }

      re = FmReceiverJNI.startSearchNative (fd, dir );
      return re;
   }

啟動搜索 FmReceiverJNI.startSearchNative (fd, dir );

關閉搜索

FMRadio 調用 FMRadioService 的CancelSearch()方法

public boolean cancelSearch()

public boolean cancelSearch()
   {
      boolean bCommandSent=false;
      if (mReceiver != null)
      {
         Log.d(LOGTAG, "cancelSearch");
         bCommandSent = mReceiver.cancelSearch();
      }
      return bCommandSent;
   }
調用FRReceiver的cancelSearch()

mReceiver.cancelSearch()

更新搜索 FMRadio.java中

updateSearchProgress();

private void updateSearchProgress() {
      boolean searchActive = isScanActive() || isSeekActive() || isSearchActive();
      if (searchActive) {
         synchronized (this) {
            if(mProgressDialog == null) {
               showDialog(DIALOG_PROGRESS_PROGRESS);
            }else {
               Message msg = new Message();
               msg.what = UPDATE_PROGRESS_DLG;
               mSearchProgressHandler.sendMessage(msg);
            }
         }
      }else {
         Message msg = new Message();
         msg.what = END_PROGRESS_DLG;
         mSearchProgressHandler.sendMessage(msg);
      }
   }

初始化菜單 invalidateOptionsMenu();

調用FMRxControls類的public void cancelSearch (int fd)方法

最後調用FMReceiver類的cancelSearchNative()

/* cancel search in progress */
   public void cancelSearch (int fd){
      FmReceiverJNI.cancelSearchNative(fd);
   }
最後發送一個mSearchProgressHandler

msg.what = END_PROGRESS_DLG;

mSearchProgressHandler.sendMessage(msg)

刪除handler發送消息關閉對話框

private Handler mSearchProgressHandler = new Handler() {
       public void handleMessage(Message msg) {
           if (msg.what == UPDATE_PROGRESS_DLG) {
              if(mProgressDialog != null) {
                 double frequency = mTunedStation.getFrequency() / 1000.0;
                 String titleStr = getString(R.string.msg_search_title, ("" + frequency));
                 mProgressDialog.setTitle(titleStr);
              }
           }else if (msg.what == END_PROGRESS_DLG) {
              mSearchProgressHandler.removeMessages(END_PROGRESS_DLG);
              mSearchProgressHandler.removeMessages(UPDATE_PROGRESS_DLG);
              mSearchProgressHandler.removeMessages(TIMEOUT_PROGRESS_DLG);
              removeDialog(DIALOG_PROGRESS_PROGRESS);
              mProgressDialog = null;
           }else if (msg.what == TIMEOUT_PROGRESS_DLG) {
              cancelSearch();
           }
       }
   };

在搜索中更新FMRadioUI界面的監聽類FmRxEventListner.java

 public void startListner (final int fd, final FmRxEvCallbacks cb) {
        /* start a thread and listen for messages */
        mThread = new Thread(){
            public void run(){
                byte [] buff = new byte[STD_BUF_SIZE];
                Log.d(TAG, "Starting listener " + fd);

                while ((!Thread.currentThread().isInterrupted())) {

                    try {
                        int index = 0;
                        int state = 0;
                        Arrays.fill(buff, (byte)0x00);
                        int freq = 0;
                        int eventCount = FmReceiverJNI.getBufferNative (fd, buff, EVENT_LISTEN);

                        if (eventCount >= 0)
                            Log.d(TAG, "Received event. Count: " + eventCount);

                        for (  index = 0; index < eventCount; index++ ) {
                            Log.d(TAG, "Received <" +buff[index]+ ">" );

                            switch(buff[index]){
                            case 0:Log.d(TAG, "Got READY_EVENT");
                                if(FmTransceiver.getFMPowerState() == FmTransceiver.subPwrLevel_FMRx_Starting) {
                                    /*Set the state as FMRxOn */
                                    FmTransceiver.setFMPowerState(FmTransceiver.FMState_Rx_Turned_On);
                                    Log.v(TAG, "RxEvtList: CURRENT-STATE : FMRxStarting ---> NEW-STATE : FMRxOn");
                                    cb.FmRxEvEnableReceiver();
                                }
                                else if (FmTransceiver.getFMPowerState() == FmTransceiver.subPwrLevel_FMTurning_Off) {
                                    /*Set the state as FMOff */
                                    FmTransceiver.setFMPowerState(FmTransceiver.FMState_Turned_Off);
                                    Log.v(TAG, "RxEvtList: CURRENT-STATE : FMTurningOff ---> NEW-STATE : FMOff");
                                    FmTransceiver.release("/dev/radio0");
                                    cb.FmRxEvDisableReceiver();
                                    Thread.currentThread().interrupt();
                                }
                                break;case 1:
                                Log.d(TAG, "Got TUNE_EVENT");
                                freq = FmReceiverJNI.getFreqNative(fd);
                                state = FmReceiver.getSearchState();
                                switch(state) {
                                   case FmTransceiver.subSrchLevel_SeekInPrg :
                                        Log.v(TAG, "Current state is " + state);
                                        FmReceiver.setSearchState(FmTransceiver.subSrchLevel_SrchComplete);
                                        Log.v(TAG, "RxEvtList: CURRENT-STATE : Search ---> NEW-STATE : FMRxOn");
                                        cb.FmRxEvSearchComplete(freq);
                                        break;
                                   default:
                                        if (freq > 0)
                                            cb.FmRxEvRadioTuneStatus(freq);
                                        else
                                            Log.e(TAG, "get frequency command failed");
                                        break;
                                }
                                break;
                            case 2:Log.d(TAG, "Got SEEK_COMPLETE_EVENT");
                                state = FmReceiver.getSearchState();
                                switch(state) {
                                   case FmTransceiver.subSrchLevel_ScanInProg:
                                      Log.v(TAG, "Current state is " + state);
                                      FmReceiver.setSearchState(FmTransceiver.subSrchLevel_SrchComplete);
                                      Log.v(TAG, "RxEvtList: CURRENT-STATE : Search ---> NEW-STATE : FMRxOn");
                                      cb.FmRxEvSearchComplete(FmReceiverJNI.getFreqNative(fd));
                                      break;
                                   case FmTransceiver.subSrchLevel_SrchAbort:
                                      Log.v(TAG, "Current state is SRCH_ABORTED");
                                      Log.v(TAG, "Aborting on-going search command...");
                                      FmReceiver.setSearchState(FmTransceiver.subSrchLevel_SrchComplete);
                                      Log.v(TAG, "RxEvtList: CURRENT-STATE : Search ---> NEW-STATE : FMRxOn");
                                      cb.FmRxEvSearchComplete(FmReceiverJNI.getFreqNative(fd));
                                      break;
                                }
                                break;
                            case 3:Log.d(TAG, "Got SCAN_NEXT_EVENT");
                                cb.FmRxEvSearchInProgress();
                                break;
                            case 4:
                                Log.d(TAG, "Got RAW_RDS_EVENT");
                                cb.FmRxEvRdsGroupData();
                                break;
                            case 5:
                                Log.d(TAG, "Got RT_EVENT");
                                cb.FmRxEvRdsRtInfo();
                                break;
                            case 6:
                                Log.d(TAG, "Got PS_EVENT");
                                cb.FmRxEvRdsPsInfo();
                                break;
                            case 7:
                                Log.d(TAG, "Got ERROR_EVENT");
                                break;
                            case 8:
                                Log.d(TAG, "Got BELOW_TH_EVENT");
                                cb.FmRxEvServiceAvailable (false);
                                break;
                            case 9:Log.d(TAG, "Got ABOVE_TH_EVENT");
                                cb.FmRxEvServiceAvailable(true);
                                break;
                            case 10:
                                Log.d(TAG, "Got STEREO_EVENT");
                                cb.FmRxEvStereoStatus (true);
                                break;
                            case 11:
                                Log.d(TAG, "Got MONO_EVENT");
                                cb.FmRxEvStereoStatus (false);
                                break;
                            case 12:
                                Log.d(TAG, "Got RDS_AVAL_EVENT");
                                cb.FmRxEvRdsLockStatus (true);
                                break;
                            case 13:
                                Log.d(TAG, "Got RDS_NOT_AVAL_EVENT");
                                cb.FmRxEvRdsLockStatus (false);
                                break;
                            case 14:Log.d(TAG, "Got NEW_SRCH_LIST");
                                state = FmReceiver.getSearchState();
                                switch(state) {
                                   case FmTransceiver.subSrchLevel_SrchListInProg:
                                      Log.v(TAG, "FmRxEventListener: Current state is AUTO_PRESET_INPROGRESS");
                                      FmReceiver.setSearchState(FmTransceiver.subSrchLevel_SrchComplete);
                                      Log.v(TAG, "RxEvtList: CURRENT-STATE : Search ---> NEW-STATE : FMRxOn");
                                      cb.FmRxEvSearchListComplete ();
                                      break;
                                   case FmTransceiver.subSrchLevel_SrchAbort:
                                      Log.v(TAG, "Current state is SRCH_ABORTED");
                                      Log.v(TAG, "Aborting on-going SearchList command...");
                                      FmReceiver.setSearchState(FmTransceiver.subSrchLevel_SrchComplete);
                                      Log.v(TAG, "RxEvtList: CURRENT-STATE : Search ---> NEW-STATE : FMRxOn");
                                      cb.FmRxEvSearchCancelled();
                                      break;
                                }
                                break;
                            case 15:Log.d(TAG, "Got NEW_AF_LIST");
                                cb.FmRxEvRdsAfInfo();
                                break;
                            case 18:
                                Log.d(TAG, "Got RADIO_DISABLED");
                                if (FmTransceiver.getFMPowerState() == FmTransceiver.subPwrLevel_FMTurning_Off) {
                                    /*Set the state as FMOff */
                                    FmTransceiver.setFMPowerState(FmTransceiver.FMState_Turned_Off);
                                    Log.v(TAG, "RxEvtList: CURRENT-STATE : FMTurningOff ---> NEW-STATE : FMOff");
                                    FmTransceiver.release("/dev/radio0");
                                    cb.FmRxEvDisableReceiver();
                                    Thread.currentThread().interrupt();
                                } else {
                                    Log.d(TAG, "Unexpected RADIO_DISABLED recvd");
                                    cb.FmRxEvRadioReset();
                                }
                                break;
                            case 19:FmTransceiver.setRDSGrpMask(0);
                                break;
                            case 20:
                                Log.d(TAG, "got RT plus event");
                                cb.FmRxEvRTPlus();
                                break;
                            case 21:
                                Log.d(TAG, "got eRT event");
                                cb.FmRxEvERTInfo();
                                break;
                            default:
                                Log.d(TAG, "Unknown event");
                                break;
                            }
                        }//end of for
                    } catch ( Exception ex ) {
                        Log.d( TAG,  "RunningThread InterruptedException");
                        ex.printStackTrace();
                        Thread.currentThread().interrupt();
                    }
                }
            }
        };
        mThread.start();
    }

Switch case取1的時候就FMReceiverJNI類中獲取頻率,調FmRxEvRadioTuneStatus接收讀取頻率

freq= FmReceiverJNI.getFreqNative(fd);

cb.FmRxEvRadioTuneStatus(freq);

將頻率保存起來

FmSharedPreferences.setTunedFrequency(frequency);

mPrefs.Save();

清除狀態信息 clearStationInfo();

調用改變界面狀態 mCallbacks.onTuneStatusChanged();

可用存儲,設置可用模擬器 enableStereo(FmSharedPreferences.getAudioOutputMode());


public void FmRxEvRadioTuneStatus(int frequency)
      {
         Log.d(LOGTAG, "FmRxEvRadioTuneStatus: Tuned Frequency: " +frequency);
         try
         {
            FmSharedPreferences.setTunedFrequency(frequency);
            mPrefs.Save();
            //Log.d(LOGTAG, "Call mCallbacks.onTuneStatusChanged");
            /* Since the Tuned Status changed, clear out the RDSData cached */
            if(mReceiver != null) {
               clearStationInfo();
            }
            if(mCallbacks != null)
            {
               mCallbacks.onTuneStatusChanged();
            }
            /* Update the frequency in the StatusBar's Notification */
            startNotification();
            enableStereo(FmSharedPreferences.getAudioOutputMode());
         }
         catch (RemoteException e)
         {
            e.printStackTrace();
         }
      }


最後調到底層

FmReceiverJNI.setMonoStereoNative (fd, 1)

/* force mono/stereo mode */
   public int stereoControl(int fd, boolean stereo) {

     if (stereo){
       return  FmReceiverJNI.setMonoStereoNative (fd, 1);
     }
     else {
       return  FmReceiverJNI.setMonoStereoNative (fd, 0);
     }

   }

通過mCallbacks.onTuneStatusChanged();調用到FMRadio.java的內部存根類IFMRadioServiceCallbacks.stub類的public void onTuneStatusChanged()方法進行存入fm頻率,數據最後調用FMRadio的resetFMStationInfoUI()刷新UI

 public void onTuneStatusChanged()  {
         Log.d(LOGTAG, "mServiceCallbacks.onTuneStatusChanged: ");
         if (mIsScaning) {
             Log.d(LOGTAG, "isScanning....................");
             SharedPreferences sp = getSharedPreferences(SCAN_STATION_PREFS_NAME, 0);
             SharedPreferences.Editor editor = sp.edit();
             int station_number = sp.getInt(NUM_OF_STATIONS, 0);
             station_number++;
             editor.putInt(NUM_OF_STATIONS, station_number);
             editor.putString(STATION_NAME + station_number, station_number + "");
             editor.putInt(STATION_FREQUENCY + station_number,
                                   FmSharedPreferences.getTunedFrequency());
             editor.commit();
         }
         cleanupTimeoutHandler();
         mHandler.post(mUpdateStationInfo);
         mHandler.post(mOnStereo);
      }

發送一handler跟新UI,調用此回調方法Runnable mUpdateStationInfo = new Runnable()

 Runnable mUpdateStationInfo = new Runnable() {
      public void run() {
         cleanupTimeoutHandler();
         PresetStation station = new PresetStation("", FmSharedPreferences.getTunedFrequency());
         if (station != null) {
             mTunedStation.Copy(station);
         }
         updateSearchProgress();
         resetFMStationInfoUI();
      }
   };

updateStationInfoToUI();

private void updateStationInfoToUI() {
      double frequency = mTunedStation.getFrequency() / 1000.0;
      mTuneStationFrequencyTV.setText("" + frequency + "MHz");
      if ((mPicker != null) && mUpdatePickerValue) {
          mPicker.setValue(((mTunedStation.getFrequency() - mPrefs.getLowerLimit())
                              / mPrefs.getFrequencyStepSize()));
      }
      mStationCallSignTV.setText(mTunedStation.getPIString());
      mProgramTypeTV.setText(mTunedStation.getPtyString());
      mRadioTextTV.setText("");
      mERadioTextTV.setText("");
      mRadioTextScroller.mOriginalString = "";
      mRadioTextScroller.mStringlength = 0;
      mRadioTextScroller.mIteration = 0;
      mERadioTextScroller.mOriginalString = "";
      mERadioTextScroller.mStringlength = 0;
      mERadioTextScroller.mIteration = 0;
      mProgramServiceTV.setText("");
      mStereoTV.setText("");
      setupPresetLayout();
   }
FM啟動和關閉搜索都是通過JNI調到底層實現,代碼路徑是:vendor\qcom\opensource\fm\jni

android_hardware_fm.cpp

/*
 * JNI registration.
 */
static JNINativeMethod gMethods[] = {
        /* name, signature, funcPtr */
        { "acquireFdNative", "(Ljava/lang/String;)I",
            (void*)android_hardware_fmradio_FmReceiverJNI_acquireFdNative},
        { "closeFdNative", "(I)I",
            (void*)android_hardware_fmradio_FmReceiverJNI_closeFdNative},
        { "getFreqNative", "(I)I",
            (void*)android_hardware_fmradio_FmReceiverJNI_getFreqNative},
        { "setFreqNative", "(II)I",
            (void*)android_hardware_fmradio_FmReceiverJNI_setFreqNative},
        { "getControlNative", "(II)I",
            (void*)android_hardware_fmradio_FmReceiverJNI_getControlNative},
        { "setControlNative", "(III)I",
            (void*)android_hardware_fmradio_FmReceiverJNI_setControlNative},
        { "startSearchNative", "(II)I",
            (void*)android_hardware_fmradio_FmReceiverJNI_startSearchNative},
        { "cancelSearchNative", "(I)I",
            (void*)android_hardware_fmradio_FmReceiverJNI_cancelSearchNative}, { "getRSSINative", "(I)I",
            (void*)android_hardware_fmradio_FmReceiverJNI_getRSSINative},
        { "setBandNative", "(III)I",
            (void*)android_hardware_fmradio_FmReceiverJNI_setBandNative},
        { "getLowerBandNative", "(I)I",
            (void*)android_hardware_fmradio_FmReceiverJNI_getLowerBandNative},
        { "getUpperBandNative", "(I)I",
            (void*)android_hardware_fmradio_FmReceiverJNI_getUpperBandNative},
        { "getBufferNative", "(I[BI)I",
            (void*)android_hardware_fmradio_FmReceiverJNI_getBufferNative},
        { "setMonoStereoNative", "(II)I",
            (void*)android_hardware_fmradio_FmReceiverJNI_setMonoStereoNative},
        { "getRawRdsNative", "(I[BI)I",
            (void*)android_hardware_fmradio_FmReceiverJNI_getRawRdsNative},
       { "setNotchFilterNative", "(IIZ)I",
            (void*)android_hardware_fmradio_FmReceiverJNI_setNotchFilterNative},
        { "startRTNative", "(ILjava/lang/String;I)I",
            (void*)android_hardware_fmradio_FmReceiverJNI_startRTNative},
        { "stopRTNative", "(I)I",
            (void*)android_hardware_fmradio_FmReceiverJNI_stopRTNative},
        { "startPSNative", "(ILjava/lang/String;I)I",
            (void*)android_hardware_fmradio_FmReceiverJNI_startPSNative},  { "stopPSNative", "(I)I",
            (void*)android_hardware_fmradio_FmReceiverJNI_stopPSNative},
        { "setPTYNative", "(II)I",
            (void*)android_hardware_fmradio_FmReceiverJNI_setPTYNative},
        { "setPINative", "(II)I",
            (void*)android_hardware_fmradio_FmReceiverJNI_setPINative},
        { "setPSRepeatCountNative", "(II)I",
            (void*)android_hardware_fmradio_FmReceiverJNI_setPSRepeatCountNative},
        { "setTxPowerLevelNative", "(II)I",
            (void*)android_hardware_fmradio_FmReceiverJNI_setTxPowerLevelNative},
       { "setAnalogModeNative", "(Z)I",
            (void*)android_hardware_fmradio_FmReceiverJNI_setAnalogModeNative},
        { "SetCalibrationNative", "(I)I",
            (void*)android_hardware_fmradio_FmReceiverJNI_SetCalibrationNative},
        { "configureSpurTable", "(I)I",
            (void*)android_hardware_fmradio_FmReceiverJNI_configureSpurTable},

};
上面寫明了從jni的調用關系。具體的函數實現,請到Android_hardware_fm.cpp中去查看。我就不一一寫出來了。以上就是FM搜索頻率與取消搜索頻率的操作與實現。搜索到頻率後就可以聽FM了。






  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved