아래의 방법으로 wiktionary.org에서 페이지를 요청할 수 있습니다. 문제는 서버가 Cache-control => private, must-revalidate, max-age=0
을 헤더에 반환하여 HttpsURLConnection
이 요청을 저장하지 못하게하는 것입니다.HttpsURLConnection 및 HttpResponseCache를 Android에서 강제로 캐싱하는 방법은 무엇입니까?
강제로 페이지를 캐싱 할 수있는 방법이 있습니까?
protected static synchronized String getUrlContent(String url) throws ApiException {
if (sUserAgent == null) {
throw new ApiException("User-Agent string must be prepared");
}
try {
URL obj = new URL(url);
HttpsURLConnection connection = (HttpsURLConnection) obj.openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("User-Agent", sUserAgent);
//connection.addRequestProperty("Cache-Control", "max-stale");
//connection.addRequestProperty("Cache-Control", "public, max-age=3600");
//connection.addRequestProperty("Cache-Control", "only-if-cached");
int responseCode = connection.getResponseCode();
if (responseCode != HttpURLConnection.HTTP_OK) { // success
throw new ApiException("Invalid response from server: " + responseCode);
}
InputStream inputStream = connection.getInputStream();
ByteArrayOutputStream content = new ByteArrayOutputStream();
// Read response into a buffered stream
int readBytes = 0;
while ((readBytes = inputStream.read(sBuffer)) != -1) {
content.write(sBuffer, 0, readBytes);
}
HttpResponseCache cache = HttpResponseCache.getInstalled();
if (cache != null) {
Log.w("!!!", "Cache hit count: " + cache.getHitCount());
//connection.addRequestProperty("Cache-Control", "public, max-age=3600");
Log.w("!!!", "Cache-Control: " + connection.getHeaderField("Cache-Control"));
//cache.put(new URI(url), connection);
}
// Return result from buffered stream
return new String(content.toByteArray());
} catch (Exception e) {
throw new ApiException("Problem communicating with API", e);
}
}
는 업데이트 :
아직수없는이 캐시는 OKHttpClient를 초기화 할 때 캐시 제어를 다시 작성 addNetworkInterceptor
대신 addInterceptor
사용하십시오 okhttp interceptors
static private OkHttpClient client;
static private Cache cache;
public static OkHttpClient getClient() {
if (client == null) {
File cacheDirectory = new File(App.getInstance().getCacheDir().getAbsolutePath(), "HttpCache");
cache = new Cache(cacheDirectory, 1024 * 1024);
client = new OkHttpClient.Builder()
.cache(cache)
.addInterceptor(REWRITE_CACHE_CONTROL_INTERCEPTOR).build();
}
return client;
}
/** 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();
}
};
protected static synchronized String getUrlContent(String url) throws ApiException {
try {
OkHttpClient httpClient = getClient();
Request request = new Request.Builder()
.url(url)
.build();
Response response = httpClient.newCall(request).execute();
Log.w("!!!", "hitCount: " + cache.hitCount());
return response.body().string();
} catch (Exception e) {
throw new ApiException("Problem communicating with API", e);
}
}
리포지토리 등의 HTTP 요청 레이어 위에 직접 캐시하지 않으시겠습니까? – CommonsWare
@CommonsWare 도메인을 캐싱을 지원하는 다른 사이트로 변경하면 데이터를 직접 캐싱하지 않기 위해 캐시 히트를 확인해야합니다. 그것은'HttpsURLConnection'도'HttpResponseCache'도이를 확인하지 못하는 것 같습니다. 또한, 나는 아마도 연결 객체의 헤더를 변경하여 캐시에 캐시를 저장하는 것처럼 생각할 수도 있지만, cache.put (uri, connection);하지만 가능하지는 않습니다. – rraallvv
"캐싱을 지원하는 다른 사이트로 도메인을 변경하면 데이터를 직접 캐싱하지 않기 위해 캐시 히트를 확인해야합니다."또는 HTTP 스택에 캐싱하지 말고 처리하십시오. 응용 프로그램 계층 OkHttp는하지만 HttpsURLConnection이 제공하는지 모르겠습니다. 빠른 스캔에서 볼 수는 없지만 목표로하는 것을 처리하는 OkHttp 구성이있을 수 있습니다. – CommonsWare