Android?WebView基礎(chǔ)舉例詳解
一、簡介
WebView是一個(gè)基于webkit引擎、展現(xiàn)web頁面的控件。Android的Webview在低版本和高版本采用了不同的webkit版本內(nèi)核,4.4后直接使用了Chrome。
二、重要類
以WebView類為基礎(chǔ),WebSettings、WebViewClient、WebChromeClient為輔助共同完成安卓段加載網(wǎng)頁的操作。
1、WebView
//1、加載網(wǎng)頁相關(guān) //直接加載服務(wù)器網(wǎng)頁 my_web_view.loadUrl("https://www.baidu.com") //直接加載本地網(wǎng)頁file:///android_asset/為固定寫法) my_web_view.loadUrl("file:///android_asset/1.html") // 緩存歷史清理 //Clears the resource cache. Note that the cache is per-application, // so this will clear the cache for all WebViews used. my_web_view.clearCache(true) // 清空歷史(本webView瀏覽的) my_web_view.clearHistory() // 結(jié)合工具類 my_web_view.webViewClient = object : WebViewClient() // 設(shè)置webViewClient my_web_view.webChromeClient = object : WebChromeClient()// 設(shè)置WebChromeClient /** * 返回鍵處理,網(wǎng)頁中可返回上一頁,不處理返回鍵直接退出App * */ override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { //when user press back code and canGoBack if (keyCode == KeyEvent.KEYCODE_BACK && my_web_view.canGoBack()) { my_web_view.goBack() return true } return super.onKeyDown(keyCode, event) }
2、WebSettings
/** * WebSettings類:對webView 進(jìn)行配置管理 * */ @SuppressLint("SetJavaScriptEnabled", "ObsoleteSdkInt") private fun webViewSettings() { val webSettings = my_web_view.settings // js交互控制 //支持js交互,動(dòng)畫等操作會造成cpu、電量消耗可在activity、 fragment的onResume、onStop進(jìn)行開關(guān)控制 webSettings.javaScriptEnabled = true // 適配 webSettings.useWideViewPort = true//自適應(yīng)屏幕->自動(dòng)將圖片調(diào)整到自適應(yīng)webView 大小 webSettings.loadWithOverviewMode = true//自適應(yīng)屏幕->縮放到屏幕大小 //縮放 webSettings.setSupportZoom(true)//支持縮放,默認(rèn)為true。 webSettings.builtInZoomControls = true//設(shè)置是否展示內(nèi)置的縮放控件,默認(rèn)為false webSettings.displayZoomControls = true//顯示原生的縮放控件 //其他 webSettings.allowFileAccess = true // 可訪問文件 webSettings.javaScriptCanOpenWindowsAutomatically = true // 支持js 自動(dòng)打開新窗口 webSettings.loadsImagesAutomatically = true // 支持自動(dòng)加載圖片 webSettings.defaultTextEncodingName = "UTF-8" // 默認(rèn)值也是UTF-8 //緩存控制 webSettings.domStorageEnabled = true // 開啟dom緩存功能 webSettings.databaseEnabled = true // 開啟數(shù)據(jù)庫緩存功能 webSettings.setAppCacheEnabled(true)// 開啟application 緩存功能 webSettings.cacheMode = WebSettings.LOAD_CACHE_ELSE_NETWORK //設(shè)置緩存模式 (LOAD_CACHE_ELSE_NETWORK,有緩存時(shí)加載緩存,即使緩存過期,沒有時(shí)從網(wǎng)絡(luò)加載) webSettings.setAppCachePath("") // 設(shè)置app緩存目錄,api已棄用。 // 5.1以上默認(rèn)禁止了https和http混用,開啟如下 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) { webSettings.mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW } }
3、WebViewClient
協(xié)助WebView工作,有一些列回調(diào)方法,用于處理各種通知 & 請求事件等。
my_web_view.webViewClient = object : WebViewClient() { //加載url、返回false 代表使用webView 加載url 不使用系統(tǒng)瀏覽器。 override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean { // 如下loadUrl,return true 這種也代表不使用系統(tǒng)瀏覽器。但是官方建議直接 return false // view?.loadUrl("https://www.baidu.com") // return true return false// 直接return false即可 } // 頁面加載時(shí)回調(diào) override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) { super.onPageStarted(view, url, favicon) } // 頁面加載完成時(shí)回調(diào) override fun onPageFinished(view: WebView?, url: String?) { super.onPageFinished(view, url) } // 加載頁面資源時(shí)調(diào)用(如頁面上有好多圖片,沒加載一張就會回調(diào)一次) override fun onLoadResource(view: WebView?, url: String?) { super.onLoadResource(view, url) } // 加載頁面時(shí)服務(wù)器出現(xiàn)錯(cuò)誤(例如404) override fun onReceivedError(view: WebView?, request: WebResourceRequest?, error: WebResourceError?) { super.onReceivedError(view, request, error) // todo 展示自定義html頁面,提示錯(cuò)誤。 } // 處理https請求 override fun onReceivedSslError(view: WebView?, handler: SslErrorHandler?, error: SslError?) { // 不要使用super,否則有些手機(jī)訪問不了,因?yàn)榘艘粭l handler.cancel() // super.onReceivedSslError(view, handler, error); // 接受所有網(wǎng)站的證書,忽略SSL錯(cuò)誤,執(zhí)行訪問網(wǎng)頁。這種方式在發(fā)生ssl不會影響網(wǎng)頁加載。 // 但是google play 認(rèn)為這是不安全的操作。會給你警告。 handler?.proceed() // handler?.cancel() // 發(fā)生ssl時(shí)掛起連接表現(xiàn)為白屏,默認(rèn)方式。 } }
4、WebChromeClient
/** * WebChromeClient類:輔助webView 處理js dialog、網(wǎng)站icon、網(wǎng)站title。 * js的各種dialog事件觸發(fā)時(shí)可由webChromeClient的響應(yīng)方法回調(diào)到。 * */ private fun webChromeClient() { my_web_view.webChromeClient = object : WebChromeClient() { // 獲得網(wǎng)頁進(jìn)度時(shí)回調(diào) override fun onProgressChanged(view: WebView?, newProgress: Int) { super.onProgressChanged(view, newProgress) } // 獲取網(wǎng)頁的標(biāo)題時(shí)回調(diào) override fun onReceivedTitle(view: WebView?, title: String?) { super.onReceivedTitle(view, title) } // 是否由客戶端處理js Alert 事件,true 代表客戶端處理,false 代表客戶端不處理。 // 一般客戶端處理時(shí)客戶端 展示對話框讓用戶進(jìn)行選擇 override fun onJsAlert(view: WebView?, url: String?, message: String?, result: JsResult?): Boolean { AlertDialog.Builder(mContext) .setTitle("Title") .setMessage(message) .setPositiveButton("確定") { dialog, which -> result?.confirm() }.setCancelable(false) .show() return true } // js Confirm 對話框攔截,true代表點(diǎn)擊確定,false 代表點(diǎn)擊取消。 override fun onJsConfirm(view: WebView?, url: String?, message: String?, result: JsResult?): Boolean { return super.onJsConfirm(view, url, message, result) } // 輸入框攔截,true 代表返回輸入框的值,false 代表返回null override fun onJsPrompt( view: WebView?, url: String?, message: String?, defaultValue: String?, result: JsPromptResult? ): Boolean { return super.onJsPrompt(view, url, message, defaultValue, result) } } }
三、Android 調(diào)用 JS 代碼
方式
- webView的loadUrl(" javascript:js方法()")
- webView的evaluateJavascript()
<html> <head> <meta charset="UTF-8"> <title>SunnyDay</title> <!--內(nèi)部引入法--> <script> function showAlertDialog(result){ alert("i am js alert dialog,i am js method!"+result) return "i am js method!" } </script> </head> <body> <h3>i am a simple html page</h3> </body> </html>>
如上準(zhǔn)備個(gè)1.html文件
1、webView#loadUrl 加載原理及其代碼
借助webChromeClient 的各種回調(diào)處理。一般為js的各種dialog 方法觸發(fā)時(shí)被安卓webViewClient的各種回調(diào)監(jiān)聽方法攔截消費(fèi)。
webSettings = web_view.settings webSettings.javaScriptEnabled = true//允許啟用js功能 webSettings.javaScriptCanOpenWindowsAutomatically = true // 允許js彈窗 // 加載Assets下html文件(這時(shí)js代碼也就載入了) //加載assets文件夾下的html文件時(shí)使用固定格式語法即可:file:///android_asset/文件名.html web_view.loadUrl("file:///android_asset/1.html") web_view.webViewClient = object : WebViewClient(){} callByLoadUrl() //webView只是載體,內(nèi)容的渲染需要使用webViewChromeClient類去實(shí)現(xiàn),所以在這里寫回調(diào)處理。 web_view.webChromeClient = object : WebChromeClient() { // 此方法可回調(diào)到alert警告框的信息。 override fun onJsAlert(view: WebView?, url: String?, message: String?, result: JsResult?): Boolean { val build = AlertDialog.Builder(mContext) .setTitle("Js showAlertDialog Method") .setMessage(message) .setPositiveButton("確定") { dialog, which -> result?.confirm() }.setCancelable(false) build.create().show() return true } } /** * 方式1:webView的loadUrl() * */ private fun callByLoadUrl() { // 點(diǎn)擊安卓按鈕加載js方法 btn_call_js_method.setOnClickListener { // 調(diào)用js時(shí)要保證網(wǎng)頁加載完成,否則js代碼調(diào)用失敗。因?yàn)閔tml中也是頁面加載完成才響應(yīng)的js。 web_view.loadUrl("javascript:showAlertDialog(\"result\")") } }
2、webView#evaluateJavascript
webSettings = web_view.settings webSettings.javaScriptEnabled = true//允許啟用js功能 webSettings.javaScriptCanOpenWindowsAutomatically = true // 允許js彈窗 // 加載Assets下html文件(這時(shí)js代碼也就載入了) web_view.loadUrl("file:///android_asset/1.html")//加載assets文件夾下的html文件時(shí)使用固定格式語 法即可:file:///android_asset/文件名.html web_view.webViewClient = object : WebViewClient(){} callByEvaluateJavascript() /** *方式2:webView的evaluateJavascript * js 方法無返回值時(shí)it為 null */ private fun callByEvaluateJavascript() { btn_call_js_method.setOnClickListener { web_view.evaluateJavascript("javascript:showAlertDialog()") { Log.d("AndroidCallJsActivity", "" + it)//AndroidCallJsActivity"i am js method!" } } }
3、總結(jié)
/** * Android call js method practice * 兩種方式: * 1、webView的loadUri(" javascript:js方法()") * 這種方式一般調(diào)用的為js的dialog方法,使用安卓的WebChromeClient 對應(yīng)回調(diào)方法進(jìn)行攔截處理。 * 2、webView的evaluateJavascript * 直接調(diào)用js的方法,還可以獲得js方法返回值回調(diào) * js方法結(jié)果回調(diào)為String 類型值 * js方法無返回值,這里回調(diào)為null * * 建議以這種方式,既可快捷獲得返回值,又可通過1中的dialog回調(diào)處理。 * * 小結(jié):Android call js method * 安卓調(diào)用js方法后可以在安卓端獲得結(jié)果回調(diào)處理。 * */
調(diào)用方式 | 優(yōu)點(diǎn) | 缺點(diǎn) | 適用場景 |
---|---|---|---|
loadUrl | 方便簡潔 | 效率低,獲取返回值麻煩 | 不需要獲取返回值時(shí) |
evaluateJavascript | 效率高 | 安卓4.4以上才能使用 | 安卓4.4以上 |
四、Js調(diào)用安卓代碼
方式
- 通過webView的addJavascriptInterface方法
- 通過重寫webViewClient的shouldOverrideUrlLoading方法篩選url調(diào)用
- 通過 WebChromeClient 的dialog 回調(diào)判斷篩選url調(diào)用
<html> <head> <meta charset="UTF-8"> <title>SunnyDay</title> <!--內(nèi)部引入法--> <script> //方式1:對象映射方式 function callAndroid(){ // 調(diào)用安卓的hello方法,由于安卓中添加了對象映射,test.hello()就相當(dāng)于安卓的 //JsInterface().hello() test.hello(" i am js code! "); } //方式2:重寫shouldOverrideUrlLoading 進(jìn)行攔截 function callAndroid2(){ document.location = "js://webview?arg1=111&arg2=222"; } //方式3:WebChromeClient 的 onJsAlert、onJsConfirm、onJsPrompt 方法回調(diào)攔截 JS 對話框 function callAndroid3(){ //1、首先搞個(gè)輸入框,觸發(fā)時(shí)安卓可獲得回調(diào) //2、收到回調(diào)后安卓處理,點(diǎn)擊確定返回輸入框值,點(diǎn)擊取消返回null var result=prompt("js://demo?arg1=111&arg2=222"); alert("demo " + result); } </script> </head> <body> <h3>i am a simple html page</h3> //方式1 <button type="button" id="btn" onclick="callAndroid()">點(diǎn)我即可調(diào)用Android的hello方法</button> //方式2 <button type="button" id="btn2" onclick="callAndroid2()">方式2</button> //方式3 <button type="button" id="button3" onclick="callAndroid3()">方式3</button> </body> </html>>
1、addJavascriptInterface
(1)定義對象映射方法
/** * 1、自定義對象用于對象映射 * 2、自定義方法,映射后供js對象使用 * 3、方法必須加JavascriptInterface注解 */ class JsInterface { @JavascriptInterface fun hello(msg: String) { Log.d("JsCallAndroidActivity", "android method hello is called:$msg") } }
(2)映射
//js調(diào)用安卓方法方式1: webSettings = web_view_th.settings webSettings.javaScriptEnabled = true//允許啟用js功能 webSettings.javaScriptCanOpenWindowsAutomatically = true // 允許js彈窗 web_view_th.loadUrl("file:///android_asset/2.html") // 定義對象映射,把自定義的JsInterface映射給"test",供js對象使用。 web_view_th.addJavascriptInterface(JsInterface(), "test")// 一行代碼十分簡單
2、重寫webViewClient的shouldOverrideUrlLoading方法
webSettings = web_view_th.settings webSettings.javaScriptEnabled = true//允許啟用js功能 webSettings.javaScriptCanOpenWindowsAutomatically = true // 允許js彈窗 web_view_th.loadUrl("file:///android_asset/2.html") web_view_th.webViewClient = object : WebViewClient() { override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean { //view?.url //file:///android_asset/2.html , //注意這里的兩個(gè)url不相同 get的url為 webViewLoad的,request的為動(dòng)態(tài)定義的 val requestUrl = request?.url Log.i("JsCallAndroidActivity", "" + requestUrl) //js://webview?arg1=111&arg2=222 return if (requestUrl.toString() == "js://webview?arg1=111&arg2=222") { // 符合篩選,調(diào)用安卓方法。 printLog() true } else { super.shouldOverrideUrlLoading(view, request) } } } private fun printLog() { Log.i("JsCallAndroidActivity", "android method:print log !") }
3、通過 WebChromeClient 的dialog 回調(diào)判斷篩選url調(diào)用
webSettings = web_view_th.settings webSettings.javaScriptEnabled = true//允許啟用js功能 webSettings.javaScriptCanOpenWindowsAutomatically = true // 允許js彈窗 web_view_th.loadUrl("file:///android_asset/2.html") web_view_th.webChromeClient = object : WebChromeClient() { override fun onJsPrompt( view: WebView?, url: String?, message: String?, defaultValue: String?, result: JsPromptResult? ): Boolean { val uri = Uri.parse(message) if ("js" == uri.scheme) { if ("demo" == uri.authority) { result?.confirm("JS 調(diào)用了 Android 的方法") // 符合篩選,調(diào)用安卓方法。 printLog() } return true } return super.onJsPrompt(view, url, message, defaultValue, result) } }
4、小結(jié)
/** * js call android method practise * 1、webView的addJavascriptInterface(自定義對象,“映射給的自定義字符串對象”) * 這種方式最簡單,自定義對象,內(nèi)部定義一系列方法供js調(diào)用。js拿到映射對象即可調(diào)用安卓自定義的對象方法 * * 2、重寫webViewClient的shouldOverrideUrlLoading方法,篩選請求的url是否為js規(guī)定的url,是規(guī)定的則調(diào)用安卓的相應(yīng)方法。 * * 3、通過 WebChromeClient 的onJsAlert()、onJsConfirm()、onJsPrompt()方法回調(diào)攔截JS對話框alert()、confirm()、prompt(),原理與2一致。 * */
調(diào)用方式 | 優(yōu)點(diǎn) | 缺點(diǎn) | 適用場景 |
---|---|---|---|
WebView.addJavascriptInterface 對象映射 | 方便簡潔 | Android 4.2 一下存在漏洞 | Android 4.2 以上相對簡單的應(yīng)用場景 |
WebViewClient.shouldOverrideUrlLoading 回調(diào)攔截 | 不存在漏洞 | 使用復(fù)雜,需要協(xié)議約束 | 不需要返回值情況下 |
WebChormeClient.onJsAlert / onJsConfirm / onJsPrompt 方法回調(diào)攔截 | 不存在漏洞 | 使用復(fù)雜,需要協(xié)議約束 | 能滿足大多數(shù)場景 |
五、Android 內(nèi)嵌網(wǎng)頁時(shí)登錄狀態(tài)同步方案
1、使用 WebView 和 Cookie 同步
Android 的 WebView 是一種能在應(yīng)用中顯示網(wǎng)頁的組件。WebView 會自動(dòng)處理 Cookies,但為了確保登錄狀態(tài)的同步,可能需要手動(dòng)同步應(yīng)用和 WebView 的 Cookies。
(1) 獲取應(yīng)用中的 Cookie
如果你的應(yīng)用在登錄后保存了 Cookie,可以通過 CookieManager 來獲取這些 Cookie。
(2) 將 Cookie 注入 WebView:
在加載網(wǎng)頁前,將這些 Cookie 注入 WebView 的 CookieManager。
CookieManager cookieManager = CookieManager.getInstance(); cookieManager.setAcceptCookie(true); // 獲取應(yīng)用的 Cookie,假設(shè)名為 "appCookie" String appCookie = "key=value; domain=yourdomain.com"; cookieManager.setCookie("yourdomain.com", appCookie); // 加載網(wǎng)頁 webView.loadUrl("https://yourdomain.com");
(3) 確保同步:
在 WebView 加載新頁面時(shí),確保 Cookie 同步。
webView.setWebViewClient(new WebViewClient() { @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); CookieManager.getInstance().flush(); } });
2、使用 Shared Preferences 和 JavaScript Bridge
這種方法可以通過 JavaScript 與 Android 應(yīng)用交互,保持登錄狀態(tài)同步。
(1)保存登錄狀態(tài):
登錄后,將登錄狀態(tài)(例如 token)保存到 Shared Preferences。
SharedPreferences sharedPref = getSharedPreferences("MyApp", Context.MODE_PRIVATE); SharedPreferences.Editor editor = sharedPref.edit(); editor.putString("token", "your_token"); editor.apply();
(2)設(shè)置 JavaScript 接口:
在 WebView 中設(shè)置 JavaScript 接口,用于獲取登錄狀態(tài)。
webView.addJavascriptInterface(new Object() { @JavascriptInterface public String getToken() { SharedPreferences sharedPref = getSharedPreferences("MyApp", Context.MODE_PRIVATE); return sharedPref.getString("token", ""); } }, "Android");
(3)在網(wǎng)頁中使用:
在網(wǎng)頁的 JavaScript 中調(diào)用這個(gè)接口,獲取登錄狀態(tài)。
function getToken() { return Android.getToken(); } // 在需要時(shí)調(diào)用 getToken(),例如頁面加載完成后 document.addEventListener("DOMContentLoaded", function() { var token = getToken(); if (token) { // 使用 token 做進(jìn)一步處理 } });
3、使用 OAuth 進(jìn)行單點(diǎn)登錄(SSO)
如果你的應(yīng)用和網(wǎng)頁都支持 OAuth,可以使用 OAuth 進(jìn)行單點(diǎn)登錄。
(1)在應(yīng)用中獲取 OAuth Token:
用戶在應(yīng)用中登錄后,獲取 OAuth Token 并保存。
(2)WebView 加載網(wǎng)頁時(shí)附加 Token:
在加載網(wǎng)頁時(shí),將 Token 附加在 URL 或請求頭中。
String url = "https://yourdomain.com?token=" + oauthToken; webView.loadUrl(url); // 或者設(shè)置請求頭 webView.setWebViewClient(new WebViewClient() { @Override public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) { Map<String, String> headers = new HashMap<>(); headers.put("Authorization", "Bearer " + oauthToken); request.setRequestHeaders(headers); return super.shouldInterceptRequest(view, request); } });
4、使用統(tǒng)一的身份認(rèn)證系統(tǒng)
如果你的應(yīng)用和網(wǎng)頁都使用統(tǒng)一的身份認(rèn)證系統(tǒng)(如 Firebase Authentication),可以通過相同的身份認(rèn)證機(jī)制同步登錄狀態(tài)。
(1)應(yīng)用中登錄:
使用統(tǒng)一的身份認(rèn)證系統(tǒng)登錄,并獲取認(rèn)證信息。
(2)WebView 中共享認(rèn)證信息:
通過與身份認(rèn)證系統(tǒng)的集成,在 WebView 中實(shí)現(xiàn)自動(dòng)登錄。
FirebaseAuth mAuth = FirebaseAuth.getInstance(); FirebaseUser currentUser = mAuth.getCurrentUser(); if (currentUser != null) { String idToken = currentUser.getIdToken(false).getResult().getToken(); String url = "https://yourdomain.com?token=" + idToken; webView.loadUrl(url); }
六、WebView相關(guān)優(yōu)化建議
1、給 WebView 加一個(gè)加載進(jìn)度條
為了友好展示,重寫 WebChromeClient 的 onProgressChanged 方法。未加載完成時(shí)展示loading進(jìn)度條
2、提高 HTML 網(wǎng)頁加載速度,等頁面 finsh 在加載圖片
public void load () { if(Build.VERSION.SDK_INT >= 19) { webView.getSettings().setLoadsImagesAutomatically(true); } else { webView.getSettings().setLoadsImagesAutomatically(false); } }
3、onReceivedError 時(shí)加載自定義界面
web的error 頁面比較丑,我們可以在加載失敗時(shí),展示安卓自定義的錯(cuò)誤展示頁。
4、動(dòng)畫、銀屏、視頻 合適加載釋放
動(dòng)畫、銀屏、視頻 加載會造成cpu、電量消耗可在activity、 fragment的onResume、onStop進(jìn)行開關(guān)控制。
七、收獲
1、明文傳輸控制
Android P 阻止加載任何 http 的請求,在清單文件application節(jié)點(diǎn) 添加android:usesCleartextTraffic=“true”
2、Android 5.0 之后 WebView 禁止加載 http 與 https 混合內(nèi)容 。這樣會造成某些資源加載失敗。
if (Build.VERSION.SDK_INT>Build.VERSION_CODES.LOLLIPOP){ webview.getSettings(). setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW); } /* 例如:https://www.aaa.com.cn/a/b/c/d/e/index.html?uid=0011&URL=http://www.bbb.com.cn/1.png 這個(gè)url 1、實(shí)際頁面為:https://www.aaa.com.cn/a/b/c/d/e/index.html 后面追加了一些參數(shù) 2、h5頁面上src標(biāo)簽加載http://www.bbb.com.cn/1.png 此時(shí)你使用webview.loadUrl("https://www.aaa.com.cn/a/b/c/d/e/index.html?uid=0011&URL=http://www.bbb.com.cn/1.png") 就會出現(xiàn)h5 圖片顯示失敗。 解決方案開啟MixedContentMode */
3、硬件加速開啟導(dǎo)致問題
比如不能打開 PDF,播放視頻花屏等等。關(guān)閉硬件加速。
4、重寫webViewClient的shouldOverrideUrlLoading
否則系統(tǒng)不知道你是想用webview打開url 還是使用系統(tǒng)瀏覽器。
5、WebView白屏問題
原因:頁面進(jìn)度不到100%時(shí)顯示的就是白屏,進(jìn)度到100時(shí)開始加載網(wǎng)頁資源。
解決:網(wǎng)上方案較多這里提示一種:進(jìn)度不到100時(shí)展示加載提示。
The end
到此這篇關(guān)于Android WebView基礎(chǔ)的文章就介紹到這了,更多相關(guān)Android WebView基礎(chǔ)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android實(shí)現(xiàn)夜間模式切換功能實(shí)現(xiàn)代碼
現(xiàn)在很多App都有夜間模式,特別是閱讀類的App,夜間模式現(xiàn)在已經(jīng)是閱讀類App的標(biāo)配,本篇文章主要介紹了Android實(shí)現(xiàn)夜間模式功能實(shí)現(xiàn)代碼,有興趣的可以了解一下。2017-03-03Android中ListView結(jié)合CheckBox實(shí)現(xiàn)數(shù)據(jù)批量選擇(全選、反選、全不選)
這篇文章主要介紹了Android編程中ListView結(jié)合CheckBox實(shí)現(xiàn)批量選擇,包括實(shí)現(xiàn)全選、反選、全不選等操作,感興趣的小伙伴們可以參考一下2016-01-01Android 5.1 WebView內(nèi)存泄漏問題及快速解決方法
下面小編就為大家?guī)硪黄狝ndroid 5.1 WebView內(nèi)存泄漏問題及快速解決方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-05-05Android中操作SQLite數(shù)據(jù)庫快速入門教程
這篇文章主要介紹了Android中操作SQLite數(shù)據(jù)庫快速入門教程,本文講解了數(shù)據(jù)庫基礎(chǔ)概念、Android平臺下數(shù)據(jù)庫相關(guān)類、創(chuàng)建數(shù)據(jù)庫、向表格中添加數(shù)據(jù)、從表格中查詢記錄等內(nèi)容,需要的朋友可以參考下2015-03-03Android圖表庫HelloCharts的實(shí)例詳解
這篇文章主要介紹了Android中的圖標(biāo)庫HelloCharts的一些簡單使用實(shí)例,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)有一定的參考價(jià)值,需要的可以參考一下2022-01-01Android Studio編寫AIDL文件后如何實(shí)現(xiàn)自動(dòng)編譯生成
這篇文章主要介紹了Android Studio編寫AIDL文件后如何實(shí)現(xiàn)自動(dòng)編譯生成,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-03-03詳解Android應(yīng)用main函數(shù)的調(diào)用
Android常識,App主線程初始化了Looper,調(diào)用prepare的地方是ActivityThread.main函數(shù)。問題來了,App的main函數(shù)在哪兒調(diào)用,下面我們來一起學(xué)習(xí)一下吧2019-06-06Android EditText實(shí)現(xiàn)分割輸入內(nèi)容
這篇文章主要為大家詳細(xì)介紹了Android EditText實(shí)現(xiàn)分割輸入內(nèi)容的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-04-04