2012-07-31 15 views
14

में ट्राई/कैच का उपयोग कर मैं अपने एंड्रॉयड आवेदन से नेटवर्क अनुरोध करने के लिए उपयोग कर रहा हूँ HttpUrlConnection बिना 401 प्रतिक्रिया प्राप्त करने के लिए। सबकुछ एक चीज को छोड़कर ठीक काम करता है, 401. जब भी सर्वर स्टेटस कोड 401 के साथ प्रतिक्रिया देता है, तो मेरा ऐप को "no authentication challenge found" बताते हुए संदेश के साथ फेंकता है। इसे गुगल करने के बाद, मुझे एक भी समाधान नहीं मिला है, लेकिन केवल वर्कअराउंड (कोशिश/पकड़ का उपयोग करके इसे संभालने, इसे 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

सर्वर को 'डब्ल्यूडब्ल्यूडब्लू-प्रमाणीकरण' हेडर मिला है, लेकिन फिर भी मुझे यह त्रुटि मिल रही है। – jtanveer

+0

मैं सिर्फ इस में भाग गया, और यह भी समझ नहीं कैसे इसे 'getResponseCode के बाद से IOException (पकड़ने()' ही 'कनेक्ट के रूप में ही IOException (फेंक देते हैं) के बाद एक 401 है ग्रहण करने के लिए बिना इस प्रतिक्रिया कोड वापस पाने के लिए/getInputStream()/getOutputStream() ')। स्टैकट्रेस से ऐसा लगता है '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 एक बहुत ही सामान्य अपवाद है। इसे किसी भी चीज़ के लिए फेंक दिया जा सकता है। आपके उत्तर से, मुझे लगता है कि मुझे मुख्य प्रयास/पकड़ ब्लॉक के अंदर एक और प्रयास/पकड़ ब्लॉक लिखना है ताकि यह सुनिश्चित किया जा सके कि प्रतिक्रिया कोड पुनर्प्राप्त करने के कारण अपवाद फेंक दिया गया है। उस मामले में, यह फिर से एक कामकाज है! लेकिन चूंकि, यह एक वर्ष रहा है और मुझे कोई समाधान नहीं मिला है, मैं आपका जवाब स्वीकार कर रहा हूं! – jtanveer

+0

इसने एंड्रॉइड वर्जन 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' का उपयोग नहीं करना चाहता क्योंकि यह इतना हल्का वजन नहीं है। फ़ाइल अपलोड करने के मामले में, मुझे एक और तृतीय पक्ष लाइब्रेरी ('मल्टीपार्ट एंटीटी') का उपयोग करना होगा, जो एंड्रॉइड एसडीके के साथ नहीं आता है। मुझे एपीके आकार को छोटा रखने की जरूरत है। इसके अलावा, Google 'HttpUrlConnection' का उपयोग करने का सुझाव देता है क्योंकि इसका हल्का वजन और वे सक्रिय रूप से उस पर काम कर रहे हैं। – jtanveer

संबंधित मुद्दे