Android and ResponseCache... Request Headers are missing
I am implementing ResponseCache for HttpUrlConnection in android. Everything seems to work. I call
ResponseCache.setDefault(new ResCache());
And the methods in my ResCache class are being used as expected. The only problem I am having is that the Map with request Parameters is empty. If I try this very same code outside of an android environment, I will be able to see the request Header parameter, but inside an activity and all that stuff is not working. Here is the code for the Activity.
package com.httptest;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.CacheRequest;
import java.net.CacheResponse;
import java.net.HttpURLConnection;
import java.net.ResponseCache;
import java.net.URI;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import java.util.Map;
import android.app.Activity;
import android.os.Bundle;
public class HttpTest extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ResponseCache.setDefault(new ResCache());
HttpURLConnection urlConnection = null;
try {
URL url = new URL("http://169.254.198.146//patch/500.php");
urlConnection = (HttpURLConnection) url
.openConnection();
urlConnec开发者_开发技巧tion.setUseCaches(true);
urlConnection.setRequestProperty("MY_PROPERTY", "MY_VALUE");
InputStream in = new BufferedInputStream(
urlConnection.getInputStream());
String aux = readStream(in);
}catch(Exception e){
e.printStackTrace();
}finally {
urlConnection.disconnect();
}
}
public static String readStream(InputStream in) throws IOException {
StringBuilder sb = new StringBuilder();
BufferedReader r = new BufferedReader(new InputStreamReader(in), 1000);
for (String line = r.readLine(); line != null; line = r.readLine()) {
sb.append(line);
}
in.close();
return sb.toString();
}
public class ResCache extends ResponseCache{
@Override
public CacheResponse get(URI arg0, String arg1,
Map<String, List<String>> arg2) throws IOException {
System.out.println(arg2);
return null;
}
@Override
public CacheRequest put(URI uri, URLConnection connection)
throws IOException {
return null;
}
}
}
In the method ResCache.get(URI, String, Map), the map is always empty. I would like to see the parameters I added to the request. By the way the parameters all well set in the request, as I can read them in the server when performing the request.
Again, this works outside of an android environment.
Any help with this?
Thank you!
I think there is a bug in Android's HttpURLConnection implementation where the response headers are passed to this method instead of the request headers.
I have solved this problem in my code as below, although I did not google for more details for the bug in android, but I'm pretty convinced android's implementation for httpurlconnection has some problem, as you can see it works on non-android jvms:
Basically I fixed it by passing a VirenRequestHeadersMap instead of passing URLConnection#getRequestProperies() to be consistent with the values passed from put(...).
@Override
public CacheRequest put(URI uri, URLConnection connection)
throws IOException {
MyPrivateContext context = <>;
context.setConnection(connection);
//...
}
@Override
public CacheResponse get(URI arg0, String arg1,
Map<String, List<String>> arg2) throws IOException {
System.out.println(arg2);
MyPrivateContext context = <>;
URLConnection connection = context.getConnection();
arg2 = new VirenRequestHeadersMap(connection);
//...
}
And here is the entire VirenRequestHeadersMap class if you are curious as to how it looks like:
class VirenRequestHeadersMap implements Map<String, List<String>> {
private final URLConnection mConnection;
public VirenRequestHeadersMap(URLConnection connection) {
mConnection = connection;
}
public void clear() {
throw new UnsupportedOperationException();
}
public boolean containsKey(Object key) {
if (key instanceof String) {
String field = (String) key;
return mConnection.getRequestProperty(field) != null;
} else {
return false;
}
}
public boolean containsValue(Object value) {
throw new UnsupportedOperationException();
}
public Set<Entry<String, List<String>>> entrySet() {
throw new UnsupportedOperationException();
}
public List<String> get(Object key) {
if (key instanceof String) {
String field = (String) key;
String value = mConnection.getRequestProperty(field);
return value != null ? Collections.singletonList(value) : null;
} else {
return null;
}
}
public boolean isEmpty() {
throw new UnsupportedOperationException();
}
public Set<String> keySet() {
throw new UnsupportedOperationException();
}
public List<String> put(String key, List<String> value) {
throw new UnsupportedOperationException();
}
public void putAll(Map<? extends String, ? extends List<String>> value) {
throw new UnsupportedOperationException();
}
public List<String> remove(Object key) {
throw new UnsupportedOperationException();
}
public int size() {
throw new UnsupportedOperationException();
}
public Collection<List<String>> values() {
throw new UnsupportedOperationException();
}
}
精彩评论