我试图简单地找到一个带有mDNS的设备,保存IP并在完成后终止“网络服务发现”(NSD) .
NSD和AsyncTask在这里发生冲突 .
使用NSD获取IP有效,但如果AsyncTask不是静态的,则会发出泄漏警告 .
如果AsyncTask是静态的,那么NSD会从onPostExecute();
Non-static field 'mNsdManager' cannot be referenced from a static context
如果应用程序退出,如果我使AsyncTask静态但是必须在onPostExecute()中注释 mNsdManager.stopServiceDiscovery( mDiscoveryListener); 来执行此操作,NSD仍然会从onDestroy中被杀死 .
使用 NSD 我在5-15秒内获得IP,但如果AsyncTask是静态的,我不能杀死NSD .
如果我通过使其静态 mNsdManager 抱怨来满足AsyncTask:
Non-static field 'mNsdManager' cannot be referenced from a static context
我可以编译的唯一方法是使AsyncTask非静态并接受可能的泄漏 -OR- 保留AsyncTask静态并注释掉onPostExecute()中的KILL行 .
2错误标记在下面的代码中 .
使用基于Android事件的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
ERROR This AsyncTask class should be static or leaks might occur
A static field will leak contexts.
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
ERROR Non-static field 'mNsdManager' cannot be referenced from a static context
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 //
}