3

ネットワーク ベースのスレッドが UI スレッドに大混乱を引き起こすことを心配しなければならないことに気づき、アプリとリモート サーバー間のコマンドと応答の TCP/IP ネットワーク ピンポン用のカスタム ハンドラーとカスタム スレッドを作成するプロセス全体を実行しました。 . うまくいきました。(以下のコードでは として参照されていることがわかりますmainCommunicationThread(controlCommands);)

ただし、そのスレッド/ハンドラーがトリガーされる前に、SQL から IP またはホスト名を取得し (それを currIPstr と呼びます)、それを他の変数と共にスレッド/ハンドラーに送信します。ただし、私がしなければならないことの 1 つは、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 を実行している Samsung Google Galaxy Nexus にロードすると、NetworkOnMainThreadException クラッシュが発生します。上記がランナブル内にラップされていても。

これを修正する方法について、私は完全に途方に暮れています。

4

3 に答える 3

4

ランナブルでネットワーク操作を実行しようとしているので、次のコードをonCreateメソッドに追加してみてください。

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

または、Runnableスレッドを使用する代わりにasynctaskを使用することをお勧めします

于 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 に答える