我有一些典型的代码,它们使用HttpURLConnection来获取带有URL的文件。 他们在android 1.x和2.x中运行良好。但在Android 4.1中失败了!
我在网上搜索但发现的信息很少。 请问有人帮忙调查这个问题吗?
private String mURLStr;
private HttpURLConnection mHttpConnection;
...
url = new URL(mURLStr);
...
mHttpConnection = (HttpURLConnection) url.openConnection();
mHttpConnection.setDoOutput(true);
mHttpConnection.setRequestMethod("GET");
...
InputStream is = mHttpConnection.getInputStream();
getInputStream方法抛出异常:
08-01 15:56:48.856: W/System.err(13613): java.io.IOException: No authentication challenges found
08-01 15:56:48.856: W/System.err(13613): at libcore.net.http.HttpURLConnectionImpl.getAuthorizationCredentials(HttpURLConnectionImpl.java:427)
08-01 15:56:48.866: W/System.err(13613): at libcore.net.http.HttpURLConnectionImpl.processAuthHeader(HttpURLConnectionImpl.java:407)
08-01 15:56:48.866: W/System.err(13613): at libcore.net.http.HttpURLConnectionImpl.processResponseHeaders(HttpURLConnectionImpl.java:356)
08-01 15:56:48.866: W/System.err(13613): at libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:292)
08-01 15:56:48.866: W/System.err(13613): at libcore.net.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:168)
...
答案 0 :(得分:27)
我目前面临同样的问题。在4.1 Jelly Bean上,我在HttpURLConnection上调用getResponseCode()时收到IOException“未发现身份验证质询”。
我在网上搜索了一下Android源代码中的变化,发现了以下内容: 4.0.4(工作):https://bitbucket.org/seandroid/libcore/src/7ecbe081ec95/luni/src/main/java/libcore/net/http/HttpURLConnectionImpl.java 4.1.1(不工作):https://bitbucket.org/seandroid/libcore/src/6b27266a2856/luni/src/main/java/libcore/net/http/HttpURLConnectionImpl.java
正如4.1 JB中所见,方法getAuthorizationCredentials()抛出IOException。如果响应代码为401或407,它会使用HeaderParser.parseChallenges(..)解析它在响应中找到的挑战标头。如果返回的List为空,则抛出异常。
我们目前正在调查究竟是什么导致List为空,但怀疑我们的服务器可能在质询标头中使用realm = ...而不是realm =“...”。缺少引号可能是导致此问题的原因。如果确实如此,我们必须进一步调查,如果我们能够使它发挥作用。
答案 1 :(得分:25)
每RFC2617:
原始服务器使用401(未授权)响应消息 挑战用户代理的授权。这个回应必须 包括至少包含一个的WWW-Authenticate头字段 适用于所请求资源的挑战。
在Android中,当服务器返回java.io.IOException: No authentication challenges found
或401 Unauthorized
状态代码而没有设置WWW-Authenticate标头时,HttpURLConnection getResponseCode()方法会抛出407 Proxy Authentication Required
。
如果您拥有服务器端API,那么您可以通过在返回401或407时添加所需的WWW-Authenticate标头来修复它。就我而言,我在PHP中修复它,如下所示:
header('WWW-Authenticate: OAuth realm="users"');
header('HTTP/1.1 401 Unauthorized');
答案 2 :(得分:6)
我有同样的问题。我发现这个解决方法,但它不适用于Android 2.在Jelly Bean上,它工作正常。只需使用getErrorStream()而不是getInputStream()。
try
{
responseStream = new BufferedInputStream(connection.getInputStream());
}
catch(IOException e)
{
responseStream = new BufferedInputStream(connection.getErrorStream());
}
答案 3 :(得分:1)
标题
我已经解决了果冻豆的问题。请将以下代码用于上述方案
DefaultHttpClient client = new DefaultHttpClient();
client.getCredentialsProvider().setCredentials(new AuthScope(null, -1), new UsernamePasswordCredentials(userName,userPass));
HttpGet request = new HttpGet();
request.addHeader("Accept", "application/xml");
request.setURI(new URI(service));
HttpResponse response = client.execute(request);
你得到了适当的回应。
答案 4 :(得分:0)
我遇到了类似的问题,需要使用Cookie才能正常运行。显然,Jelly Bean默认情况下不会自动创建cookie存储(与以前的版本不同),因此每次我尝试访问时,服务都无法找到我的会话并抛出401。将以下代码行添加到我的应用程序初始化中解决了问题:
// enable VM-wide cookie support for HttpUrlConnection
// see http://developer.android.com/reference/java/net/HttpURLConnection.html for details
CookieManager cookieManager = new CookieManager();
CookieHandler.setDefault(cookieManager);
答案 5 :(得分:0)
使用基本身份验证而不调用setDoOutput(true)时,我们仍然遇到此问题:
以下是解决方案:
HTTP Basic Authentication issue on Android Jelly Bean 4.1 using HttpURLConnection
答案 6 :(得分:0)
检查您的服务器是否返回Error 401 - Not Authorised
。我相信Android代码会看到响应,并认为它是为了提供身份验证详细信息。在我的情况下,我只是向我的服务器提供了错误的令牌。
答案 7 :(得分:0)
有一个解决方案
在您的代码中删除此
它适用于ICS
或Jelly Bean
答案 8 :(得分:0)
我使用的解决方案(我使用Android' Volley库)是用的 Square's OkHttp library。它们的实现正确处理了这个问题,并将按预期返回401。