前一章主要是FM的自动调频, 接下来我们就看看FM手动调频是如何进行的。如果不清楚FM自动调频的过程,请打开超链接查看FM搜索频率流程。

首先来看一下流程图:

2.滑动刻度盘HorizontalNumberPicker控件在监听事件里使用方法valueToFrequency(newVal)

1.长按左右箭头居中的频率字符串,弹出FrequencyPickerDialog调频对话框确定调用tuneRadio(frequency)调频。

获取到频率

protected int valueToFrequency(int value) {
       mFrequency = mPrefs.getLowerLimit() + value *
                             mPrefs.getFrequencyStepSize();
       return mFrequency;
   }

发送一个handler 回调一个tuneRadio(frequency)调频。

Runnable mRadioChangeFrequency = new Runnable(){
       public void run() {
           mUpdatePickerValue = false;
           tuneRadio(mFrequency);
       }
   };

3.手动点击按钮左右箭头, 通过监听调用:

int frequency =FmSharedPreferences.getNextTuneFrequency();

int frequency =FmSharedPreferences.getPrevTuneFrequency();

tuneRadio(frequency);进行调频

getNextTuneFrequency()方法通过判断频率最大限制范围,后加200(刻度)

getPrevTuneFrequency()方法通过判断频率最小限制范围,后减200(刻度)

调频方法分析

private void tuneRadio(int frequency)

private void tuneRadio(int frequency){
    /* Issue the tune command only if tuneCommand is already not active */
    if((mService != null) && (mCommandActive != CMD_TUNE) && isFmOn()) {
      boolean bStatus = false;
      try {
         bStatus = mService.tune(frequency);
         if (bStatus) {
            postTimeoutHandler(CMD_TUNE);
         }else {
          if (isFmOn()) {
            mCommandFailed = CMD_TUNE;
            Log.e(LOGTAG, "mService.tune failed");
            showDialog(DIALOG_CMD_FAILED);
          }
         }mTunedStation.setName("");
         mTunedStation.setPI(0);
         mTunedStation.setPty(0);
         updateStationInfoToUI();
      }catch (RemoteException e) {
        e.printStackTrace();
      }
    }else {
      Log.e(LOGTAG, "Delayed Tune handler stopped");
    }
  }

通过回调引用类调用FMRadioService类的tune()方法进行调频

bStatus = mService.tune(frequency);

发送一个广播连接是否超时

postTimeoutHandler(CMD_TUNE);

设置调频名字,更新FMRadioUI界面信息

mTunedStation.setName("");

mTunedStation.setPI(0);

mTunedStation.setPty(0);

updateStationInfoToUI()

(通过IFMRadioSrevice.aidl通信机制onbind返回的类的引用调用FMRadioService中的调频方法)

FMRadioService中的tune方法

public boolean tune(int frequency)

public boolean tune(int frequency) {
  boolean bCommandSent=false;
  double doubleFrequency = frequency/1000.00;

  Log.d(LOGTAG, "tuneRadio:  " + doubleFrequency);
  if (mReceiver != null)
  {
     mReceiver.setStation(frequency);
     bCommandSent = true;
  }
  return bCommandSent;
   }

调用FMReceiver类的setStation方法调频

public boolean setStation (intfrequencyKHz)

public boolean setStation (int frequencyKHz) {
  int ret;

  mControl.setFreq(frequencyKHz);
  ret = mControl.setStation(sFd);
  if(ret < 0 )
  {
     return false;
  }
  else
  {
     return true;
  }
   }

调用FMRxControls类(FM读取控制台信息)设置频率

mControl.setFreq(frequencyKHz);

设置优化调频核心指定的频率

ret = mControl.setStation(sFd);

public int setStation(int fd) {
      Log.d(TAG, "** Tune Using: "+fd);
      int ret = FmReceiverJNI.setFreqNative(fd, mFreq);
      Log.d(TAG, "** Returned: "+ret);
      return ret;
   }

最后调用FmReceiverJNI类

setFreqNative(fd, mFreq); 本地方法 JNI到 cpp文件

/*native interface */
static jint android_hardware_fmradio_FmReceiverJNI_setFreqNative
  (JNIEnv * env, jobject thiz, jint fd, jint freq)
{
  int err;
  double tune;
  struct v4l2_frequency freq_struct;
  freq_struct.type = V4L2_TUNER_RADIO;
  freq_struct.frequency = (freq*TUNE_MULT/1000);
  err = ioctl(fd, VIDIOC_S_FREQUENCY, &freq_struct);
  if(err < 0){
      return FM_JNI_FAILURE;
  }
  return FM_JNI_SUCCESS;
}
posted on 2015-02-02 19:59  King_Li  阅读(637)  评论(0编辑  收藏  举报