作為一款“認(rèn)真的”產(chǎn)品,那么就要為用戶的數(shù)據(jù)負(fù)責(zé),就要足夠的了解用戶的行為桐腌,掌握一些可以幫助我們分析用戶行為的數(shù)據(jù)。而項(xiàng)目的后臺苟径,就是將這些數(shù)據(jù)展示給我們的運(yùn)營人員案站,從而給他們的工作提供數(shù)據(jù)支持
沒錯,其實(shí)上面的話并不是什么偉人說的棘街,而是我隨手寫的蟆盐。
但是,了解用戶真的很重要遭殉。
所以石挂,在我司的后臺就有一些基本的用戶數(shù)據(jù),其中就包括用戶使用的設(shè)備平臺险污,型號等等痹愚。
然后,某一天負(fù)責(zé)后臺的通知跟我說:“怎么最近有很多desktop的用戶蛔糯,而且使用的OS還是無法識別的拯腮?”
這的確是個奇怪的現(xiàn)象,但是奇怪歸奇怪蚁飒,問題還是要解決的动壤。我問了一些后臺的同志,是怎么識別設(shè)備平臺的淮逻,答曰:根據(jù)用戶請求中的header中的user-agent來識別的狼电。
解決問題前:確定為什么會出問題
研究一下出問題的user的請求數(shù)據(jù)
發(fā)現(xiàn)原來真的是Android設(shè)備的鍋了
其中user-agent是okhttp蜒灰,這個就是前陣子才換上的一個網(wǎng)絡(luò)請求庫(這個真的好用)。
那么問題就明顯了:因?yàn)槲仪瓣囎幼约悍庋b了Okhttp+retrofit+rxjava,所以自那之后所以經(jīng)過OkHttp的請求中的user-agent就被修改成Okhttp自己的標(biāo)志了肩碟。然后人家后臺的同志都不認(rèn)識你强窖,所以就給標(biāo)上了Other OS。削祈。翅溺。
對于解決方案的思考
既然已經(jīng)發(fā)現(xiàn)了問題所在,那么自然就要想辦法解決問題了髓抑。解決問題的核心無外乎就是對癥下藥
方法一:
讓后臺的同志認(rèn)識一下okhttp咙崎,以后只要遇到okhttp就不管三七二十一,直接當(dāng)做Android OS來對付就行了吨拍。
后臺的同志就有意見了:明明是你的鍋褪猛,為何我來背?
好吧羹饰,好像很有道理伊滋。
方法二:
那就換回原生的網(wǎng)絡(luò)請求庫咯!what队秩?笑旺??這簡直就有點(diǎn)zz了馍资,先不說現(xiàn)在okhttp的優(yōu)越性筒主,單單換回去也是要成本的,更何況當(dāng)初集成okhttp+retrofit+rxjava都已經(jīng)花了一些時間了鸟蟹。
那么這個方法也pass乌妙!
方法三:
那既然是okhttp請求的user-agent的問題,那就換掉它的user-agent咯建钥!
bingo藤韵,這才是正解!=跽搿!
接下來就開始正文了置蜀,如何替換okhttp中的user-agent奈搜?
讓我們擼起袖子開始干吧
問題找到了,解決方案也敲定了盯荤,那么就可以開始開工了馋吗。
first
要替換okhttp請求的user-agent,就要先攔截okhttp的請求秋秤,在請求真正發(fā)出去之前我們先給它弄一下
根據(jù)okhttp的文檔宏粤,我們知道在創(chuàng)建Okhtpp client時是可以添加一個攔截器的:
okHttpClientBuilder.addNetworkInterceptor()脚翘;
因此我們就可以在請求前先拿到request了,如下
okHttpClientBuilder.addNetworkInterceptor(new Interceptor() {
@Override
? ? ? ? ? ? public Responseintercept(Chain chain)throws IOException {
????????????????Request original = chain.request();
? ? ? ? ? ? ? ? Request.Builder builder = original.newBuilder();
//在此修改就可以開始修改user_agent
?????????????????builder.method(original.method(), original.body());
? ? ? ? ? ? ? ? Request request = builder.build();
?????????????????return chain.proceed(request);
? ? ? ? ? ? }
});
second
拿到request的build之后绍哎,就可以準(zhǔn)備動個小手術(shù)了
? ? ? ? ? ? ? ? //修改成默認(rèn)的user_agent
? ? ? ? ? ? ? ? builder.removeHeader("User-Agent").addHeader("User-Agent", getUserAgent()).build();
third
你可能會問getUserAgent()是什么鬼来农?
其實(shí)這只是一個獲取Android默認(rèn)user-agent的函數(shù)罷了,如下
private static StringgetUserAgent() {
String userAgent ="";
? ? if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
try {
userAgent = WebSettings.getDefaultUserAgent(TalkpalApplication.getContext());
? ? ? ? }catch (Exception e) {
userAgent = System.getProperty("http.agent");
? ? ? ? }
}else {
userAgent = System.getProperty("http.agent");
? ? }
StringBuffer sb =new StringBuffer();
? ? for (int i =0, length = userAgent.length(); i < length; i++) {
char c = userAgent.charAt(i);
? ? ? ? if (c <='\u001f' || c >='\u007f') {
sb.append(String.format("\\u%04x", (int) c));
? ? ? ? }else {
sb.append(c);
? ? ? ? }
}
return sb.toString();
}
last
打包崇堰、編譯沃于、測試之后
終于是正常了!
結(jié)束語
其實(shí)在日常的開發(fā)過程中海诲,最好的學(xué)習(xí)方法就是上手去做繁莹。
這只是一個小小的例子,通過研究一個小小的bug特幔,我們更加的了解了okhttp咨演,甚至舉一反三,在日后要對請求做身份識別之類的限制蚯斯,也都可以很快的運(yùn)用上(例如每個用戶都要有自己的token薄风,請求時要在header中加上token來識別身份)。
文筆不行溉跃,得空隨手記錄一下
請輕噴