본문 바로가기

나의 플랫폼/안드로이드

[ Android ] Sockettimeout에 대해...

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

 사용자 위치를 얻어서 현재 날씨정보를 받아오기 위해 소켓 통신을 이용했습니다.
(소켓 통신이라기 보다 Http에 연결 시켜서 데이터 값을 가지고 왔지요.)

Http로 연결 시키는 방법이 두가지가 있었습니다.

try{

String getUrl = "인터넷 주소";

URL url = new URL(getUrl);

httpConnection = (HttpURLConnection) url.openConnection();
httpConnection.setConnectTimeout(3000);

httpConnection.setReadTimeout(3000);


if(httpConnection.getResponseCode() == HttpURLConnection.HTTP_OK){
InputStream in = null; 

in = httpConnection.getInputStream();

}catch (SocketTimeoutException e)

{

    e.printStackTrace();

}

catch (ConnectTimeoutException e)

{

    e.printStackTrace();

}

catch (IOException e)

{

    e.printStackTrace();

}catch (Exception e) {

e.printStackTrace();

}finally{

try {

if(in!=null){

in.close();

}

} catch (IOException e) {

//Suppressed

}


 

String getUrl = "인터넷 주소";

URL url = new URL(getUrl);


HttpClient dhc = new DefaultHttpClient();

HttpGet httpGet = new HttpGet(getUrl);


HttpParams httpParams = ahc.getParams();

HttpConnectionParams.setConnectionTimeout(httpParams, 3000);

HttpConnectionParams.setSoTimeout(httpParams, 3000);

ResponseHandler<String> responseHandler = new BasicResponseHandler();

String data = ahc.execute(httpGet,responseHandler);
InputStream in = null; 
in = new ByteArrayInputStream(data.getBytes("UTF-8")); 

 
위와 같이 쓸 수가 있습니다.

HttpParam에 TimeOut을 3초로 설정해놔도 도무지 3초는 커녕 10초나 15초가 지나야 Exception을 발생시키더라구요. 
전 제한을 걸어 놓고 Exception 띄워서 강제적으로 연결중인 Http를 제거 할려구 했거든요.
하지만! 그게 안되었던 겁니다. 
머 안드로이드 버그니... Thread를 써보라니... AndroidHttpClient로도 해봤는데 전부 무용지물이더군요.

결국! 열심히 날세면서 파본 결과..... AsycTask를 이용하기로 했습니다.(저도 처음 다뤄봤다는;;;;)

로직을 말하자면, AsycTask에서 백그라운드로 Http의 정보를 받아오고,
그 정보를 확인하는 부분을 계속 돌리는 겁니다.
Thread사용과 같이 일반 변수를 하나 만들구요. 그 변수를 변화 시켜줌으로써 Http의 정보를 제거 시키는 거지요.

private DownloadTask mDownTask;   // AsycTask 전역 변수

private boolean getLocationData;        // 시간 제한 및 정보 여부 확인 변수

private class DownloadTask extends AsyncTask<String, Void, Boolean> {

boolean noLocationData;

// 백그라운드로 돌아갈 때

protected Boolean doInBackground(String... urls) {

updateLocation(); // 위치를 받아온다.

noLocationData = settingWeatherAboutLocation(); // 정보 결과 값을 넘긴다.

return false;

}

 
 
               // 백그라운드가 완료 됐을 때 실행된다.

protected void onPostExecute(Boolean result) {

getLocationData = noLocationData;

}



 
// 실행되는 부분

if(mDownTask == null){

mDownTask = new DownloadTask();

mDownTask.execute("WeatherDown");

}

long downDelay = System.currentTimeMillis();
 

while(!getLocationData){

        if(System.currentTimeMillis() - downDelay > 3000){

         getLocationData = true;

        }else{

        try {

        Thread.sleep(100);

         } catch (Exception e) {

         e.printStackTrace();

        }

}

}

mDownTask.cancel(true);


3초가 지나면 변수를 변경 시킨다.

여기서 참고사항.
AsycTask에서 백그라운드로 받아오기 있지만,
Http의 받는 속도가 문제가 된다.
즉, AsycTask를 정지 시키는 명령을 내려도, Http가 받아올 때까지 AsycTask는 계속 돌아간다는 의미이다.

그러므로!!!!!
getLocationData의 변화를 조금 씩 파악한 후,
그에 맞춰 예외처리를 해줘야한다.!!!

예를 들어 getLocationData가 이미 true로 되어 있으면, Http에서 받아온 결과를 할당 시키지 않는 것이다.!
중요한 부분이니 알아두셔도 좋을 듯^^

혹시 질문 있으시면 댓글 달아주세요.
아는 한도내에서 알려드림..

그럼 오늘도 모두들 즐코딩^^