17

現在開発中Androidのアプリで、 を使用してゼロ設定ネットワークを接続したいと考えていますNsdManager

ネットワーク サービス ディスカバリを実行して目的のネットワークに接続できましたが、ディスカバリNsdManagerスレッドを停止した後も実行中です。これにより、画面を数回回転させた後、NsdManager接続を参照しているスレッドが多数あるという状況が発生します。

ここに画像の説明を入力

いずれかのネットワークが利用可能な場合、デバイスは何度も同期を試みるため、NsdManagerサービス ディスカバリを停止しても、すべてのネットワークが引き続きアクティブになります。

以下は私のコードです:

package dtokarzewsk.nsdservicetest;

import android.content.Context;
import android.net.nsd.NsdManager;
import android.net.nsd.NsdServiceInfo;
import android.util.Log;
import java.net.InetAddress;

public class NsdTest {
    private static final String NSD_SERVICE_NAME = "TestService";
    private static final String NSD_SERVICE_TYPE = "_http._tcp.";
    private int mPort;
    private InetAddress mHost;
    private Context mContext;
    private NsdManager mNsdManager;
    private android.net.nsd.NsdManager.DiscoveryListener mDiscoveryListener;
    private android.net.nsd.NsdManager.ResolveListener mResolveListener;

    public NsdTest(Context context) {
        mContext = context;
    }

    public void startListening() {
        initializeResolveListener();
        initializeDiscoveryListener();
        mNsdManager = (NsdManager) mContext.getSystemService(Context.NSD_SERVICE);
        mNsdManager.discoverServices(NSD_SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, mDiscoveryListener);
    }

    public void stopListening() {
        mNsdManager.stopServiceDiscovery(mDiscoveryListener);
    }

    private void initializeResolveListener() {
        mResolveListener = new NsdManager.ResolveListener() {
            @Override
            public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode) {
                Log.d("NSDService test","Resolve failed");
            }

            @Override
            public void onServiceResolved(NsdServiceInfo serviceInfo) {
                NsdServiceInfo info = serviceInfo;
                Log.d("NSDService test","Resolve failed");
                mHost = info.getHost();
                mPort = info.getPort();
                Log.d("NSDService test","Service resolved :" + mHost + ":" + mPort);
            }
        };
    }

    private void initializeDiscoveryListener() {
        mDiscoveryListener = new NsdManager.DiscoveryListener() {
            @Override
            public void onStartDiscoveryFailed(String serviceType, int errorCode) {
                Log.d("NSDService test","Discovery failed");
            }

            @Override
            public void onStopDiscoveryFailed(String serviceType, int errorCode) {
                Log.d("NSDService test","Stopping discovery failed");
            }

            @Override
            public void onDiscoveryStarted(String serviceType) {
                Log.d("NSDService test","Discovery started");
            }

            @Override
            public void onDiscoveryStopped(String serviceType) {
                Log.d("NSDService test","Discovery stopped");
            }

            @Override
            public void onServiceFound(NsdServiceInfo serviceInfo) {
                NsdServiceInfo info = serviceInfo;
                Log.d("NSDService test","Service found: " + info.getServiceName());
                if (info.getServiceName().equals(NSD_SERVICE_NAME))
                    mNsdManager.resolveService(info, mResolveListener);
            }

            @Override
            public void onServiceLost(NsdServiceInfo serviceInfo) {
                NsdServiceInfo info = serviceInfo;
                Log.d("NSDService test","Service lost: " + info.getServiceName());
            }
        };
    }
}

そしてメインでActivity

private NsdTest mNsdTest;

@Override
protected void onResume() {
    super.onResume();
    mNsdTest = new NsdTest(this);
    mNsdTest.startListening();
}

@Override
protected void onPause() {
    mNsdTest.stopListening();
    super.onPause();
}

この問題を解決するにはどうすればよいですか?

4

2 に答える 2

7

これに対する私の現在の解決策は、NsdManager(上記の例ではNsdTest)を含むクラスをコンテキストを変更するシングルトンにすることです。

サービス ディスカバリを停止した後も NSdManager スレッドが常に実行されていることに変わりはありませんが、アプリケーションの再開後、アクティブな NsdManager スレッドは少なくとも 1 つだけです。

多分それは最もエレガントな方法ではありませんが、私にとっては十分です。

public class NsdTest {

private static NsdTest mInstance;

private static final String NSD_SERVICE_NAME = "TestService";
private static final String NSD_SERVICE_TYPE = "_http._tcp.";
private int mPort;
private InetAddress mHost;
private Context mContext;
private NsdManager mNsdManager;
private android.net.nsd.NsdManager.DiscoveryListener mDiscoveryListener;
private android.net.nsd.NsdManager.ResolveListener mResolveListener;
private static NsdTest mInstance;

private NsdTest(Context context) {
    mContext = context;
}

public static NsdTest getInstance(Context context) {
    if (mInstance == null) {
        mInstance = new NsdTest(context);
    } else {
       mContext = context;
    }
    return mInstance;
}
...}

誰かがより良い解決策を知っている場合は、投稿してください。

于 2015-05-03T00:00:00.523 に答える
1

理由NsdManager.stopServiceDiscoveryは非同期だからです。ドキュメントからonDiscoveryStopped(String)、検出セッションが実際に終了するまで待つ必要があります。

非同期リクエストを送信した直後に一時停止するということは、おそらく、アプリケーションがバックグラウンドにあったため、トリガーされたはずのコールバックが「失われた」ことを意味します。非同期コールバックには、バックグラウンドにあることをうまく処理できない傾向があります。

于 2015-05-03T01:13:59.723 に答える