2017-01-10 91 views
2

我想从我的公司API缓存HTTP响应,但它看起来像应用程序不能访问缓存目录缓存错误:与改造2和3 okhttp

W/System.err的:删除失败: ENOENT(没有这样的文件或目录): /data/user/0/com.appname/cache/cache_file/journal.tmp

W/System.err的: 的java.net.UnknownHostException:无法解析主机 “www.domain.com”:没有与主机名关联的地址

我按照这个tutorial。下面是我安装改造(2.1.0):

import lu.CompanyName.R; 
import lu.CompanyName.interfaces.CompanyNameAPI; 
import okhttp3.Cache; 
import okhttp3.Interceptor; 
import okhttp3.OkHttpClient; 
import okhttp3.Request; 
import okhttp3.Response; 
import okhttp3.logging.HttpLoggingInterceptor; 
import retrofit2.Retrofit; 
import retrofit2.converter.gson.GsonConverterFactory; 

import static okhttp3.logging.HttpLoggingInterceptor.Level.HEADERS; 


public class Injector { 

    private static final String CACHE_CONTROL = "Cache-Control"; 

    private static Retrofit provideRetrofit (String baseUrl) { 
     return new Retrofit.Builder() 
       .baseUrl(baseUrl) 
       .client(provideOkHttpClient()) 
       .addConverterFactory(GsonConverterFactory.create()) 
       .build(); 
    } 

    private static OkHttpClient provideOkHttpClient() { 
     return new OkHttpClient.Builder() 
       .addInterceptor(provideHttpLoggingInterceptor()) 
       .addInterceptor(provideOfflineCacheInterceptor()) 
       .addNetworkInterceptor(provideCacheInterceptor()) 
       .cache(provideCache()) 
       .build(); 
    } 

    private static Cache provideCache() { 
     /* 
     Cache cache = null; 
     try 
     { 
      File dir = CompanyName.getInstance().getExternalCacheDir(); 

      if (dir == null) 
       dir = CompanyName.getInstance().getCacheDir(); 

      if (dir == null) 
       Log.e("provideCache", "dir is null"); 

      cache = new Cache(new File(dir, "http-cache"), 10 * 1024 * 1024); // 10 MB 

      if (cache == null) 
       Log.e("provideCache", "cache is null"); 

     } 
     catch (Exception e) 
     { 
      Log.e("provideCache", "Could not create Cache!"); 
     } 
     return cache;*/ 

     /* 
     File httpCacheDirectory = new File(CompanyName.getInstance().getCacheDir(), "responses"); 
     httpCacheDirectory.getParentFile().mkdirs(); 
     int cacheSize = 10 * 1024 * 1024; // 10 MiB 
     Cache cache = new Cache(httpCacheDirectory, cacheSize); 
     try { 
      cache.initialize(); 
      Iterator<String> iterator = cache.urls(); 
      Log.i("provideCache", "URLs in cacheHttpClient : "); 
      while (iterator.hasNext()) { 
       Log.i("provideCache", iterator.next()); 
      } 
     } catch (IOException e) { 
      e.printStackTrace(); 
      Log.i("provideCache", "CACHE NOT INIT"); 
     } 
     return cache;*/ 

     return new Cache(new File(CompanyName.getInstance().getCacheDir(), "cache_file"), 20 * 1024 * 1024); 
    } 

    private static HttpLoggingInterceptor provideHttpLoggingInterceptor() { 
     HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(); 
     httpLoggingInterceptor.setLevel(HEADERS); 
     return httpLoggingInterceptor; 
    } 

    private static Interceptor provideCacheInterceptor() { 
     /*return new Interceptor() { 
      @Override 
      public Response intercept (Chain chain) throws IOException { 
       Response response = chain.proceed(chain.request()); 

       // re-write response header to force use of cache 
       CacheControl cacheControl = new CacheControl.Builder() 
         .maxAge(2, TimeUnit.HOURS) 
         .build(); 

       return response.newBuilder() 
         .header(CACHE_CONTROL, cacheControl.toString()) 
         .build(); 
      } 
     };*/ 
     return new Interceptor() { 
      @Override 
      public Response intercept(Chain chain) throws IOException { 
       Request originalRequest = chain.request(); 
       String cacheHeaderValue = CompanyName.getInstance().checkIfHasNetwork() 
         ? "public, max-age=2419200" 
         : "public, only-if-cached, max-stale=2419200" ; 
       Request request = originalRequest.newBuilder().build(); 
       Response response = chain.proceed(request); 
       return response.newBuilder() 
         .removeHeader("Pragma") 
         .removeHeader("Cache-Control") 
         .header("Cache-Control", cacheHeaderValue) 
         .build(); 
      } 
     }; 
    } 

    private static Interceptor provideOfflineCacheInterceptor() { 
     /*return new Interceptor() 
     { 
      @Override 
      public Response intercept (Chain chain) throws IOException 
      { 
       Request request = chain.request(); 

       if (!CompanyName.hasNetwork()) 
       { 
        CacheControl cacheControl = new CacheControl.Builder() 
          //.maxStale(7, TimeUnit.DAYS) 
          .build(); 

        request = request.newBuilder() 
          .cacheControl(cacheControl) 
          .build(); 
       } 

       return chain.proceed(request); 
      } 
     };*/ 
     return new Interceptor() { 
      @Override 
      public Response intercept(Chain chain) throws IOException { 
       Request originalRequest = chain.request(); 
       String cacheHeaderValue = CompanyName.getInstance().checkIfHasNetwork() 
         ? "public, max-age=2419200" 
         : "public, only-if-cached, max-stale=2419200" ; 
       Request request = originalRequest.newBuilder().build(); 
       Response response = chain.proceed(request); 
       return response.newBuilder() 
         .removeHeader("Pragma") 
         .removeHeader("Cache-Control") 
         .header("Cache-Control", cacheHeaderValue) 
         .build(); 
      } 
     }; 
    } 

    public static CompanyNameAPI provideCompanyNameAPI() { 
     return provideRetrofit(CompanyName.getInstance().getString(R.string.base_url)).create(CompanyNameAPI.class); 
    } 
} 

我试图找到在互联网和计算器的一些解决方案(仍然在上面的代码注释),因为起初我以为这是一个“缓存控制”重写问题。

我还向清单添加了权限READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE,但它不会更改任何内容。

我错过了什么吗? (我正在使用Android 6.0.1 API 23在三星进行测试)

回答

0

您可能缺少清单中的INTERNET权限。

<uses-permission android:name="android.permission.INTERNET" />

这对于越来越UnknownHostException错误的一个常见原因。

或者,通过在浏览器中访问该网站,确保您可以实际访问该设备上的该网站

+1

不,我已经添加了此权限。事实上,只有当我关闭互联网连接(飞行模式)时,我才得到上述错误:我的测试包括首次获取数据(互联网)以获取缓存,然后从缓存中获取数据(互联网关闭)。 – Bogy

0

关于第一个错误,让我们来看看提供OkHttpClient缓存目录:

private static OkHttpClient provideOkHttpClient() { 
    return new OkHttpClient.Builder() 
      .addInterceptor(provideHttpLoggingInterceptor()) 
      .addInterceptor(provideOfflineCacheInterceptor()) 
      .addNetworkInterceptor(provideCacheInterceptor()) 
      .cache(provideCache()) 
      .build(); 
} 

您已经使用了相同的缓存目录许多OkHttpClient,很多情况下可以踩对方,破坏响应缓存。 要解决这个问题,你可以使用OkHttpClient一次,配置它的缓存,并在任何地方使用同一个实例。您可以尝试如下:

private static Retrofit provideRetrofit (String baseUrl) { 
    return new Retrofit.Builder() 
      .baseUrl(baseUrl) 
      .client(okHttpClient) 
      .addConverterFactory(GsonConverterFactory.create()) 
      .build(); 
} 

private static OkHttpClient okHttpClient = new OkHttpClient.Builder() 
      .addInterceptor(provideHttpLoggingInterceptor()) 
      .addInterceptor(provideOfflineCacheInterceptor()) 
      .addNetworkInterceptor(provideCacheInterceptor()) 
      .cache(provideCache()) 
      .build(); 

有关缓存,OkHttpClient更多信息,你可以在this link看一看。