Hello Web Android
一个简单但功能强大的HTML/JavaScript版“Hello World”应用模板
引言
在本文中,我们将介绍一个使用简单HTML页面作为界面的小型Android应用。你将学会如何将JavaScript代码连接到应用的Java代码,并为任何基于HTML/JavaScript的Android应用打下基础。这对于具有Web开发背景的初学者来说是学习Android应用开发的绝佳方式。
在这个例子中,我们将看到如何从JavaScript调用Java代码,以便保存用户的名字,以便稍后向他们问好。
你应该已经设置好了Android开发环境才能尝试此操作。如果你还没有,可以欣赏一下代码 :)
使用哪个IDE并不重要。本文的目标是独立于任何IDE。我使用的是Eclipse ADT,并且附加的项目文件是从那里导出的。
编写Hello Web Android应用
步骤 1 - 创建新项目
在你的IDE中,创建一个新的Android应用程序项目。将应用命名为“Hello Web Android”,并从一个空的Activity开始。
步骤 2 - 创建index.html页面
由于你可能对HTML和JavaScript更熟悉,所以在继续学习Java代码之前,我们先来看看要使用的index.html页面。这个HTML页面将显示在我们Java代码的WebView对象中,我们将在下一步中了解如何做到这一点。
在项目中的assets目录中创建一个名为index.html的新文件。该目录应该位于项目根目录内。文件内容如下:
<html> <head> <style type="text/css"> body { background: #99AA99; font-size: 32px; } </style> <script> function askForName() { JavaCode.askForName(); } function getGreeting() { var name = JavaCode.getName(); if (name) { return "Hello " + name; } else { return "Press the button to tell me your name."; } } function updateGreeting() { document.getElementById("greetingDiv").innerText = getGreeting(); } window.onload = function() { updateGreeting(); } </script> </head> <body> <div id="greetingDiv"></div> <br /><br /> <button type="button" id="nameButton" onclick="askForName();">Change name</button> </body> </html>
这是一个简单的网页,包含一个div元素,我们将用它来向用户显示问候消息,以及一个用户可以点击以设置其姓名的按钮。在JavaScript中,请注意名为JavaCode
的内容。这是我们将在下一步传递给WebView元素的JavaScript接口的名称。
来看一下简单的JavaScript函数。
- askForName函数将简单地调用应用Java代码中一个也称为askForName的函数。它会向用户显示一个对话框,询问他们的姓名。
- getGreeting函数将返回我们将显示给用户的问候语。请注意,我们将调用Java代码中的一个名为getName的函数。这将返回保存在我们应用中的用户姓名。因此,如果未保存姓名,我们将告诉用户单击按钮来设置其姓名。
- updateGreeting函数只是用问候消息设置页面上的greetingDiv元素的文本。我们将从window.onload函数中立即调用它。
步骤 3 - 主Activity
主Activity是应用启动时运行的类。在我们的例子中,它负责设置和显示WebView。要创建主Activity,我们需要一个布局文件(定义显示的元素的XML文件)以及创建视图对象的MainActivity.java文件。在IDE中创建新的Android项目时,它应该在项目src目录中创建MainActivity.java文件,并在res/layout目录中创建activity_main.xml文件。
activity_main.xml文件内容如下:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="${relativePackage}.${activityClass}" > <WebView android:id="@+id/webViewMain" android:layout_width="fill_parent" android:layout_height="match_parent" /> </RelativeLayout>
这是一个简单的Activity布局示例,它使用RelativeLayout对象来容纳其他对象。在本例中,RelativeLayout对象中唯一的内容是我们用于显示HTML页面的WebView。如果你不理解这里的所有内容,也不要担心,但请确保你看到WebView对象将位于RelativeLayout对象内,并且我们希望它尽可能填充屏幕。Android应用的主要区域将由我们的WebView对象填充。
现在,让我们看看MainActivity.java文件如何从activity_main.xml文件创建UI。MainActivity.java文件内容如下:
package com.hello.hellowebworld; import android.annotation.SuppressLint; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.webkit.WebChromeClient; import android.webkit.WebView; @SuppressLint("SetJavaScriptEnabled") public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); WebView myWebView = (WebView) findViewById(R.id.webViewMain); myWebView.setWebChromeClient(new WebChromeClient()); myWebView.getSettings().setJavaScriptEnabled(true); JavascriptBridge jsb = new JavascriptBridge(this, getPreferences(Context.MODE_PRIVATE), myWebView); myWebView.addJavascriptInterface(jsb, "JavaCode"); myWebView.loadUrl("file:///android_asset/index.html"); } }
这里没有太多内容。onCreate方法在Activity创建时被调用,即应用启动时。有一个对setContentView方法的调用,该方法引用了R.layout.activity_main。R是对我们资源的引用,因此获取activity_main布局是合乎逻辑的。这就是我们的activity_main.xml文件如何用于构建UI。
为了设置WebView以显示我们的index.html页面,我们通过findViewById方法获取WebView对象,并将WebView的ID(如activity_main.xml文件中定义的)传递给它。一旦我们有了WebView,我们就启用JavaScript,创建并添加JavaScript接口,然后指示它加载我们的index.html页面。
我们作为JavaScript接口传递给WebView的JavascriptBridge类是我们尚未查看的唯一代码。在上面的代码中,你看到了我们如何将JavaCode
引用添加到WebView。现在,让我们看看我们的JavascriptBridge类是如何工作的。
步骤 4 - 创建JavaScript接口
在MainActivity.java类中,我们将JavascriptBridge类的实例传递给WebView作为JavaScript接口。这意味着WebView中的JavaScript代码可以调用JavascriptBridge对象的某些方法。让我们看看代码是如何设置的,以及我们如何使用JavascriptBridge对象调用WebView对象中的JavaScript代码。JavascriptBridge.java文件内容如下:
package com.hello.hellowebworld; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.SharedPreferences; import android.text.InputType; import android.webkit.JavascriptInterface; import android.webkit.WebView; import android.widget.EditText; public class JavascriptBridge { private static final String NAME_KEY = "Name"; SharedPreferences sharedPref; Context context; WebView webView; public JavascriptBridge(Context ctx, SharedPreferences preferences, WebView wv) { sharedPref = preferences; context = ctx; webView = wv; } @JavascriptInterface public void askForName() { AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle("What is your name?"); // Set up the input final EditText input = new EditText(context); // Specify the type of input expected input.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_CAP_WORDS); builder.setView(input); // Set up the buttons builder.setPositiveButton("OK", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { changeName(input.getText().toString()); } }); builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.cancel(); } }); builder.show(); } protected void changeName(String name) { setName(name); webView.loadUrl("javascript:updateGreeting()"); } protected void setName(String name) { SharedPreferences.Editor editor = sharedPref.edit(); editor.putString(NAME_KEY, name); editor.commit(); } @JavascriptInterface public String getName() { return sharedPref.getString(NAME_KEY, null); } }
首先,我们来看看这个类中的实例变量。我们有一个SharedPreferences对象——我们使用它来保存应用中的键值对数据,例如用户的姓名。它通过MainActivity类构造函数传入。Context对象实际上是我们MainActivity类的引用,它也通过JavascriptBridge构造函数传入,并且需要它来创建显示给用户的对话框。WebView对象也通过构造函数传入。它是显示我们index.html文件的主要WebView的引用。
现在,看看JavascriptBridge类拥有的方法:
- askForName方法有一个注解:@JavascriptInterface。这个注解意味着该方法可以从WebView中的JavaScript代码调用。在方法内部,会创建一个对话框,提示用户输入姓名并点击“确定”。点击“确定”后,将调用changeName方法。如果点击“取消”,我们将直接关闭对话框,不再采取任何进一步行动。
- changeName方法调用setName方法,该方法通过我们应用的SharedPreferences对象保存用户的姓名,然后调用WebView中的JavaScript函数updateGreeting。这将执行我们在index.html文件中前面看到的updateGreeting函数。
- setName函数是如何将键值对保存到应用SharedPreferences的一个例子。在本例中,保存的是用户的姓名。
- getName方法具有@JavascriptInterface注解,因此可以从WebView中的index.html页面调用。它所做的只是返回保存在应用SharedPreferences中的用户姓名值。
运行应用程序
现在,项目已完成,你可以在模拟器或物理设备上运行该应用。如何设置模拟器或设备进行测试可能因你使用的IDE而异。运行该应用并尝试一下!以下是应用外观的截图演练。
首次启动
设置你的名字
在我输入名字Zach并点击“确定”后,显示问候语
现在,应用记住了我!每次打开它,我的名字都会被保存,并显示问候语。
想要一个小挑战吗? take this app and add a button to the index.html page that can be clicked to have the app forget the saved name. Write the additional Java and JavaScript code needed to do this.
结论
在这个例子中,这个应用使用Java中的对话框来获取用户的姓名。这也可以很容易地从HTML页面完成!有了这个简单的模板,你就有了用HTML和JavaScript构建界面的Android应用的基础。你也知道如何连接到Java代码来执行你无法在网页上完成的操作。
现在,试试今天就将你自己的Web应用打包成Android应用吧!