1

我试图简单地找到一个带有 mDNS 的设备,保存 IP 并在完成后终止“网络服务发现”(NSD)。

NSD 和 AsyncTask 在这里发生冲突。

使用 NSD 获取 IP 是可行的,但如果 AsyncTask 不是静态的,它会警告泄漏。

如果 AsyncTask 是静态的,NSD 说 from onPostExecute();
不能从静态上下文中引用非静态字段“mNsdManager”

如果我将 AsyncTask 设为静态但必须注释掉mNsdManager.stopServiceDiscovery(mDiscoveryListener); 在 onPostExecute() 中执行此操作。

使用NSD,我可以在 5-15 秒内获得 IP,但是如果 AsyncTask 是静态的,如果我无法杀死它,NSD 会保持非常忙碌。

如果我通过使其成为静态mNsdManager来满足 AsyncTask 的抱怨:
无法从静态上下文中引用非静态字段“mNsdManager”

我可以编译的唯一方法是使 AsyncTask 非静态并接受可能的泄漏- 或 -将 AsyncTask 保留为静态并注释掉 onPostExecute() 中的 KILL 行。

下面的代码中标记了 2 个错误。

使用基于 Android 事件的 AsyncTask 似乎是最好的方法,但它是正确的方法吗?

我怎样才能杀死mNsdManager并仍然使AsyncTask静态以阻止泄漏?

    包 com.fib.onacci.fibonacci;

    私人静态最终字符串标签=“时钟:”;
    私有 TextView mIP_address;

    // NSD 成员,允许应用发现“fibonacci.local”
    // 参考:
    // http://developer.android.com/training/connect-devices-wireless/nsd.html

          私有静态 NsdManager mNsdManager;
          私有静态 NsdManager.DiscoveryListener mDiscoveryListener;
          私有 NsdManager.ResolveListener mResolveListener;
          私有 NsdServiceInfo mServiceInfo;
          公共字符串 mRPiAddress;
          公共静态字符串IP地址="-"; // 寻找改变的东西
          private static final String SERVICE_TYPE = "_http._tcp.";

        公共类 MainActivity 扩展 AppCompatActivity {

        私人静态最终字符串标签=“时钟:”;

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

              新的 getIPtoTextView().execute(); // 启动异步任务

              // 设置 nDNS 并查找 IP
              mRPiAddress = "";
              IP地址=“-”;
              mNsdManager = (NsdManager)(getApplicationContext().getSystemService(Context.NSD_SERVICE));
              初始化解析监听器();
              初始化发现监听器();
              mNsdManager.discoverServices(SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, mDiscoveryListener);

          } // 结束 onCreate

         // NSD 启动 - 网络发现

错误此 AsyncTask 类应该是静态的,否则可能会发生泄漏
          静态字段会泄漏上下文。   

          私有静态类 getIPtoTextView 扩展 AsyncTask {
              /** nDiscovery 的一部分 - 查找时钟并终止发现服务
               * `doInBackground` 在单独的后台线程上运行
               */
              @覆盖
              受保护的无效doInBackground(无效...参数){
                  字符串 mloop = IP 地址;
                  while ( mloop.equals("-")) {
                      mloop = IP地址;
                      尝试 {
                          线程.sleep(100);
                      } 捕捉(InterruptedException e){
                          e.printStackTrace();
                      }
                  }
                  Log.i( TAG, "doInBackground - IP Found - " + mloop );
                  返回空值;
              }

              /** nDiscovery 的一部分
               * `onPostExecute` 在 `doInBackground` 之后运行,它是
               * 在 main/ui 线程上运行,所以你可以安全地更新 ui
               *它的组件。(这是更新ui的正确方法
               * 成分。)
               */
              @覆盖
              受保护的无效onPostExecute(无效参数){
                Log.i( TAG, "onPostExecute - IP Found - " + IPaddress );

                  TextView IP_Window = findViewById(R.id.IP_address);
                  IP_Window.setText(IP地址); // 将 IP 地址发布到 TextView

错误不能从静态上下文引用非静态字段“mNsdManager”
                  mNsdManager.stopServiceDiscovery(mDiscoveryListener); // 杀死 mDiscoveryListener
              }
          } // 结束 asyncTask 类

          私人无效初始化发现侦听器(){

            mDiscoveryListener = new NsdManager.DiscoveryListener() { // 监听器

                  @覆盖
                  公共无效 onDiscoveryStarted(字符串 regType){
                  }

                  @覆盖
                  public void onServiceFound(NsdServiceInfo service) { // 找到服务!
                      字符串名称 = service.getServiceName();
                      字符串类型 = service.getServiceType();

                      if ( type.equals(SERVICE_TYPE) && name.contains("Fibonacci")) {
                          Log.i( TAG, "\n\tNSD 服务找到@'" + 名称 + "'");
                          mNsdManager.resolveService(service, mResolveListener);
                      }
                  }

                  @覆盖
                  公共无效 onServiceLost(NsdServiceInfo 服务){  
                  }

                  @覆盖
                  公共无效 onDiscoveryStopped(字符串服务类型){
                  }

                  @覆盖
                  公共无效 onStartDiscoveryFailed(字符串 serviceType,int errorCode){
                      mNsdManager.stopServiceDiscovery(this);
                  }

                  @覆盖
                  公共无效 onStopDiscoveryFailed(String serviceType, int errorCode) {
                      mNsdManager.stopServiceDiscovery(this);
                  }
              };
          }

          私人无效initializeResolveListener(){
              mResolveListener = new NsdManager.ResolveListener(){

                  @覆盖
                  公共无效onResolveFailed(NsdServiceInfo serviceInfo,int errorCode){
                      Log.i( TAG, "\n\t\tNSD 解析失败 " + errorCode + "\n\n" );
                  }

                  @覆盖
                  公共无效onServiceResolved(NsdServiceInfo serviceInfo){
                      mServiceInfo = 服务信息;
                      InetAddress 主机 = mServiceInfo.getHost();
                       IPaddress = host.getHostAddress();
                      mRPiAddress = IP 地址;
                      Log.i( TAG, "\n\t\tNSD 解析地址 = " + IPaddress + "\n\n" );
                    }
                };
            }

            @覆盖
            受保护的无效 onPause() {
                超级.onPause();
                if ( mDiscoveryListener != null) {
                    mNsdManager.stopServiceDiscovery(mDiscoveryListener);
                }
            }

            @覆盖
            受保护的无效 onResume() {
                超级.onResume();
                if ( mDiscoveryListener != null) {
                  mIP_address.setText(R.string.searching); // TextView - 搜索 -
                    尝试 {
                        线程.sleep(1500);
                    } 捕捉(InterruptedException e){
                        e.printStackTrace();
                    }
                    初始化发现监听器();
                }
            }

            @覆盖
            受保护的无效 onDestroy() {
                super.onDestroy();
                mNsdManager.stopServiceDiscovery(mDiscoveryListener);  
            }
        // NSD结束 //
      }

4

1 回答 1

0

需要重写,因为我无法在 没有太多错误的情况下将类 getIPtoTextView 设为静态。

一旦我可以将类 getIPtoTextView 设为静态,我就移动了 mNsdManager.stopServiceDiscovery(mDiscoveryListener); onPause() 和 onDestroy() 都可以正常工作。

于 2020-01-07T03:40:19.757 回答