我试图简单地找到一个带有 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结束 //
}