2017-06-06 26 views
5

Uygulamamda WebServices'ı aramak için Retrofit'i uyguladım ve Interceptor ve Authenticator'ı kullanmak için OkHttp kullanıyorum. Bazı isteklerin token'a ihtiyacı var ve yenilemeyi yönetmek için Authenticator arabirimini uyguladım (resmi documentation'u izleyerek). Ancak şu sorunum var: Uygulamamda zaman zaman birden fazla isteği tek seferde aramak zorundayım. Bundan dolayı, bunlardan biri için 401 hatasını alacağım.OkHttp ve Güçlendirme, eşzamanlı isteklerle yenileme belirteci

İşte istek aramalar için benim kodudur:

public static <S> S createServiceAuthentication(Class<S> serviceClass, boolean hasPagination) { 

     final String jwt = JWT.getJWTValue(); //Get jwt value from Realm 

     if (hasPagination) { 
      Gson gson = new GsonBuilder(). 
        registerTypeAdapter(Pagination.class, new PaginationTypeAdapter()).create(); 

      builder = 
        new Retrofit.Builder() 
          .baseUrl(APIConstant.API_URL) 
          .addConverterFactory(GsonConverterFactory.create(gson)); 
     } 

     OkHttpClient.Builder httpClient = 
       new OkHttpClient.Builder(); 

     httpClient.addInterceptor(new AuthenticationInterceptor(jwt)); 
     httpClient.authenticator(new Authenticator() { 
      @Override 
      public Request authenticate(Route route, Response response) throws IOException { 
       if (responseCount(response) >= 2) { 
        // If both the original call and the call with refreshed token failed, 
        // it will probably keep failing, so don't try again. 
        return null; 
       } 

       if (jwt.equals(response.request().header("Authorization"))) { 
        return null; // If we already failed with these credentials, don't retry. 
       } 

       APIRest apiRest = createService(APIRest.class, false); 
       Call<JWTResponse> call = apiRest.refreshToken(new JWTBody(jwt)); 
       try { 
        retrofit2.Response<JWTResponse> refreshTokenResponse = call.execute(); 
        if (refreshTokenResponse.isSuccessful()) { 

         JWT.storeJwt(refreshTokenResponse.body().getJwt()); 

         return response.request().newBuilder() 
           .header(CONTENT_TYPE, APPLICATION_JSON) 
           .header(ACCEPT, APPLICATION) 
           .header(AUTHORIZATION, "Bearer " + refreshTokenResponse.body().getJwt()) 
           .build(); 
        } else { 
         return null; 
        } 
       } catch (IOException e) { 
        return null; 
       } 
      } 
     }); 

     builder.client(httpClient.build()); 
     retrofit = builder.build(); 

     return retrofit.create(serviceClass); 
    } 

    private static int responseCount(Response response) { 
     int result = 1; 
     while ((response = response.priorResponse()) != null) { 
      result++; 
     } 
     return result; 
    } 

mesele basit, ilk istek başarıyla belirteci yenilenir ancak bir belirteç zaten tazelenmiş yenilemek için çalışacaktır çünkü başkalarının başarısız olacaktır. WebService 500 hatası veriyor. Bunu önlemek için herhangi bir zarif çözüm var mı?

Teşekkür ederiz!

+0

Bu size yardımcı olabilir, umarım çok geç değildir https://stackoverflow.com/a/48518733/8187386 –

cevap

0

Yazma Hizmeti. Ben senin sorunu anlamak ise belirteç güncellenirken, bazı istekler gönderilir

public class TokenService extends Service { 

private static final String TAG = "HelloService"; 

private boolean isRunning = false; 
OkHttpClient client; 
JSONObject jsonObject; 
public static String URL_LOGIN = "http://server.yoursite"; 
String phone_number, password; 

@Override 
public void onCreate() { 
    Log.i(TAG, "Service onCreate"); 
    jsonObject = new JSONObject(); 
    client = new OkHttpClient(); 

    SharedPreferences pref_phone = getSharedPreferences("Full_Phone", MODE_PRIVATE); 
    phone_number = pref_phone.getString("Phone", ""); 

    SharedPreferences pref_password = getSharedPreferences("User_Password", MODE_PRIVATE); 
    password = pref_password.getString("Password", ""); 

    isRunning = true; 
} 

@Override 
public int onStartCommand(Intent intent, int flags, int startId) { 

    Log.i(TAG, "Service onStartCommand"); 
    try { 
     jsonObject.put("phone_number", phone_number); 
     jsonObject.put("password", password); 

    } catch (JSONException e) { 
     e.printStackTrace(); 
    } 
    new Thread(new Runnable() { 
     @Override 
     public void run() { 
      for (; ;) { 
       try { 
        Thread.sleep(1000 * 60 * 2); 
       } catch (Exception e) { 
       } 

       if (isRunning) { 

        AsyncTaskRunner myTask = new AsyncTaskRunner(); 
        myTask.execute(); 

       } else { 

        Log.d("CHECK__", "Check internet connection"); 

       } 
      } 
     } 
    }).start(); 

    return Service.START_STICKY; 
} 

@Override 
public IBinder onBind(Intent arg0) { 
    Log.i(TAG, "Service onBind"); 
    return null; 
} 

@Override 
public void onDestroy() { 

    isRunning = false; 
    Log.i(TAG, "Service onDestroy"); 
} 

String post(String url, JSONObject login) { 
    try { 
     MediaType mediaType = MediaType.parse("application/json"); 
     RequestBody body = RequestBody.create(mediaType, login.toString()); 
     okhttp3.Request request = new okhttp3.Request.Builder() 
       .url(url) 
       .post(body) 
       .build(); 

     okhttp3.Response response = client.newCall(request).execute(); 

     try { 
      return response.body().string(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
    return ""; 
} 

String response; 

private class AsyncTaskRunner extends AsyncTask<String, String, String> { 

    @Override 
    protected void onPreExecute() { 
    } 

    @Override 
    protected String doInBackground(String... params) { 

     try { 
      response = post(
        URL_LOGIN, jsonObject); 

     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
     return null; 
    } 

    @Override 
    protected void onPostExecute(String result) { 
     Log.d("---OKHTTP---", response); 
    } 
} 

}

+0

Yanıtınızı anlayabilir miyim? Benim için tamamen konu dışı. Üstelik söylediğim gibi uyarlama kullanıyorum, AyncTask değil – Guimareshh

0

, bu size bir hata veriyor.

Bir belirteci güncelleştirilirken ('senkronize edilmiş' bir nesne ile) tüm istekleri engellemeye çalışabilirsiniz, ancak bu zaten gönderilen bir talebi kapsamaz. Bu sorunun tamamen engellenmesi zor olduğundan, belki de buradaki doğru yaklaşım iyi bir geri dönüş davranışına sahip olmaktır. Örneğin, güncellenmiş belirteçle isteği yeniden çalıştırarak, bir simge güncellemesi sırasında istekte bulunduğunuzda aldığınız hatayı işleme.

İlgili konular