近期團隊接到一個新的項目,企業內部的一個掌上超市項目,最初考慮經過公衆號或者小程序來作,後面說是部署在企業內網,就考慮到作網站應用,因爲須要經過運營商分配的apn鏈接企業內網,因此在打開應用以前須要檢測一下網絡,若是是web端的話,那就無法檢測網絡了,因此考慮使用安卓的 webview 封裝一下H5的應用。
一、配置網絡鏈接權限html
<uses-permission android:name="android.permission.INTERNET"/>
注: 從Android 9.0(API級別28)開始,默認狀況下禁用明文支持。所以http的url均沒法在webview中加載 ,因此只配置以上信息可能會致使net::ERR_CLEARTEXT_NOT_PERMITTED報錯,還須要在配置文件的 application中加入下面的配置。參照文章: net::ERR_CLEARTEXT_NOT_PERMITTEDandroid
android:usesCleartextTraffic="true"
webview 網絡配置異常
net::ERR_CLEARTEXT_NOT_PERMITTED 配置
二、建立layout文件
使用idea的話,會自動建立MainActivity和對應的layout文件,直接在文件的基礎上修改便可,使用Webview控件,若是須要使用進度條的話,能夠將ProgressBar 的配置打開便可。web
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.ctjsoft.jxf.shop.MainActivity"> <WebView android:id="@+id/webview" android:layout_width="match_parent" android:layout_height="match_parent"/> <!--<ProgressBar android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/progressbar" style="@android:style/Widget.ProgressBar.Horizontal" android:max="100" android:progress="0" android:visibility="gone"/>--> </androidx.constraintlayout.widget.ConstraintLayout>
三、修改 MainActivity 文件
重寫onCreate方法:小程序
protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //progressBar = (ProgressBar) findViewById(R.id.progressbar);//進度條 webView = (WebView) findViewById(R.id.webview); webView.getSettings().setAllowUniversalAccessFromFileURLs(true); webView.getSettings().setAllowFileAccessFromFileURLs(true); // webview的設置中添加以下代碼 try { if (Build.VERSION.SDK_INT >= 16) { Class<?> clazz = webView.getSettings().getClass(); Method method = clazz.getMethod("setAllowUniversalAccessFromFileURLs", boolean.class); if (method != null) { method.invoke(webView.getSettings(), true); } } } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } //webView.loadUrl("http://172.17.1.176:8082/");//加載url webView.loadUrl(API); //使用webview顯示html代碼 // webView.loadDataWithBaseURL(null,"<html><head><title> 歡迎您 </title></head>" + // "<body><h2>使用webview顯示 html代碼</h2></body></html>", "text/html" , "utf-8", null); webView.addJavascriptInterface(this, "android");//添加js監聽 這樣html就能調用客戶端 webView.setWebChromeClient(webChromeClient); webView.setWebViewClient(webViewClient); WebSettings webSettings = webView.getSettings(); /** * LOAD_CACHE_ONLY: 不使用網絡,只讀取本地緩存數據 * LOAD_DEFAULT: (默認)根據cache-control決定是否從網絡上取數據。 * LOAD_NO_CACHE: 不使用緩存,只從網絡獲取數據. * LOAD_CACHE_ELSE_NETWORK,只要本地有,不管是否過時,或者no-cache,都使用緩存中的數據。 */ webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);//不使用緩存,只從網絡獲取數據. webView.getSettings().setTextZoom(100); webView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);//設置js能夠直接打開窗口,如window.open(),默認爲false webView.getSettings().setJavaScriptEnabled(true);//是否容許執行js,默認爲false。設置true時,會提醒可能形成XSS漏洞 webView.getSettings().setSupportZoom(true);//是否能夠縮放,默認 webView.getSettings().setBuiltInZoomControls(true);//是否顯示縮放按鈕,默認false webView.getSettings().setUseWideViewPort(true);//設置此屬性,可任意比例縮放。大視圖模式 webView.getSettings().setLoadWithOverviewMode(true);//和setUseWideViewPort(true)一塊兒解決網頁自適應問題 webView.getSettings().setAppCacheEnabled(true);//是否使用緩存 webView.getSettings().setDomStorageEnabled(true);//DOM Storage }
配置WebviewClientapi
//WebViewClient主要幫助WebView處理各類通知、請求事件 private WebViewClient webViewClient = new WebViewClient() { @Override public void onPageFinished(WebView view, String url) {//頁面加載完成 //progressBar.setVisibility(View.GONE); } public void onPageStarted(WebView view, String url, Bitmap favicon) {//頁面開始加載 //progressBar.setVisibility(View.VISIBLE); } @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) @Override public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { Log.i("ansen", "攔截url:" + request.getUrl()); return super.shouldOverrideUrlLoading(view, request); } }; //WebChromeClient主要輔助WebView處理Javascript的對話框、網站圖標、網站title、加載進度等 private WebChromeClient webChromeClient = new WebChromeClient() { //不支持js的alert彈窗,須要本身監聽而後經過dialog彈窗 public boolean onJsAlert(WebView webView, String url, String message, JsResult result) { AlertDialog.Builder localBuilder = new AlertDialog.Builder(webView.getContext()); localBuilder.setMessage(message).setPositiveButton("肯定", null); localBuilder.setCancelable(false); localBuilder.create().show(); //注意: //必需要這一句代碼:result.confirm()表示: //處理結果爲肯定狀態同時喚醒WebCore線程 //不然不能繼續點擊按鈕 result.confirm(); return true; } //獲取網頁標題 @Override public void onReceivedTitle(WebView view, String title) { super.onReceivedTitle(view, title); Log.i("ansen", "網頁標題:" + title); } //加載進度回調 @Override public void onProgressChanged(WebView view, int newProgress) { // progressBar.setProgress(newProgress); } }; @Override public boolean onKeyDown(int keyCode, KeyEvent event) { Log.i("ansen", "是否有上一個頁面:" + webView.canGoBack()); if (webView.canGoBack() && keyCode == KeyEvent.KEYCODE_BACK) {//點擊返回按鈕的時候判斷有沒有上一頁 webView.goBack(); // goBack()表示返回webView的上一頁面 return true; } return super.onKeyDown(keyCode, event); } /** * JS調用android的方法 * * @param str * @return */ @JavascriptInterface //仍然必不可少 public void getClient(String str) { Log.i("ansen", "html調用客戶端:" + str); } @Override protected void onDestroy() { super.onDestroy(); //釋放資源 webView.destroy(); webView = null; }