Убить обнаружение сетевых служб из AsyncTask, когда это сделано без утечек - PullRequest
0 голосов
/ 29 сентября 2018

Я пытаюсь просто найти устройство с mDNS, сохранить IP-адрес и завершить «Обнаружение сетевых служб» (NSD).

NSD и AsyncTask находятся в конфликте.

Получение IP с помощью NSD работает, но если AsyncTask не является статическим, оно предупреждает о утечках.

Если AsyncTask является статическим, NSD сообщает из onPostExecute ();
Нестатическое поле 'mNsdManager'нельзя ссылаться из статического контекста

NSD по-прежнему уничтожается из onDestroy, если приложение завершается, если я делаю AsyncTask статическим, но приходится комментировать mNsdManager.stopServiceDiscovery (mDiscoveryListener); в onPostExecute (), чтобы сделать это.

С NSD Я получаю IP через 5-15 секунд, но NSD остается серьезно занятым, если я не могу убить его, если AsyncTask статичен.

Если я удовлетворяю AsyncTask, делая его статическим mNsdManager жалуется:
Нестатическое поле 'mNsdManager' нельзя ссылаться из статического контекста

Единственный способ, которым я могу скомпилироватьs делает AsyncTask нестатичным и принимает возможные утечки -OR- , оставляя AsyncTask статичным и закомментирует строку KILL в onPostExecute ().

2 ОШИБКИ, отмеченные в коде ниже.

С Android Event на основе AsyncTask кажется лучшим способом, но это правильный путь?

Как я могу убить mNsdManager и при этом сделать AsyncTask статический, чтобы блокировать утечки?


    package com.fib.onacci.fibonacci;

    private static final String TAG = "CLOCK : ";
    private TextView mIP_address;

    // NSD members, Allows app to discover the "fibonacci.local"
    // Reference: 
    // http://developer.android.com/training/connect-devices-wirelessly/nsd.html

          private static NsdManager mNsdManager;
          private static NsdManager.DiscoveryListener mDiscoveryListener;
          private NsdManager.ResolveListener mResolveListener;
          private NsdServiceInfo mServiceInfo;
          public String mRPiAddress;
          public static String IPaddress ="-"; // something to look for change
          private static final String SERVICE_TYPE = "_http._tcp."; 

        public class MainActivity extends AppCompatActivity {

        private static final String TAG = "CLOCK: ";

          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);

              new getIPtoTextView().execute();  // start the AsyncTask

              // setup nDNS and find IP
              mRPiAddress = "";
              IPaddress = "-";
              mNsdManager = (NsdManager)(getApplicationContext().getSystemService(Context.NSD_SERVICE));
              initializeResolveListener();
              initializeDiscoveryListener();
              mNsdManager.discoverServices( SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, mDiscoveryListener);

          }  // END onCreate

         // NSD start - Network discovery

<b>ERROR This AsyncTask class should be static or leaks might occur 
          A static field will leak contexts.</b>   

          private static class getIPtoTextView extends AsyncTask {
              /** part of nDiscovery - find clock and kill discovery service
               *  `doInBackground` is run on a separate, background thread
               */
              @Override
              protected Void doInBackground(Void... params) {
                  String mloop = IPaddress;
                  while ( mloop.equals("-")) {
                      mloop = IPaddress;
                      try {
                          Thread.sleep(100);
                      } catch (InterruptedException e) {
                          e.printStackTrace();
                      }
                  }
                  Log.i( TAG, "doInBackground - IP Found - " + mloop );
                  return null;
              }

              /** part of nDiscovery
               * `onPostExecute` is run after `doInBackground`, and it's
               * run on the main/ui thread, so you it's safe to update ui
               * components from it. (this is the correct way to update ui
               * components.)
               */
              @Override
              protected void onPostExecute(Void param) {
                Log.i( TAG, "onPostExecute - IP Found - " + IPaddress );

                  TextView IP_Window = findViewById(R.id.IP_address); 
                  IP_Window.setText( IPaddress);  // post IP address to TextView

<b>ERROR Non-static field 'mNsdManager' cannot be referenced from a static context</b>
                  mNsdManager.stopServiceDiscovery( mDiscoveryListener);                     // kill mDiscoveryListener
              }
          }  // end asyncTask class

          private void initializeDiscoveryListener() {

            mDiscoveryListener = new NsdManager.DiscoveryListener() { // Listener

                  @Override
                  public void onDiscoveryStarted(String regType) {
                  }

                  @Override
                  public void onServiceFound(NsdServiceInfo service) { // service found!
                      String name = service.getServiceName();
                      String type = service.getServiceType();

                      if ( type.equals(SERVICE_TYPE) && name.contains("Fibonacci")) {
                          Log.i( TAG, "\n\tNSD Service Found @ ' " + name + "'");
                          mNsdManager.resolveService(service, mResolveListener);
                      }
                  }

                  @Override
                  public void onServiceLost(NsdServiceInfo service) {  
                  }

                  @Override
                  public void onDiscoveryStopped(String serviceType) {
                  }

                  @Override
                  public void onStartDiscoveryFailed(String serviceType, int errorCode) {
                      mNsdManager.stopServiceDiscovery(this);
                  }

                  @Override
                  public void onStopDiscoveryFailed(String serviceType, int errorCode) {
                      mNsdManager.stopServiceDiscovery(this);
                  }
              };
          }

          private void initializeResolveListener() {
              mResolveListener = new NsdManager.ResolveListener(){

                  @Override
                  public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode) {
                      Log.i( TAG, "\n\t\tNSD Resolve failed " + errorCode + "\n\n" );
                  }

                  @Override
                  public void onServiceResolved( NsdServiceInfo serviceInfo ) {
                      mServiceInfo = serviceInfo;
                      InetAddress host = mServiceInfo.getHost();
                       IPaddress = host.getHostAddress();
                      mRPiAddress = IPaddress;
                      Log.i( TAG, "\n\t\tNSD Resolved address = " + IPaddress + "\n\n" );
                    }
                };
            }

            @Override
            protected void onPause() {
                super.onPause();
                if ( mDiscoveryListener != null) {
                    mNsdManager.stopServiceDiscovery( mDiscoveryListener);
                }
            }

            @Override
            protected void onResume() {
                super.onResume();
                if ( mDiscoveryListener != null) {
                  mIP_address.setText( R.string.searching );  // TextView - Searching -
                    try {
                        Thread.sleep( 1500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    initializeDiscoveryListener();
                }
            }

            @Override
            protected void onDestroy() {
                super.onDestroy();
                mNsdManager.stopServiceDiscovery( mDiscoveryListener);  
            }
        // NSD end //
      }

...