美文网首页
在WebView中构建Web应用程序(二)

在WebView中构建Web应用程序(二)

作者: 鹿小纯0831 | 来源:发表于2018-08-19 20:07 被阅读41次

    如果要将Web应用程序(或仅仅是网页)作为客户端应用程序的一部分提供,则可以使用WebView执行此操作。 WebView类是AndroidView类的扩展,允许您将Web页面显示为活动布局的一部分。它不包括完全开发的Web浏览器的任何功能,例如导航控件或地址栏。默认情况下,WebView所做的就是显示一个网页。

    本文档向您展示了如何开始使用WebView以及如何执行其他操作,例如处理页面导航以及将网页中的JavaScript绑定到Android应用程序中的客户端代码。

    一、将WebView添加到您的应用程序

    要将WebView添加到应用程序,可以在活动布局中包含<WebView>元素,也可以将整个“活动”窗口设置为onCreate()中的WebView

    在活动布局中添加WebView

    将以下代码添加到活动的布局XML文件中:

    <WebView
        android:id="@+id/webview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
    />
    

    要在WebView中加载网页,请使用loadUrl()。 例如:

    WebView myWebView = (WebView) findViewById(R.id.webview);
    myWebView.loadUrl("http://www.example.com");
    
    在onCreate()中添加WebView

    在活动的onCreate()方法中向您的应用添加WebView

    WebView myWebView = new WebView(activityContext);
    setContentView(myWebView);
    

    然后加载页面:

    myWebView.loadUrl("https://www.example.com");
    

    或者从HTML字符串加载URL

    // Create an unencoded HTML string
    // then convert the unencoded HTML string into bytes, encode
    // it with Base64, and load the data.
    String unencodedHtml =
         "&lt;html&gt;&lt;body&gt;'%23' is the percent code for ‘#‘ &lt;/body&gt;&lt;/html&gt;";
    String encodedHtml = Base64.encodeToString(unencodedHtml.getBytes(),
            Base64.NO_PADDING);
    myWebView.loadData(encodedHtml, "text/html", "base64");
    

    注意:此HTML可以执行的操作有一些限制。 有关编码选项的详细信息,请参阅loadData()loadDataWithBaseURL()

    权限

    在此之前,您的应用必须能够访问Internet。 请在清单文件中请求INTERNET权限:

    <manifest ... >
        <uses-permission android:name="android.permission.INTERNET" />
        ...
    </manifest>
    

    这就是显示网页的基本WebView所需的全部内容。 此外,您可以通过修改以下内容来自定义WebView

    • 使用WebChromeClient启用全屏支持。 当WebView需要更改主机应用程序UI的权限时,也会调用此类,例如创建或关闭窗口以及向用户发送JavaScript对话框。
    • 处理影响内容呈现的事件,例如表单提交上的错误或使用WebViewClient导航。 您还可以使用此子类来拦截URL加载。
    • 通过修改WebSettings启用JavaScript
    • 使用JavaScript访问已注入WebViewAndroid框架对象。

    二、在WebView中使用JavaScript

    如果您计划在WebView中加载的网页使用JavaScript,则必须为WebView启用JavaScript。 启用JavaScript后,您还可以在应用代码和JavaScript代码之间创建接口。

    启用JavaScript

    默认情况下,在WebView中禁用JavaScript

    WebView myWebView = (WebView) findViewById(R.id.webview);
    WebSettings webSettings = myWebView.getSettings();
    webSettings.setJavaScriptEnabled(true);
    

    WebSettings提供对您可能会发现有用的各种其他设置的访问。 例如,如果您正在开发专门为Android应用程序中的WebView设计的Web应用程序,则可以使用setUserAgentString()定义自定义用户代理字符串,然后在网页中查询自定义用户代理以验证,请求您的网页的客户实际上是您的Android应用。

    将JavaScript代码绑定到Android代码

    在开发专为Web应用程序中的WebView设计的Web应用程序时,您可以在JavaScript代码和客户端Android代码之间创建接口。 例如,您的JavaScript代码可以调用Android代码中的方法来显示Dialog,而不是使用JavaScriptalert()函数。

    要绑定JavaScriptAndroid代码之间的新接口,请调用addJavascriptInterface(),向其传递一个类实例以绑定到您的JavaScript以及您可以调用以访问该类的接口名称。
    例如,您可以在Android应用中包含以下类:

    public class WebAppInterface {
        Context mContext;
    
        /** Instantiate the interface and set the context */
        WebAppInterface(Context c) {
            mContext = c;
        }
    
        /** Show a toast from the web page */
        @JavascriptInterface
        public void showToast(String toast) {
            Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show();
        }
    }
    

    警告:如果已将targetSdkVersion设置为17或更高,则必须将@JavascriptInterface注释添加到您希望JavaScript可用的任何方法(该方法也必须是公共的)。 如果您未提供注释,则在Android 4.2或更高版本上运行时,您的网页无法访问该方法。
    在此示例中,WebAppInterface类允许网页使用showToast()方法创建Toast消息。
    您可以使用addJavascriptInterface()将此类绑定到在WebView中运行的JavaScript,并将接口命名为Android。 例如:

    WebView webView = (WebView) findViewById(R.id.webview);
    webView.addJavascriptInterface(new WebAppInterface(this), "Android");
    

    这将在WebView中创建一个名为Android for JavaScript的界面。 此时,您的Web应用程序可以访问WebAppInterface类。 例如,以下是一些HTMLJavaScript,当用户单击按钮时,使用新界面创建Toast消息:

    <input type="button" value="Say hello" onClick="showAndroidToast('Hello Android!')" />
    
    <script type="text/javascript">
        function showAndroidToast(toast) {
            Android.showToast(toast);
        }
    </script>
    

    无需从JavaScript初始化Android界面。 WebView会自动将其提供给您的网页。 因此,只需单击按钮,showAndroidToast()函数就会使用Android界面调用WebAppInterface.showToast()方法。

    注意:绑定到JavaScript的对象在另一个线程中运行,而不是在构造它的线程中运行。

    警告:使用addJavascriptInterface()可以让JavaScript控制您的Android应用。 这可能是一个非常有用的功能或危险的安全问题。 当WebView中的HTML不可信(例如,部分或全部HTML由未知的人或进程提供)时,攻击者可以包含执行客户端代码的HTML,也可能包括攻击者选择的任何代码。 因此,除非您编写了WebView中显示的所有HTMLJavaScript,否则不应使用addJavascriptInterface()。 您也不应允许用户在WebView中导航到不属于您自己的其他网页(而是允许用户的默认浏览器应用程序打开外部链接 - 默认情况下,用户的Web浏览器会打开所有URL链接,因此 只有在按照以下部分所述处理页面导航时才要小心)。

    三、处理页面导航

    当用户从WebView中的网页单击链接时,Android的默认行为是启动处理URL的应用程序。 通常,默认Web浏览器会打开并加载目标URL。 但是,您可以为WebView覆盖此行为,以便在WebView中打开链接。 然后,您可以允许用户在WebView维护的网页历史记录中前后导航。

    注意:出于安全考虑,系统的浏览器应用程序不会与您的应用共享其应用程序数据。

    要打开用户单击的链接,请使用setWebViewClient()WebView提供WebViewClient。 例如:

    WebView myWebView =  (WebView) findViewById(R.id.webview); 
    myWebView.setWebViewClient(MyWebViewClient);
    

    现在,用户在WebView中单击加载的所有链接。

    如果您想要更好地控制单击链接的加载位置,请创建自己的WebViewClient来覆盖shouldOverrideUrlLoading()方法。 例如:

    private  class  MyWebViewClient  extends  WebViewClient  {  
        @Override  
        public  boolean shouldOverrideUrlLoading( WebView view,  String url)  {  
            if  (Uri.parse(url).getHost().equals("https://www.example.com"))  {  
            // This is my website, so do not override; let my WebView load the page  
            return  false;
        } 
        // Otherwise, the link is not for a page on my site, so launch another Activity         that handles URLs 
        Intent intent =  new  Intent(Intent.ACTION_VIEW,  Uri.parse(url));   
        startActivity(intent); 
        return  true;  
        } 
    }
    

    然后为WebView创建这个新WebViewClient的实例:

    WebView myWebView =  (WebView) findViewById(R.id.webview); 
    myWebView.setWebViewClient(new  MyWebViewClient());
    

    现在,当用户单击链接时,系统调用shouldOverrideUrlLoading(),它会检查URL主机是否与特定域匹配(如上所述)。 如果它匹配,则该方法返回false以便不覆盖URL加载(它允许WebView像往常一样加载URL)。 如果URL主机不匹配,则会创建一个Intent以启动处理URL的默认活动(解析为用户的默认Web浏览器)。

    浏览网页历史记录

    WebView覆盖URL加载时,它会自动累积访问过的网页的历史记录。 您可以使用goBack()goForward()在历史记录中前后导航。

    例如,以下是您的Activity如何使用设备后退按钮向后导航:

    @Override  
    public  boolean  onKeyDown(int keyCode,  KeyEvent event)  {  
        // Check if the key event was the Back button and if there's history  
        if  ((keyCode ==  KeyEvent.KEYCODE_BACK)  && myWebView.canGoBack())  { 
            myWebView.goBack(); 
            return  true;  
        }  
        // If it wasn't the Back key or there's no web page history, bubble up to the default  
        // system behavior (probably exit the activity)  
        return  super.onKeyDown(keyCode, event);  
        }  
    }
    
    

    如果实际存在用户要访问的网页历史记录,则canGoBack()方法返回true。 同样,您可以使用canGoForward()来检查是否存在转发历史记录。 如果您不执行此检查,那么一旦用户到达历史记录的末尾,goBack()goForward()就不会执行任何操作。

    处理设备配置更改

    在运行时期间,当设备的配置发生更改(例如,用户旋转设备或关闭输入法编辑器(IME)时)会发生活动状态更改。 这些更改将导致销毁WebView对象的活动并创建新活动,这也会创建一个新的WebView对象,该对象将加载销毁对象的URL。 要修改活动的默认行为,您可以更改其在清单中处理方向更改的方式。

    四、管理窗口

    默认情况下,将忽略打开新窗口的请求。 无论是通过JavaScript还是通过链接中的target属性打开它都是如此。 您可以自定义WebChromeClient以提供打开多个窗口的行为。

    警告:为了使您的应用更安全,最好防止弹出窗口和新窗口打开。 实现此行为的最安全方法是将“true”传递给setSupportMultipleWindows(),但不覆盖setSupportMultipleWindows()依赖的onCreateWindow()方法。 但请记住,此逻辑还会阻止任何在其链接中使用target =“_ blank”的页面加载。

    相关文章

      网友评论

          本文标题:在WebView中构建Web应用程序(二)

          本文链接:https://www.haomeiwen.com/subject/dgrzbftx.html