前情提要:
上一篇我們提到將藍芽裝置像是 Tag 一般感應後,
藍芽配對的流程解釋完畢,
這時候我們就可以來稍微看一下,
P2P 模式最終以藍芽傳輸的過程。
此時用戶已經點擊屏幕,開始回調 (Callback) 發送事件。
對應的 HandoverClient
和 HandoverServer
已經啟動。
也就是從 P2pLinkManager
類的 SendTask
內部類開始分析:
packages/apps/Nfc/src/com/android/nfc/P2pLinkManager.java
832 final class SendTask extends AsyncTask<Void, Void, Void> {
833 NdefPushClient nppClient;
834 SnepClient snepClient;
835 HandoverClient handoverClient;
836
**//需要通過BT傳輸的操作,等等又會再跳回來這裡**
837 int **doHandover**(Uri[] uris, UserHandle userHandle) throws IOException {
838 NdefMessage response = null;
**//先實例化BeamManager,用於管理從開始到結束的傳輸的動作**
839 BeamManager beamManager = BeamManager.getInstance();
840
... ...
**//如下是接收端根據協議把要請求的信息如藍牙地址等,封裝成NDEF格式的信息用於往外發送給
//另一個手機也就是發送端,然後發送端開啟自己的BT進行配對等等的操作,暫不分析此處細節**
845 NdefMessage request = mHandoverDataParser.createHandoverRequestMessage();
846 if (request != null) {
847 if (handoverClient != null) {
**//通過Client向接收端發送請求,內部就是往指定的服務器地址發送NDEF請求信息,請求用handover來傳輸
//此處的信息還是通過NFC來發送的**
848 response = handoverClient.sendHandoverRequest(request);
849 }
**//如果遠端的手機或裝置不支持handover,那麼改用別的方式**
850 if (response == null && snepClient != null) {
851 // Remote device may not support handover service,
852 // try the (deprecated) SNEP GET implementation
853 // for devices running Android 4.1
854 SnepMessage snepResponse = snepClient.get(request);
855 response = snepResponse.getNdefMessage();
856 }
... ...
走到這裡證明遠端的 Handover 是成功的,
打算開始調用 BT (藍芽) 進行真正數據的傳輸。
這裡可以看到 mHandoverDataParser.getOutgoingHandoverData(response)
來把 HandoverServer
傳過來的 NDEF 數據解析,
並且賦值給我們需要的變量,比如把藍牙地址、名稱、數據配對信息等,
賦值給了 BeamManager
的 startBeamSend
函式的參數。
這些數據內容多半是藍芽協議的部份,暫不分析:
packages/apps/Nfc/src/com/android/nfc/P2pLinkManager.java
867 if (!beamManager.**startBeamSend**(mContext,
868 **mHandoverDataParser.getOutgoingHandoverData(response)**, uris, userHandle)) {
869 return HANDOVER_BUSY;
870 }
871
872 return HANDOVER_SUCCESS;
873 }
... ...
因為一開始有實作 AsynkTask,所以會調用到 doInBackground
,
有興趣可以自行參考 AsynkTask 官網說明。
當解析傳過來的數據發現需要使用 Handover 的時候,uris
有值時,此時進入到 doHandover
:
packages/apps/Nfc/src/com/android/nfc/P2pLinkManager.java
884 @Override
885 public Void doInBackground(Void... args) {
... ...
905 if (uris != null) {
906 if (DBG) Log.d(TAG, "Trying handover request");
907 try {
908 int handoverResult = **doHandover**(uris, userHandle);
909 switch (handoverResult) {
910 case HANDOVER_SUCCESS:
911 result = true;
912 break;
913 case HANDOVER_FAILURE:
914 result = false;
915 break;
916 case HANDOVER_UNSUPPORTED:
917 result = false;
918 onHandoverUnsupported();
919 break;
920 case HANDOVER_BUSY:
921 result = false;
922 onHandoverBusy();
923 break;
924 }
925 } catch (IOException e) {
926 result = false;
927 }
928 }
接下來我們就來看看 BeamManager 的簡單介紹:
這時候我們又回到剛剛 startBeamSend
函式執行階段,
已經收到回應開始嘗試使用 handover 模式,也稱為 Beam 模式。
注意第二個參數就是遠端的 Handoverserver 給出的回應,進一步封裝的數據。packages/apps/Nfc/src/com/android/nfc/beam/BeamManager.java
97 public boolean startBeamSend(Context context,
98 **HandoverDataParser.BluetoothHandoverData outgoingHandoverData**,
99 Uri[] uris, UserHandle userHandle) {
100 synchronized (mLock) {
101 if (mBeamInProgress) {
102 return false;
103 } else {
104 mBeamInProgress = true;
105 }
106 }
107
**//這個Record如其名字,就是記錄了remoteDevice(遠端的device)、uris(存放的要傳輸的數據的uri)等**
108 BeamTransferRecord transferRecord = BeamTransferRecord.forBluetoothDevice(
109 **outgoingHandoverData.device**, outgoingHandoverData.carrierActivating,
110 **uris**);
**//啟動BeamReceiveService來通過service進一步完成正真的傳輸**
111 Intent sendIntent = new Intent(context.getApplicationContext(),
112 **BeamSendService.class**);
113 sendIntent.putExtra(BeamSendService.EXTRA_BEAM_TRANSFER_RECORD, transferRecord);
114 sendIntent.putExtra(BeamSendService.EXTRA_BEAM_COMPLETE_CALLBACK,
115 new Messenger(mCallback));
116 context.startServiceAsUser(sendIntent, userHandle);
117 return true;
118 }
再來就看看 intent 送過去之後做了什麼事吧:
packages/apps/Nfc/src/com/android/nfc/beam/BeamSendService.java
32 public class BeamSendService extends Service implements BeamTransferManager.Callback {
... ...
48 private final BroadcastReceiver mBluetoothStateReceiver = new BroadcastReceiver() {
49 @Override
50 public void onReceive(Context context, Intent intent) {
51 String action = intent.getAction();
52 if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
53 **handleBluetoothStateChanged(intent)**;
54 }
55 }
56 };
57
**//先得到BluetoothAdapter後面作使用**
58 public BeamSendService() {
59 mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
60 }
執行傳送的部份:
packages/apps/Nfc/src/com/android/nfc/beam/BeamSendService.java
81 @Override
82 public int **onStartCommand**(Intent intent, int flags, int startId) {
... ...
95 if (**doTransfer(transferRecord)**) {
96 if (DBG) Log.i(TAG, "Starting outgoing Beam transfer");
97 return START_STICKY;
98 } else {
... ...
103 }
packages/apps/Nfc/src/com/android/nfc/beam/BeamSendService.java
105 boolean **doTransfer**(BeamTransferRecord transferRecord) {
106 if (**createBeamTransferManager**(transferRecord)) {
... ...
**//Ndef信息中攜帶的是藍牙的傳輸鏈接的時候才進行傳輸。**
112 if (transferRecord.dataLinkType == BeamTransferRecord.DATA_LINK_TYPE_BLUETOOTH) {
113 if (mBluetoothAdapter.isEnabled()) {
114 // Start the transfer
**//直接調用TransferManager的start開始傳送**
115 **mTransferManager.start()**;
**//若藍芽沒打開,調用BT相關的接口去打開藍牙,打開成功後會發送藍牙狀態改變你的廣播**
116 } else {
117 if (!mBluetoothAdapter.enableNoAutoConnect()) {
118 Log.e(TAG, "Error enabling Bluetooth.");
119 mTransferManager = null;
120 return false;
121 }
122 mBluetoothEnabledByNfc = true;
123 if (DBG) Log.d(TAG, "Queueing out transfer "
124 + Integer.toString(transferRecord.id));
... ...
這裡很重要,實例化 BeamTransferManager
來管理傳輸中的流程顯示等,
關於 BeamTransferManager
細部下一篇再來詳解:
packages/apps/Nfc/src/com/android/nfc/beam/BeamSendService.java
133 boolean createBeamTransferManager(BeamTransferRecord transferRecord) {
... ...
142
143 mTransferManager = new **BeamTransferManager**(this, this, transferRecord, false);
144 mTransferManager.updateNotification();
145 return true;
146 }
收到BT開啟的廣播以後開始準備傳送:
packages/apps/Nfc/src/com/android/nfc/beam/BeamSendService.java
148 private void **handleBluetoothStateChanged**(Intent intent) {
149 int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
150 BluetoothAdapter.ERROR);
151 if (state == BluetoothAdapter.STATE_ON) {
152 if (mTransferManager != null &&
153 mTransferManager.mDataLinkType == BeamTransferRecord.DATA_LINK_TYPE_BLUETOOTH) {
**//收到廣播以後同樣是調用TransferManager的start開始傳輸**
154 **mTransferManager.start()**;
155 }
156 } else if (state == BluetoothAdapter.STATE_OFF) {
157 mBluetoothEnabledByNfc = false;
158 }
159 }
傳輸完成的回調 (Callback):
173 @Override
174 public void onTransferComplete(BeamTransferManager transfer, boolean success) {
175 // Play success sound
176 if (!success) {
177 if (DBG) Log.d(TAG, "Transfer failed, final state: " +
178 Integer.toString(transfer.mState));
179 }
180
181 if (mBluetoothEnabledByNfc) {
182 mBluetoothEnabledByNfc = false;
183 mBluetoothAdapter.disable();
184 }
185
186 invokeCompleteCallback(success);
187 stopSelf(mStartId);
188 }
可以看到如上的很多的工作都是在 BeamTransferManager
中完成的!BeamTransferManager
代碼較多此處就一點點分析先從實例化看起。
下一篇待續!
https://blog.csdn.net/zy00000000001/article/details/73730458