拿到一臺支持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(一)