• Android FM模块学习之一 FM启动流程


    最近在学习FM模块,FM是一个值得学习的模块,可以从上层看到底层。

    上层就是FM的按扭操作和界面显示,从而调用到FM底层驱动来实现广播收听的功能。

    FM启动流程:如下图:

    Android FM模块学习之一 FM启动流程0

    先进入FMRadio.java类,onCreate初始化一些数据,画出FM界面,启动fm在onStart()方法里启动FMRadioService.java (调用bindToService(this, osc)方法)。

    Android FM模块学习之一 FM启动流程1

    注册下fm设置(在设置后发送一个设置广播,更新FMRadio类的状态)。Android FM模块学习之一 FM启动流程2

    加载初始化数据,获取频率地址

    newPresetStation("",FmSharedPreferences.getTunedFrequency());

    Android FM模块学习之一 FM启动流程3

    在bindToService(this,osc)方法中,先启动StartService(同一个Service只onCreate一次),再启动bindservice(这样有个好处按返回键service不会走onDestroy方法)bindservice通过onBind回传一个IBinder对象到FMRadio类的内部类ServiceConnection的onServiceConnected方法中,调用enableRadio()方法。

    Android FM模块学习之一 FM启动流程4 

    在enableRaido方法中调用FMRadio.java的isAntennaAvailable()方法进行耳机判断,天线判断是否可用,通过一个插入拔出广播接收来控制的(FMRadio中的registerHeadsetListener()方法)action(Intent.ACTION_HEADSET_PLUG) 

    mHeadsetPlugged =(intent.getIntExtra("state", 0) == 1); 等于1说明耳机可用,等于0可用。

    调用FmRadio方法FmOn  (mService.fmOn())

    界面可用enableRadioOnOffUI()

    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()) && isAntennaAvailable()) {
                        bStatus = mService.fmOn();
                        if(bStatus) {
                           tuneRadio(FmSharedPreferences.getTunedFrequency());
                           enableRadioOnOffUI();
                        }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();
                 }
              }
          }
       }
    

    在FMRadioService.java的fmOn()方法中初始化FmReceiver的引用mReceiver = newFmReceiver(FMRADIO_DEVICE_FD_STRING, fmCallbacks);

    取出设置保存的地区频率的属性

    FmConfig config =FmSharedPreferences.getFMConfiguration();

    真正接受fm声音在

    bStatus =mReceiver.enable(FmSharedPreferences.getFMConfiguration());

    isSpeakerEnabled()扬声器可用,用户设置扬声器

    设置铃声路径

    boolean state =mReceiver.setAnalogMode(analogMode); analogMode模拟设置低功率

    bStatus = setLowPowerMode(false);

    电话不在闲置状太下

    int state = getCallState();

    fmActionOnCallState(state);

    启动FM  startFM();设置耳机等可以接受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
    FmReceiverJNI.setControlNative (sFd, V4L2_CID_PRIVATE_TAVARUA_ANTENNA,iAntenna)

    mReceiver.setInternalAntenna(false)

    总结:

    1.由于Android版本不同,各大厂商对FM做了不同的定制,代码均有差异,但是总体框架没有变;

    2.FM为Google完全开源代码,代码路径在vendor/qcom里面;

    3.FM不同于其他应用,待续....

    vendor 目录                        (厂家定制内容)

    |-- aosp                                (android open source project)
    |   `-- products                (一些板级规则)
    |-- htc                                (HTC公司)
    |   |-- common-open        (通用部分)
    |   |   `-- akmd                (解压img用的工具)
    |   |-- dream-open                (G1开放部分)
    |   |-- prebuilt-open        (预编译开放部分)
    |   `-- sapphire-open        (sapphire这款型号开放内容)
    |-- pv-open                        (没东西)
    |-- qcom                                (里面基本是空的)
    `-- sample                        (google提供的样例)
        |-- apps                        (应用)
        |   |-- client                (用户)
        |   `-- upgrade        (升级)
        |-- frameworks                (框架)
        |   `-- PlatformLibrary        (平台库)
        |-- products                (产品)
        |-- sdk_addon                (sdk添加部分)
        `-- skins                        (皮肤)
            `-- WVGAMedDpi        (WVGA适用的图片)

  • 相关阅读:
    Tutorial: Getting Started with TFS in VS2010 (转载)
    Flex开源组件——FlexReport
    GIS和开源见解(摘录)
    Google Wave了解(资料收集)
    分享ArcGis For Flex API 1.3 Diagram
    基于.NET的开源GIS项目收集整理(转载)
    TFS 2010 for SourceSafe Users (转载)
    一个处理UTF8编码文件BOM头的简单方法
    用ISO文件制作启动U盘
    为Ubuntu安装buildessential软件包
  • 原文地址:https://www.cnblogs.com/kings-boke/p/4247820.html
Copyright © 2020-2023  润新知