Внутренняя ошибка при использовании Network Service Discovery в Android

Во время первой реализации NSDManager с использованием примеров и учебника на странице разработчика , приложение успешно запустило обнаружение и обнаружило устройства.

Однако сейчас он кажется сломанным...

Когда программа запускается, после некоторой инициализации код вводит следующий метод и успешно запускается:

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

Лог-сообщение получено. Через некоторое время (скажем, около 5 минут) это выводится из программы:

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)

Также из сервисов:

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'

Код ошибки "0" описан в классе NSDManager как внутренняя ошибка. Основными обновлениями, которые я сделал, был доступ к контексту во вспомогательном классе под названием NsdCamera. Вот некоторые, вероятно, злые фрагменты кода:

Конструктор вспомогательного класса:

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

Инициализация NSD вспомогательного класса:

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 вызывает вспомогательный класс

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();

person Mazze    schedule 21.05.2013    source источник


Ответы (2)


Основываясь на своем опыте, я полагаю, что это проблема всей жизни слушателя.

Поскольку вы предоставляете системной службе NSD два слушателя, один для startServiceDiscovery(), а другой для stopServiceDiscovery(). вам нужно убедиться, что эти слушатели все еще живы, когда система обращается к этим слушателям.

Одним из фактов является то, что onStartDiscoveryFailed() вызывается через 2 минуты после вызова startServiceDiscovery(), это должно быть много времени по сравнению со временем жизни слушателя.

Таким образом, если прослушиватель является локальным объектом и освобождается после вызова startServiceDiscovery(), это может привести к сбою службы NSD.

public void stopServiceDiscovery (слушатель NsdManager.DiscoveryListener)

Остановить обнаружение службы, инициированное с помощью DiscoverServices(). Об обнаружении активной службы сообщается приложению с помощью onDiscoveryStarted(String), и оно остается активным до тех пор, пока приложение не вызовет обнаружение остановки службы. Об успешной остановке сообщается вызовом onDiscoveryStopped(String).

Если не удается остановить обнаружение службы, приложение уведомляется через onStopDiscoveryFailed(String, int).

Параметры listener Это должен быть объект прослушивателя, который был передан в discoveryServices(String, int, NsdManager.DiscoveryListener). Он идентифицирует обнаружение, которое следует остановить, и уведомляет об успешной остановке.

и ниже фрагмент кода убедитесь, что не вызывается API NsdManager.

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

Удачи.

person Zephyr    schedule 26.09.2013
comment
Хороший ответ! Спасибо за помощь. Ну, это фактически решило нулевой указатель! Однако внутренняя ошибка (код ошибки 0) все еще сохраняется: S - person Mazze; 03.03.2015

Решением оказался простой перезапуск тестируемого устройства. Надо сказать, что ошибка довольно странная. Я думаю, что демон разбился и не перезапустился.

(Если кто-то может опубликовать анализ или предложить гораздо лучшее решение, опубликуйте его)

person Mazze    schedule 21.05.2013
comment
Что такое ДУТ? У меня такая же ошибка, но мое устройство перезагружается. - person fsschmitt; 27.06.2013
comment
DUT = тестируемое устройство. У многих есть проблема, некоторые устройства перезагружаются из-за сбоя демона, однако min не... «обнаружение сетевых принтеров Android nullpointerexception»> stackoverflow.com/questions/16907102/ - person Mazze; 28.06.2013
comment
не совсем уверен, что это должно быть помечено как правильный ответ - person Vlad Ilie; 22.12.2014
comment
Интересно - я видел, как несколько устройств перезагружались, а некоторые просто зависали. - person slott; 28.03.2016