面向 Web 开发者的 WebView 应用

发布时间:2014 年 2 月 28 日

了解如何创建新的 Android 项目、添加 WebView、加载远程网址以及加载本地 HTML 网页。

本教程假定您是一位开发者,对 Android 开发环境只有有限的了解或没有任何了解,但对 Kotlin 有一定了解。如果您已经熟悉 Android 编程,建议您阅读 Android 开发者网站上的在 WebView 中构建 Web 应用

安装 Android Studio

本教程使用 Android Studio,这是 Android 的设计和构建 IDE。

创建新的 Android 项目

Android Studio 安装完成后,系统会启动设置向导。

要创建新项目,请执行以下操作:

  1. 点击新建项目
  2. 点击 Empty Activity 模板,将其选为项目的模板。 模板可用来创建项目结构以及在 Android Studio 中构建项目所需的文件。
  3. 点击 Next 以打开“New Project”对话框。
  4. 配置项目。输入应用名称、软件包名称和目标 SDK。然后点击下一步
  5. Minimum required SDK 设置为 API 24: Android 7.0 (Nougat)。
  6. 点击完成

Android Studio 会打开新项目。

项目结构

Android Studio 创建的初始项目包含用于设置应用的样板代码。一些常见的导入文件夹包括:

  • src/main/java. Android Java 源代码。
  • src/main/res。应用使用的资源。
  • src/main/res/drawable。应用使用的图片资源。
  • src/main/res/xml。用于定义界面组件结构的 XML 布局文件。
  • src/main/res/values。您可能不想在应用中对其进行硬编码的维度、字符串和其他值。
  • src/main/AndroidManifest.xml。清单文件定义了应用中包含的内容,例如 activity、权限和主题。

添加 WebView

接下来,向主 activity 的布局添加 WebView

  1. 打开 src/main/res/xml 目录中的 activity_main.xml 文件(如果尚未打开)。(您可能还会看到一个 fragment_main.xml 文件。您可以忽略此问题,因为本教程不需要执行此操作。)

    选择 activity_main.xml 编辑器底部的 Text 标签页,查看 XML 标记。

    此文件用于定义主要 activity 的布局,Preview 窗格会显示该 activity 的预览。空白 activity 布局不包含任何子项。您需要添加 WebView。

  2. 在“XML”窗格中,从 FrameLayout 元素的末尾移除自闭斜线,然后添加 <WebView> 元素和新的结束标记,如下所示:

    <FrameLayout xmlns:android="https://schemas.android.com/apk/res/android"
        xmlns:tools="https://schemas.android.com/tools"
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
        tools:ignore="MergeRootFrame">
    
        <WebView
          android:id="@+id/activity_main_webview"
          android:layout_width="match_parent"
          android:layout_height="match_parent" />
    </FrameLayout>
    
  3. 如需使用 WebView,您需要在 activity 中对其进行引用。打开主 activity 的 Java 源文件 MainActivity.java(位于 src/main/java/<PackageName> 目录中)。

    添加粗体显示的代码行。

    public class MainActivity extends Activity {
    
        private WebView mWebView;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            mWebView = (WebView) findViewById(R.id.activity_main_webview);
    

    onCreate 方法中的现有代码会负责将 activity 与布局相关联。添加的行会创建一个新的成员变量 mWebView 来引用网页视图。

    移除以下代码:

    if (savedInstanceState == null) {
      getSupportFragmentManager().beginTransaction()
        .add(R.id.container, new PlaceholderFragment())
        .commit();
    }
    

    WebView 由资源 ID 标识,该 ID 由布局文件中的这行代码指定:

    android:id="@+id/activity_main_webview"
    

    添加代码后,您会在编辑器的边线中看到一些警告消息。这是因为您未为 WebView 导入正确的类。幸运的是,Android Studio 可以帮助您填充缺少的类。最简单的方法是点击并将鼠标悬停在未知类名称上,然后等待模块显示“快速修复”提示(在本例中,为 WebView 类添加 import 语句)。

    按 Alt + Enter(在 Mac 上,则按 Option + Enter)接受快速修复。

    有了 WebView,您就可以继续进行设置并加载一些精彩的 Web 内容了。

启用 JavaScript

WebView 默认不允许使用 JavaScript。如需在 WebView 中运行 Web 应用,您需要向 onCreate 方法添加以下代码行,以明确启用 JavaScript:

// Enable Javascript
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);

加载远程网址

如果您要从远程网址加载数据,您的应用需要拥有访问互联网的权限。此权限需要添加到应用的清单文件中。

  1. 打开 src/res 目录中的 AndroidManifest.xml 文件。在闭合的 </manifest> 标记之前添加粗体行。

    <?xml version="1.0" encoding="utf-8"?>
    <manifest ...>
    ...
     
      </application>
      <uses-permission android:name="android.permission.INTERNET" />
    </manifest>
    
  2. 下一步是调用 WebView 上的 loadUrl 方法。将以下代码行添加到 onCreate 方法的末尾。

    mWebView.loadUrl("[https://beta.html5test.com/][8]");
    

    现在,尝试运行该项目。如果您没有方便使用的设备,可以依次选择 Tools > Android > AVD Manager 创建模拟器(AVD 或 Android 虚拟设备)。

处理导航

请尝试将要加载的网址更改为 https://www.css-tricks.com/,然后重新运行应用。您会发现一些奇怪的现象。

如果您现在使用包含重定向(例如 css-tricks.com)的网站运行应用,您的应用最终会在设备上的浏览器中打开该网站,而不是在 WebView 中打开该网站,这可能不是您预期的结果。这是因为 WebView 处理导航事件的方式。

事件顺序如下:

  1. WebView 会尝试从远程服务器加载原始网址,并会重定向到新网址。
  2. WebView 会检查系统是否可以处理网址的 View intent,如果可以,系统会处理网址导航;否则,WebView 会在内部导航(例如,如果用户的设备上未安装浏览器)。
  3. 系统会选择用户的首选应用来处理 https:// 网址架构,即用户的默认浏览器。如果您安装了多个浏览器,此时可能会看到一个对话框。

如果您要在 Android 应用中使用 WebView 显示内容(例如帮助页面),这可能正是您想要做的。不过,对于更复杂的应用,您可能需要自行处理导航链接。

如需处理 WebView 中的导航,您需要替换 WebView 的 WebViewClient,该函数用于处理 WebView 生成的各种事件。您可以使用它来控制 WebView 如何处理链接点击和网页重定向。

WebViewClient 的默认实现会在 WebView 中打开任何网址:

// Force links and redirects to open in the WebView instead of in a browser
mWebView.setWebViewClient(new WebViewClient());

这是一个很好的进步,但如果您只想处理您网站的链接,同时在浏览器中打开其他网址,该怎么办?

为此,您需要扩展 WebViewClient 类并实现 shouldOverrideUrlLoading 方法。每当 WebView 尝试导航到其他网址时,系统都会调用此方法。如果返回 false,WebView 会自行打开网址。(默认实现始终返回 false,因此在前面的示例中有效。)

创建新类:

  1. 右键点击应用的软件包名称,然后依次选择 New > Java Class
  2. 输入 MyAppWebViewClient 作为类名称,然后点击 OK
  3. 在新 MyAppWebViewClient.java 文件中,添加以下代码(更改以粗体显示):

    public class MyAppWebViewClient extends WebViewClient {
      @Override
      public boolean shouldOverrideUrlLoading(WebView view, String url) {
        if(Uri.parse(url).getHost().endsWith("css-tricks.com")) {
          return false;
        }
                   
        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
        view.getContext().startActivity(intent);
        return true;
      }
    }
    

    新代码将 MyAppWebViewClient 定义为 WebViewClient 的子类,并实现了 shouldOverrideUrlLoading 方法。

    每当 WebView 即将加载网址时,系统都会调用 shouldOverrideUrlLoading 方法。此实现会检查网址主机名的末尾是否包含字符串“css-tricks.com”。如果字符串存在,该方法会返回 false,这会告知平台不要替换网址,而是在 WebView 中加载该网址。

    对于任何其他主机名,该方法都会向系统发出打开网址的请求。为此,它会创建一个新的 Android intent,并使用它启动一个新 activity。在方法结束时返回 true 会阻止将网址加载到 WebView。

  4. 如需使用新的自定义 WebViewClient,请将以下代码行添加到 MainActivity 类中:

    // Stop local links and redirects from opening in browser instead of WebView
    mWebView.setWebViewClient(new MyAppWebViewClient());
    

    现在,用户可以点击任何 CSS Tricks 链接,并留在应用内,但指向外部网站的链接会在浏览器中打开。

处理 Android 返回按钮

当您开始浏览 CSS Tricks 文章时,点击 Android 设备上的返回按钮会退出应用。

WebView 方法 canGoBack 会告知您页面堆栈中是否有可弹出的项。如需检测按下返回按钮并确定是否应通过 WebView 的历史记录返回,或允许平台确定正确的行为,请将 onBackPressed() 方法添加到 MainActivity

public class MainActivity extends Activity {

 private WebView mWebView;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
     ...
 }

    @Override
    public void onBackPressed() {
      if(mWebView.canGoBack()) {
        mWebView.goBack();
      } else {
        super.onBackPressed();
      }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
       ...
    }
}

从文件系统加载 HTML

在可安装的应用中使用 WebView 的一个主要优势是,您可以在应用中存储资源。这样,您的应用就可以离线运行,并且加载时间会缩短,因为 WebView 可以直接从本地文件系统检索资源。

如需在本地存储文件(包括 HTML、JavaScript 和 CSS),请将其存储在 assets 目录中。这是 Android 用于原始文件的预留目录。您的应用需要访问此目录,因为它可能需要最小化或压缩某些文件。

  1. 在 main (src/main/assets/www) 中创建 assets/www 目录。

    • 最佳实践是将 Web 文件保存在 /assets 的子目录中。
  2. 将所有文件上传到该目录。

  3. 加载相应的文件:

    mWebView.loadUrl("file:///android_asset/www/index.html");
    
  4. 更新 shouldOverrideUrlLoading 方法,以便为非本地网页打开浏览器:

    public class MyAppWebViewClient extends WebViewClient {
      @Override
      public boolean shouldOverrideUrlLoading(WebView view, String url) {
        if(Uri.parse(url).getHost().length() == 0) {
          return false;
        }
    
        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
        view.getContext().startActivity(intent);
        return true;
      }
    }
    

现在,您可以开始构建出色的 WebView 应用了。

如需有关如何获得理想视觉效果的提示,请参阅 WebView 中的精美像素风格界面

如果您遇到问题,Chrome 开发者工具会是您的好帮手。如需开始使用,请参阅 Android 上的远程调试