在Android中使用网络服务发现内部错误 [英] Internal error using Network Service Discovery in Android

查看:3076
本文介绍了在Android中使用网络服务发现内部错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在NSDManager的使用的实施例和显影剂页面上的教程第一实施,应用程序成功启动的发现和找到的设备。

但是现在看来,被打破......

当开始该程序,一些初始化之后,code进入下面的方法,成功地运行:

 公共无效discoverServices(){
    Log.d(TAG初始化发现的NSD);
    mNsdManager.discoverServices(
            SERVICE_TYPE,NsdManager.PROTOCOL_DNS_SD,mDiscoveryListener);
}
 

时,接收到的日志消息。过了好一会儿(大约说5分钟)。这是从程序输出:

 一十一月5日至21日:08:32.518:E / NsdCamera(12236):发现失败错误:code:0
11月5号至21日:08:32.518:W / dalvikvm(12236):主题ID = 12:线程退出与未捕获的异常(组= 0x40c9c930)
11月5号至21日:08:32.518:E / AndroidRuntime(12236):致命异常:NsdManager
11月5号至21日:08:32.518:E / AndroidRuntime(12236):显示java.lang.NullPointerException
11月5号至21日:08:32.518:E / AndroidRuntime(12236):在android.net.nsd.NsdManager $ ServiceHandler.handleMessage(NsdManager.java:338)
11月5号至21日:08:32.518:E / AndroidRuntime(12236):在android.os.Handler.dispatchMessage(Handler.java:99)
11月5号至21日:08:32.518:E / AndroidRuntime(12236):在android.os.Looper.loop(Looper.java:137)
11月5号至21日:08:32.518:E / AndroidRuntime(12236):在android.os.HandlerThread.run(HandlerThread.java:60)
 

同时从服务:

 一十一月5日至21日:50:49.108:E / NativeDaemonConnector.ResponseQueue(8858):超时等待响应
11月5号至21日:50:49.108:E / mDnsConnector(8858):超时等待响应10 mdnssd发现6 _http._tcp。
11月5号至21日:50:49.108:E / NsdService(8858):无法discoverServices com.android.server.NativeDaemonConnector $ NativeDaemonFailureException:命令'10 mdnssd发现6 _http._tcp失败,'空'
 

错误code0中的 NSDManager类的描述一个内部错误。 主要更新我所做的就是访问在辅助类叫NsdCamera上下文。 下面是一些可能是邪恶的code-片段:

辅助类的构造函数:

 公共NsdCamera(CameraChooseActivity上下文){
    mContext =背景;
    的updateUI =新的updateUI();
    mNsdManager =(NsdManager)context.getSystemService(Context.NSD_SERVICE);
    mServiceName =新矢量< NsdServiceInfo>();
 

辅助类NSD初始化:

 公共无效initializeNsd(){
    initializeDiscoveryListener();
}

公共无效initializeDiscoveryListener(){
    mDiscoveryListener =新NsdManager.DiscoveryListener(){

        @覆盖
        公共无效onDiscoveryStarted(字符串regType){
            Log.d(TAG,服务发现启动);
        }
        / **
         *一个名称检查,看是否DNS发现是正确的。如果它包含检查
         *轴和具有所需的MAC地址空间
         *参数主机名,从发现周期的输入主机名
         * @返回true,如果它是一个轴相机。
         * /
        公共布尔nameCheck(字符串主机名){
            返程(hostname.contains(轴)及和放大器; hostname.contains(00408C));

        }
        @覆盖
        公共无效onServiceFound(NsdServiceInfo服务){
            Log.d(TAG,服务发现的成功:+ service.getServiceName());
            如果(!service.getServiceType()。等于(SERVICE_TYPE)){
                Log.d(TAG,未知服务类型:+ service.getServiceType());
            }否则,如果(nameCheck(service.getServiceName())){
                mServiceName.add(服务);
// updateUI.execute(新BundleUI(mContext,服务,NULL));
            }
        }

        @覆盖
        公共无效onServiceLost(NsdServiceInfo服务){
            Log.e(TAG的服务失去了+服务);
            如果(mServiceName.remove(服务)){
                //去做
                Log.e(TAG,删除视图,服务将丢失);
            }
        }

        @覆盖
        公共无效onDiscoveryStopped(字符串的serviceType){
            Log.i(TAG,发现停:+的serviceType);
            //必要??
            mServiceName.clear();
        }

        @覆盖
        公共无效onStartDiscoveryFailed(字符串的serviceType,诠释错误code){
            Log.e(TAG,发现失败错误:code:+错误code);
            mNsdManager.stopServiceDiscovery(本);
        }

        @覆盖
        公共无效onStopDiscoveryFailed(字符串的serviceType,诠释错误code){
            Log.e(TAG,发现失败错误:code:+错误code);
            mNsdManager.stopServiceDiscovery(本);
        }
    };
}
 

CameraChooseActivity - >的onCreate 被调用的辅助类

 保护无效的onCreate(包savedInstanceState){
    super.onCreate(savedInstanceState);
    的setContentView(R.layout.activity_camerachoose);

    //设置的动画在RelativeLayout的文本
    mDescription =(TextSwitcher)findViewById(R.id.camera_add);
    mDescription.setFactory(本);
    mDescription.setInAnimation(AnimationUtils.loadAnimation(这一点,android.R.anim.fade_in));
    mDescription.setOutAnimation(AnimationUtils.loadAnimation(这一点,android.R.anim.fade_out));
    mDescription.setText(的getText(R.string.camera_add));

    //大厦警告对话框
    mBuilder =新AlertDialog.Builder(这一点,AlertDialog.THEME_HOLO_DARK);
    mBuilder.setMessage(R.string.dialog_about).setTitle(R.string.action_about);
    mBuilder.setIcon(android.R.drawable.ic_dialog_info);

    mLayout =(RelativeLayout的)findViewById(R.id.layout_camerachoose);

    //初始化NSD
    mNSDHelper =新NsdCamera(本);
    mNSDHelper.initializeNsd();
 

解决方案

我的经验基础,我想这是一个监听器的寿命问题。

由于您提供两个侦听到系统NSD服务,一个是startServiceDiscovery(),另一个用于stopServiceDiscovery()。你需要确保这些听众还活着的时候,系统访问这些听众。

有一个事实是,onStartDiscoveryFailed()称为2分钟startServiceDiscovery()被调用之后,应该是很长的时间相比,在听众的寿命。

因此​​,如果听者是一个本地对象并调用startServiceDiscovery()释放后,它可能会导致NSD服务崩溃。

  

公共无效stopServiceDiscovery(NsdManager.DiscoveryListener   听众)

     

与discoverServices开始停止服务发现()。一个活动   服务发现被通知给与应用程序   onDiscoveryStarted(String)和它保持激活状态,直到应用程序   调用一个一站式服务的发现。一个成功的停止通知   通过调用onDiscoveryStopped(字符串)。

     

一旦出现故障,停止服务发现,应用程序被通知   通过onStopDiscoveryFailed(字符串,INT)。

     

参数listener这应该是传递的侦听器对象   到discoverServices(字符串,整型,NsdManager.DiscoveryListener)。它   标识应停止,并通知的发现   成功站。

和下方段确保不调用任何NsdManager API。

  @覆盖
公共无效onStartDiscoveryFailed(字符串的serviceType,诠释错误code){
     Log.i(TAG,onStartDiscoveryFailed错误:code:+错误code);
}

@覆盖
公共无效onStopDiscoveryFailed(字符串的serviceType,诠释错误code){
    Log.i(TAG,onStopDiscoveryFailed错误:code:+错误code);
}
 

好运。

During the first implementation of the NSDManager using the examples and the tutorial on the developer page , the application successfully started the discovery and found the devices.

However now it seems to be broken...

When the program is started, after some initialization, the code enters the following method and successfully run:

public void discoverServices() {
    Log.d(TAG, "Initializing discovery on NSD");
    mNsdManager.discoverServices(
            SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, mDiscoveryListener);
} 

The log-message is received. After a good while (say approx 5 mins.) this is outputted from the program:

05-21 11:08:32.518: E/NsdCamera(12236): Discovery failed: Error code:0
05-21 11:08:32.518: W/dalvikvm(12236): threadid=12: thread exiting with uncaught exception (group=0x40c9c930)
05-21 11:08:32.518: E/AndroidRuntime(12236): FATAL EXCEPTION: NsdManager
05-21 11:08:32.518: E/AndroidRuntime(12236): java.lang.NullPointerException
05-21 11:08:32.518: E/AndroidRuntime(12236):    at android.net.nsd.NsdManager$ServiceHandler.handleMessage(NsdManager.java:338)
05-21 11:08:32.518: E/AndroidRuntime(12236):    at android.os.Handler.dispatchMessage(Handler.java:99)
05-21 11:08:32.518: E/AndroidRuntime(12236):    at android.os.Looper.loop(Looper.java:137)
05-21 11:08:32.518: E/AndroidRuntime(12236):    at android.os.HandlerThread.run(HandlerThread.java:60)

Also from the services:

05-21 11:50:49.108: E/NativeDaemonConnector.ResponseQueue(8858): Timeout waiting for response
05-21 11:50:49.108: E/mDnsConnector(8858): timed-out waiting for response to 10 mdnssd discover 6 _http._tcp.
05-21 11:50:49.108: E/NsdService(8858): Failed to discoverServices com.android.server.NativeDaemonConnector$NativeDaemonFailureException: command '10 mdnssd discover 6 _http._tcp.' failed with 'null'

Error code "0" is described in the NSDManager class as an internal error. The major updates I did was the access to the context in the helper-class called NsdCamera. Here is some probably evil code-snippets:

Helper-class constructor:

public NsdCamera(CameraChooseActivity context) {
    mContext = context;
    updateUI =  new UpdateUI();
    mNsdManager = (NsdManager) context.getSystemService(Context.NSD_SERVICE);
    mServiceName = new Vector<NsdServiceInfo>();

Helper-class NSD initialization:

public void initializeNsd() {
    initializeDiscoveryListener();
}

public void initializeDiscoveryListener() {
    mDiscoveryListener = new NsdManager.DiscoveryListener() {

        @Override
        public void onDiscoveryStarted(String regType) {
            Log.d(TAG, "Service discovery started");
        }
        /**
         * A name check to see if the DNS discovery was correct. Checks if it contains 
         * AXIS and has the desired MAC address-space
         * @param hostname ,the inputted hostname from the discovery cycle
         * @return true if it's an Axis camera. 
         */
        public boolean nameCheck(String hostname){
            return (hostname.contains("AXIS") && hostname.contains("00408C"));

        }
        @Override
        public void onServiceFound(NsdServiceInfo service) {
            Log.d(TAG, "Service discovery success: " + service.getServiceName());
            if (!service.getServiceType().equals(SERVICE_TYPE)) {
                Log.d(TAG, "Unknown Service Type: " + service.getServiceType());
            } else if (nameCheck(service.getServiceName())){
                mServiceName.add(service);
//                  updateUI.execute(new BundleUI(mContext,service, null));
            }
        }

        @Override
        public void onServiceLost(NsdServiceInfo service) {
            Log.e(TAG, "service lost" + service);
            if(mServiceName.remove(service)){
                //TODO
                Log.e(TAG, "remove the view, service is lost");
            }
        }

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

        @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);
        }
    };
}

CameraChooseActivity -> onCreate is calling the helper-class

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_camerachoose);

    //Setup the animation for the text in the Relativelayout
    mDescription = (TextSwitcher) findViewById(R.id.camera_add);
    mDescription.setFactory(this);
    mDescription.setInAnimation(AnimationUtils.loadAnimation(this, android.R.anim.fade_in));
    mDescription.setOutAnimation(AnimationUtils.loadAnimation(this, android.R.anim.fade_out));
    mDescription.setText(getText(R.string.camera_add));

    //Building alert dialog
    mBuilder = new AlertDialog.Builder(this,AlertDialog.THEME_HOLO_DARK);
    mBuilder.setMessage(R.string.dialog_about).setTitle(R.string.action_about);
    mBuilder.setIcon(android.R.drawable.ic_dialog_info);

    mLayout = (RelativeLayout) findViewById(R.id.layout_camerachoose);

    //Initialize the NSD
    mNSDHelper = new NsdCamera(this);
    mNSDHelper.initializeNsd();

解决方案

Base on my experience, I suppose this is a listener lifetime issue.

Because you supply two listeners to the system NSD service, one is for startServiceDiscovery() and another for stopServiceDiscovery(). you need to make sure these listeners still alive when the system accesses these listeners.

One fact is that onStartDiscoveryFailed() is called 2 minutes after startServiceDiscovery() is called, it should be a long time compared to the lifetime of the listener.

So if the listener is a local object and is released after calling the startServiceDiscovery(), it maybe cause the NSD service to crash.

public void stopServiceDiscovery (NsdManager.DiscoveryListener listener)

Stop service discovery initiated with discoverServices(). An active service discovery is notified to the application with onDiscoveryStarted(String) and it stays active until the application invokes a stop service discovery. A successful stop is notified to with a call to onDiscoveryStopped(String).

Upon failure to stop service discovery, application is notified through onStopDiscoveryFailed(String, int).

Parameters listener This should be the listener object that was passed to discoverServices(String, int, NsdManager.DiscoveryListener). It identifies the discovery that should be stopped and notifies of a successful stop.

and below snippet make sure do not call any NsdManager api.

@Override
public void onStartDiscoveryFailed(String serviceType, int errorCode) {
     Log.i(TAG, "onStartDiscoveryFailed : Error code:" + errorCode);
}

@Override
public void onStopDiscoveryFailed(String serviceType, int errorCode) {
    Log.i(TAG, "onStopDiscoveryFailed : Error code:" + errorCode);
}

Good Luck.

这篇关于在Android中使用网络服务发现内部错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆