2012-07-31 3 views
14

私はHttpUrlConnectionを使用して、アンドロイドアプリケーションからネットワークリクエストを作成しています。 1つのことを除いてすべて正常に動作します。401サーバーがステータスコード401の応答を返すと、私のアプリはというメッセージでIOExceptionをスローします。グーグルでそれを行った後、私は単一の解決策を見つけられませんでしたが、回避策(try/catchを使用して処理します。ここandroidでtry/catchを使用して401レスポンスを取得する方法

は、コードスニペットです:

public Bundle request(String action, Bundle params, String cookie) throws FileNotFoundException, MalformedURLException, SocketTimeoutException, 
     IOException { 

    OutputStream os; 

    String url = baseUrl + action; 
    Log.d(TAG, url); 
    HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection(); 
    conn.setConnectTimeout(30 * 1000); 
    conn.setReadTimeout(30 * 1000); 
    conn.setRequestProperty("User-Agent", System.getProperties().getProperty("http.agent") + "AndroidNative"); 
    conn.setRequestMethod("POST"); 
    conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary); 
    conn.setRequestProperty("Connection", "Keep-Alive"); 
    conn.setDoOutput(true); 
    conn.setDoInput(true); 
    if (cookie != null) { 
     conn.setRequestProperty("Cookie", cookie); 
    } 

    if (params != null) { 
     os = conn.getOutputStream(); 
     os.write(("--" + boundary + endLine).getBytes()); 
     os.write((encodePostBody(params, boundary)).getBytes()); 
     os.write((endLine + "--" + boundary + endLine).getBytes()); 
     uploadFile(params, os); 
     os.flush(); 
     os.close(); 
    } 

    conn.connect(); 

    Bundle response = new Bundle(); 
    try { 
     response.putInt("response_code", conn.getResponseCode()); 
     Log.d(TAG, conn.getResponseCode() + ""); 
     response.putString("json_response", read(conn.getInputStream())); 
     List<String> responseCookie = conn.getHeaderFields().get("set-cookie"); 
     // Log.d(TAG, responseCookie.get(responseCookie.size() - 1)); 
     response.putString("cookie", responseCookie.get(responseCookie.size() - 1)); 
    } catch (SocketTimeoutException e) { 
     throw new SocketTimeoutException(e.getLocalizedMessage()); 
    } catch (FileNotFoundException e) { 
     throw new FileNotFoundException(e.getLocalizedMessage()); 
    } catch (IOException e) { 
     e.printStackTrace(); 
     response.putInt("response_code", HttpURLConnection.HTTP_UNAUTHORIZED); 
     response.putString("json_response", read(conn.getErrorStream())); 
    } 

    // debug 
    Map<String, List<String>> map = conn.getHeaderFields(); 
    for (String key : map.keySet()) { 
     List<String> values = map.get(key); 
     for (String value : values) { 
      Log.d(key, value); 
     } 
    } 

    conn.disconnect(); 

    return response; 
} 

この例外がスローされた理由を私は本当に、知りたいですか?認証チャレンジは何を意味しますか?どのように認証の挑戦を提供する?この状況を克服するためにコード内でどのような変更を行う必要がありますか?

私を啓発してください。.. :)

+0

私はそれは、サーバーが401エラーコードで応答したが、認証チャレンジを記述する 'WWW-Authenticate'ヘッダを省略することを意味推測すると思います。 – Jens

+0

サーバは 'WWW-Authenticate'ヘッダを持っていますが、依然としてこのエラーが発生しています。 – jtanveer

+0

私はちょうどこれに出くわしました。また、この応答コードを取得する方法を理解することもできません。なぜなら、 'getResponseCode()'自身が 'connect()/'と同じIOExceptionをスローするので、 getInputStream()/ getOutputStream() ')を呼び出します。 stacktraceからは、 'org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.processAuthHeader(HttpURLConnectionImpl.java:1153)'がチェーンの上に例外をスローするようになっています(ただし、さらに潜水する)。 –

答えて

12

IOExceptionがかなり一般的な例外であり、あなたは安全に401のステータスコードにそれがスローされますたびに仮定することはできません。

初めてステータスコードを要求すると、401が発生した場合、HttpURLConnectionはIOExceptionをスローします。この時点で、接続の内部ステータスが変更され、エラーなしでステータスコードを表示できるようになります。詳細については

int status = 0; 
try { 
    status = conn.getResponseCode(); 
} catch (IOException e) { 
    // HttpUrlConnection will throw an IOException if any 4XX 
    // response is sent. If we request the status again, this 
    // time the internal status will be properly set, and we'll be 
    // able to retrieve it. 
    status = conn.getResponseCode(); 
} 
if (status == 401) { 
    // ... 
} 

http://www.tbray.org/ongoing/When/201x/2012/01/17/HttpURLConnection

+0

あなたの答えをありがとう。あなたが言ったように、IOExceptionは非常に一般的な例外です。それは何でも投げられます。あなたの答えから、私はメインのtry/catchブロックの中に別のtry/catchブロックを書き、レスポンスコードを取得して例外がスローされたことを確認しなければならないと仮定しています。その場合、これもまた回避策です!しかし、それは1年だったので、何の解決策も見つけられなかったので、私はあなたの答えを受け入れています! – jtanveer

+0

Androidバージョン4.2.2以降の問題を修正しました –

-2

を使用しようとするのHttpClient

private void setCredentials(String login, String password) { 
    if (login != null && password != null) 
     httpClient.getCredentialsProvider().setCredentials(
       new AuthScope(URL_HOST, 80), new UsernamePasswordCredentials(login, password)); 

} 



private InputStream execute(String url, String login, String password) { 
     setCredentials(login, password); 
     HttpGet get = new HttpGet(url); 
     try { 
      HttpResponse response = httpClient.execute(get); 
      int code = response.getStatusLine().getStatusCode(); 
      if (code == HttpURLConnection.HTTP_OK) { 
       InputStream stream = response.getEntity().getContent(); 
       return stream; 
      } else { 
       Log.e("TAG", "Wrong response code " + code + " for request " + get.getRequestLine().toString()); 
       return null; 
      } 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     return null; 
    } 
+2

あなたの答えをありがとう。しかし、私は実際にはそれほど軽量ではないので、 'HttpClient'を使用したくありません。ファイルをアップロードする場合は、アンドロイドSDKに付属していない別のサードパーティライブラリ( 'MultipartEntity')を使用する必要があります。私はapkサイズを小さく保つ必要があります。さらに、Googleでは、軽量で、積極的に取り組んでいるため、 'HttpUrlConnection'を使用するよう提案しています。 – jtanveer

関連する問題