2017-12-20 19 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); 
    } 
} 

アップデート:まだ

ない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スタックに指示し、アプリケーション層。私は 'HttpsURLConnection'がそれを提供しているかどうかわかりませんが、OkHttpはそうしています。クイックスキャンでは表示されませんでしたが、あなたが目指しているものを処理するOkHttp設定がある可能性があります。 – CommonsWare

答えて

2

でキャッシュヒットを取得することができ、あなたのOKHttpClientを初期化するとき、キャッシュ制御を書き換えるaddNetworkInterceptorの代わりaddInterceptorを使用してください。

+0

'User-Agent'を同じ​​インターセプタに置くことができますか、もう1つ必要ですか?代わりに' addInterceptor'を付けて追加しますか? – rraallvv

+0

なぜ 'user-agent'のインターセプタが必要ですか?あなたのリクエストを作成するときに追加するだけです。 – Puneet

+0

私はあなたが 'Request.Builder()。addHeader()'を意味することを知りました。 – rraallvv

関連する問題