NFC学习——NFC Enable 过程分析(一)

来源:互联网 发布:张宇和陈奕迅 知乎 编辑:程序博客网 时间:2024/06/01 08:41

         拿到一台支持NFC手机或是平板设备时,在Settings->more可以看到NFC的enble,disnable的选项,还有android Beam这个东西。现在来分析NFC enable的过程   

          wireless_settings.xml 在Settings配置了NFC功能项:

    <CheckBoxPreference        android:key="toggle_nfc"        android:title="@string/nfc_quick_toggle_title"        android:summary="@string/nfc_quick_toggle_summary"        android:persistent="false" />    <PreferenceScreen        android:fragment="com.android.settings.nfc.AndroidBeam"        android:key="android_beam_settings"        android:title="@string/android_beam_settings_title" />
         xml配置的对应处理代码在:packages/apps/Settings/src/com/android/settings/WirelessSettings.java

public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        addPreferencesFromResource(R.xml.wireless_settings);         CheckBoxPreference nfc = (CheckBoxPreference) findPreference(KEY_TOGGLE_NFC);        PreferenceScreen androidBeam = (PreferenceScreen) findPreference(KEY_ANDROID_BEAM_SETTINGS);         //setp1:获取NfcEnable的实例        mNfcEnabler = new NfcEnabler(activity, nfc, androidBeam);         ......        // Remove NFC if its not available                    //setp2:获取NfcAdapter实例,查看NFC功能是否可能        mNfcAdapter = NfcAdapter.getDefaultAdapter(activity);        if (mNfcAdapter == null) {            getPreferenceScreen().removePreference(nfc);            getPreferenceScreen().removePreference(androidBeam);            mNfcEnabler = null;        }  }

setp1:NFcEnable实例 packages/apps/Settings/src/com/android/settings/nfc/NfcEnabler.java 实现Preference.OnPreferenceChangeListener接口监听NFC Enable,disnable事件

public boolean onPreferenceChange(Preference preference, Object value) {        // Turn NFC on/off        final boolean desiredState = (Boolean) value;        mCheckbox.setEnabled(false);        if (desiredState) {                      //setp3:用setp2一样的方式获取NfcAdapter实例出来nfc enable            mNfcAdapter.enable();        } else {            mNfcAdapter.disable();        }        return false;    }
         同时也是在这个NfcEnabler.java中处理了,Nfc enble,diable时,android beam的灰亮显示问题。

Setp2:现在所有的分析点集中到了NfcAdaper这个类中,首先来看下NfcAdapter实例的获取

源代码的路径:frameworks/base/core/java/android/nfc/NfcAdapter.java

    public static NfcAdapter getDefaultAdapter(Context context) {           ......         /* use getSystemService() for consistency */        NfcManager manager = (NfcManager) context.getSystemService(Context.NFC_SERVICE);        if (manager == null) {            // NFC not available            return null;        }                  //setp2-1        return manager.getDefaultAdapter();    }
NFC学习——NfcService 启动过程分析  文章中NfcService的onCreate()方法中有如下code:

 //把mNfcAdapter 作为Service 添加到系统服务中,ServiceManager.getService("nfc")可以获取到binder  ServiceManager.addService(SERVICE_NAME, mNfcAdapter); 
NfcManager manager = (NfcManager) context.getSystemService(Context.NFC_SERVICE);获取到的Service 就是之前add的service。

           Setp2-1:manager.getDefaultAdapter其实饶了一圈又回到NfcAdapter类中获取NfcAdapter实例,具体看下面code

code路径:frameworks/base/core/java/android/nfc/NfcManager.java

public NfcAdapter getDefaultAdapter() {        return mAdapter;    }
这个mAdaper如何来的呢?

    public NfcManager(Context context) {        NfcAdapter adapter;        ......         try {            adapter = NfcAdapter.getNfcAdapter(context);        } catch (UnsupportedOperationException e) {            adapter = null;        }        mAdapter = adapter;    }
最终又回到NfcAdapter.gerNfcAdapter(context)这个方法上获取实例,具体来分析:

  public static synchronized NfcAdapter getNfcAdapter(Context context) {        if (!sIsInitialized) {            ......            //setp2-2:应用INfcAdapter.aidl和NfcService通信             sService = getServiceInterface();            if (sService == null) {                Log.e(TAG, "could not retrieve NFC service");                throw new UnsupportedOperationException();            }            try {                 //note2                sTagService = sService.getNfcTagInterface();            } catch (RemoteException e) {                Log.e(TAG, "could not retrieve NFC Tag service");                throw new UnsupportedOperationException();            }            sIsInitialized = true;        }        if (context == null) {            if (sNullContextNfcAdapter == null) {                sNullContextNfcAdapter = new NfcAdapter(null);            }            return sNullContextNfcAdapter;        }                      //sNFcAdapter 是个HashMap,从中取出之前创建的NfcAdapter实例        NfcAdapter adapter = sNfcAdapters.get(context);        if (adapter == null) {            adapter = new NfcAdapter(context);            sNfcAdapters.put(context, adapter);        }        return adapter;    }
          Setp2-2:应用INfcAdapter.aidl和NfcService通信 ,INfcAdapter的方法都在NfcService的内部类NfcAdapterService中实现。

    /** get handle to NFC service interface */    private static INfcAdapter getServiceInterface() {        /* get a handle to NFC service */        IBinder b = ServiceManager.getService("nfc");        if (b == null) {            return null;        }        return INfcAdapter.Stub.asInterface(b);    }
现在Setp2的NfcAdapter已经得到了它的实例,接下来就Setp3,NfcAdapter.enable()和NfcAdapter.disable():

    public boolean enable() {        try {             //从setp2-2可以知道sService.enable()通过NfcAdapterService来实现的            return sService.enable();        } catch (RemoteException e) {            attemptDeadServiceRecovery(e);            return false;        }    }
接下来看NfcAdapterService extends INfcAdapter.Stub 中的enable()方法:

public boolean enable() throws RemoteException {                  //Question 1:      NfcService.enforceAdminPerm(mContext);      //把NFC 打开状态写到SharedPreferences中保存起来      saveNfcOnSetting(true);                   ......         //AsyncTash后台处理NFC的打开            new EnableDisableTask().execute(TASK_ENABLE);      return true;}

上面code 提到一个Question 1,其实它就是给NFC 赋予一个写的权限。

EnableDisableTask 在doInBackground中调用enableInternal();来处理NFC  turn on。

 boolean enableInternal() {             //logcat 信息可以看到的log信息            Log.i(TAG, "Enabling NFC");            updateState(NfcAdapter.STATE_TURNING_ON);                               //setp3-1:调用jni initialize做init相关的动作            if (!mDeviceHost.initialize()) {                Log.w(TAG, "Error enabling NFC");                updateState(NfcAdapter.STATE_OFF);                return false;            }            synchronized(NfcService.this) {                mObjectMap.clear();                 //setp 3-2:开启一些循环监听的线程服务                mP2pLinkManager.enableDisable(mIsNdefPushEnabled, true);                updateState(NfcAdapter.STATE_ON);            }            initSoundPool();            /* Start polling loop */            applyRouting(true);//开始扫描查询tag和P2p设备            return true;        }

setp3-1:initialize()对应的是在NativeNfcManager.java 中initialize()实现的,NativeNfcManager.initialize()直接调用的是jni方法doInitialize(),doInitialize()对应的在jni的方法:com_android_nfc_NfcManager_initialize(JNIEnv *e, jobject o),这部分将在NFC学习——NFC Enable 过程分析(二)   分析。       

setp3-2:这一部分将在NFC学习——NFC Enable 过程分析(三)   分析   

以上部分的分析配合下面这张图就更清晰了

以上图片来自:NFC framework introduce(一)

原创粉丝点击