3

意识到我不得不担心基于网络的线程会对我的 UI 线程造成严重破坏,我经历了为我的应用程序和远程服务器之间的 TCP/IP 网络 ping pong 命令和响应创建自定义处理程序和自定义线程的整个过程. 工作得很好。(您会在下面的代码中看到它被引用为mainCommunicationThread(controlCommands);

不过,在触发该线程/处理程序之前,我从 SQL 中提取 IP 或主机名(称为 currIPstr),然后将其与一堆其他变量一起发送到线程/处理程序。不过,我需要做的一件事是确保它是 A)有效的 IP 地址,或 B)主机名已解析——否则,即使开始尝试也没有意义。

好的,没问题,我只是这样称呼:

currIP = InetAddress.getByName(currIPstr).toString().split("/")[1];

不过,我刚刚遇到的是,在 Gingerbread 或 StrictMode 运行时,上面的行会触发可怕的 NetworkOnMainThreadException。

是的,对 InetAddress.getByName 的简单调用就足够了。好吧,我一直在努力解决,所以我将整个函数移动到一个可运行文件中:

private String currStatIP = null;
private String currentStatIPstr = null;
private Integer currentStatIDstr = -1;
private String currentPort = null;
private String currentLocation = null;
private String currUserName = null;
private String currPassword = null;
private Integer currStatID = -1;
public void StatControl(Cursor c, final String[] commandtosend){


    /*the object will always start off with the first 4 fields being the current login information.
     * [0] = IP Address
     * [1] = port number
     * [2] = username
     * [3] = password
     * [4] = COMMAND -- this will be used in a switchcase inside the pingpong to decide what to do.
     *               -- if the Socket is not open, the first 4 fields will be used to re-initiate the connection
     *               -- otherwise, the command is drawn from this field and sent directly.
     * */


    currentStatIDstr = c.getInt(0);
    currentStatIPstr = c.getString(1);
    currentPort = c.getString(2);
    currentLocation = c.getString(3);
    currUserName = c.getString(4);
    currPassword = c.getString(5);
    currStatID = currentStatIDstr;


    Handler networkLookupHandler = new Handler();
    Runnable networkLookupRunnable = new Runnable() {
         public void run() {
             try {
                    currStatIP = InetAddress.getByName(currentStatIPstr).toString().split("/")[1];
                } catch (UnknownHostException e) {
                    e.printStackTrace();
                }
             int portNumber = 0;
                try {
                    portNumber = Integer.parseInt(currentPort);
                } catch(NumberFormatException nfe) {
                   nfe.printStackTrace();
                }
                String userName = currUserName;
                String passWord = currPassword;
                String[] command = commandtosend;

                Object[] controlCommands = new Object[]{
                        currStatID,
                        currStatIP, //InetAddress of String representing the IP address
                        portNumber,     //int representation of the port number, taken from String
                        currentLocation,
                        userName,
                        passWord,
                        command
                        };
                /*for(int i=0;i<controlCommands.length;i++){
                    Log.d("object work","controlCommands[" + i + "] is " + controlCommands[i]);
                }*/

                mainCommunicationThread(controlCommands);
         }   
    };
    networkLookupHandler.post(networkLookupRunnable);
}

而且,耶!有效!我不再收到 NetworkOnMainThreadException 了。哦……等等……是的,我是。

以上内容不会在 API 10、12、14 上触发异常,甚至 16 在模拟器中也可以正常工作,但是,如果我将其加载到运行 Jellybean 4.1.1 的三星 Google Galaxy Nexus 上,则会出现 NetworkOnMainThreadException 崩溃。即使上面包裹在runnable中。

我完全不知道如何解决这个问题。

4

3 回答 3

4

您正在尝试在可运行的网络操作中运行,因此请尝试在 onCreate 方法中添加此代码:

     StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
     StrictMode.setThreadPolicy(policy); 

或者我建议你使用 asynctask 而不是使用 Runnable 线程

于 2012-10-05T16:41:20.777 回答
4

我的解决方案:

public static InetAddress getInetAddressByName(String name)
{
    AsyncTask<String, Void, InetAddress> task = new AsyncTask<String, Void, InetAddress>()
            {

                @Override
                protected InetAddress doInBackground(String... params)
                {
                    try
                    {
                        return InetAddress.getByName(params[0]);
                    }
                    catch (UnknownHostException e)
                    {           
                        return null;
                    }                       
                }           
            };
    try
    {
        return task.execute(name).get();
    }
    catch (InterruptedException e)
    {
        return null;
    }
    catch (ExecutionException e)
    {
        return null;
    }

}
于 2016-07-25T16:39:12.960 回答
0

我通过在新线程中运行解决了我的 Inet6Address.getLocalHost() NetworkOnMainThreadException 问题。

于 2015-10-28T22:33:47.900 回答