2017-12-20 6 views
1

아래의 방법으로 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); 
    } 
} 
+0

리포지토리 등의 HTTP 요청 레이어 위에 직접 캐시하지 않으시겠습니까? – CommonsWare

+0

@CommonsWare 도메인을 캐싱을 지원하는 다른 사이트로 변경하면 데이터를 직접 캐싱하지 않기 위해 캐시 히트를 확인해야합니다. 그것은'HttpsURLConnection'도'HttpResponseCache'도이를 확인하지 못하는 것 같습니다. 또한, 나는 아마도 연결 객체의 헤더를 변경하여 캐시에 캐시를 저장하는 것처럼 생각할 수도 있지만, cache.put (uri, connection);하지만 가능하지는 않습니다. – rraallvv

+0

"캐싱을 지원하는 다른 사이트로 도메인을 변경하면 데이터를 직접 캐싱하지 않기 위해 캐시 히트를 확인해야합니다."또는 HTTP 스택에 캐싱하지 말고 처리하십시오. 응용 프로그램 계층 OkHttp는하지만 HttpsURLConnection이 제공하는지 모르겠습니다. 빠른 스캔에서 볼 수는 없지만 목표로하는 것을 처리하는 OkHttp 구성이있을 수 있습니다. – CommonsWare

답변

2

명중하세요.

+0

'User-Agent'를 같은 인터셉터에 넣을 수 있나요, 아니면 두 번째 것이 필요할까요? 대신'addInterceptor'를 붙여서 추가 할 수 있습니까? – rraallvv

+0

왜'user-agent'에 대한 인터셉터가 필요합니까? 요청을 작성할 때 추가하십시오. – Puneet

+0

나는'Request.Builder(). addHeader()'를 의미한다 ... 고마워. – rraallvv