2017-06-06 10 views
5

मेरे आवेदन में मैंने वेब सर्विसेज को कॉल करने के लिए रेट्रोफिट लागू किया और मैं इंटरसेप्टर और प्रमाणीकरणकर्ता का उपयोग करने के लिए ओकेएचटीपी का उपयोग कर रहा हूं। कुछ अनुरोधों को token की आवश्यकता है, और मैंने रीफ्रेश को संभालने के लिए प्रमाणीकरण इंटरफ़ेस लागू किया है (आधिकारिक documentation के बाद)। लेकिन मेरे पास निम्न समस्या है: मेरे ऐप में समय-समय पर मुझे एक से अधिक अनुरोधों को एक बार कॉल करना होगा। इसके कारण, उनमें से एक के लिए मुझे 401 त्रुटि होगी।ओकेएचटीपी और रेट्रोफिट, समवर्ती अनुरोधों के साथ टोकन रीफ्रेश करें

यहाँ अनुरोध कॉल के लिए मेरी कोड है:

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

मुद्दा सरल है, पहले अनुरोध सफलतापूर्वक टोकन ताज़ा होगी लेकिन दूसरों को विफल हो गया क्योंकि वे एक टोकन पहले से ही ताजा ताज़ा करने के लिए कोशिश करेंगे। WebService एक त्रुटि 500 ​​लौटाता है। क्या इससे बचने के लिए कोई सुरुचिपूर्ण समाधान है?

धन्यवाद!

+0

यह आपकी मदद कर सकता है, उम्मीद है कि यह बहुत देर हो चुकी है https://stackoverflow.com/a/48518733/8187386 –

उत्तर

0

सेवा लिखें।

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

क्या मैं आपकी प्रतिक्रिया समझ सकता हूं? मेरे लिए यह पूरी तरह से विषय से बाहर है। इसके अलावा मैं रेट्रोफिट का उपयोग कर रहा हूं जैसे मैंने कहा, AyncTask नहीं – Guimareshh

0

अगर मैं आपकी समस्या को समझते हैं, कुछ अनुरोध करते हुए टोकन अद्यतन किया जा रहा है भेजा जाता है, इस पर आपको एक त्रुटि देता है।

टोकन अपडेट होने के दौरान आप सभी अनुरोधों को रोकने की कोशिश कर सकते हैं ('सिंक्रनाइज़' ऑब्जेक्ट के साथ) लेकिन यह पहले से भेजे गए अनुरोध के मामले को कवर नहीं करेगा।

चूंकि इस मुद्दे को पूरी तरह से टालना मुश्किल है, शायद यहां सही दृष्टिकोण एक अच्छा फॉलबैक व्यवहार होना है। उदाहरण के लिए अद्यतन टोकन के साथ अनुरोध को फिर से चलाकर टोकन अपडेट के दौरान अनुरोध करते समय आपको मिली त्रुटि को संभालना।

संबंधित मुद्दे