2017-01-10 5 views
2

Ich versuche, HTTP-Antworten von meiner Firma API zwischenzuspeichern, aber es sieht aus wie die App nicht das Cache-Verzeichnis zugreifen kann:Caching Fehler mit Retrofit 2 und 3 okhttp

W/System.err: Entfernen fehlgeschlagen: ENOENT (Keine solche Datei oder das Verzeichnis): /data/user/0/com.appname/cache/cache_file/journal.tmp

W/System.err: java.net.UnknownHostException: Kann Host lösen "www.domain.com": Keine Adresse mit Hostname

verknüpft

Ich habe diese tutorial gefolgt. Hier ist, wie ich ein Setup Retrofit (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); 
    } 
} 

ich einige Lösungen versucht, über das Internet und Stackoverflow gefunden (noch im Kommentar im Code oben), weil ich zuerst dachte, es war ein „Cache-Control“ Problem neu schreiben.

Ich habe auch die Berechtigung READ_EXTERNAL_STORAGE und WRITE_EXTERNAL_STORAGE zum Manifest hinzugefügt, aber es ändert nichts.

Habe ich etwas übersehen? (Ich teste auf einem Samsung mit Android 6.0.1 API 23)

Antwort

0

Sie vermissen möglicherweise die INTERNET-Berechtigung im Manifest.

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

Das ist für immer UnknownHostException Fehler ein häufiger Grund ist.

Alternativ stellen Sie sicher, dass Sie tatsächlich die Website in Frage auf diesem Gerät durch den Besuch der Website in einem Browser erreichen können.

+1

Nein Ich habe diese Erlaubnis bereits hinzugefügt. In der Tat, ich habe den oben beschriebenen Fehler nur, wenn ich Internet-Verbindung (Flugzeug-Modus) ausschalten: Mein Test besteht darin, die Daten ein erstes Mal (Internet on), um Cache zu bekommen, und dann um Daten aus dem Cache (Internet aus). – Bogy

0

den ersten Fehler betrifft, so lassen Sie sich das Cache-Verzeichnis für OkHttpClient zur Verfügung gestellt sehen:

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

Sie haben das gleiche Cache-Verzeichnis für viele OkHttpClient verwendet, viele Instanzen aufeinander, korrupte Antwort Cache stampfen können. Um dies zu beheben, können Sie genau einmal OkHttpClient verwenden, konfigurieren Sie mit ihrem Cache und verwenden Sie diese Instanz überall. Sie können wie unten versuchen:

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(); 

Für weitere Informationen über Cache mit OkHttpClient Sie einen Blick auf this link nehmen.