Android源码-WirelessSettings之NFC小结

来源:互联网 发布:西北师范大学知行 编辑:程序博客网 时间:2024/06/05 17:59

Android Settings中包含有无线通信功能,其中有NFC,蓝牙,wifi等部分。最近看了和NFC有关的部分逻辑代码。做一个大概的记录。
首先是WirelessSettings结构图:
这里写图片描述

NFC的开关控制

NfcEnabler.java
NfcEnabler类就是对NFC进行开关状态管理的类
关键属性:
SwitchPreference mSwitch; //代表NFC这个SwitchPreference选项
PreferenceScreen mAndroidBeam; //代表AndroidBeam这个PreferenceScreen
NfcAdapter mNfcAdapter; //NfcAdapter适配器
mBeamDisallowedBySystem = RestrictedLockUtils.hasBaseUserRestriction(context,
UserManager.DISALLOW_OUTGOING_BEAM,UserHandle.myUserId()); //根据UserManage判断当前用是人否可以用AndroidBeam

主要方法:

handleNfcStateChanged(int newState)          //newState是mNfcAdapter.getAdapterState():NfcAdapter.STATE_OFF,NfcAdapter.STATE_ON,    STATE_TURNING_ON,STATE_TURNING_OF。根据newState来对 mSwitch,mAndroidBeam设置// 一个对nfcAdapter的state改变的广播监听来调用handleNfcStateChanged方法private final BroadcastReceiver mReceiver = new BroadcastReceiver() {        @Override        public void onReceive(Context context, Intent intent) {            String action = intent.getAction();            if (NfcAdapter.ACTION_ADAPTER_STATE_CHANGED.equals(action)) {                handleNfcStateChanged(intent.getIntExtra(NfcAdapter.EXTRA_ADAPTER_STATE,                        NfcAdapter.STATE_OFF));            }        }    }; 

NFC的service

NfcAdapter.java

这个类帮助我们去获得Nfc的Service
NfcAdapter类的getServiceInterface()方法会返回一个AIDL的Binder对应的service(这个service就是NfcService,用处很大),其中Binder是这样获得的 IBinder b = ServiceManager.getService(“nfc”)。
我们去看ServiceManager的getService()的代码发现涉及到getIServiceManager().getService(name); 而这个getIServiceManager()会返回一个IServiceManager对象,而这个IServiceManager对象是ServiceManagerNative.asInterface(BinderInternal.getContextObject())获得的。
我们进ServiceManagerNative里面看一下,这是一个抽象类(extends Binder implements IServiceManager),关键在于它实现了IServiceManager这个接口,IServiceManager应该是一个AIDL文件声明的接口。

ServiceManagerNative.java

//这一过程是把Client端的参数转换成Parcel(_data)传递到Server端,//而在Server端又会把返回数据保存到_reply中,这就形成了一次交互。public IBinder getService(String name) throws RemoteException {               Parcel data = Parcel.obtain();        Parcel reply = Parcel.obtain();        data.writeInterfaceToken(IServiceManager.descriptor);        data.writeString(name);        mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);        IBinder binder = reply.readStrongBinder();        reply.recycle();        data.recycle();        return binder;    }

所以这就是我们在NfcAdapter.java里看到的ServiceManager.getService(“nfc”)的具体实现。为什么要这样来获取服务?
因为这样可以远程获取服务,传递的参数,如:“nfc”被序列化放入Parcel,再被远程调用,这样获得service对象是可以跨进程访问的。一般Android源码中获得系统级的服务都会采用这种设计,保证跨进程访问的安全性。
那么后续的问题是我们怎么获得NFCAdapter

怎么获得一个NfcAdapter

NfcAdapter类的getDefaultAdapter(Context context)方法会返回一个NfcAdapter对象,它会通过 NfcManager来获得NfcManager对象,keycode如下:

NfcManager manager = (NfcManager) context.getSystemService(Context.NFC_SERVICE); return manager.getDefaultAdapter(); 我们进NfcManager.java里看,这里很关键,keycode如下: public NfcManager(Context context) {        NfcAdapter adapter;        context = context.getApplicationContext();        if (context == null) {            throw new IllegalArgumentException(                    "context not associated with any application (using a mock context?)");        }        try {            adapter = NfcAdapter.getNfcAdapter(context);      //其实还是调用的是NfcAdapter类的NfcAdapter.getNfcAdapter(context)方法        } catch (UnsupportedOperationException e) {            adapter = null;        }        mAdapter = adapter;    } public NfcAdapter getDefaultAdapter() {        return mAdapter;    }

这段代码中构造函数会在开机进行系统服务注册时执行,然后以后想得到NfcAdapter就只需要((NfcManager) context.getSystemService(Context.NFC_SERVICE)).getDefaultNfcAdapter(),不会重新执行getNfcAdapter()方法,节省资源开支。

NfcAdapter类的NfcAdapter.getNfcAdapter(context)方法,里面生成我们所需的NfcAdapter的keycode:

 NfcAdapter adapter = sNfcAdapters.get(context);    //sNfcAdapters:HashMap<Context, NfcAdapter>        if (adapter == null) {            adapter = new NfcAdapter(context);            sNfcAdapters.put(context, adapter);        } //构造方法 NfcAdapter(Context context) {        mContext = context;        mNfcActivityManager = new NfcActivityManager(this);        mNfcUnlockHandlers = new HashMap<NfcUnlockHandler, INfcUnlockHandler>();        mLock = new Object();    }
0 0
原创粉丝点击