Wi-Fi 感知功能可讓搭載 Android 8.0 (API 級別 26) 和 而不需要其他類型 ,探索彼此並互相交流 以及應用程式之間的連線Wi-Fi Aware 也稱為「鄰近感知」 Networking (網路)。
Wi-Fi Aware 網路的運作方式為結合鄰近裝置的叢集,或 如果裝置位置內第一,請建立新叢集這個 叢集行為會套用至整部裝置,並由 Wi-Fi 管理 感知系統服務;因此應用程式無法控制叢集行為。應用程式使用情形 Wi-Fi Aware API 連線至 Wi-Fi Aware 系統服務, 才能啟動裝置的 Wi-Fi 感知硬體
Wi-Fi Aware API 可讓應用程式執行以下作業:
探索其他裝置:這個 API 提供尋找其他裝置的機制 附近的裝置。這項程序會在一部裝置發布一部裝置時開始執行 或更多可探索的服務之後,只要裝置訂閱一或多個方案 並輸入發布商的 Wi-Fi 範圍,訂閱者就會收到 通知,告知已有相符發布商。在 訂閱者找到發布者時,訂閱者可以 訊息,或與偵測到的裝置建立網路連線。 裝置可以同時為發布者和訂閱者。
建立網路連線:兩部裝置在發現兩者後 其他人就能建立 沒有存取點的雙向 Wi-Fi Aware 網路連線。
Wi-Fi Aware 網路連線支援更長的處理量傳輸速率 距離藍牙 連線狀態。這些連結類型對於應用程式 例如使用者之間的資料量,例如相片共享應用程式。
Android 13 (API 級別 33) 改善項目
在搭載 Android 13 (API 級別 33) 以上版本的裝置上,且支援免安裝技術
應用程式可以使用
PublishConfig.Builder.setInstantCommunicationModeEnabled()
和
SubscribeConfig.Builder.setInstantCommunicationModeEnabled()
方法,即可
啟用或停用發布者或訂閱者的即時通訊模式
探索過程。即時通訊模式可以加快訊息交換速度
服務探索,以及任何為發布者或訂閱者設定的資料路徑
探索過程。判斷裝置是否支援即時通訊
模式,請使用 isInstantCommunicationModeSupported()
方法。
Android 12 (API 級別 31) 改善項目
Android 12 (API 級別 31) 為 Wi-Fi Aware 新增了幾項改善:
- 在搭載 Android 12 (API 級別 31) 以上版本的裝置中,您可以使用
onServiceLost()
敬上 當應用程式因為 服務停止或移出範圍外。 - 已成功設定 Wi-Fi Aware 資料路徑。較舊版本 使用 L2 訊息提供發起人的 MAC 位址, 但有些許延遲在搭載 Android 12 以上版本的裝置上,回應者 (伺服器) 可以設定為接受任何對等互連,也就是說 且預先知道啟動器的 MAC 位址。這樣可以加快資料路徑 整合並啟用多個點對點連結,而且只需要一個網路 請求。
- 在 Android 12 以上版本中執行的應用程式可使用
WifiAwareManager.getAvailableAwareResources()
敬上 方法,以取得目前可用的資料路徑數量、發布工作階段數, 以及訂閱工作階段這可協助應用程式判斷 有足夠的可用資源來執行所需功能。
初始設定
如要設定應用程式使用 Wi-Fi Aware 探索和網路功能,請執行 步驟如下:
在應用程式資訊清單中要求下列權限:
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /> <uses-permission android:name="android.permission.INTERNET" /> <!-- If your app targets Android 13 (API level 33) or higher, you must declare the NEARBY_WIFI_DEVICES permission. --> <uses-permission android:name="android.permission.NEARBY_WIFI_DEVICES" <!-- If your app derives location information from Wi-Fi APIs, don't include the "usesPermissionFlags" attribute. --> android:usesPermissionFlags="neverForLocation" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" <!-- If any feature in your app relies on precise location information, don't include the "maxSdkVersion" attribute. --> android:maxSdkVersion="32" />
透過以下方式檢查裝置是否支援 Wi-Fi Aware:
PackageManager
API,如下所示:Kotlin
context.packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_AWARE)
Java
context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_AWARE);
檢查目前是否提供 Wi-Fi Aware。Wi-Fi Aware 可能位於 裝置,但目前可能因為使用者停用而無法使用 Wi-Fi 或位置資訊。視硬體和韌體功能而定,某些裝置會 開啟 Wi-Fi Direct、SoftAP 或網路共用功能時,可能不支援 Wi-Fi Aware 相關單位會如何運用資料,並讓他們覺得自己 獲得充分告知,且能夠針對該使用方式表示同意如要確認目前是否提供 Wi-Fi Aware,請撥打
isAvailable()
。Wi-Fi Aware 的可用性可能隨時變更。您的應用程式應 註冊
BroadcastReceiver
即可接收ACTION_WIFI_AWARE_STATE_CHANGED
, 每當有供應情形變更,系統就會傳送這個磁碟區。應用程式收到 廣播意圖,應捨棄所有現有的工作階段 (假設 Wi-Fi Aware 服務中斷,然後檢查 可用性,並據此調整其行為。 例如:Kotlin
val wifiAwareManager = context.getSystemService(Context.WIFI_AWARE_SERVICE) as WifiAwareManager? val filter = IntentFilter(WifiAwareManager.ACTION_WIFI_AWARE_STATE_CHANGED) val myReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { // discard current sessions if (wifiAwareManager?.isAvailable) { ... } else { ... } } } context.registerReceiver(myReceiver, filter)
Java
WifiAwareManager wifiAwareManager = (WifiAwareManager)context.getSystemService(Context.WIFI_AWARE_SERVICE) IntentFilter filter = new IntentFilter(WifiAwareManager.ACTION_WIFI_AWARE_STATE_CHANGED); BroadcastReceiver myReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // discard current sessions if (wifiAwareManager.isAvailable()) { ... } else { ... } } }; context.registerReceiver(myReceiver, filter);
詳情請參閱廣播的相關說明。
取得課程
如要開始使用 Wi-Fi Aware,您的應用程式必須取得
致電給WifiAwareSession
attach()
。這個方法
會執行以下動作:
- 開啟 Wi-Fi Aware 硬體。
- 加入或建立 Wi-Fi Aware 叢集。
- 使用不重複的命名空間建立 Wi-Fi Aware 工作階段 容器存放所有在其中建立的探索工作階段。
如果應用程式成功連接,系統就會執行
onAttached()
回呼。
這個回呼會提供 WifiAwareSession
物件
應用程式應用於所有後續工作階段作業。應用程式可以使用
發布服務
訂閱服務。
應用程式應呼叫
僅限attach()
一次。如果
您的應用程式會呼叫 attach()
多次,應用程式每次呼叫都會收到不同的工作階段,且
各自的命名空間這在複雜情況下非常實用
一般而言,我們會避免
發布服務
如要讓服務可供搜尋,請呼叫
publish()
方法,
請使用下列參數:
PublishConfig
會指定 服務和其他設定屬性,例如比對篩選器DiscoverySessionCallback
會指定 事件發生時要執行的動作,例如訂閱者收到訊息時 一則訊息
範例如下:
Kotlin
val config: PublishConfig = PublishConfig.Builder() .setServiceName(AWARE_FILE_SHARE_SERVICE_NAME) .build() awareSession.publish(config, object : DiscoverySessionCallback() { override fun onPublishStarted(session: PublishDiscoverySession) { ... } override fun onMessageReceived(peerHandle: PeerHandle, message: ByteArray) { ... } })
Java
PublishConfig config = new PublishConfig.Builder() .setServiceName(“Aware_File_Share_Service_Name”) .build(); awareSession.publish(config, new DiscoverySessionCallback() { @Override public void onPublishStarted(PublishDiscoverySession session) { ... } @Override public void onMessageReceived(PeerHandle peerHandle, byte[] message) { ... } }, null);
如果發布成功,
onPublishStarted()
回呼方法。
發布後,執行相符訂閱者應用程式的裝置會改為
發布裝置的 Wi-Fi 範圍,則由訂閱者找到服務。時間
訂閱者找到發布商後,發布者不會收到
通知;如果訂閱者傳送訊息給出版商,則
發布商會收到通知發生這種情況時
onMessageReceived()
回呼方法。您可以使用
將 PeerHandle
引數從這個方法
傳送訊息給訂閱者,或
建立連線。
如要停止發布服務,請呼叫
DiscoverySession.close()
。
探索工作階段與家長相關聯
WifiAwareSession
。如果父項工作階段
封閉式探索工作階段也已關閉。捨棄時
即使超出範圍,也無法保證
工作階段就會關閉,因此建議您明確呼叫 close()
方法。
訂閱服務
如要訂閱服務,請呼叫
subscribe()
方法,
該參數會使用下列參數:
-
SubscribeConfig
會指定 訂閱服務和其他設定屬性 (例如比對符合) 篩選。 DiscoverySessionCallback
會指定 觸發動作時要執行的動作,例如發現發布商時。
範例如下:
Kotlin
val config: SubscribeConfig = SubscribeConfig.Builder() .setServiceName(AWARE_FILE_SHARE_SERVICE_NAME) .build() awareSession.subscribe(config, object : DiscoverySessionCallback() { override fun onSubscribeStarted(session: SubscribeDiscoverySession) { ... } override fun onServiceDiscovered( peerHandle: PeerHandle, serviceSpecificInfo: ByteArray, matchFilter: List<ByteArray> ) { ... } }, null)
Java
SubscribeConfig config = new SubscribeConfig.Builder() .setServiceName("Aware_File_Share_Service_Name") .build(); awareSession.subscribe(config, new DiscoverySessionCallback() { @Override public void onSubscribeStarted(SubscribeDiscoverySession session) { ... } @Override public void onServiceDiscovered(PeerHandle peerHandle, byte[] serviceSpecificInfo, List<byte[]> matchFilter) { ... } }, null);
如果訂閱作業成功,系統會呼叫
onSubscribeStarted()
回呼。由於您可以使用
SubscribeDiscoverySession
引數的
在應用程式找到發布商後與發布商通訊的回呼。
應儲存這個參照您隨時可以透過以下方法更新訂閱工作階段:
撥號中
updateSubscribe()
我會深入探討
此時,您的訂閱項目會等待相符發布者加入
Wi-Fi 範圍。在這種情況下,系統會執行
onServiceDiscovered()
敬上
回呼方法。您可以使用 PeerHandle
引數,以便傳送訊息或
連結該發布商。
若要停止訂閱服務,請呼叫
DiscoverySession.close()
。
探索工作階段與家長相關聯
WifiAwareSession
。如果父項工作階段
封閉式探索工作階段也已關閉。捨棄時
即使超出範圍,也無法保證
工作階段就會關閉,因此建議您明確呼叫 close()
方法。
傳送訊息
如要傳送訊息至其他裝置,您需要下列物件:
DiscoverySession
。這個物件可讓您 通話sendMessage()
。 您的應用程式會透過下列方式取得DiscoverySession
發布服務或訂閱 服務。其他裝置的
PeerHandle
,以便轉送 撰寫新的電子郵件訊息您的應用程式取得了其他裝置的PeerHandle
可透過以下兩種方式之一:- 您的應用程式發布服務,並收到訂閱者傳送的訊息。
應用程式會取得訂閱者的
來自
onMessageReceived()
的PeerHandle
回呼。 - 您的應用程式訂閱服務。接著,當 Google 偵測到
這樣您的應用程式就會從發布商的廣告請求中獲得
PeerHandle
的onServiceDiscovered()
回呼。
- 您的應用程式發布服務,並收到訂閱者傳送的訊息。
應用程式會取得訂閱者的
來自
如要傳送訊息,請撥打
sendMessage()
。
下列回呼可能會發生:
- 對等點成功收到訊息後,系統會呼叫
onMessageSendSucceeded()
傳送應用程式中的回呼。 - 對等連線收到訊息時,系統會呼叫
onMessageReceived()
接收應用程式中的回呼。
雖然與同類應用程式通訊時需要使用 PeerHandle
,但請勿
並視為對等的永久 ID。高階 ID 可以是
內嵌於探索服務本身,或位於
後續訊息。您可以在探索服務中嵌入 ID,例如
這個
setMatchFilter()
敬上
或
setServiceSpecificInfo()
。
PublishConfig
方法或
SubscribeConfig
。
setMatchFilter()
方法會影響探索,而
setServiceSpecificInfo()
方法不會影響探索作業。
將 ID 嵌入訊息中即意味著修改訊息位元組陣列到 包括 ID (例如前幾個位元組)。
建立連線
Wi-Fi Aware 支援在兩部 Wi-Fi Aware 裝置之間使用用戶端伺服器網路。
如要設定用戶端與伺服器連線:
訂閱者找到發布者後 訂閱者傳送訊息給發布商。
為發布商啟動
ServerSocket
,接著設定或取得其連接埠:Kotlin
val ss = ServerSocket(0) val port = ss.localPort
Java
ServerSocket ss = new ServerSocket(0); int port = ss.getLocalPort();
使用
ConnectivityManager
: 使用WifiAwareNetworkSpecifier
, 並指定探索工作階段 訂閱者的PeerHandle
, 從訂閱者傳送的訊息中取得:Kotlin
val networkSpecifier = WifiAwareNetworkSpecifier.Builder(discoverySession, peerHandle) .setPskPassphrase("somePassword") .setPort(port) .build() val myNetworkRequest = NetworkRequest.Builder() .addTransportType(NetworkCapabilities.TRANSPORT_WIFI_AWARE) .setNetworkSpecifier(networkSpecifier) .build() val callback = object : ConnectivityManager.NetworkCallback() { override fun onAvailable(network: Network) { ... } override fun onCapabilitiesChanged(network: Network, networkCapabilities: NetworkCapabilities) { ... } override fun onLost(network: Network) { ... } } connMgr.requestNetwork(myNetworkRequest, callback);
Java
NetworkSpecifier networkSpecifier = new WifiAwareNetworkSpecifier.Builder(discoverySession, peerHandle) .setPskPassphrase("somePassword") .setPort(port) .build(); NetworkRequest myNetworkRequest = new NetworkRequest.Builder() .addTransportType(NetworkCapabilities.TRANSPORT_WIFI_AWARE) .setNetworkSpecifier(networkSpecifier) .build(); ConnectivityManager.NetworkCallback callback = new ConnectivityManager.NetworkCallback() { @Override public void onAvailable(Network network) { ... } @Override public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) { ... } @Override public void onLost(Network network) { ... } }; ConnectivityManager connMgr.requestNetwork(myNetworkRequest, callback);
發布商請求聯播網後,應該 傳送訊息給訂閱者。
訂閱者收到發布者傳來的訊息後,請要求 Wi-Fi 連線 訂閱者使用與發布商相同的方法提升品牌知名度。正確做法 建立 Pod 時未指定通訊埠
NetworkSpecifier
。 網路連線 可用、變更或遺失在訂閱者上呼叫
onAvailable()
方法後,Network
物件由以下服務提供: 您可以開啟Socket
與發布商的ServerSocket
互動,但您必須瞭解ServerSocket
的 IPv6 位址和通訊埠。這些資訊來自NetworkCapabilities
物件onCapabilitiesChanged()
回呼中提供的方法:Kotlin
val peerAwareInfo = networkCapabilities.transportInfo as WifiAwareNetworkInfo val peerIpv6 = peerAwareInfo.peerIpv6Addr val peerPort = peerAwareInfo.port ... val socket = network.getSocketFactory().createSocket(peerIpv6, peerPort)
Java
WifiAwareNetworkInfo peerAwareInfo = (WifiAwareNetworkInfo) networkCapabilities.getTransportInfo(); Inet6Address peerIpv6 = peerAwareInfo.getPeerIpv6Addr(); int peerPort = peerAwareInfo.getPort(); ... Socket socket = network.getSocketFactory().createSocket(peerIpv6, peerPort);
網路連線完成後,請呼叫
unregisterNetworkCallback()
。
選擇同類應用程式及可辨識位置的探索方式
已安裝 Wi-Fi 即時文字訊息位置資訊的裝置 可直接測量與同類應用程式的距離,並使用這項資訊 限制 Wi-Fi Aware 服務探索。
Wi-Fi RTT API 可讓您使用 MAC 位址或其 PeerHandle。
只要將 Wi-Fi Aware 探索功能設為限制,就只能搜尋
特定地理圍欄例如,您可以設定地理圍欄
的裝置發布了 "Aware_File_Share_Service_Name"
服務,
介於 3 公尺 (指定為 3,000 公釐) 且不超過 10 公尺
(指定為 10,000 公釐)。
如要啟用地理圍欄功能,發布者與訂閱者必須採取下列行動:
發布商必須使用 setRangingEnabled(true)。
如果發布商未啟用範圍,有任何地理圍欄限制 會忽略訂閱者指定的內容,並執行一般探索。 忽略距離。
訂閱者必須使用 setMinDistanceMm 和 setMaxDistanceMm,
對於任一值,未指定距離代表無限制。僅指定 最大距離表示最短距離 0。只有指定 最小距離表示無上限。
如果在地理圍欄內發現對等互連服務, onServiceDiscoveredWithinRange 觸發回呼,進而提供與對等點之間的測量距離。 然後視需要呼叫直接 Wi-Fi RTT API,以測量距離 再聯絡。