我想在android设备之间交换数据,因此应该使用NSD来查找其他设备。我遵循了Android Developers上的示例
服务端成功在网络上注册服务,客户端设备识别服务并进入discoveryListener回调方法onServiceFound()。然后我初始化resolveListener并调用resolveService(),但是应用程序崩溃了
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.net.nsd.NsdManager.resolveService(android.net.nsd.NsdServiceInfo, android.net.nsd.NsdManager$ResolveListener)' on a null object reference
at de.niklasdahlheimer.oboeapitest.oboeapitest.NSDFinder$1.onServiceFound(NSDFinder.java:59)
at android.net.nsd.NsdManager$ServiceHandler.handleMessage(NsdManager.java:333)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.os.HandlerThread.run(HandlerThread.java:61)
我的 mNsdManager 在 NSDFinder 类中不为空,但在 DiscoveryListener 的回调方法中不知何故为空。似乎我在使用不同的线程时遇到了问题,或者在使用上下文时存在误解。我的 NSDFinder 类应该扩展服务还是什么?我不希望主要活动中的 NSD 代码保持代码结构良好。
(缩短)主要活动
public class MainActivity extends AppCompatActivity {
//Variable Declarations
NSDFinder my_nsdfinder;
@Override
protected void onCreate(Bundle savedInstanceState) {
button_discoverserver =(Button) findViewById(R.id.button_discoverServer);
//Variables Instantiations
my_nsdfinder = new NSDFinder();
button_discoverserver.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
my_nsdfinder.initializeDiscoveryListener();
my_nsdfinder.startDiscovery(getApplicationContext());
Toast.makeText(getApplicationContext(),"Suche nach Servern...",Toast.LENGTH_LONG).show();
}
});
}
}
NSDFinder 类 (NSDFinder.java)
public class NSDFinder{
String TAG = "NSDFINDER";
NsdManager mNsdManager;
NsdManager.DiscoveryListener mDiscoveryListener;
String mServiceName;
String SERVICE_TYPE = "_http._tcp.";
Context mContext;
int mDiscoveryActive = 0;
FragmentManager m_DialogManager;
NsdManager.ResolveListener mResolveListener;
NsdServiceInfo mService;
int mServiceport;
InetAddress mServicehostAdress;
public void initializeDiscoveryListener() {
// Instantiate a new DiscoveryListener
mDiscoveryListener = new NsdManager.DiscoveryListener() {
// Called as soon as service discovery begins.
@Override
public void onDiscoveryStarted(String regType) {
Log.d(TAG, "Service discovery started");
mDiscoveryActive = 1;
}
@Override
public void onServiceFound(NsdServiceInfo service) {
// A service was found! Do something with it.
Log.d(TAG, "Service discovery success\n" + 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(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);
} else if (service.getServiceName().contains("LTCTool")){
Toast.makeText(mContext,"LTCTool Server gefunden! "+service,Toast.LENGTH_LONG).show();
initializeResolveListener();
mNsdManager.resolveService(service,mResolveListener);
//mNsdManager.stopServiceDiscovery(mDiscoveryListener);
}
}
@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);
mDiscoveryActive = 0;
}
@Override
public void onStartDiscoveryFailed(String serviceType, int errorCode) {
Log.e(TAG, "Discovery failed: Error code:" + errorCode);
mNsdManager.stopServiceDiscovery(this);
}
@Override
public void onStopDiscoveryFailed(String serviceType, int errorCode) {
Log.e(TAG, "Discovery failed: Error code:" + errorCode);
mNsdManager.stopServiceDiscovery(this);
}
};
}
public void startDiscovery(Context _c){
mContext = _c;
NsdManager mNsdManager = (NsdManager) _c.getSystemService(Context.NSD_SERVICE);
mNsdManager.discoverServices(SERVICE_TYPE, mNsdManager.PROTOCOL_DNS_SD, mDiscoveryListener);
}
public void initializeResolveListener() {
Log.d(TAG, "start initalizing ResolveListener");
mResolveListener = 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(mServiceName)) {
Log.d(TAG, "Same IP.");
return;
}
mService = serviceInfo;
mServiceport = mService.getPort();
mServicehostAdress = mService.getHost();
Toast.makeText(mContext,"Dienstinformationen aufgelöst! Port: "+mServiceport+" Adresse: "+mServicehostAdress,Toast.LENGTH_LONG).show();
}
};
Log.d(TAG, "ResolveListener initialized");
}
}