1 /* <lambda>null2 * Copyright 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.example.testdiscoverservice 17 18 import android.net.nsd.NsdManager 19 import android.net.nsd.NsdManager.ServiceInfoCallback 20 import android.net.nsd.NsdServiceInfo 21 import android.os.Bundle 22 import android.text.TextUtils 23 import android.util.Log 24 import android.widget.RadioGroup 25 import android.widget.TextView 26 import androidx.annotation.RequiresApi 27 import androidx.appcompat.app.AppCompatActivity 28 29 private val TAG = DiscoverActivity::class.simpleName 30 31 class DiscoverActivity : AppCompatActivity() { 32 33 private val nsdManager by lazy { getSystemService(NsdManager::class.java) } 34 private val lblLog by lazy { findViewById<TextView>(R.id.lblMainActivity) } 35 private val radioGroupMode by lazy { findViewById<RadioGroup>(R.id.radioGroupMode) } 36 private val log = mutableListOf<String>() 37 private var discoveryListener: DiscoveryListener? = null 38 private var serviceInfoListener: WatchListener? = null 39 private var resolveListener: ResolveListener? = null 40 41 @RequiresApi(34) 42 override fun onCreate(savedInstanceState: Bundle?) { 43 super.onCreate(savedInstanceState) 44 setContentView(R.layout.activity_main) 45 46 radioGroupMode.setOnCheckedChangeListener { _, _ -> 47 stop() 48 startNsdManager() 49 } 50 } 51 52 @RequiresApi(34) 53 override fun onStart() { 54 super.onStart() 55 startNsdManager() 56 } 57 58 @RequiresApi(34) 59 private fun startNsdManager() { 60 when (radioGroupMode.checkedRadioButtonId) { 61 R.id.radioDiscover -> startDiscovery() 62 R.id.radioWatch -> startWatch() 63 R.id.radioResolve -> startResolve() 64 } 65 } 66 67 private fun startDiscovery() { 68 log("Starting discovery") 69 discoveryListener = DiscoveryListener() 70 nsdManager.discoverServices("_nmt._tcp", NsdManager.PROTOCOL_DNS_SD, discoveryListener) 71 } 72 73 @RequiresApi(34) 74 private fun startWatch() { 75 log("Starting watch") 76 77 val serviceInfo = NsdServiceInfo().apply { 78 serviceName = "test_service" 79 serviceType = "_nmt._tcp" 80 } 81 82 serviceInfoListener = WatchListener().also { listener -> 83 nsdManager.registerServiceInfoCallback(serviceInfo, { it.run() }, listener) 84 } 85 } 86 87 private fun startResolve() { 88 log("Starting resolve") 89 90 val serviceInfo = NsdServiceInfo().apply { 91 serviceName = "test_service" 92 serviceType = "_nmt._tcp" 93 } 94 95 resolveListener = ResolveListener("Test1").also { listener -> 96 nsdManager.resolveService(serviceInfo, { it.run() }, listener) 97 } 98 } 99 100 @RequiresApi(34) 101 override fun onStop() { 102 super.onStop() 103 104 stop() 105 } 106 107 @RequiresApi(34) 108 private fun stop() { 109 log("Stopping current operation") 110 discoveryListener?.let { nsdManager.stopServiceDiscovery(it) } 111 discoveryListener = null 112 serviceInfoListener?.let { nsdManager.unregisterServiceInfoCallback(it) } 113 serviceInfoListener = null 114 resolveListener?.let { nsdManager.stopServiceResolution(it) } 115 resolveListener = null 116 } 117 118 private fun log(msg: String) { 119 runOnUiThread { 120 log.add(msg) 121 Log.i(TAG, msg) 122 lblLog.text = TextUtils.join("\n", log) 123 } 124 } 125 126 inner class DiscoveryListener : NsdManager.DiscoveryListener { 127 override fun onStartDiscoveryFailed(serviceType: String?, errorCode: Int) { 128 log("Start discovery failed for type $serviceType, error $errorCode") 129 } 130 131 override fun onStopDiscoveryFailed(serviceType: String?, errorCode: Int) { 132 log("Stop discovery failed for type $serviceType, error $errorCode") 133 } 134 135 override fun onDiscoveryStarted(serviceType: String?) { 136 log("Discovery started for type $serviceType") 137 } 138 139 override fun onDiscoveryStopped(serviceType: String?) { 140 log("Discovery stopped for type $serviceType") 141 } 142 143 override fun onServiceFound(serviceInfo: NsdServiceInfo?) { 144 log("Service found for type $serviceInfo") 145 146 } 147 148 override fun onServiceLost(serviceInfo: NsdServiceInfo?) { 149 log("Service lost for type $serviceInfo") 150 } 151 } 152 153 inner class ResolveListener(private val name : String) : NsdManager.ResolveListener { 154 override fun onResolveFailed(serviceInfo: NsdServiceInfo?, errorCode: Int) { 155 log("listenerName $name Resolve failed for service $serviceInfo with code $errorCode") 156 } 157 158 override fun onServiceResolved(serviceInfo: NsdServiceInfo?) { 159 log("listenerName $name Service resolved: $serviceInfo") 160 } 161 } 162 163 @RequiresApi(34) 164 inner class WatchListener : ServiceInfoCallback { 165 override fun onServiceInfoCallbackRegistrationFailed(p0: Int) {} 166 167 override fun onServiceUpdated(serviceInfo: NsdServiceInfo) { 168 log("Service updated: $serviceInfo") 169 } 170 171 override fun onServiceLost() { 172 log("Watched service lost") 173 } 174 175 override fun onServiceInfoCallbackUnregistered() {} 176 } 177 }