美文网首页Android-Rxjava&retrofit&dagger
Android OkHttp Retrofit Token过期重

Android OkHttp Retrofit Token过期重

作者: 小尤学习 | 来源:发表于2017-09-13 23:33 被阅读0次

    遇到问题:

    请求接口时遇到token过期重新获取token之后,不会再次请求当前接口。

    解决办法:

    在 OkHttpManager 这个类 里面 直接把 30001 和30002 拦截 重新获取接口 在重新请求一遍方法 虽然是这么简单,但是走了好多弯路,所以几下笔记,避免更多小伙伴踩坑

    参考:

    http://www.jianshu.com/p/8d1ee61bc2d2

    遇到的坑

    报java.lang.IllegalStateException: closed,java.lang.IllegalStateException: closed,原因为OkHttp请求回调中response.body().string()只能有效调用一次

    解决办法

         @Override
        public Response intercept(Chain chain) throws IOException
        {
            Request request = chain.request();
            logForRequest(request);
            Response response = chain.proceed(request);
           MediaType mediaType = response.body().contentType();
            String content= response.body().string();
            Log.e("tag", content);
            return response.newBuilder()
                    .body(ResponseBody.create(mediaType, string))
                    .build();
          // return logForResponse(response);
    

    贴出代码部分

    
    public class OkHttpManager {
    
        private static OkHttpClient mOkHttpClient;
        public static OkHttpClient getInstance() {
            if (mOkHttpClient == null) {
                synchronized (OkHttpManager.class) {
                    if (mOkHttpClient == null) {
    
    //                    //设置 请求的缓存
    //                    File cacheFile = new File(IeouApplication.getInstance().getCacheDir(), "cache");
    //                    Cache cache = new Cache(cacheFile, 1024 * 1024 * 50); //50Mb
    
                        mOkHttpClient = new OkHttpClient.Builder()
                                .connectTimeout(Constants.HTTP_CONNECT_TIMEOUT, TimeUnit.MILLISECONDS)
                                .readTimeout(Constants.HTTP_CONNECT_TIMEOUT, TimeUnit.MILLISECONDS)
     //                           .addInterceptor(mIntercepter)
                                .addInterceptor(new TokenInterceptor())
                                .addInterceptor(new OKHTTPLogInterceptor())
                                .addNetworkInterceptor(new HttpCacheInterceptor())
    //                            .cache(cache)
                                .build();
                    }
                }
            }
            return mOkHttpClient;
        }
    
        /**
         * 通用的请求头
         */
        private static HashMap<String, String> addHeader() {
            HashMap<String, String> header = new HashMap<>();
            header.put(Constants.HEADER_Client, PsUtils.getString(IeouApplication.getInstance(), "accessToken") == null ? Constants.FROM_ANDROID :
                    PsUtils.getString(IeouApplication.getInstance(), "accessToken"));
            header.put("account_type", "CUSTOMER");
            return header;
        }
    
        /**
         * 拦截器 给所有的请求添加消息头
         */
        private static Interceptor mIntercepter = chain -> {
    
            Request.Builder builder = chain.request().newBuilder();
    
            HashMap<String, String> header = addHeader();
    
            if (header != null) {
                for (HashMap.Entry<String, String> entry : header.entrySet()) {
                    builder.addHeader(entry.getKey(), entry.getValue());
                }
            }
            return chain.proceed(builder.build());
        };
    
      /**
         * 重新获取token
         */
        private static class TokenInterceptor implements Interceptor {
    
            private Handler mHandler = new Handler();
            private String resultStr;
    
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request request = chain.request().newBuilder()
                        .header("access_token", PsUtils.getString(IeouApplication.getInstance(), "accessToken") == null ? Constants.FROM_ANDROID :
                                PsUtils.getString(IeouApplication.getInstance(), "accessToken"))
                        .header("account_type", "CUSTOMER")
                        .build();
                ;
                Response response = chain.proceed(request);
    //            HashMap<String, String> header = addHeader();
    //            if (header != null) {
    //                for (HashMap.Entry<String, String> entry : header.entrySet()) {
    //                    request.newBuilder().addHeader(entry.getKey(), entry.getValue());
    //                }
    //            }
                MediaType mediaType = response.body().contentType();
    
    
                if (isTokenExpired(response)) {
                    //同步请求方式,获取最新的Token
                    Log.e("OkHttpManager", "静默自动刷新Token,然后重新请求数据");
                    //同步请求方式,获取最新的Token
                    String newSession = getNewToken();
                    //使用新的Token,创建新的请求
                    if (null != newSession && newSession.length() > 0) {
                        Request newRequest = chain.request()
                                .newBuilder()
                                .header("access_token", newSession)
                                .header("account_type", "CUSTOMER")
                                .build();
                        //重新请求上次的接口
                        return chain.proceed(newRequest.newBuilder().build());
                    }
    
                }
                //如果token正常返回结果
                return response.newBuilder().body(ResponseBody.create(mediaType, resultStr)).build();
            }
            /**
             * 根据Response,判断Token是否失效
             *
             * @param response
             * @return
             */
            private boolean isTokenExpired(Response response) {
                try {
                    resultStr = response.body().string();
                    RequestCode requestCode = new Gson().fromJson(resultStr, RequestCode.class);
                    Log.e("OkHttpManager", requestCode.getResultCode() + "----requestCode");
                    Log.e("OkHttpManager", resultStr + "----requestCode");
                    if (requestCode.getResultCode() == 30001) {
                        Log.e("OkHttpManager", "----requestCode,Token登录过期了");
                        return true;
                    }
                    if (requestCode.getResultCode() == 30002) {
                        Log.e("OkHttpManager", "----requestCode,Token过期了");
                        return true;
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
    
                return false;
            }
    
            String getNewToken() {
    //            Call<ResponseBody> bodyCall = HttpFactory.getHttpApi().getTasks(PsUtils.getString(IeouApplication.getInstance(), "refreshToken"));
    //            retrofit2.Response<ResponseBody> response = bodyCall.execute();
    
              /**
                 * 必须使用同步请求
                 */
                String url = IeouUrl.baseUrl + "user/refreshToken?refreshToken=" + PsUtils.getString(IeouApplication.getInstance(), "refreshToken");
                Log.e("OkHttpManager", "重新请求---" + url);
                OkHttpClient client = new OkHttpClient();
    
                Request request = new Request.Builder().url(url).build();
                okhttp3.Call call = client.newCall(request);
                try {
                    Response response = call.execute();
                    TokenEntity data = new Gson().fromJson(response.body().string(), TokenEntity.class);
                    Log.e("OkHttpManager", "重新请求---"+data.resultCode);
                    if (data.resultCode == 0) {
                        if (null != data.data.accessToken && null != data.data.refreshToken) {
                            PsUtils.putString(IeouApplication.getInstance(), "accessToken", data.data.accessToken);
                            PsUtils.putString(IeouApplication.getInstance(), "refreshToken", data.data.refreshToken);
                            PsUtils.putString(IeouApplication.getInstance(), "upToken", data.data.upToken);
                            Log.e("OkHttpManager", data.data.accessToken);
                        }
                    }else {
                        mHandler.post(() -> ToastUtils.showToast("登录已过期,请重新登录..."));
                        JPushInterface.deleteAlias(IeouApplication.getInstance(), 1);
                        AppManager.getInstance().finishAllActivity();
                        MyIntent(LoginActivity.class);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
    
    
                return PsUtils.getString(IeouApplication.getInstance(), "accessToken");
            }
    
            /**
             * 跳转页面
             */
            public void MyIntent(Class clazz) {
                Intent intent = new Intent(IeouApplication.getInstance(), clazz);
                intent.putExtra("fromWhere", getClass().getSimpleName());
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                IeouApplication.getInstance().startActivity(intent);
            }
    
        }
    
        /**
         * log 拦截器
         */
        private static class OKHTTPLogInterceptor implements Interceptor {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request request = chain.request();
                Response response = chain.proceed(chain.request());
                okhttp3.MediaType mediaType = response.body().contentType();
                String content = response.body().string();
    //            Logger.e(mediaType.toString());
                Logger.e(request.toString());
                Logger.init("json");
                Logger.json(content);
    
                if (response.body() != null) {
                    // 打印 body 后原 ResponseBody 会被清空,需要重新设置 body
                    ResponseBody body = ResponseBody.create(mediaType, content);
                    return response.newBuilder().body(body).build();
                } else {
                    return response;
                }
            }
        }
    
        /**
         * 缓存拦截器
         */
        static class HttpCacheInterceptor implements Interceptor {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request request = chain.request();
                if (!NetUtils.isConnected(IeouApplication.getInstance())) {
                    request = request.newBuilder()
                            .cacheControl(CacheControl.FORCE_CACHE)
                            .build();
                }
    
                Response originalResponse = chain.proceed(request);
                if (NetUtils.isConnected(IeouApplication.getInstance())) {
                    // 有网的时候读接口上的 @Headers 里的配置,你可以在这里进行统一的设置
                    String cacheControl = request.cacheControl().toString();
                    return originalResponse.newBuilder()
                            .header("Cache-Control", cacheControl)
                            .removeHeader("Pragma")
                            .build();
                } else {
                    return originalResponse.newBuilder()
                            .header("Cache-Control", "public, only-if-cached, max-stale=2419200")
                            .removeHeader("Pragma")
                            .build();
                }
            }
        }
    }
    
    

    请求接口封装

    public abstract class BaseSubCallback<T> extends Subscriber<T> {
        private static final String TAG = "BaseCallback";
        private static final int CODEOK = 0;
        private static final int INLOGINSOMEWHEREELSE = 30001;
        private static final int BEOVERDUE = 30002;
        private Context mContext;
        private AlertDialog mDialog;
        private CompositeSubscription compositeSubscription = new CompositeSubscription();
    
        public BaseSubCallback(Context mContext) {
            this.mContext = mContext;
        }
    
        protected abstract void onDone(int code, String object, String msg) throws IOException;
    
        /**
         * 显示进度条
         */
        @Override
        public void onStart() {
            if (!NetUtils.isConnected(mContext)) {
                ToastUtils.showToast("亲,你断网了啊!");
                // 一定要调用这个方法才会生效
                onCompleted();
                return;
            }
            showProgressDialog();
    //        onCompleted();
        }
    
        /**
         * 关闭进度条
         */
        @Override
        public void onCompleted() {
            Log.d(TAG, "onCompleted----------------");
            hideProgressDialog();
    
        }
    
        /**
         * 网络请求发生错误的处理
         *
         * @param e
         */
        @Override
        public void onError(Throwable e) {
            e.printStackTrace();
            hideProgressDialog();
            if (!NetUtils.isConnected(mContext)) {
                ToastUtils.showToast("服务器连接失败,请检查网络设置!");
                return;
            }
            ToastUtils.showToast("服务器链接超时");
    
        }
    
        /**
         * @param
         */
        @Override
        public void onNext(T responseBody) {
            Log.d(TAG, "accessToken--" + PsUtils.getString(mContext, "accessToken"));
            ResponseBody body = (ResponseBody) responseBody;
            try {
                String result = new String(body.bytes());
                Log.d("BaseonNext---------", result);
                RequestCode requestCode = new Gson().fromJson(result, RequestCode.class);
                JSONObject jsonObject = new JSONObject(result);
                if (requestCode.getResultCode() == CODEOK) {
    
                    onDone(requestCode.getResultCode(), jsonObject.getString("data"), requestCode.getMessage());
                }
    //            else if (requestCode.getResultCode() == INLOGINSOMEWHEREELSE) {//30001
    //                ToastUtils.showToast("登录已过期,请重新登录...");
    //            }
    //            else if (requestCode.getResultCode() == BEOVERDUE) {//30002
    ////                ToastUtils.showToast("登录已过期,请重新登录...");
    //            }
                else {
                    ToastUtils.showToast(requestCode.getMessage());
                    Log.e("BaseonNext---------", jsonObject.getString("data"));
                }
            } catch (IOException | JSONException e) {
                e.printStackTrace();
            }
    
    
        }
    }
    

    相关文章

      网友评论

        本文标题:Android OkHttp Retrofit Token过期重

        本文链接:https://www.haomeiwen.com/subject/cqhrsxtx.html