Retrofit2+OkHttp3如何高效率的切换线上线下环境
来源:互联网 发布:淘宝怎么优化店铺 编辑:程序博客网 时间:2024/05/06 23:13
现在Android开发非常流行使用Retrofit2+OkHttp3的组合做网络请求,在平时开发测试中,会有频繁切换线上线下环境的需求。一般情况下,线上线下环境url地址就是前缀不一样,修改一下前缀,重新编译打包。相当的费时间,特别是,产品,测试,后端,leader随时会丢过来一句:这是线下包,给我打个线上包;这个是线上包给我打个线下包。。。如果你正在全力奋战修改一个bug时,感觉就要崩溃了有木有。
这时就会想,如果不需要重新编译该有多好,在app里面留一个后门,在某个地方连击多少下切换线上线下环境该有多好,当然为了不被用户发现后门,可以限制在debug包里面才有这个后门。
我解决这个问题的核心是拦截器Interceptor,okhttp支持拦截器,在拦截器里面可以添加header,可以打印请求网络的日志等等,总之功能很多。我们就是要在拦截器里面替换掉url的前缀。代码如下:
public class ChangeUrlInterceptor implements Interceptor{private Context context;public ChangeUrlInterceptor(Context context){this.context = context;}@Overridepublic Response intercept(Chain chain) throws IOException {Request request = chain.request();Request.Builder requestBuilder = request.newBuilder();String url = request.url().toString();if(Config.isDebugMode(context)) {//默认是线上环境,如果是线下调试,将url前缀替换成线下的url前缀if (url.contains(Config.UC_REQUEST_PREFIX)) {url = url.replace(Config.UC_REQUEST_PREFIX, Config.DEBUG_UC_REQUEST_PREFIX);}}request = requestBuilder.url(url).build();return chain.proceed(request);}}默认采用线上环境, 也就是Config.UC_REQUEST_PREFIX,拦截器里做一个判断如果是线下环境而且url里也包含线上url前缀,那么将前缀替换成线下环境的前缀Config.DEBUG_UC_REQUEST_PREFIX。
添加拦截器到OKHttp
OkHttpClient.Builder builder = new OkHttpClient.Builder().connectTimeout(20 * 1000, TimeUnit.MILLISECONDS) .readTimeout(20 * 1000, TimeUnit.MILLISECONDS); ChangeUrlInterceptor changeUrlInterceptor = new ChangeUrlInterceptor(context); builder.addInterceptor(changeUrlInterceptor); return builder.build();
再看看请求
@POST(Config.UC_REQUEST_PREFIX + "member/mobilelogin") Observable<UCResponse<UCMobileLoginData>> mobileLogin(@Body String request);因为我项目中采用了Dagger2注入,所以我项目中只用了一个retrofit对象,然后就交给Dagger2了,加上项目中请求有好几种不同的url前缀,所以baseUrl我基本上没用,请求上用的是全量的url地址。而且是用了注解,注解不支持方法,所以我才用拦截器拦截,不然的话可以写个方法获取url前缀,是线下就返回一个线下的url前缀,是线上就返回一个线上的url前缀。所以我使用拦截器来实现是有很多前提条件的,大家如果不受上面所说的限制,可以使用更轻量的解决方案。
回到正题,我们可以再应用的某个地方留一个后门,比方说点击连续点击五下,弹出一个对话框,告诉我们当前是线上还是线下环境,然后是否切换环境。重点是点击切换环境要做什么事情。当然为了规避风险,这个后门可以做到只在debug模式的的时候才有。
exitConfirmDialog.dismiss(); if(isOnline==0){ SharedPreferencesUtils.saveIntData(getActivity(),"isOnline",1); }else if(isOnline==1){ SharedPreferencesUtils.saveIntData(getActivity(),"isOnline",0); } //退出登录 //清除一切跟登录信息相关的缓存 RestartAPPTool.restartAPP(getContext(),1000);先改变一下线上线下环境的状态值,然后退出登录,清除跟登录信息相关的一切缓存,为什么呢,因为切换了环境,再登录相当于是另外一个用户了,缓存里不能再有当前账号相关的东西了。最后一个操作是重启app。
public class RestartAPPTool { public static void restartAPP(Context context, long Delayed){ /**开启一个新的服务,用来重启本APP*/ Intent intent1=new Intent(context,KillSelfService.class); intent1.putExtra("PackageName",context.getPackageName()); intent1.putExtra("Delayed",Delayed); context.startService(intent1); /**杀死整个进程**/ killAllProcess(context); } /***重启整个APP*/ public static void restartAPP(Context context){ restartAPP(context,2000); } public static void killAllProcess(Context context) { String processName = getServiceProcessName(context,NimService.class); if(!TextUtils.isEmpty(processName)){ XLog.e("NimService processName: " + processName); final ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); // ActivityManager getRunningAppProcesses() List<ActivityManager.RunningAppProcessInfo> appProcessList = am .getRunningAppProcesses(); if (appProcessList == null) { return; } for (ActivityManager.RunningAppProcessInfo appProcess : appProcessList) { XLog.e("processName: " + appProcess.processName); if(processName.equals(appProcess.processName)){ android.os.Process.killProcess(appProcess.pid); } } } android.os.Process.killProcess(android.os.Process.myPid()); } private static String getServiceProcessName(Context context, Class<? extends Service> serviceClass) { PackageManager packageManager = context.getPackageManager(); ComponentName component = new ComponentName(context, serviceClass); ServiceInfo serviceInfo; try { serviceInfo = packageManager.getServiceInfo(component, 0); } catch (Throwable ignored) { // Service is disabled. return null; } return serviceInfo.processName; }}
这里就额外有一个杀死网易云信的进程,因为项目中使用了网易云信,然后这个网易云信跟咱们的用户系统是绑定的,我们用户登录了之后还要去网易云信登录。如果不杀死网易云信这个进程,去网易云信登录就会失败。
public class KillSelfService extends Service { /**关闭应用后多久重新启动*/ private static long stopDelayed=2000; private Handler handler; private String PackageName; public KillSelfService() { handler=new Handler(); } @Override public int onStartCommand(final Intent intent, int flags, int startId) { stopDelayed=intent.getLongExtra("Delayed",2000); PackageName=intent.getStringExtra("PackageName"); handler.postDelayed(new Runnable() { @Override public void run() { Intent LaunchIntent = getPackageManager().getLaunchIntentForPackage(PackageName); startActivity(LaunchIntent); KillSelfService.this.stopSelf(); } },stopDelayed); return super.onStartCommand(intent, flags, startId); } @Override public IBinder onBind(Intent intent) { return null; }}
杀死app后一秒后重启应用。
介绍完了,这样以后切换线上线下环境就方便高效多了。
2 0
- Retrofit2+OkHttp3如何高效率的切换线上线下环境
- Retrofit2 + OkHttp3下统一设置Http请求的Headers
- Retrofit2 + OkHttp3下统一设置Http请求的Headers
- 最简单的方法如何从测试环境切换到线上
- Retrofit2.0 + OkHttp3 遇到的坑
- rxjava2 + retrofit2 + okhttp3遇到的问题
- okhttp3 retrofit2 缓存问题
- Rxjava+Retrofit2+Okhttp3
- Retrofit2+okhttp3 使用教程
- 初探Okhttp3+Retrofit2+RXJava
- Retrofit2+OkHttp3+RxJava2
- Retrofit2、okHttp3、RxAndroid使用
- Rxjava2+okhttp3+Retrofit2封装
- Okhttp3+Rxjava+Retrofit2封装
- Retrofit2.0+okhttp3缓存机制以及遇到的问题
- Android Retrofit2&OkHttp3添加统一的请求头Header
- retrofit2+okhttp3+ rxjava 遇到的问题及解决方案
- 基于Retrofit2,okhttp3的数据缓存(cache)技术
- 了解tomcat 3 -- tomcat容器
- IPMI 笔记
- 集合框架 1~5
- 实习生java面试题集及详细答案
- 常见问题处理
- Retrofit2+OkHttp3如何高效率的切换线上线下环境
- PHP之十六个魔术方法详解 (一)
- 函数判断键盘输入数字,限制用户输入
- 数组和向量类
- laravel文件上传
- 微擎读写分离
- 蓝桥杯 抽签
- laravel文件目录树
- 剑指offer41:和为s的两个数字VS和为s的连续正数序列