I am using Picasso for image loading. Picasso doesn't have a disk cache. OkHttp maintains an HTTP cache that is controlled by HTTP cache headers. I want to set an expiry for disk cached images so added cache-control headers in HTTP response cache-control: public, max-age=7200 but it is not respecting cache headers. The current behavior is the default HTTPResponseCache which honors RFC 7234.
Is there anything we are missing?
You can rewrite cache headers in the response with a network interceptor. Here's an example from the OkHttp interceptors doc to get you started:
/** Dangerous interceptor that rewrites the server's cache-control header. */
private static final Interceptor REWRITE_CACHE_CONTROL_INTERCEPTOR = new Interceptor() {
#Override public Response intercept(Interceptor.Chain chain) throws IOException {
Response originalResponse = chain.proceed(chain.request());
return originalResponse.newBuilder()
.header("Cache-Control", "max-age=60")
.build();
}
};
Note that you might need to remove headers from the server's response to get your desired caching behavior.
Note also that it's strictly better to fix the server to do what you want; that way it'll work correctly on iOS and on the web.
Related
I am using picasso to fetch images from server.
This is what i am using.
Picasso.with(getApplicationContext()).load(imageURL)
.placeholder(R.drawable.card_loading)
.fit().centerCrop()
.into(imageView);
The above code should cache the images, but when i update the same image on server, without changing its URL, it starts displaying the new image on app, whereas it should display the cached old image on the app.
In some devices it was displaying the older images, i closed and restart the app multiple times, then it started displaying the new images on those devices as well.
My Question is that how long picasso keep an image in cache, and how can i increase this from server or client
I'm not sure how long cache file valid. But you can change cache file validity with incoming http response header. Basically you can create interceptor and add new header with "Cache-Control" name.
OkHttpClient httpClient = new OkHttpClient();
httpClient.networkInterceptors().add(new Interceptor(){
#Override
public Response intercept(Chain chain) throws IOException {
Response originalResponse = chain.proceed(chain.request());
return originalResponse.newBuilder().header("Cache-Control", "max-age=" + (60 * 60 * 24 * 365)).build();
}
});
After that you can pass it to picasso as a http client
I am novice android developer and developing app for the first time so please be gentle if i am making any mistake in asking question.
I have API Document which is attached (Consist of Access Token) and i want to call category Using GetCateogry method as stated in the APIdocument also want to display the Category in the Gridview.
I have tried different methods but enable to figure out how to display the Json Response to GridView. I am bit confuse about how to handle Access token using GET & Post method.
Any help would be Highly Appreciated.
Thanks in advance.
Postman showing Getcategory
API Dcoument
Access Token
If you're using a library like Retrofit to manage your network requests (which I highly recommend), you could easily add the token as header to your request with:
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addInterceptor(new Interceptor() {
#Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request original = chain.request();
// Request customization: add request headers
Request.Builder requestBuilder = original.newBuilder()
.header("Authentication", "accessToken"); // <-- this is the important line
Request request = requestBuilder.build();
return chain.proceed(request);
}
});
OkHttpClient client = httpClient.build();
Check out this tutorial for further reading.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I am having an issue in my app, I need to be able to see or log the full network request so that I can see exactly what parameters are being posted to my server with what headers, currently it only shows me the URL, is there a way of doing this in android studio or is there some code I can write to display this data?
To further explain things seems the terms network request, parameters and headers are confusing people, I use the google volley library for all my htpp requests; GET, POST, PUT etc. Now when posting data to a URL or getting data via a specific URL i need to be able to confirm that the right parameters and headers are being sent to the server.
If you are talking about testing the parameters for your API, you probably looking for REST clients like:
Postman
Rest Client
to validate services. But before that, you should have proper documentation of all the web services.
Solution:
In Android Studio, to debug your code, simply place breakpoints on the code and press debug button to execute
You can place breakpoint by clicking on left of each line where breakpoint is shown.
Also check this tutorial:
Simple Debugging in Android Studio and follow further videos for proper debugging.
I would recommend you to use OkHttp for making all network calls. OkHttp provides Interceptors which will serve your exact purpose.
Defining an interceptor:
class LoggingInterceptor implements Interceptor {
#Override public Response intercept(Interceptor.Chain chain) throws IOException {
Request request = chain.request();
long t1 = System.nanoTime();
logger.info(String.format("Sending request %s on %s%n%s",
request.url(), chain.connection(), request.headers()));
HttpUrl url = request.url(); // url of the request.
Headers reqHeaders = request.headers(); // Here you are able to access headers which are being sent with the request.
RequestBody body = request.body(); // provides body of request, which you can inspect to see what is being sent.
Response response = chain.proceed(request);
long t2 = System.nanoTime();
logger.info(String.format("Received response for %s in %.1fms%n%s",
response.request().url(), (t2 - t1) / 1e6d, response.headers()));
Headers resHeaders = response.headers(); // Headers received in the response.
return response;
}
}
Using it to make network calls:
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new LoggingInterceptor())
.build();
Request request = new Request.Builder()
.url("http://www.publicobject.com/helloworld.txt")
.header("User-Agent", "OkHttp Example")
.build();
Response response = client.newCall(request).execute();
response.body().close();
Explore the Interceptors for more customization.
I'm building an Android application which uses Volley to load images from the web.
I'm using an LruCache with Volley to cache bitmaps in memory, and this is fine. In addition, I'd like Volley to leverage the built in support for http disk based caching using HttpResponseCache.
I implemented the example in the given link, but I noticed that nothing is being cached in the HttpResponseCache (I checked by sampling the HitCount field in the cache object).
After sniffing around in the Volley source code, I found that Volley manually removes the caching flag when opening a URLConnection:
private URLConnection openConnection(URL url, Request<?> request) throws IOException {
URLConnection connection = createConnection(url);
int timeoutMs = request.getTimeoutMs();
connection.setConnectTimeout(timeoutMs);
connection.setReadTimeout(timeoutMs);
connection.setUseCaches(false); // <-- Disables the caching
connection.setDoInput(true);
// use caller-provided custom SslSocketFactory, if any, for HTTPS
if ("https".equals(url.getProtocol()) && mSslSocketFactory != null) {
((HttpsURLConnection)connection).setSSLSocketFactory(mSslSocketFactory);
}
return connection;
}
You can see this code for yourself here: Volley - HurlStack (line 167)
The moment I comment out this line, the HttpResponseCahce works as expected.
My question is: Why does Volley disable the UseCaches flag in all URLConnections, and what is the risk / side-effects of removing this?
In my Application onCreate, I'm creating a 10MB cache:
try
{
File httpCacheDir = new File(getApplicationContext().getCacheDir(), Constants.AppName);
long httpCacheSize = 10 * 1024 * 1024; // 10 MiB
HttpResponseCache.install(httpCacheDir, httpCacheSize);
}
catch (IOException ex)
{
Log.i(Constants.AppName, "HTTP response cache installation failed: " + ex);
}
And my call to a resource:
OkHttpClient client = new OkHttpClient();
client.setResponseCache(HttpResponseCache.getInstalled());
HttpURLConnection connection = client.open(url);
connection.addRequestProperty("Cache-Control", "max-age=60");
InputStream inputStream = connection.getInputStream();
I'll initialize this call twice, within 10 seconds of one another, and the OkHttp-Response-Source header is always NETWORK 200.
for (Map.Entry<String, List<String>> k : connection.getHeaderFields().entrySet())
{
for (String v : k.getValue())
{
Log.d(Constants.AppName, k.getKey() + ": " + v);
}
}
What am I missing here?
OkHttp implement the HTTP 1.1 RFC for HTTP cache. That means, for any URL your are trying to reach, the response needs to return at least the Cache-Control header:
The basic cache mechanisms in HTTP/1.1 (server-specified expiration
times and validators) are implicit directives to caches. In some
cases, a server or client might need to provide explicit directives to
the HTTP caches. We use the Cache-Control header for this purpose.
The Cache-Control header allows a client or server to transmit a
variety of directives in either requests or responses. These
directives typically override the default caching algorithms. As a
general rule, if there is any apparent conflict between header values,
the most restrictive interpretation is applied (that is, the one that
is most likely to preserve semantic transparency). However,
in some cases, cache-control directives are explicitly specified as
weakening the approximation of semantic transparency (for example,
"max-stale" or "public").
The cache-control directives are described in detail in section 14.9.