拿到一台支持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" />
- 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;
- }
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();
- }
- //把mNfcAdapter 作为Service 添加到系统服务中,ServiceManager.getService("nfc")可以获取到binder
- ServiceManager.addService(SERVICE_NAME, mNfcAdapter);
Setp2-1:manager.getDefaultAdapter其实饶了一圈又回到NfcAdapter类中获取NfcAdapter实例,具体看下面code
code路径:frameworks/base/core/java/android/nfc/NfcManager.java
- public NfcAdapter getDefaultAdapter() {
- return mAdapter;
- }
- public NfcManager(Context context) {
- NfcAdapter adapter;
- ......
- try {
- adapter = NfcAdapter.getNfcAdapter(context);
- } catch (UnsupportedOperationException e) {
- adapter = null;
- }
- mAdapter = adapter;
- }
- 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;
- }
- /** 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);
- }
- public boolean enable() {
- try {
- //从setp2-2可以知道sService.enable()通过NfcAdapterService来实现的
- return sService.enable();
- } catch (RemoteException e) {
- attemptDeadServiceRecovery(e);
- return false;
- }
- }
- 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(一)