2017-01-10 7 views
2

Я пытаюсь кэшировать ответы HTTP от моей компании API, но это выглядит как приложение не может получить доступ к каталогу кэша:Кэширование ошибки с Модернизированным 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); 
    } 
} 

Я пробовал некоторые решения, найденные через Интернет и StackOverflow (до сих пор в комментариях в коде выше), потому что сначала я подумал, что это был «Cache-Control» проблема перезаписи.

Я также добавил в манифест READ_EXTERNAL_STORAGE и WRITE_EXTERNAL_STORAGE, но ничего не изменил.

Я что-то пропустил? (Я тестирую на Samsung с 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.