Ağ hizmeti keşfini kullanma

Ağ hizmeti keşfi (NSD), uygulamanızın başka yerel bir ağda sağlar. NSD'yi destekleyen cihazlar arasında yazıcılar ve HTTPS sunucuları ve diğer mobil cihazlar için de geçerlidir.

NSD, DNS tabanlı Hizmet Keşfi (DNS-SD) mekanizmasını uygular. Uygulamanızın bir hizmet türü ve ad belirterek hizmet istemesine olanak tanır sağlayan bir cihaz örneğidir. DNS-SD (yeni): hem Android'de hem de diğer mobil platformlarda desteklenir.

Uygulamanıza NSD eklemek, kullanıcılarınızın diğer cihazları tanımasına olanak sağlar uygulamanızın istediği hizmetleri destekleyen yerel ağ. Bu işlem, dosya paylaşımı veya çok oyunculu oyun gibi çeşitli eşler arası uygulamalar bahsedeceğim. Android'in NSD API'leri, Google Ads API'lerini uygulamak için izin verir.

Bu derste, Schema.org'u yayınlayabilen bir uygulamanın nasıl yerel ağ adını ve bağlantı bilgilerini gözden geçirin ve bilgi için tarayın diğer uygulamalardan ayırt edebilirsiniz. Son olarak bu derste, başka bir cihazda çalışan aynı uygulamaya bağlanmak zorundadır.

Hizmetinizi ağa kaydetme

Not: Bu adım isteğe bağlıdır. Eğer uygulamanızın hizmetlerini yerel ağ üzerinden yayınlamak sizin için önemli değilse, ileri doğru atlayabilirsiniz. Ağdaki Hizmetleri Keşfetme başlıklı makaleye göz atın.

Hizmetinizi yerel ağa kaydetmek için önce bir NsdServiceInfo nesnesi oluşturun. Bu nesne, tablodaki bilgileri ağdaki diğer cihazların, kablosuz ağa bağlanmaya karar verirken kullandıkları geliştirmenizi sağlar.

Kotlin

fun registerService(port: Int) {
    // Create the NsdServiceInfo object, and populate it.
    val serviceInfo = NsdServiceInfo().apply {
        // The name is subject to change based on conflicts
        // with other services advertised on the same network.
        serviceName = "NsdChat"
        serviceType = "_nsdchat._tcp"
        setPort(port)
        ...
    }
}

Java

public void registerService(int port) {
    // Create the NsdServiceInfo object, and populate it.
    NsdServiceInfo serviceInfo = new NsdServiceInfo();

    // The name is subject to change based on conflicts
    // with other services advertised on the same network.
    serviceInfo.setServiceName("NsdChat");
    serviceInfo.setServiceType("_nsdchat._tcp");
    serviceInfo.setPort(port);
    ...
}

Bu kod snippet'i, hizmet adını "NsdChat" olarak ayarlar. Hizmetin adı örnek adıdır: ağdaki diğer cihazlar tarafından görülebilen addır. Bu ad, ağ üzerinde NSD kullanan tüm cihazlar tarafından yerel hizmetler. Bu adın Android, çakışma çözümünü otomatik olarak işler. Eğer ağdaki iki cihazda da NsdChat uygulaması yüklü olmalıdır. hizmet adını otomatik olarak "NsdChat" gibi bir şekilde değiştirir. (1)" olarak değiştirin.

İkinci parametre hizmet türünü belirler, hangi protokolü ve aktarımını katmanız var. Söz dizimi: "_<protokol>._<transportlayer>". kod snippet'i varsa hizmet TCP üzerinden çalışan HTTP protokolü kullanır. Uygulama bir yazıcı hizmeti (örneğin, bir ağ yazıcısı) sunmak, hizmet türünü "_ipp._tcp" olarak ayarlayın.

Not: Uluslararası Atanan Numaralar Otorite (IANA) merkezi, NSD ve Bonjour gibi hizmet keşfi protokolleri tarafından kullanılan yetkili hizmet türlerinin listesi. Listeyi Hizmet adlarının ve bağlantı noktası numaralarının IANA listesi. Yeni bir hizmet türü kullanmak istiyorsanız IANA Limanları ve Hizmeti kayıt formunu doldurun.

Hizmetiniz için bağlantı noktasını ayarlarken başka uygulamalarla çakışmadığından emin olun. Örneğin, Yeşil Ofis’in uygulamanızın her zaman bağlantı noktası 1337'yi kullanması, aynı bağlantı noktasını kullanan yüklü diğer uygulamalardır. Bunun yerine cihazın bir sonraki kullanılabilir bağlantı noktasını seçin. Bu bilgiler diğer uygulamalara uygulamanızın kullandığı bağlantı noktasının diğer uygulamalar tarafından bilinen kodu otomatik olarak alır. Bunun yerine uygulamalar bu bilgileri, servis yayınınızdan hemen önce, geliştirmenizi sağlar.

Yuvalarla çalışıyorsanız bir soketi herhangi bir cihazda şu şekilde başlatabilirsiniz: bağlantı noktasını 0 olarak ayarlamanız yeterlidir.

Kotlin

fun initializeServerSocket() {
    // Initialize a server socket on the next available port.
    serverSocket = ServerSocket(0).also { socket ->
        // Store the chosen port.
        mLocalPort = socket.localPort
        ...
    }
}

Java

public void initializeServerSocket() {
    // Initialize a server socket on the next available port.
    serverSocket = new ServerSocket(0);

    // Store the chosen port.
    localPort = serverSocket.getLocalPort();
    ...
}

Artık NsdServiceInfo nesnesini tanımladığınıza göre, RegistrationListener arayüzünü uygulamanız gerekir. Bu Arayüz, Android tarafından uygulamanızı Hizmet kaydının başarılı veya başarısız olması ve kaydın silinmesi.

Kotlin

private val registrationListener = object : NsdManager.RegistrationListener {

    override fun onServiceRegistered(NsdServiceInfo: NsdServiceInfo) {
        // Save the service name. Android may have changed it in order to
        // resolve a conflict, so update the name you initially requested
        // with the name Android actually used.
        mServiceName = NsdServiceInfo.serviceName
    }

    override fun onRegistrationFailed(serviceInfo: NsdServiceInfo, errorCode: Int) {
        // Registration failed! Put debugging code here to determine why.
    }

    override fun onServiceUnregistered(arg0: NsdServiceInfo) {
        // Service has been unregistered. This only happens when you call
        // NsdManager.unregisterService() and pass in this listener.
    }

    override fun onUnregistrationFailed(serviceInfo: NsdServiceInfo, errorCode: Int) {
        // Unregistration failed. Put debugging code here to determine why.
    }
}

Java

public void initializeRegistrationListener() {
    registrationListener = new NsdManager.RegistrationListener() {

        @Override
        public void onServiceRegistered(NsdServiceInfo NsdServiceInfo) {
            // Save the service name. Android may have changed it in order to
            // resolve a conflict, so update the name you initially requested
            // with the name Android actually used.
            serviceName = NsdServiceInfo.getServiceName();
        }

        @Override
        public void onRegistrationFailed(NsdServiceInfo serviceInfo, int errorCode) {
            // Registration failed! Put debugging code here to determine why.
        }

        @Override
        public void onServiceUnregistered(NsdServiceInfo arg0) {
            // Service has been unregistered. This only happens when you call
            // NsdManager.unregisterService() and pass in this listener.
        }

        @Override
        public void onUnregistrationFailed(NsdServiceInfo serviceInfo, int errorCode) {
            // Unregistration failed. Put debugging code here to determine why.
        }
    };
}

Artık hizmetinizi kaydetmek için gereken her şeye sahipsiniz. Yöntemi çağırın registerService()

Bu yöntemin eşzamansız olduğunu, dolayısıyla çalıştırılması gereken tüm kodların hizmet kaydedildikten sonra onServiceRegistered() yöntemine geçmelidir.

Kotlin

fun registerService(port: Int) {
    // Create the NsdServiceInfo object, and populate it.
    val serviceInfo = NsdServiceInfo().apply {
        // The name is subject to change based on conflicts
        // with other services advertised on the same network.
        serviceName = "NsdChat"
        serviceType = "_nsdchat._tcp"
        setPort(port)
    }

    nsdManager = (getSystemService(Context.NSD_SERVICE) as NsdManager).apply {
        registerService(serviceInfo, NsdManager.PROTOCOL_DNS_SD, registrationListener)
    }
}

Java

public void registerService(int port) {
    NsdServiceInfo serviceInfo = new NsdServiceInfo();
    serviceInfo.setServiceName("NsdChat");
    serviceInfo.setServiceType("_http._tcp.");
    serviceInfo.setPort(port);

    nsdManager = Context.getSystemService(Context.NSD_SERVICE);

    nsdManager.registerService(
            serviceInfo, NsdManager.PROTOCOL_DNS_SD, registrationListener);
}

Ağdaki hizmetleri keşfedin

Ağ, canavarlık ağ yazıcılarından ufak tefek ağ web kameraları, yakındaki tik-tac-toe savaşlarının acımasız oyunculardan biri. Uygulamanızın bu canlı ekosistemini görmesini sağlamanın anahtarı, sunulan hizmet keşfidir. Uygulamanızın hizmeti dinlemesi gerekiyor ağdaki yayınları görebilir ve hangi hizmetlerin kullanılabilir olduğunu görebilir uygulamanın çalışamayacağı tüm öğeleri içerir.

Hizmet kaydı gibi hizmet keşfinin iki adımı vardır: alakalı geri çağırmalarla bir keşif işleyici oluşturma ve tek bir eşzamansız uygulama oluşturma discoverServices() için API çağrısı.

Öncelikle, NsdManager.DiscoveryListener işlemini uygulayan anonim bir sınıf örneği oluşturun. Aşağıdaki snippet'te bir basit bir örnek:

Kotlin

// Instantiate a new DiscoveryListener
private val discoveryListener = object : NsdManager.DiscoveryListener {

    // Called as soon as service discovery begins.
    override fun onDiscoveryStarted(regType: String) {
        Log.d(TAG, "Service discovery started")
    }

    override fun onServiceFound(service: NsdServiceInfo) {
        // A service was found! Do something with it.
        Log.d(TAG, "Service discovery success$service")
        when {
            service.serviceType != SERVICE_TYPE -> // Service type is the string containing the protocol and
                // transport layer for this service.
                Log.d(TAG, "Unknown Service Type: ${service.serviceType}")
            service.serviceName == mServiceName -> // The name of the service tells the user what they'd be
                // connecting to. It could be "Bob's Chat App".
                Log.d(TAG, "Same machine: $mServiceName")
            service.serviceName.contains("NsdChat") -> nsdManager.resolveService(service, resolveListener)
        }
    }

    override fun onServiceLost(service: NsdServiceInfo) {
        // When the network service is no longer available.
        // Internal bookkeeping code goes here.
        Log.e(TAG, "service lost: $service")
    }

    override fun onDiscoveryStopped(serviceType: String) {
        Log.i(TAG, "Discovery stopped: $serviceType")
    }

    override fun onStartDiscoveryFailed(serviceType: String, errorCode: Int) {
        Log.e(TAG, "Discovery failed: Error code:$errorCode")
        nsdManager.stopServiceDiscovery(this)
    }

    override fun onStopDiscoveryFailed(serviceType: String, errorCode: Int) {
        Log.e(TAG, "Discovery failed: Error code:$errorCode")
        nsdManager.stopServiceDiscovery(this)
    }
}

Java

public void initializeDiscoveryListener() {

    // Instantiate a new DiscoveryListener
    discoveryListener = new NsdManager.DiscoveryListener() {

        // Called as soon as service discovery begins.
        @Override
        public void onDiscoveryStarted(String regType) {
            Log.d(TAG, "Service discovery started");
        }

        @Override
        public void onServiceFound(NsdServiceInfo service) {
            // A service was found! Do something with it.
            Log.d(TAG, "Service discovery success" + service);
            if (!service.getServiceType().equals(SERVICE_TYPE)) {
                // Service type is the string containing the protocol and
                // transport layer for this service.
                Log.d(TAG, "Unknown Service Type: " + service.getServiceType());
            } else if (service.getServiceName().equals(serviceName)) {
                // The name of the service tells the user what they'd be
                // connecting to. It could be "Bob's Chat App".
                Log.d(TAG, "Same machine: " + serviceName);
            } else if (service.getServiceName().contains("NsdChat")){
                nsdManager.resolveService(service, resolveListener);
            }
        }

        @Override
        public void onServiceLost(NsdServiceInfo service) {
            // When the network service is no longer available.
            // Internal bookkeeping code goes here.
            Log.e(TAG, "service lost: " + service);
        }

        @Override
        public void onDiscoveryStopped(String serviceType) {
            Log.i(TAG, "Discovery stopped: " + serviceType);
        }

        @Override
        public void onStartDiscoveryFailed(String serviceType, int errorCode) {
            Log.e(TAG, "Discovery failed: Error code:" + errorCode);
            nsdManager.stopServiceDiscovery(this);
        }

        @Override
        public void onStopDiscoveryFailed(String serviceType, int errorCode) {
            Log.e(TAG, "Discovery failed: Error code:" + errorCode);
            nsdManager.stopServiceDiscovery(this);
        }
    };
}

NSD API, keşif sırasında uygulamanızı bilgilendirmek için bu arayüzdeki yöntemleri kullanır hizmetlerin bulunması ve kaybedilmesi (kayıp, "kayıp", artık kullanılamıyor"). Bu snippet'in bazı özellikleri bir hizmet bulunduğunda.

  1. Bulunan hizmetin hizmet adı hizmetle karşılaştırılır yerel hizmetin adı yayını (geçerli bir şekilde) sağlar.
  2. Hizmet türü kontrol edilir. Bu, müşterinizin bir uygulamadır.
  3. Doğru bir uygulamadır.

Hizmet adının kontrol edilmesi her zaman gerekli değildir ve yalnızca veya belirli bir uygulamaya bağlanmak istiyorsunuz. Örneğin, uygulama yalnızca diğer cihazlarda çalışan kendi örneklerine bağlanmak istiyorlar. Ancak, bir ağ yazıcısına bağlanmak istiyorsa hizmet türünün bu özelliği "_ipp._tcp" şeklindedir.

Dinleyiciyi ayarladıktan sonra, hizmet türünü ileterek discoverServices() adlı kişiyi arayın. ve kullanılacak Keşif Protokolü'nü, dinleyicidir.

Kotlin

nsdManager.discoverServices(SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, discoveryListener)

Java

nsdManager.discoverServices(
        SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, discoveryListener);

Ağdaki hizmetlere bağlan

Uygulamanız bağlanmak için ağ üzerinde bir hizmet bulduğunda, öncelikle resolveService() yöntemini çağırın. Bunu aktarmak için bir NsdManager.ResolveListener uygulayın yöntemini kullanın ve şunu içeren bir NsdServiceInfo bağlantı bilgilerini yazın.

Kotlin

private val resolveListener = object : NsdManager.ResolveListener {

    override fun onResolveFailed(serviceInfo: NsdServiceInfo, errorCode: Int) {
        // Called when the resolve fails. Use the error code to debug.
        Log.e(TAG, "Resolve failed: $errorCode")
    }

    override fun onServiceResolved(serviceInfo: NsdServiceInfo) {
        Log.e(TAG, "Resolve Succeeded. $serviceInfo")

        if (serviceInfo.serviceName == mServiceName) {
            Log.d(TAG, "Same IP.")
            return
        }
        mService = serviceInfo
        val port: Int = serviceInfo.port
        val host: InetAddress = serviceInfo.host
    }
}

Java

public void initializeResolveListener() {
    resolveListener = new NsdManager.ResolveListener() {

        @Override
        public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode) {
            // Called when the resolve fails. Use the error code to debug.
            Log.e(TAG, "Resolve failed: " + errorCode);
        }

        @Override
        public void onServiceResolved(NsdServiceInfo serviceInfo) {
            Log.e(TAG, "Resolve Succeeded. " + serviceInfo);

            if (serviceInfo.getServiceName().equals(serviceName)) {
                Log.d(TAG, "Same IP.");
                return;
            }
            mService = serviceInfo;
            int port = mService.getPort();
            InetAddress host = mService.getHost();
        }
    };
}

Hizmet çözümlendikten sonra uygulamanız gereken ayrıntılı bilgiler hizmet bilgilerini (IP adresi ve bağlantı noktası numarası dahil) Her şey bu hizmetle kendi ağ bağlantınızı oluşturmanız gerekir.

Uygulama kapatıldığında hizmetinizin kaydını iptal edin

NSD'yi etkinleştirmek ve devre dışı bırakmak önemlidir uygun şekilde çalışması sırasında, yaşam döngüsü boyunca geçerlidir. Uygulamanız kapatıldığında kaydını iptal etmeniz, uygulamanızın kapatılmasını olduğunu düşünmesini ve diğer uygulamalara bağlanmaya çalışmasını somut olarak ortaya koyar. Ayrıca, hizmet keşfi pahalı bir işlemdir ve durdurulmalıdır duraklatıldığında ve Etkinlik yeniden etkinleştirildiğinde, devam ettirildi. Ana etkinliğinizin yaşam döngüsü yöntemlerini geçersiz kılın ve kod ekleyin ve hizmet yayınını ve keşfini uygun şekilde başlatıp durdurun.

Kotlin

    // In your application's Activity

    override fun onPause() {
        nsdHelper?.tearDown()
        super.onPause()
    }

    override fun onResume() {
        super.onResume()
        nsdHelper?.apply {
            registerService(connection.localPort)
            discoverServices()
        }
    }

    override fun onDestroy() {
        nsdHelper?.tearDown()
        connection.tearDown()
        super.onDestroy()
    }

    // NsdHelper's tearDown method
    fun tearDown() {
        nsdManager.apply {
            unregisterService(registrationListener)
            stopServiceDiscovery(discoveryListener)
        }
    }

Java

    // In your application's Activity

    @Override
    protected void onPause() {
        if (nsdHelper != null) {
            nsdHelper.tearDown();
        }
        super.onPause();
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (nsdHelper != null) {
            nsdHelper.registerService(connection.getLocalPort());
            nsdHelper.discoverServices();
        }
    }

    @Override
    protected void onDestroy() {
        nsdHelper.tearDown();
        connection.tearDown();
        super.onDestroy();
    }

    // NsdHelper's tearDown method
    public void tearDown() {
        nsdManager.unregisterService(registrationListener);
        nsdManager.stopServiceDiscovery(discoveryListener);
    }