我正在使用Google的Volley库作为我的应用程序项目,目标是最低api级别14.因此,Volley库使用HttpURLConnection作为NetworkClient。
因此,不应该有任何与删除Apache HTTPClient相关的问题。但是,我已经完成了6.0 Sdk所需的配置,即compileSdkVersion 23,build-tool-version 23.0.1和build:gradle:1.3.1'甚至尝试添加useLibrary' org.apache.http.legacy'。在我的应用程序中为Volley库项目更新了相同内容。
最近,我尝试在Android 6.0(MarshMallow)上运行我的应用程序,我的项目编译并运行。但是那些需要身份验证标头的请求在MarshMallow上失败了:
BasicNetwork.performRequest:意外的响应代码401 com.android.volley.AuthFailureError
然而,在23以下的所有Api等级上运行相同。
我已多次检查过标题。但是,那些不需要身份验证的请求会给出200 OK的响应。
现在我完全不知道是什么打破了请求,是否有人知道新版本中HttpURLConnection请求仅在Api级别23失败了什么?是否有其他人使用Volley并面临类似的问题?
这是我的CustomRequest类
public class CustomRequest extends Request<Void> {
int id, cmd;
Map<String, String> params;
BaseModel model;
public CustomRequest(int method, int cmd, String url, Map<String, String> params, int id, BaseModel model) {
super(method, url, null);
this.id = id;
this.cmd = cmd;
this.params = params;
this.model = model;
if (method == Method.GET) {
setUrl(buildUrlForGetRequest(url));
}
Log.v("Volley", "Making request to: " + getUrl());
}
private String buildUrlForGetRequest(String url) {
if (params == null || params.size() == 0) return url;
StringBuilder newUrl = new StringBuilder(url);
Set<Entry<String, String>> paramPairs = params.entrySet();
Iterator<Entry<String, String>> iter = paramPairs.iterator();
newUrl.append("?");
while (iter.hasNext()) {
Entry<String, String> param = iter.next();
newUrl
.append(param.getKey())
.append("=")
.append(param.getValue());
if (iter.hasNext()) newUrl.append("&");
}
return newUrl.toString();
}
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> headers = new HashMap<String, String>();
headers.put("X-Api-Version", Contract.API_VERSION);
headers.put("X-Client", "android");
String accessToken = APP.getInstance().getToken();
if (!accessToken.equals("")) {
headers.put("Authorization", "Bearer " + accessToken);
}
return headers;
}
@Override
protected Response<Void> parseNetworkResponse(NetworkResponse response) {
Exception ex;
try {
String jsonString = new String(
response.data, HttpHeaderParser.parseCharset(response.headers));
JsonNode json = new ObjectMapper().readTree(jsonString);
if (model != null) model.parse(id, json);
EventBus.getDefault().post(new EventResponse(cmd, true, null));
return Response.success(null, HttpHeaderParser.parseCacheHeaders(response)); //Doesn't return anything. BaseModel.parse() does all the storage work.
} catch (NoMoreDataException e) {
ex = e;
EventBus.getDefault().post(new NoMoreDataModel(cmd, e));
EventBus.getDefault().post(new EventResponse(cmd, false, null));
return Response.success(null, HttpHeaderParser.parseCacheHeaders(response));
} catch (Exception e) {
ex = e;
Log.e("CustomRequest", Log.getStackTraceString(e));
String message = APP.getInstance().getString(R.string.failedRequest);
if (!TextUtils.isEmpty(e.getMessage()))
message = e.getMessage();
EventBus.getDefault().post(new ErrorEventModel(cmd, message, e));
return Response.error(new ParseError(ex));
}
}
@Override
protected Map<String, String> getParams() throws AuthFailureError {
return params;
}
@Override
protected void deliverResponse(Void response) {
Log.v("Volley", "Delivering result: " + getUrl());
}
@Override
public void deliverError(VolleyError error) {
Log.e("CustomRequest", "Delivering error: Request=" + getUrl() + " | Error=" + error.toString());
String message = APP.getInstance().getString(R.string.failedRequest);
EventBus.getDefault().post(new ErrorEventModel(cmd, message, error));
}
}
我在Api 23和其他人之间找到的唯一区别是 HostNameVerifier 。 对于Api等级23:com.android.okhttp.internal.tls.OkHostnameVerifier 对于Api等级&lt; 23:javax.net.ssl.DefaultHostnameVerifier。
答案 0 :(得分:1)
检查我的应用程序的服务器端后,找到问题背后的原因。 对于Android 6.0(MarshMallow),标题变为空白,而其他版本则不然。
所以对我有用的修复:
创建并添加了新的自定义标头 X-Proxy-No-Redirect =&gt; 1 并与其他标题一起传递。
背后的理论:
我们向其发送请求的API服务器,然后API服务器根据oAuth令牌将请求重定向到相应的站点 重定向时 为了实现重定向,有两种方法可以做到这一点
1 - 我们只是向呼叫者发回一条回复,说明要重定向到某个页面。然后调用者(网络库)负责重定向
2 - API服务器本身会发出重定向请求并获得响应,然后传递给调用者
早些时候我们使用方法1。
在Android 6.0上 - 网络库(Volley)在进行重定向请求时似乎没有设置所有标头。 一旦设置了这个新标题,方法2就会生效。
P.S 此修复程序适用于我的应用程序项目,可能不适用于其他人。只提供错误和帮助我的内容。