前一章咱們學習了FM的自動調頻,接下來咱們就看看FM手動調頻是如何進行的。若是不清楚FM自動調頻的過程,請打開超連接查看FM搜索頻率流程。android
首先來看一下流程圖:post
2.滑動刻度盤HorizontalNumberPicker控件在監聽事件裏使用方法valueToFrequency(newVal)學習
1.長按左右箭頭居中的頻率字符串,彈出FrequencyPickerDialog調頻對話框肯定調用tuneRadio(frequency)調頻。優化
獲取到頻率blog
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);
}
};get
3.手動點擊按鈕左右箭頭, 經過監聽調用:it
int frequency =FmSharedPreferences.getNextTuneFrequency();io
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; }