Android開發:通過 webview 將網頁打包成安卓應用

来源:https://www.cnblogs.com/35youth/archive/2020/03/25/12565001.html
-Advertisement-
Play Games

商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。 For commercial use, please contact the author for authorization. For non commercial use, please indicate the source. 協議(Lice ...


商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。

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;
}
	```

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 上一篇介紹了邏輯備份工具mysqldump,本文將通過應用更為普遍的物理備份工具xtrabackup來演示數據備份及恢復的第二篇內容。 1. xtrabackup 工具的安裝 1.1 安裝依賴包 /* xtrabackup 的使用需要安裝相關的依賴包 否則使用過程中會報相關錯誤 */ yum ins ...
  • MySQL 字元串截取函數:left(), right(), substring(), substring_index()。還有 mid(), substr()。 其中,mid(), substr() 等價於 substring() 函數,substring() 的功能非常強大和靈活。 1. 字元串 ...
  • MySQL資料庫 前言: 隨著時代的進步,大數據也逐漸走進大家的生活中,成為大家密不可分的一樣東西。因此,作為程式員的我們,要學習並會使用資料庫。 什麼是資料庫? 資料庫就是一個文件系統,通過標準的SQL語句獲取數據 MySQL資料庫又是什麼呢? MySQL資料庫是一個關係型資料庫。 (關係型資料庫 ...
  • 7.關於pyinstaller打包生成exe的方法 安裝pip 、 pyinstaller 在pycharm 的Terminal視窗中輸入 註:輸入參數的含義 F 表示生成單個可執行文件 w 表示去掉控制台視窗,這在GUI界面時非常有用。不過如果是命令行程式的話那就把這個選項刪除吧! p 表示你自己 ...
  • 經常提到資料庫的事務,那你知道資料庫還有事務隔離的說法嗎,事務隔離還有隔離級別,那什麼是事務隔離,隔離級別又是什麼呢?本文就幫大家梳理一下。 MySQL 事務 本文所說的 MySQL 事務都是指在 InnoDB 引擎下,MyISAM 引擎是不支持事務的。 資料庫事務指的是一組數據操作,事務內的操作要 ...
  • 不適配深色模式 直接在info新加一個欄位 設置值為 適配深色模式 適配深色模式info裡面的那個欄位就不用添加了 但是需要在每個 裡面增加下麵的這個方法 在這個方法里去判斷和更改當前界面所有元素的顏色 我專門做了一個單例,把應用程式中的所有顏色都單獨保存起來 還有兩個方法,分別是把所有的顏色改成與 ...
  • 1.win10安裝ubuntu 18.04或Ubuntu發行版 搜索:Microsoft Store >搜索:Ubuntu //下載即可 >下載完之後安裝,啟動即可. 搜索:ubuntu啟動即可. 註意:源最好不要替換 2.安裝所需的庫 安裝emacs的cscope + autocomplete需要 ...
  • 本文旨在成為iOS動畫的入門讀物,目的是詳盡地介紹不同的實現方法。 鑒於該主題的廣泛性,我們將在相當高的層次上簡潔地涵蓋每個部分。這樣做的目的是通過一組選項來教育讀者將動畫添加到他/她的iOS應用程式中。 在我們開始討論與IOS相關的主題之前,讓我們先簡單地看一看動畫的速度。 60 Fps動畫 通常 ...
一周排行
    -Advertisement-
    Play Games
  • Dapr Outbox 是1.12中的功能。 本文只介紹Dapr Outbox 執行流程,Dapr Outbox基本用法請閱讀官方文檔 。本文中appID=order-processor,topic=orders 本文前提知識:熟悉Dapr狀態管理、Dapr發佈訂閱和Outbox 模式。 Outbo ...
  • 引言 在前幾章我們深度講解了單元測試和集成測試的基礎知識,這一章我們來講解一下代碼覆蓋率,代碼覆蓋率是單元測試運行的度量值,覆蓋率通常以百分比表示,用於衡量代碼被測試覆蓋的程度,幫助開發人員評估測試用例的質量和代碼的健壯性。常見的覆蓋率包括語句覆蓋率(Line Coverage)、分支覆蓋率(Bra ...
  • 前言 本文介紹瞭如何使用S7.NET庫實現對西門子PLC DB塊數據的讀寫,記錄了使用電腦模擬,模擬PLC,自至完成測試的詳細流程,並重點介紹了在這個過程中的易錯點,供參考。 用到的軟體: 1.Windows環境下鏈路層網路訪問的行業標準工具(WinPcap_4_1_3.exe)下載鏈接:http ...
  • 從依賴倒置原則(Dependency Inversion Principle, DIP)到控制反轉(Inversion of Control, IoC)再到依賴註入(Dependency Injection, DI)的演進過程,我們可以理解為一種逐步抽象和解耦的設計思想。這種思想在C#等面向對象的編 ...
  • 關於Python中的私有屬性和私有方法 Python對於類的成員沒有嚴格的訪問控制限制,這與其他面相對對象語言有區別。關於私有屬性和私有方法,有如下要點: 1、通常我們約定,兩個下劃線開頭的屬性是私有的(private)。其他為公共的(public); 2、類內部可以訪問私有屬性(方法); 3、類外 ...
  • C++ 訪問說明符 訪問說明符是 C++ 中控制類成員(屬性和方法)可訪問性的關鍵字。它們用於封裝類數據並保護其免受意外修改或濫用。 三種訪問說明符: public:允許從類外部的任何地方訪問成員。 private:僅允許在類內部訪問成員。 protected:允許在類內部及其派生類中訪問成員。 示 ...
  • 寫這個隨筆說一下C++的static_cast和dynamic_cast用在子類與父類的指針轉換時的一些事宜。首先,【static_cast,dynamic_cast】【父類指針,子類指針】,兩兩一組,共有4種組合:用 static_cast 父類轉子類、用 static_cast 子類轉父類、使用 ...
  • /******************************************************************************************************** * * * 設計雙向鏈表的介面 * * * * Copyright (c) 2023-2 ...
  • 相信接觸過spring做開發的小伙伴們一定使用過@ComponentScan註解 @ComponentScan("com.wangm.lifecycle") public class AppConfig { } @ComponentScan指定basePackage,將包下的類按照一定規則註冊成Be ...
  • 操作系統 :CentOS 7.6_x64 opensips版本: 2.4.9 python版本:2.7.5 python作為腳本語言,使用起來很方便,查了下opensips的文檔,支持使用python腳本寫邏輯代碼。今天整理下CentOS7環境下opensips2.4.9的python模塊筆記及使用 ...