iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 20
0
  • Guide :
    • 介紹
    • Service
    • Adapter
    • Handover
    • Kernel

前情提要:

上一篇提到很多工作都在 BeamTransferManafer 裡面完成的,
那我們就先來看一下第一個通知 updateNotification

packages/apps/Nfc/src/com/android/nfc/beam/BeamTransferManager.java

302     void updateNotification() {
... ...
309         String beamString;
**//下面判斷是往外發送還是接受的,此處我們分析的是發送的。(看接受的是不是從HandoverServer)**
310         if (mIncoming) {
311             beamString = mContext.getString(R.string.beam_progress);
312         } else {
313             beamString = mContext.getString(R.string.beam_outgoing);
314         }
**//第一次的時候mState == STATE_NEW在構造中進行的實例化**
315         if (mState == STATE_NEW || mState == STATE_IN_PROGRESS || 
316                 mState == STATE_W4_NEXT_TRANSFER || mState == STATE_W4_MEDIA_SCANNER) {
317             notBuilder.setAutoCancel(false);
318             notBuilder.setSmallIcon(mIncoming ? android.R.drawable.stat_sys_download :
319                     android.R.drawable.stat_sys_upload);
320             notBuilder.setTicker(beamString);
321             notBuilder.setContentTitle(beamString);
322             notBuilder.addAction(R.drawable.ic_menu_cancel_holo_dark,
323                     mContext.getString(R.string.cancel), mCancelIntent);
**//下面就是處理進度條顯示的問題**
324             float progress = 0;         
325             if (mTotalCount > 0) {      
326                 float progressUnit = 1.0f / mTotalCount;
327                 progress = (float) mCurrentCount * progressUnit + mProgress * progressUnit;
328             }
329             if (mTotalCount > 0 && progress > 0) {
330                 notBuilder.setProgress(100, (int) (100 * progress), false);
331             } else {
332                 notBuilder.setProgress(100, 0, true);
333             }
**//傳輸成功的時候**
334         } else if (mState == STATE_SUCCESS) { 
335             notBuilder.setAutoCancel(true);
... ...
**//傳輸失敗的時候**
349         } else if (mState == STATE_FAILED) {
350             notBuilder.setAutoCancel(false);
... ...
**//傳輸取消的時候**
355         } else if (mState == STATE_CANCELLED || mState == STATE_CANCELLING) {
356             notBuilder.setAutoCancel(false);
... ...
361         } else {
362             return;
363         }
364 
**//這裡把不同的顯示結果提示出去即可**
365         mNotificationManager.notify(null, mTransferId, notBuilder.build());
366     }

再來就是上一篇一直提到的 BeamTransferManagerstart() 的部份:

packages/apps/Nfc/src/com/android/nfc/beam/BeamTransferManager.java

191     public void start() { 
... ...
**//往外傳輸的時候**
199         if (!mIncoming) {
**//通過藍芽傳輸的時候**
200             if (mDataLinkType == BeamTransferRecord.DATA_LINK_TYPE_BLUETOOTH) {
**//傳入Handoverserver後返回的NDEF消息用於和本地藍牙配對鏈接等**
201                 new **BluetoothOppHandover(mContext, mRemoteDevice, mUris, mRemoteActivating).start()**;
202             }    
203         }        
204     }

再來跳到 BluetoothOppHandoverstart() 部份:

packages/apps/Nfc/src/com/android/nfc/beam/BluetoothOppHandover.java

 77     public void start() {   
 78         if (mRemoteActivating) {       
 79             Long timeElapsed = SystemClock.elapsedRealtime() - mCreateTime;
 80             if (timeElapsed < REMOTE_BT_ENABLE_DELAY_MS) { 
 81                 mHandler.sendEmptyMessageDelayed(MSG_START_SEND,
 82                         REMOTE_BT_ENABLE_DELAY_MS - timeElapsed);
 83             } else {        
 84                 // Already waited long enough for BT to come up
 85                 // - start send.               
 86                 **sendIntent()**;
 87             }   
 88         } else {            
 89             // Remote BT enabled already, start send immediately
 90             **sendIntent()**;   
 91         }                   
 92     }

packages/apps/Nfc/src/com/android/nfc/beam/BluetoothOppHandover.java

 98     void sendIntent() { 
 99         Intent intent = new Intent();  
100         intent.setPackage(mContext.getString(R.string.bluetooth_package));
101         String mimeType = MimeTypeUtil.getMimeTypeForUri(mContext, mUris.get(0));
102         intent.setType(mimeType);      
103         intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice);
104         for (Uri uri : mUris) {        
105             // TODO we need to transfer our permission grant from NFC
106             // to the Bluetooth process. This works, but we don't have
107             // a good framework API for revoking permission yet.
108             try {     
109                 mContext.grantUriPermission(mContext.getString(R.string.bluetooth_package), uri,
110                         Intent.FLAG_GRANT_READ_URI_PERMISSION);
111             } catch (SecurityException e) {
112                 Log.e(TAG, "Failed to transfer permission to Bluetooth process.");
113             } 
114         }     
115         if (mUris.size() == 1) {
116             intent.setAction(ACTION_HANDOVER_SEND);
117             intent.putExtra(Intent.EXTRA_STREAM, mUris.get(0));
118         } else {
119             intent.setAction(ACTION_HANDOVER_SEND_MULTIPLE);
120             intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, mUris);
121         }     
122         if (DBG) Log.d(TAG, "Handing off outging transfer to BT");
123         intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
124         mContext.sendBroadcast(intent);
125               
126         complete();
127     }

結語:

到此我們就完成了 NFC 端的發送廣播和 BT 通信去完成最終的數據傳輸,
一旦開始傳輸,BT 就會在每個傳輸的階段發送廣播給 NFC 的應用,
以便 NFC 應用可以更新通知的顯示。
後面相對地有點無趣,就不去介紹了。
再來下一篇就繼續把 Kernel 的部份講完吧,
NFC 系列就先暫時這樣了。


Reference :


上一篇
[Day-20] Android Pie NFC (7) Handover (4)
下一篇
[Day-22] Android Pie NFC (9) Kernel (1)
系列文
Android Pie 底層開發學習心得30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言