商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
For commercial use, please contact the author for authorization. For non-commercial use, please indicate the source.
協議(License):署名-非商業性使用-相同方式共享 4.0 國際 (CC BY-NC-SA 4.0)
作者(Author):
鏈接(URL):https://www.35youth.cn/817.html
來源(Source):搬磚少年
近期團隊接到一個新的項目,企業內部的一個掌上超市項目,最初考慮通過公眾號或者小程序來做,后面說是部署在企業內網,就考慮到做網站應用,由於需要通過運營商分配的apn連接企業內網,所以在打開應用之前需要檢測一下網絡,如果是web端的話,那就沒法檢測網絡了,所以考慮使用安卓的 webview 封裝一下H5的應用。
1、配置網絡連接權限
在AndroidManifest.xml文件中加上以下配置信息
<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_PERMITTED
android:usesCleartextTraffic="true"
webview 網絡配置異常
net::ERR_CLEARTEXT_NOT_PERMITTED 配置
2、創建layout文件
使用idea的話,會自動創建MainActivity和對應的layout文件,直接在文件的基礎上修改即可,使用Webview控件,如果需要使用進度條的話,可以將ProgressBar 的配置打開即可。
<?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>
3、修改 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
}
```
配置WebviewClient
//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;
}
```