понимая, что мне нужно беспокоиться о сетевом потоке, вызывающем хаос в моем потоке пользовательского интерфейса, я прошел весь процесс создания пользовательского обработчика и пользовательского потока для моей сети TCP/IP, пинг-понг команд и ответов между моим приложением и удаленным сервером. . Работал отлично. (вы увидите, что в приведенном ниже коде он упоминается как mainCommunicationThread(controlCommands);
)
Однако до того, как этот поток/обработчик будет запущен, я извлекаю IP-адрес или имя хоста из SQL (называя его 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, отлично работает в эмуляторе. Однако, если я загружаю его на свой Samsung Google Galaxy Nexus с Jellybean 4.1.1, я получаю сбой NetworkOnMainThreadException. Даже с учетом вышеизложенного, завернутого внутрь runnable.
Я в полной растерянности, как это исправить.
mainCommunicationThread()
выше. Самое странное, что это работает на эмуляторе 4.1, но не на моем телефоне 4.1. - person Octoth0rpe   schedule 05.10.2012