Android FM 模块学习之四 源码解析(1)
?
前一章我們了解了FM手動(dòng)調(diào)頻,接下來(lái)我們要分析FM模塊用到的源碼。此源碼是基于高通平臺(tái)的,別的平臺(tái)都大同小異,只不過(guò)是平臺(tái)自己作了些小改動(dòng)而已。
首先要看的當(dāng)然是主activity,
?
FMRadio.java
?fmradio 類(lèi)啟動(dòng)FMRadioService.java 類(lèi)調(diào)用FmSharedPreferences類(lèi)進(jìn)行存儲(chǔ)數(shù)據(jù),PresetStation調(diào)整頻率
?setVolumeControlStream(AudioManager.STREAM_MUSIC); 音樂(lè)回放即媒體音量
?LoadedDataAndState 加載數(shù)據(jù)狀態(tài)
?HorizontalNumberPicker 水平刻度盤(pán)類(lèi)繼承LinearLayout?
?mPicker.setTextSize(mDisplayWidth/ TEXTSIZE_PARAMETER_FOR_NUMBER_PICKER); 設(shè)置字體的大小,屏幕寬度除以20
?mPicker.setDensity(outMetrics.densityDpi); 設(shè)置控件密度
?mPicker.setOnValueChangedListener 設(shè)置監(jiān)聽(tīng)事件
?valueToFrequency(newVal); 刻度滑動(dòng)選中的值,上升下降調(diào)整限制值FmConfig 配置文件里setLowerLimit(int lowLimit)在設(shè)置里選中地區(qū)時(shí)候的頻率取值范圍
?mPrefs.getFrequencyStepSize() ,獲得設(shè)置的步長(zhǎng)大小
?mHandler.post(mRadioChangeFrequency); 更新在刻度盤(pán)上顯示頻率信息、
?tuneRadio(int frequency) 調(diào)整fm 頻率
?
?FMRadioService.java 類(lèi)isFmOn() 方法:
?registerCallbacks 注冊(cè)回調(diào)IFMRadioServiceCallbacks 的對(duì)象、
?ServiceStub 繼承IFMRadioService.Stub 使用到WeakReferenc弱引用, WeakReference 是弱于 SoftReference 的引用類(lèi)型。弱引用的特性和基本與軟引用相似,區(qū)別就在于弱引用所指向的對(duì)象只要進(jìn)行系統(tǒng)垃圾回收,不管內(nèi)存使用情況如何,永遠(yuǎn)對(duì)其進(jìn)行回收(get() 方法返回 null)。
?IBindermBinder = new ServiceStub(this); bindService IBinder 等于serviceStub 對(duì)象。
?
fmOn() 部分代碼:
?/**
?* 當(dāng)來(lái)電話(huà)不是閑置的時(shí)候就返回false
?*/
?
if (TelephonyManager.CALL_STATE_IDLE != getCallState() ) {
? return bStatus;
?}
?
mReceiver= new FmReceiver(FMRADIO_DEVICE_FD_STRING, fmCallbacks);
?FmReceiver 接受廣播類(lèi)繼承FmTransceiver
?/ * * * 構(gòu)造函數(shù)接收方對(duì)象,
?路徑
電臺(tái)和事件回調(diào)。
?
* @param devicePath 調(diào)頻設(shè)備路徑字符串。
回調(diào)事件回調(diào)處理
從調(diào)頻接收機(jī)* 事件。
?* /
?public FmReceiver(String devicePath, FmRxEvCallbacksAdaptorcallback) throws InstantiationException {
? mControl = new FmRxControls();
? mRxEvents = new FmRxEventListner();
//registerClient(callback);
? mCallback = callback;
?}
?
獲得FM 現(xiàn)在的狀態(tài)
?public int getFMState()
?{
?/* Current State of FM device */
? int currFMState =FmTransceiver.getFMPowerState();
? return currFMState;
?}
?
滑動(dòng)刻度盤(pán)動(dòng)畫(huà)效果:
?mAnimation= AnimationUtils.loadAnimation(this,R.anim.preset_select);
?靜音控件監(jiān)聽(tīng),點(diǎn)擊控件有聲無(wú)聲切換。
?mMuteButton.setOnClickListener(mMuteModeClickListener);
?喇叭與耳機(jī)監(jiān)聽(tīng)切換
?mSpeakerButton.setOnClickListener(mSpeakerClickListener);
?開(kāi)啟關(guān)閉fm 控件切換
?mOnOffButton.setOnClickListener(mTurnOnOffClickListener);
?向右調(diào)頻控件監(jiān)聽(tīng)
?mForwardButton.setOnClickListener(mForwardClickListener);
?mForwardButton.setOnLongClickListener(mForwardLongClickListener);
?向左調(diào)頻控件監(jiān)聽(tīng)
?mBackButton.setOnClickListener(mBackClickListener);
?mBackButton.setOnLongClickListener(mBackLongClickListener);
?單擊收藏按鈕把收藏頻率定位調(diào)頻到刻度盤(pán)上,長(zhǎng)期按鈕將刻度盤(pán)頻率收藏到按鈕上存儲(chǔ)到data 分區(qū)下的fmradio_prefs.xml文件 key是tation_name0x1
?頻率顯示控件
?mTuneStationFrequencyTV= (TextView)findViewById(R.id.prog_frequency_tv);
?長(zhǎng)按頻率顯示控件監(jiān)聽(tīng)方法:
?mTuneStationFrequencyTV.setOnLongClickListener(mFrequencyViewClickListener);
?錄音視圖顯示與監(jiān)聽(tīng)事件
?mRecordingMsgTV= (TextView)findViewById(R.id.record_msg_tv);
?if (mRecordingMsgTV != null) {
? mRecordingMsgTV.setOnClickListener(mRecordButtonListener);
?}
?
自動(dòng)關(guān)掉FM 時(shí)間顯示
?mSleepMsgTV= (TextView)findViewById(R.id.sleep_msg_tv);
?fm 信號(hào)強(qiáng)度
?mRSSI =(ImageView)findViewById(R.id.signal_level);
?if (mRSSI != null) {
? mRSSI.setVisibility(View.INVISIBLE);
?}
?
顯示控件顯示信息等數(shù)據(jù)顯示
?protectedvoid setDisplayvalue()
?onRestart()
?獲取 IFMRadioService 請(qǐng)求焦點(diǎn)
?onStop 中方法調(diào)用private boolean isSleepTimerActive() 是否是睡眠。
?if(isSleepTimerActive()){
? mSleepUpdateHandlerThread.interrupt();
?}
?
如果是睡眠活動(dòng)就睡眠更新線(xiàn)程中斷線(xiàn)程
當(dāng)錄音開(kāi)始,走onStop() 方法時(shí)候就停止錄音更新線(xiàn)程
?private boolean isRecording()
?if (null!= mRecordUpdateHandlerThread) {
? mRecordUpdateHandlerThread.interrupt();
?}
?
public void onStart()
?用戶(hù)選擇高清晰多媒體顯示創(chuàng)建命令失敗.
?1 、如果未保存則調(diào)用onCreateDialog(int) ,然后再調(diào)用onPrepareDialog(int, Dialog)
?(2) 如果保存了對(duì)話(huà)框?qū)ο?#xff0c;則直接調(diào)用onPrepareDialog(int,Dialog), 不會(huì)再去create,所以有時(shí)候當(dāng)你再輸入框里無(wú)論如何輸入什么內(nèi)容,對(duì)話(huà)框的內(nèi)容都是第一次產(chǎn)生的。
?removeDialog(int) 是用來(lái)清除Activity 保存下來(lái)的Dialog對(duì)象,如果不加removeDialog將會(huì)導(dǎo)致無(wú)論在對(duì)話(huà)框里輸入什么內(nèi)容,
?彈出來(lái)的對(duì)話(huà)框始終都是第一次保留下來(lái)的,這里所以要加上它
?創(chuàng)建搜索dialog
?createSearchDlg(id,dlgBuilder)
?
?FMConfig.java 類(lèi)
?public int getRdsStd () {
? return mRdsStd;
?}
?registerFMSettingListner(); 注冊(cè)收音機(jī)設(shè)置配置文件
?mPrefs.Load(); 調(diào)用FmSharedPreferences 的Load()方法獲取fmradio_prefs.xml數(shù)據(jù)
?遇見(jiàn)bug: 將設(shè)置地區(qū)自動(dòng)選擇印度(外單項(xiàng)目)
?/* LoadConfiguration */
?if(Locale.getDefault().equals(Locale.CHINA)) {
? setCountry(sp.getInt(FMCONFIG_COUNTRY,REGIONAL_BAND_CHINA));
?} else {
? setCountry(sp.getInt(FMCONFIG_COUNTRY, REGIONAL_BAND_NORTH_AMERICA));
?}
?
/* Last list the user was navigating */
?Local.getDafault() 在第一次刷機(jī)后設(shè)置本地語(yǔ)言后
?protected void onPause() 的時(shí)候,將信息保存mPrefs.Save();
?ScrollerText 控件繼承Handler 、
?/ * * * 移動(dòng)一個(gè)字符留下的文字和文章
?*SCROLLER_UPDATE_DELAY_MS 后延遲下更新消息。 * 如果滾動(dòng)整個(gè)字符串, 然后它會(huì)顯示整個(gè)字符串 * 并等待SCROLLER_RESTART_DELAY_MS 滾動(dòng)重啟 * /
?voidupdateText() 更新錄音時(shí)間
?停止錄音時(shí)間跟新
?void stopScroll() {
? mStatus = SCROLLER_STOPPED;
? removeMessages(SCROLLER_MSG_TICK);
? removeMessages(SCROLLER_MSG_RESTART);
? removeMessages(SCROLLER_MSG_START);
? resetScroll();
?}
?
重新設(shè)置錄音時(shí)間顯示
?private void resetScroll()
?啟動(dòng)錄音時(shí)間
?void startScroll() {
?初始化搜索
?private void initiateSearch(int pty)
?resetSearch() 重新收索
?private void cancelSearch() 關(guān)閉收索
?初始化搜索列表
?private void initiateSearchList()
?初始化睡眠定時(shí)器
?private void initiateSleepTimer(long seconds) {
? mSleepAtPhoneTime =(SystemClock.elapsedRealtime()) + (seconds * 1000);
? Log.d(LOGTAG, "Sleep in seconds:" + seconds);
? initiateSleepThread();
?}
?
初始化睡眠線(xiàn)程
?private void initiateSleepThread()
?在
?Intent launchPreferencesIntent = new Intent().setClass(this,
?Settings.class);
?launchPreferencesIntent.putExtra(Settings.RX_MODE,true);
?startActivityForResult(launchPreferencesIntent,
?ACTIVITY_RESULT_SETTINGS);
?private void enableSpeaker() ? 揚(yáng)聲器可用
?private void updateExpiredRecordTime() 更新錄音時(shí)間
?private Runnable doRecordProcessing = new Runnable() 錄音進(jìn)度
?public void onResume()
?mService.registerCallbacks(mServiceCallbacks); 注冊(cè)回調(diào)service
?mService.cancelDelayedStop(FMRadioService.STOP_SERVICE); 延遲關(guān)閉FMRadioService
?public? boolean bindToService(Context context,ServiceConnection callback) 啟動(dòng)在FMRadio 的onStart()方法判斷條件啟動(dòng)FMRadioService
?if((mService == null ) && (false == bindToService(this, osc)))
?onDestroy() 方法中解綁nRegisterReceiver(mFmSettingReceiver);
?boolean isWiredHeadsetAvailable() 判斷耳機(jī)是否可用,在FMRadioService 類(lèi)里添加public void registerHeadsetListener()注冊(cè)耳機(jī)監(jiān)聽(tīng)事件,mHeadsetPlugged = (intent.getIntExtra("state", 0) == 1);狀態(tài)監(jiān)聽(tīng)
?Intent 里的public static final String ACTION_HEADSET_PLUG =
?"android.intent.action.HEADSET_PLUG"; 耳機(jī)靜態(tài)常量定義。
?
再啟動(dòng)FMRadioService 監(jiān)聽(tīng) registerHeadsetListener();耳機(jī)
?/ * *
?確定是否一個(gè)內(nèi)部天線(xiàn)。
?* FMOn
?返回緩存的值初始化。
?*
?* @return
?真正的如果內(nèi)部天線(xiàn)可用或連線(xiàn)
?*
?耳機(jī)插入,如果內(nèi)部天線(xiàn)是錯(cuò)誤的
?*沒(méi)有和有線(xiàn)耳機(jī)不是插入。
?* /
?
public boolean isAntennaAvailable()FMRadioService 類(lèi)
?public void readInternalAntennaAvailable() 確定是否有內(nèi)部天線(xiàn),調(diào)用類(lèi)FMReceivce 的父類(lèi)FMTransceiver類(lèi)發(fā)送接收信號(hào)類(lèi)
?public boolean getInternalAntenna() 方法,通過(guò)FmReceiverJNI 類(lèi)調(diào)用getControlNative方法。
?恢復(fù)設(shè)置默認(rèn)地區(qū)設(shè)置private voidRestoreDefaults()
?當(dāng)天線(xiàn)可以用的時(shí)候就調(diào)用UI 界面可用顯示
?private void enableRadioOnOffUI() {
? boolean bEnable = isFmOn();
? /* Disable if no antenna/headset isavailable */
? if (!isAntennaAvailable()) {
? bEnable = false;
? }
? enableRadioOnOffUI(bEnable);
?? }
?
調(diào)用此方法private void enableRadioOnOffUI(boolean bEnable) 顯示FMRadio.java UI界面
?boolean isCallActive() 電話(huà)呼叫活動(dòng),FMRadioService 類(lèi)isCallActive當(dāng)狀態(tài)不為零表示在通話(huà)中
?public boolean isCallActive()
?{
???? //Non-zero: Call state is RINGING orOFFHOOK on the available subscriptions
? //zero: Call state is IDLE on all theavailable subscriptions
? if(0 != getCallState()) return true;
? return false;
?}
?
private void enableRadio() 可使用收音機(jī)
?private void disableRadio() 不可用收音機(jī)
?private void resetRadio() 重新設(shè)置收音機(jī)
?public void clearStationList() 清除電臺(tái)列表信息
?public boolean fmConfigure() 收音機(jī)配置
?/ *
?設(shè)置調(diào)頻模塊自動(dòng)切換到另一個(gè)頻率
?*
?站如果一個(gè)頻率的信號(hào)強(qiáng)度比
?*目前調(diào)諧頻率。
?*
?*布爾bEnable:真:自動(dòng)切換到更強(qiáng)的交替頻率。
?*假:不要切換到備用頻率。
?* @return真實(shí)如果設(shè)置自動(dòng)對(duì)焦模式api調(diào)用成功,錯(cuò)誤如果api失敗了。
?*注:回調(diào)FmRxEvRadioTuneStatus時(shí)將調(diào)用
?*完成不同的頻率。
?* /
?調(diào)用FMRadioService 類(lèi) publicboolean enableAutoAF(boolean bEnable)方法。
?public void fmAudioOutputMode() 輸出立體聲音
?private void startRecording() 錄音開(kāi)始
?private void setRecordingStopImage() 錄音停止圖片設(shè)置
?private void setRecordingStartImage() 錄音開(kāi)始圖片設(shè)置、
?private void startRecordingTimer() 錄音啟動(dòng)的時(shí)間
?private void stopRecording() 停止錄音
?private boolean isRecording() 判斷是否在錄音
?private boolean isSpeakerEnabled() 判斷揚(yáng)聲器是可用
?private boolean stationExists(PresetStationstation ) 長(zhǎng)按收藏按鈕式電臺(tái)頻率是都存在
?private void addToPresets() 添加電臺(tái)頻率顯示到按鈕上
?FmSharedPreferences.addStation(selectedStation.getName(),selectedStation.getFrequency(),currentList);
?setupPresetLayout();
?
調(diào)用FmSharedPreferences 類(lèi)的addStation方法添加到mListOfPlists列表里
?private void resetSearchProgress() 重置搜索進(jìn)度
?updateSearchProgress() 更新搜索進(jìn)度
?setupPresetLayout() 安裝頻率布局,收藏頻率至按鈕上初始化
?updateStationInfoToUI() 更新電臺(tái)信息界面信息
?private boolean isFmOn() 收音機(jī)是否開(kāi)啟
?
/* 如果啟用了模擬路徑返回true */
?public boolean isAnalogModeEnabled() {
? return misAnalogPathEnabled;
?}
?
/ * 返回調(diào)頻(Soc) 音頻硬件是否有限。
?* @return真如果調(diào)頻音頻是柔和的,假如果不低調(diào)。
?* /
?public boolean isMuted() {
? return mMuted;
?}
?private boolean isScanActive() 掃描活動(dòng)布爾值
?private boolean isSeekActive() 查找活動(dòng)布爾值
?private boolean isSearchActive() 搜索活動(dòng)布爾值
?public PresetStation getCurrentTunedStation() 獲得現(xiàn)在調(diào)整電臺(tái)
?private void SeekNextStation() 在搜索查找下一個(gè)頻率
?private void initiateSearch(int pty) 初始化搜索
?/** SEEK Station with the matching PI */
?private void initiatePISearch(int pi) 需找匹配的頻率
?private void resetSearch() 從新搜索
?private void cancelSearch() 關(guān)閉搜索
?private void initiateSearchList() 初始化搜索列表
?private void initiateSleepTimer(long seconds)? 初始化睡眠計(jì)時(shí)器
?private void initiateSleepThread() 初始化睡眠線(xiàn)程
?private void endSleepTimer() 結(jié)束睡眠計(jì)時(shí)器時(shí)間
?private boolean hasSleepTimerExpired() 睡眠計(jì)時(shí)器停止
?private boolean isSleepTimerActive() 睡眠計(jì)時(shí)器活動(dòng)是否活動(dòng)
?private void updateExpiredSleepTime() 更新停止睡眠時(shí)間
?private String makeTimeString(long secs) 時(shí)間格式字符串
?private void tuneRadio(int frequency) 調(diào)整收音機(jī)頻率
?private void resetFMStationInfoUI() 從新設(shè)置收音機(jī)電臺(tái)顯示界面信息
?
IFMRadioServiceCallbacks 類(lèi)回調(diào)時(shí)候
?Runnable mRadioEnabled = new Runnable() 收音機(jī)可用
?Runnable mRadioDisabled = new Runnable() 收音機(jī)不可用
?Runnable mRadioReset = new Runnable() 收音機(jī)重新設(shè)置
?Runnable mUpdateStationInfo = new Runnable() 跟新收音機(jī)電臺(tái)信息
?Runnable mOnMute = new Runnable() 收音機(jī)靜音設(shè)置
?Runnable mOnStereo = new Runnable() 立體聲音
?Runnable mUpdateRadioText = new Runnable() 更新收音機(jī)文本信息
?Runnable mRadioChangeFrequency = newRunnable() 調(diào)整頻率
?Runnable mUpdateExtenRadioText = newRunnable() 更新延伸收音機(jī)文本信息
?Runnable mUpdateProgramService = newRunnable() 跟新service 進(jìn)度
?private void DebugToasts(String str, intduration) 彈出提示信息
?private void registerFMSettingListner()? 注冊(cè)設(shè)置改變監(jiān)聽(tīng)
?private void unRegisterReceiver(BroadcastReceiver myReceiver) 卸載注冊(cè)避免重復(fù)注冊(cè)報(bào)異常
?
?
下面分享的是FM模塊的保存方法,即FmSharedPreferences.java
?
??? FmSharedPreferences(Context context)在構(gòu)造方法中加載Load()方法,
??? public void? Load(){
????????? Log.d(LOGTAG, "Load preferences ");
????????? if(mContext == null)
????????? {
???????????? return;
????????? }
????????? SharedPreferences sp = mContext.getSharedPreferences(SHARED_PREFS, Context.MODE_PRIVATE);
????????? mTunedFrequency = sp.getInt(PREF_LAST_TUNED_FREQUENCY, DEFAULT_NO_FREQUENCY);
????????? mRecordDuration = sp.getInt(LAST_RECORD_DURATION, RECORD_DUR_INDEX_0_VAL);
????????? mAFAutoSwitch = sp.getBoolean(LAST_AF_JUMP_VALUE, true);
????????? mAudioOutputMode = sp.getBoolean(AUDIO_OUTPUT_MODE, true);
????????? if(sp.getInt(FMCONFIG_COUNTRY, 0) == REGIONAL_BAND_USER_DEFINED) {
???????????? mBandMinFreq = sp.getInt(FMCONFIG_MIN, mBandMinFreq);
???????????? mBandMaxFreq = sp.getInt(FMCONFIG_MAX, mBandMaxFreq);
???????????? mChanSpacing = sp.getInt(FMCONFIG_STEP, mChanSpacing);
????????? }
??? ?
????????? int num_lists = sp.getInt(LIST_NUM, 1);
????????? if (mListOfPlists.size() == 0) {
????????? for (int listIter = 0; listIter < num_lists; listIter++) {
???????????????? String listName = sp.getString(LIST_NAME + listIter, "FM - " + (listIter+1));
???????????????? int numStations = sp.getInt(STATION_NUM + listIter, 1);
???????????????? if (listIter == 0) {
???????????????????? createFirstPresetList(listName);
???????????????? } else {
???????????????????? createPresetList(listName);
???????????????? }
???????????????? PresetList curList = mListOfPlists.get(listIter);
???????????????? for (int stationIter = 0; stationIter < numStations; stationIter++) {
????????????????????? String stationName = sp.getString(STATION_NAME + listIter + "x" + stationIter,
????????????????????????????????????????????????????????? DEFAULT_NO_NAME);
????????????????????? int stationFreq = sp.getInt(STATION_FREQUENCY + listIter + "x" + stationIter,
?????????????????????????????????????????????????????? DEFAULT_NO_FREQUENCY);
????????????????????? PresetStation station = curList.addStation(stationName, stationFreq);
??? ?
????????????????????? int stationId = sp.getInt(STATION_ID + listIter + "x" + stationIter,
????????????????????????????????????????????????? DEFAULT_NO_STATIONID);
????????????????????? station.setPI(stationId);
??? ?
????????????????????? int pty = sp.getInt(STATION_PTY + listIter + "x" + stationIter, DEFAULT_NO_PTY);
????????????????????? station.setPty(pty);
??? ?
????????????????????? int rdsSupported = sp.getInt(STATION_RDS + listIter + "x" + stationIter,
???????????????????????????????????????????????????? DEFAULT_NO_RDSSUP);
????????????????????? if (rdsSupported != 0) {
????????????????????????? station.setRDSSupported(true);
????????????????????? } else {
????????????????????????? station.setRDSSupported(false);
????????????????????? }
????????? /* Load Configuration */?? ?
??????????? setCountry(sp.getInt(FMCONFIG_COUNTRY, REGIONAL_BAND_NORTH_AMERICA));
????????? /* Last list the user was navigating */
????????? mListIndex = sp.getInt(LAST_LIST_INDEX, 0);
????????? if(mListIndex >= num_lists)
????????? {mListIndex=0;
????????? }
?????? }
??? 初始化取出sp一些數(shù)據(jù)
??? 根據(jù)系統(tǒng)初始化地區(qū)設(shè)置當(dāng)?shù)仡l率 ?
??? /*Load Configuration */
???????? if (Locale.getDefault().equals(Locale.CHINA)) {
???????????? setCountry(sp.getInt(FMCONFIG_COUNTRY, REGIONAL_BAND_CHINA));
???????? } else {
???????????? setCountry(sp.getInt(FMCONFIG_COUNTRY, REGIONAL_BAND_NORTH_AMERICA));
???????? }
???????? /* Last list the user was navigating */
??????????? 保存頻率
??? public void Save()
???????????? 設(shè)置默認(rèn)的地區(qū)
??? public static void SetDefaults()
??????????? 設(shè)置調(diào)整頻率
??? public static void setTunedFrequency(intfrequency)
??????????? 獲取調(diào)整頻率
??? public static int getTunedFrequency()
??????????? 獲取下一個(gè)頻率
??? public static int getNextTuneFrequency(intfrequency)
??????????? 獲取上一個(gè)頻率
??? public static int getPrevTuneFrequency(intfrequency)
??? / * *
??? * @param mFMConfiguration mFMConfiguration設(shè)置
??? * /
??? public static void setFMConfiguration(FmConfig mFMConfig)
??? /**
??????? *@return the mFMConfiguration
?????? */
????? public static FmConfig getFMConfiguration() {
???????? return mFMConfiguration;
?????? }
??? 設(shè)置fm播放的頻率范圍
??? public static void setRadioBand(int band)
?????????? 獲取fm頻率范圍限制
??? public static int getRadioBand()
?? ? 獲取間隔
??? public static int getChSpacing()
??? 設(shè)置遠(yuǎn)程數(shù)據(jù)服務(wù)
??? public static void setRdsStd(int std)
??? mFMConfiguration.setRdsStd(std);
?? ? 獲取遠(yuǎn)程數(shù)據(jù)服務(wù)
??? public static int getRdsStd()
??? mFMConfiguration.getRdsStd();
??? 設(shè)置國(guó)家地區(qū)
??? public static void setCountry(intnCountryCode)
??? 獲取國(guó)家地區(qū)
??? public static int getCountry()
??????????? 設(shè)置聲音輸出模板
??? setAudioOutputMode
??? 設(shè)置錄音是否持續(xù)
??? public static void setRecordDuration(intdurationIndex)
?
?
總結(jié):個(gè)人認(rèn)為以上只能作為參考,但是大體框架變化不大。
?
轉(zhuǎn)載于:https://www.cnblogs.com/kings-boke/p/4269825.html
總結(jié)
以上是生活随笔為你收集整理的Android FM 模块学习之四 源码解析(1)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: tomcat-tunning
- 下一篇: 南邮Android Studio应用高德