前文[NFC]Tag设备响应流程中有提到P2P设备的发现的函数始于:onLlcpLinkActivated().
本文将基于onLlcpLinkActivated()开始后文的分析,进而引出P2P流程中的SNEP,NDEFPUSH,HANDOVER以及ECHOSERVER的响应过程.
程序进入 onLlcpLinkActivated() 后,有点类似notify,开始同时上层,有P2P设备靠近了,解析一下,是什么格式,看看要做什么操作.
@Override
public void onLlcpLinkActivated(NfcDepEndpoint device) {
sendMessage(NfcService.MSG_LLCP_LINK_ACTIVATION, device);
}
消息MSG_LLCP_LINK_ACTIVATION被NfcService.java自身注册的NfcServiceHandler进行处理
case MSG_LLCP_LINK_ACTIVATION:
if (mIsDebugBuild) {
//@paul: 发送LLCP_UP的广播
Intent actIntent = new Intent(ACTION_LLCP_UP);
mContext.sendBroadcast(actIntent);
}
//@paul: 解析底层传递上来的NfcDepEndpoint信息
llcpActivated((NfcDepEndpoint) msg.obj);
break;
在进入llcpActivated()之后,系统会区分Target和Initiator,这两种角色的流程基本上相同,差异点是在Target端会先执行connect(),此connect()是进行数据链路层的连接,保证底层已经是发现对方并且是可以连接的。
<span style="font-size:12px;">public void onLlcpActivated()
public void onLlcpFirstPacketReceived()
public void onLlcpDeactivated()
void onSendComplete(NdefMessage msg, long elapsedRealtime)</span>
这些函数必须在UI main thread 调用,用于接收到底层连接的各种状态的更新。各个函数的意义依照名字基本上就能理解了。
直接分析onLlcpActivated()函数:
/**
* Must be called on UI Thread.
*/
public void onLlcpActivated() {
Log.i(TAG, "LLCP activated");
synchronized (P2pLinkManager.this) {
...
mLlcpConnectDelayed = false;
//@paul: 初始状态mLinkState为LINK_STATE_DOWN
switch (mLinkState) {
case LINK_STATE_DOWN:
if (DBG) Log.d(TAG, "onP2pInRange()");
mLinkState = LINK_STATE_WAITING_PDU;
//@paul: 通知UI,发现P2P设备
mEventListener.onP2pInRange();
//@paul: 初始状态mSendState为SEND_STATE_NOTHING_TO_SEND
if (mSendState == SEND_STATE_PENDING) {
if (DBG) Log.d(TAG, "Sending pending data.");
mHandler.removeMessages(MSG_WAIT_FOR_LINK_TIMEOUT);
mSendState = SEND_STATE_SENDING;
onP2pSendConfirmed(false);
} else {
mSendState = SEND_STATE_NOTHING_TO_SEND;
//@paul: 依据APP设置的信息,准备发送的信息
prepareMessageToSend(true);
if (mMessageToSend != null ||
(mUrisToSend != null && mHandoverManager.isHandoverSupported())) {
if ((mSendFlags & NfcAdapter.FLAG_NDEF_PUSH_NO_CONFIRM) != 0) {
mSendState = SEND_STATE_SENDING;
//@paul: 不需要UI确认
onP2pSendConfirmed(false);
} else {
mSendState = SEND_STATE_NEED_CONFIRMATION;
if (DBG) Log.d(TAG, "onP2pSendConfirmationRequested()");
//@paul: 需要UI上确认过才能发送
mEventListener.onP2pSendConfirmationRequested();
}
}
}
break;
...
}
}
}
上述函数的重点就是:prepareMessageToSend() 以及mEventListener.onP2pSendConfirmationRequested(); 分析完需要确认的流程,那不需要确认的流程也就打通了。
由于NFC APP(例如Gallery,Calendar,联系簿等)在使用NFC发送数据时,都需要先设置要发送的数据的格式。设置的主要内容存放在变量:mMessageToSend ,mUrisToSend 中。此处涉及到APP部分,后续在单独开一节说明这部分。
先说明一下prepareMessageToSend(),此函数流程在注释中说明: