Need an example of HttpResponseCache in Android - android

Hi I am trying to use the HttpResponseCache introduced in Android 4.The docs do talk clearly about how to install the cache but I am at a complete loss on how to cache Images downloaded from the net.Earlier I was using the DiskLruCache to cache them. Would anyone point me towards some examples of working code where HttpResponseCache has been used..
Edit:- Can someone tell me what I am doing wrong here:-
MainActivity.java
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final long httpCacheSize = 10 * 1024 * 1024; // 10 MiB
final File httpCacheDir = new File(getCacheDir(), "http");
try {
Class.forName("android.net.http.HttpResponseCache")
.getMethod("install", File.class, long.class)
.invoke(null, httpCacheDir, httpCacheSize);
Log.v(TAG,"cache set up");
} catch (Exception httpResponseCacheNotAvailable) {
Log.v(TAG, "android.net.http.HttpResponseCache not available, probably because we're running on a pre-ICS version of Android. Using com.integralblue.httpresponsecache.HttpHttpResponseCache.");
try{
com.integralblue.httpresponsecache.HttpResponseCache.install(httpCacheDir, httpCacheSize);
}catch(Exception e){
Log.v(TAG, "Failed to set up com.integralblue.httpresponsecache.HttpResponseCache");
}
}
TheMainListFrag gf=(TheMainListFrag) getSupportFragmentManager().findFragmentByTag("thelistfrags");
if(gf==null){
gf=TheMainListFrag.newInstance();
FragmentTransaction ft=getSupportFragmentManager().beginTransaction();
ft.replace(R.id.thelefty, gf,"thelistfrags");
ft.commit();
}
}
Then in the loader of TheMainListFrag, I do the below:-
public ArrayList<HashMap<String,String>> loadInBackground() {
String datafromServer = null;
ArrayList<HashMap<String,String>> al = new ArrayList<HashMap<String,String>>();
try {
String url = "someurl";
HttpURLConnection urlConnection = (HttpURLConnection) new URL(url).openConnection();
urlConnection.setRequestProperty("Accept", "application/json");
InputStream is = new BufferedInputStream(urlConnection.getInputStream());
BufferedReader br = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = br.readLine()) != null) {
sb.append(line);
}
datafromServer=sb.toString();
Log.v("fromthread",datafromServer);
// etc
//etc
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
Log.v("fromthread", e.getClass() + "--" + e.getMessage());
}
return al;
}
When i am connected to internet, it works fine, and in the directory http-the cache directory named above, i can see the files too. But when I am not connected to the internet, the data refuses to load.
When i load images from the net, i see the cache files named as .tmp , which i believe are termed as dirty as per DiskLruCache.
Please let me know if there is any other info that you want me to provide

From the section Force a Cache Response on the HttpResponseCache documentation:
Sometimes you'll want to show resources if they are available
immediately, but not otherwise. This can be used so your application
can show something while waiting for the latest data to be
downloaded. To restrict a request to locally-cached resources, add the
only-if-cached directive:
try {
connection.addRequestProperty("Cache-Control", "only-if-cached");
InputStream cached = connection.getInputStream();
// the resource was cached! show it
} catch (FileNotFoundException e) {
// the resource was not cached
}
This technique works even better in situations where a stale response
is better than no response. To permit stale cached responses, use the
max-stale directive with the maximum staleness in seconds:
int maxStale = 60 * 60 * 24 * 28; // tolerate 4-weeks stale
connection.addRequestProperty("Cache-Control", "max-stale=" + maxStale);

When you enable HttpResponseCache, all HttpUrlConnection queries will be cached. You can't use it to cache arbitrary data, so I'd recommend keep using DiskLruCache for that.

In my case HttpResponseCache wasn't actually caching anything. What fixed it was simply:
connection.setUseCaches(true);
(This must be called on the HttpURLConnection before establishing connection.)
For finer grained control, max-stale can be used as Jesse Wilson pointed out.

Related

Reading a DropBox Text File

I have an android app that loads images and text files into Dropbox. I've figured out the authentication and upload process.
Now, using the same authenticated session, I want to read one of the uploaded text files (to look for changes). I've found a download example, but that would mean writing it to local SD, then reading for there ... not efficient at all (in part because of the additional android permission required).
I've examined Dropbox's v2 documentation and there do seem to be a bunch of read calls but I can't, for the life of me, figure out how to use them. The helpful Android-Dropbox examples also don't seem to tackle my specific problem. I couldn't find any v2 examples on stackoverflow either.
Surely, somebody can point me to a simple example that provides a nice InputStream.
You can use the Dropbox Java SDK download method to get file contents directly. There's an example of using that in the example app here. That example writes directly to a FileOutputStream.
It sounds like you just want an InputStream though, which would look like this:
DbxClientV2 client = new DbxClientV2(config, ACCESS_TOKEN);
String remotePath = "/test.txt"; // the path to the file you want to download
InputStream fileInputStream = null;
try {
fileInputStream = client.files().download(remotePath).getInputStream();
// use `fileInputStream` as desired
} catch (DbxException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
After much tooling around, here's something that works
String my_link = null;
URL my_url = null;
URLConnection conn = null;
BufferedReader reader = null;
try {
my_link = my_DbxClient.files().getTemporaryLink("/" + my_File).getLink();
my_url = new URL (my_link);
conn = my_url.openConnection();
reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
} catch (DbxException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}

HTTPResponseCache stores but never hits

I'm working on a application in Android which has a heavy load of web service requests.
I already have a LoginActivity in which the user introduces the username and the password and the server responses with the result and a token. Then, several activities (all of them extend from a common BaseActivity) do the heavy requests.
I have also a ServiceManager class which is responsible for all the service requests and HTTP petitions.
I'm working on implementing the HttpResponseCache to relieve this net load. Right now I have the following code:
In my LoginActivity's (the first being launched) onCreate:
//HTTP cache
try {
File httpCacheDir = new File(this.getCacheDir(), "http");
long httpCacheSize = 10 * 1024 * 1024; //10 MiB
HttpResponseCache.install(httpCacheDir, httpCacheSize);
Log.d(TAG, "Cache installed");
} catch (IOException e) {
Log.i(TAG, "HTTP response cache installation failed:" + e);
}
In my ServiceManager's httpRequest function, which is the one actually being executed every time I try to make an HTTP request:
//HTTPS connection
URL requestedUrl = new URL(uri);
httpsConnection = (HttpURLConnection) requestedUrl.openConnection();
httpsConnection.setUseCaches(true);
httpsConnection.setDefaultUseCaches(true);
httpsConnection.setRequestMethod("GET");
BufferedReader br = new BufferedReader(
new InputStreamReader(httpsConnection.getInputStream()));
String line;
while ((line = br.readLine()) != null) {
httpResponse += line;
}
br.close();
httpsConnection.disconnect();
HttpResponseCache cache = HttpResponseCache.getInstalled();
Log.d(TAG, "Cache: " + cache);
if (cache != null) {
Log.d(TAG, "Net count: " + cache.getNetworkCount());
Log.d(TAG, "Hit count: " + cache.getHitCount());
Log.d(TAG, "Request count: " + cache.getRequestCount());
cache.flush();
}
try{
URI uriCached = new URI("<myurl>");
CacheResponse cr = cache.get(uriCached, "GET", null);
String line;
BufferedReader br = new BufferedReader(new InputStreamReader(cr.getBody()));
while ((line = br.readLine()) != null) {
Log.d(TAG, line);
}
} catch (URISyntaxException e1) {
e1.printStackTrace();
} catch (IOException e2) {
e2.printStackTrace();
}
Right now, since the server side is not ready, the URL I'm doing the requests to is always the same.
As you can see, I'm debugging a few things, these are the results:
Cache installed
Cache: android.net.http.HttpResponseCache#b3e3b6
Net count: X
Hit count: 0
Request count: X
{myJson}
As you can see, the cache is able to read my JSON when I get it via the cache.get() method, but it's never hitting.
My server side directive Cache-Control in the header of the response is:
Cache-Control:public
Cache-Control:max-age=3800
Why is the cache never hitting?
Thank you very much!
I found the problem.
I was trying to cache petitions to a PHP that returns JSON. PHP is always considered as dynamic content (and it actually is), and it's never cached.
The path to follow when trying to cache JSON y application-side only and not server-side. This way, it won't event make a request.
Best.
EDIT
Best solution for this kind of trouble is, undoubtedly, to use Volley

How to use an installed HttpResponseCache

I've followed the developers guide and I've installed an HttpResponseCache by including the following code in the onCreate() method of my application:
try {
File httpCacheDir = new File(context.getCacheDir(), "http");
long httpCacheSize = 10 * 1024 * 1024; // 10 MiB
HttpResponseCache.install(httpCacheDir, httpCacheSize);
} catch (IOException e) {
Log.i(TAG, "HTTP response cache installation failed:" + e);
}
Now, at some point I launch an activity in this application and fetch a URL using the following code:
URL url = new URL("http://www.android.com/");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
try {
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
readStream(in);
} finally {
urlConnection.disconnect();
}
Do I have to do something when I fetch the URL to tell it to use the installed cache? Or will any activity launched inside this application automatically use it?
For example, in this example code they call connection.setUseCaches(true). Is that necessary?
The installed HttpResponseCache will be used by HttpURLConnection and HttpsURLConnection as long as you call setUseCaches(true) on the connection.
Also the response from the web server needs to be cacheable.

Android: Quick web requests

For my application I need to have the latest data from an webpage that is hosted on a server on my local network.
So I request the latest page with a HTTP GET and when the data is received, I send another request.
With my current implementation I reach around the 100 - 120 ms per request. Is there a possibility to make this quicker because it's the same url that is requested.
For example keep the connection open to the page and grep the latest data without setting up a new connection?
This page is around the 900-1100 bytes.
HTTP get code:
public static String makeHttpGetRequest(String stringUrl) {
try {
URL url = new URL(stringUrl);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setReadTimeout(300);
con.setConnectTimeout(300);
con.setDoOutput(false);
con.setDoInput(true);
con.setChunkedStreamingMode(0);
con.setRequestMethod("GET");
return readStream(con.getInputStream());
} catch (IOException e) {
Log.e(TAG, "IOException when setting up connection: " + e.getMessage());
}
return null;
}
Reading inputstream
private static String readStream(InputStream in) {
BufferedReader reader = null;
StringBuilder total = new StringBuilder();
try {
String line = "";
reader = new BufferedReader(new InputStreamReader(in));
while ((line = reader.readLine()) != null) {
total.append(line);
}
} catch (IOException e) {
Log.e(TAG, "IOException when reading InputStream: " + e.getMessage());
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return total.toString();
}
As I know there isn't an implementation like you are asking for. I've been dealing a lot with http requests and the best thing you can do is your code. There is another thing which need some attention...your connection maybe slow and depending on that connection time can be more or in some cases which I've been dealing a lot the connection's timeout isn't enough big, but that's server problem.
In my opinion you should use what you have now.

Do I need to call HttpURLConnection.disconnect after finish using it

The following code basically works as expected. However, to be paranoid, I was wondering, to avoid resource leakage,
Do I need to call HttpURLConnection.disconnect, after finish its usage?
Do I need to call InputStream.close?
Do I need to call InputStreamReader.close?
Do I need to have the following 2 line of code : httpUrlConnection.setDoInput(true) and httpUrlConnection.setDoOutput(false), just after the construction of httpUrlConnection?
The reason I ask so, is most of the examples I saw do not do such cleanup. http://www.exampledepot.com/egs/java.net/post.html and http://www.vogella.com/articles/AndroidNetworking/article.html. I just want to make sure those examples are correct as well.
public static String getResponseBodyAsString(String request) {
BufferedReader bufferedReader = null;
try {
URL url = new URL(request);
HttpURLConnection httpUrlConnection = (HttpURLConnection)url.openConnection();
InputStream inputStream = httpUrlConnection.getInputStream();
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
int charRead = 0;
char[] buffer = new char[1024];
StringBuffer stringBuffer = new StringBuffer();
while ((charRead = bufferedReader.read(buffer)) > 0) {
stringBuffer.append(buffer, 0, charRead);
}
return stringBuffer.toString();
} catch (MalformedURLException e) {
Log.e(TAG, "", e);
} catch (IOException e) {
Log.e(TAG, "", e);
} finally {
close(bufferedReader);
}
return null;
}
private static void close(Reader reader) {
if (reader != null) {
try {
reader.close();
} catch (IOException exp) {
Log.e(TAG, "", exp);
}
}
}
Yes you need to close the inputstream first and close httpconnection next. As per javadoc.
Each HttpURLConnection instance is used to make a single request but the underlying network connection to the HTTP server may be transparently shared by other instances. Calling the close() methods on the InputStream or OutputStream of an HttpURLConnection after a request may free network resources associated with this instance but has no effect on any shared persistent connection. Calling the disconnect() method may close the underlying socket if a persistent connection is otherwise idle at that time.
Next two questions answer depends on purpose of your connection. Read this link for more details.
I believe the requirement for calling setDoInput() or setDoOutput() is to make sure they are called before anything is written to or read from a stream on the connection. Beyond that, I'm not sure it matters when those methods are called.

Categories

Resources