2017-06-06 19 views
5

Trong ứng dụng của tôi, tôi đã triển khai Retrofit để gọi WebServices và tôi đang sử dụng OkHttp để sử dụng Interceptor và Authenticator. Một số yêu cầu cần token và tôi đã triển khai giao diện Authenticator để xử lý việc làm mới (theo chính thức documentation). Nhưng tôi có vấn đề sau: theo thời gian trong ứng dụng của tôi, tôi phải gọi nhiều hơn một yêu cầu cùng một lúc. Do đó, đối với một trong số họ, tôi sẽ gặp lỗi 401.OkHttp và Retrofit, mã thông báo làm mới với các yêu cầu đồng thời

Đây là mã của tôi cho các cuộc gọi yêu cầu:

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; 
    } 

Vấn đề là đơn giản, yêu cầu đầu tiên sẽ làm mới thẻ thành công nhưng những người khác sẽ thất bại bởi vì họ sẽ cố gắng để làm mới một mã thông báo đã làm mới. WebService trả về lỗi 500. Có giải pháp thanh lịch nào để tránh điều này không?

Cảm ơn bạn!

+0

Điều này có thể giúp bạn, hy vọng nó không quá muộn https://stackoverflow.com/a/48518733/8187386 –

Trả lời

0

Viết dịch vụ.

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

Tôi có thể hiểu câu trả lời của bạn không? Đối với tôi, nó hoàn toàn nằm ngoài chủ đề. Hơn nữa tôi đang sử dụng trang bị thêm như tôi đã nói, không phải AyncTask – Guimareshh

0

Nếu tôi hiểu vấn đề của bạn, một số yêu cầu được gửi trong khi thẻ đang được cập nhật, điều này mang đến cho bạn một lỗi.

Bạn có thể cố gắng ngăn chặn tất cả các yêu cầu trong khi mã thông báo đang được cập nhật (với đối tượng 'đồng bộ') nhưng điều này sẽ không bao gồm yêu cầu đã gửi.

Vì vấn đề khó tránh khỏi hoàn toàn, có thể cách tiếp cận đúng ở đây là có hành vi dự phòng tốt. Xử lý lỗi bạn nhận được khi bạn đã thực hiện yêu cầu trong khi cập nhật mã thông báo bằng cách chạy lại yêu cầu bằng mã thông báo được cập nhật chẳng hạn.

Các vấn đề liên quan