android TV端如何读取微信网页版二维码显示生成一张图片
今天講下TV端接二維碼遇到的一些問題,由于是在微信平臺(tái)申請(qǐng)的是以網(wǎng)站那種形式申請(qǐng)的,而不是服務(wù)號(hào)申請(qǐng)的,所以客戶端顯示的二維碼是以網(wǎng)頁的形式展現(xiàn)的,網(wǎng)頁是用WebView加載實(shí)現(xiàn)的,但是我們的界面是這樣的,
當(dāng)然這背景上還有顯示其他文字信息,我就沒在這說明了,為什么這圖片中間要做成透明的呢?由于WebView加載顯示二維碼其實(shí)是一個(gè)網(wǎng)頁,而不是一張圖片,所以當(dāng)時(shí)就想到了這個(gè)方法,當(dāng)時(shí)在做的過程中也遇到很多適配的問題,大部分都解決了,還是有小部分盒子適配確實(shí)不好做,所以這個(gè)版本產(chǎn)品要說改這個(gè)二維碼,當(dāng)時(shí)心想怎么弄,后來想到了一個(gè)辦法,就是先讀取二維碼的連接,當(dāng)然這個(gè)二維碼的連接是來自后臺(tái)給你的,因?yàn)檫@個(gè)要考慮到回調(diào)地址,這個(gè)回調(diào)地址就是你掃描了后微信會(huì)通知自己的服務(wù)器,然后自己請(qǐng)求到服務(wù)器拿當(dāng)前掃描客戶的微信數(shù)據(jù),比如昵稱,頭像,城市等...,第二步是把網(wǎng)頁版顯示二維碼通過IO把它讀出來后,去摘取顯示二維碼的地址,當(dāng)然這個(gè)地址不是以什么.jgp或者.png格式,讀取出來存放在本地,這個(gè)文件以.jgp為后綴名,然后再把這個(gè)圖片讀取出來,這個(gè)時(shí)候webview就可以把它隱藏,這樣就能做到適配,因?yàn)槎S碼顯示的不再是網(wǎng)頁版了而是一張圖片,現(xiàn)在貼部分代碼:
webview相關(guān)設(shè)置:
webview.addJavascriptInterface(new InJavaScriptLocalObj(), "java_obj"); webview.setFocusable(false); webview.setFocusableInTouchMode(false);//讓webview失去焦點(diǎn)防止按下鍵 網(wǎng)頁背景出來 webview.setWebChromeClient(new WebChromeClient() {@Override public void onProgressChanged(WebView view, int newProgress) {super.onProgressChanged(view, newProgress); } }); myWebViewClient mWebViewClient = new myWebViewClient(); webview.setWebViewClient(mWebViewClient); WebSettings webSettings = webview.getSettings(); webSettings.setRenderPriority(WebSettings.RenderPriority.HIGH); webSettings.setJavaScriptEnabled(true);//支持js必須設(shè)置 webSettings.setUseWideViewPort(false); webSettings.setLoadWithOverviewMode(true); webSettings.setSupportZoom(false); webview.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY); //取消滾動(dòng)條白邊效果 webSettings.setBuiltInZoomControls(false); webSettings.setSupportZoom(false);//設(shè)定支持縮放 webSettings.setAppCacheEnabled(true); String appCacheDir = getContext().getDir("cache", Context.MODE_PRIVATE).getPath(); webSettings.setAppCachePath(appCacheDir); webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE); webSettings.setAppCacheMaxSize(1024 * 1024 * 10); webSettings.setAllowFileAccess(true);//暫時(shí)改為false
class myWebViewClient extends WebViewClient {@Override public boolean shouldOverrideUrlLoading(WebView view, String url) {view.loadUrl(url); return true; }@Override public void onPageFinished(WebView view, String url) {super.onPageFinished(view, url); view.loadUrl("javascript:window.java_obj.getSource('<head>'+" +"document.getElementsByTagName('html')[0].innerHTML+'</head>');"); }@Override public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {handler.proceed(); // 接受所有證書 } }
class InJavaScriptLocalObj {@JavascriptInterface public void getSource(String html) {List<String> list = TextUtil.match(html,"img","src"); String htmlStr = list.toString(); String downUrl = Constant.WEIXIN_ZXING_PRE+htmlStr.substring(1,htmlStr.length()-1); down(downUrl); } } 在這里一定要注意一點(diǎn),如果你圖片顯示的二維碼和你webview加載出來的二維碼不一樣的話,肯定是做錯(cuò)了,我之前就遇到了這個(gè)問題,這個(gè)二維碼連接只要你使用了一次就變了,因?yàn)榫褪敲看味际遣灰粯?webview加載算一次,而你自己去讀取也算一次,這就是二次了,所以這個(gè)二維碼不一樣,怎么掃描都失敗,這個(gè)問題怎么解決的呢?也就是說只要讓這個(gè)連接只加載一次就可以,我的解決方案是用webview去加載,上面不是寫了監(jiān)聽么,
@Override public boolean shouldOverrideUrlLoading(WebView view, String url) {view.loadUrl(url); return true; }@Override public void onPageFinished(WebView view, String url) {super.onPageFinished(view, url); view.loadUrl("javascript:window.java_obj.getSource('<head>'+" +"document.getElementsByTagName('html')[0].innerHTML+'</head>');"); } webview.addJavascriptInterface(new InJavaScriptLocalObj(), "java_obj"); 定義類:
class InJavaScriptLocalObj {@JavascriptInterface public void getSource(String html) {List<String> list = TextUtil.match(html,"img","src"); String htmlStr = list.toString(); String downUrl = Constant.WEIXIN_ZXING_PRE+htmlStr.substring(1,htmlStr.length()-1); down(downUrl); } } 這個(gè)getSource方法html回調(diào)參數(shù)就是你網(wǎng)頁的內(nèi)容了,這樣就不用我們自己去加載二維碼連接獲取網(wǎng)頁版內(nèi)容,問題解決,如圖就是微信二維碼連接的html內(nèi)容:
把獲取這個(gè)值是使用了正則表達(dá)式的方式,相關(guān)代碼也在這貼下
/** * 獲取指定HTML標(biāo)簽的指定屬性的值 * @param source 要匹配的源文本 * @param element 標(biāo)簽名稱 * @param attr 標(biāo)簽的屬性名稱 * @return 屬性值列表 */ public static List<String> match(String source, String element, String attr) {List<String> result = new ArrayList<String>(); String reg = "<" + element + "[^<>]*?\\s" + attr + "=['\"]?(.*?)['\"]?(\\s.*?)?>"; Matcher m = Pattern.compile(reg).matcher(source); while (m.find()) {String r = m.group(1); result.add(r); }return result; } 使用這個(gè)獲取的集合其實(shí)就是string,就是上面的scr指向的二維碼圖片地址值了,當(dāng)然了這個(gè)src是相對(duì)路徑,所以還要加上前綴,這個(gè)你只要鼠標(biāo)放在二維碼圖片就提示一個(gè)完整的路徑,然后把前綴拿出來組成一個(gè)圖片地址,下面就是把這組成的圖片地址寫在本地,SD卡或者app目錄下,寫到本地好后就讀取出來,然后顯示出來即可,如果你想這個(gè)時(shí)候已經(jīng)ok的話就完了,你會(huì)發(fā)現(xiàn)打正式的包時(shí)會(huì)發(fā)現(xiàn)二維碼顯示不出來,其實(shí)也就是這個(gè)圖片沒顯示出來,圖片沒顯示出來也就是在讀取圖片到本地出錯(cuò)了,讀取圖片到本地的操作是在使用js讀取網(wǎng)頁html內(nèi)容里面寫的,所以錯(cuò)誤定位在這里,最終是什么問題導(dǎo)致的呢,是由于混淆的時(shí)候要做處理;如下:
#js混淆 -keepclassmembers class 包名.類名$內(nèi)部類名{ <fields>; <methods>; public *; private *; }-keepattributes *Annotation* -keepattributes *JavascriptInterface* 比如我InJavaScriptLocalObj這個(gè)類是上面用到了是定義在A中,也就是說InJavaScriptLocalObj是A的內(nèi)部類,那么混淆就是
包名.A$InJavaScriptLocalObj
到這里整個(gè)工作就完成了,下午忙了一下午就是搞這個(gè)問題,還好問題搞定了,
寫完發(fā)現(xiàn)還是要說明下:
1:webview一直是隱藏的,我們使用webview是用于用戶手機(jī)掃碼的監(jiān)聽
2:在把二維碼圖片寫入到本地然后取出要注意刪除原來的,
3:一定要記得混淆時(shí)候添加上面說的幾行代碼
4:這個(gè)做法的弊端是微信html代碼變化了 客戶端就要跟著維護(hù)
5:網(wǎng)頁版二維碼是過幾分鐘是自動(dòng)刷新的,所以要監(jiān)聽它刷新后重新上面的操作
今天在測(cè)試的時(shí)候發(fā)現(xiàn)在芒果嗨盒子上發(fā)現(xiàn)二維碼顯示不出來,經(jīng)排查是因?yàn)?/span>
class InJavaScriptLocalObj {@JavascriptInterface public void getSource(String html) {List<String> list = TextUtil.match(html,"img","src"); String htmlStr = list.toString(); String downUrl = Constant.WEIXIN_ZXING_PRE+htmlStr.substring(1,htmlStr.length()-1); down(downUrl); } } 這個(gè)方法沒有回調(diào),解決方案:
/** * 解決芒果嗨盒子不顯示二維碼的問題 */ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {webview.evaluateJavascript("enable();", null); } else {webview.loadUrl("javascript:enable();"); }總結(jié)
以上是生活随笔為你收集整理的android TV端如何读取微信网页版二维码显示生成一张图片的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MacBook:如何拆卸或安装内存
- 下一篇: uni-app 二维码扫描识别功能