转载请注明出处: http://blog.csdn.net/forwardyzk/article/details/46819925
在工作中,有一个这样的需求,需要用到WebView与javascript进行交互,下面我们就通过一个简单的需求来介绍.
先看一下效果图:
需求:
1.点击一个按钮进入一个加载WebView的界面,如果此界面需要分享此界面到其他平台,那么就在当前界面展示"分享"按钮,如果不需要分享,那么就不展示"分享"按钮.
2.在H5界面上,有一个登陆按钮,点击登陆,
2.1 如果没有登陆,则调起登陆界面,登陆成功后,在H5界面展示登陆者.
2.2 如果登陆了,就在H5界面直接显示当前的登陆者.
1.使webview支持js的调用.
webview.addJavascriptInterface(new JsHost(JsActivity.this, mHandler, webview), "jsObject");
其中JsHost是自定义的一个类, jsObject是H5页面调用客户端js方法的对象(名字也是自定义的,只要和H5javascriprt用的对象名字一样即可).
2.分享需求.
当H5页面加载完毕后,H5页面调用客户端是否分享的方法(通过此方法讲是否分享和分享的内容传递给客户端),然后控制分享按钮是否展示
H5页面javascrip方法:
window.onload = function share() {
//分享
var json = "{'isShare':0,'shareContent':'我是分享内容'}";
//不分享
var noShare = "{'isShare':-1}";
window.jsObject.toShare(json);
}
这是H5调用客户端的javascript方法
window:代表当前页面的对象
window.onload表示当前的H5页面加载完毕后,调用后面的方法
json:表示需要分享的json字符串
noshare:表示不分享额json字符串
jsObject:是客户端定义的javascript对象
toShare(json):客户端的javascript方法,这样在客户端就可以收到json字符串.(这里传的是需要分享的json字符串)
在客户端的JsHost中定义javascript的分享方法
/**
* 分享的方法
*
* @param json
*/
@JavascriptInterface
public void toShare(String json) {
Log.d(TAG, "web:" + json);
try {
JSONObject jsonObject = new JSONObject(json);
int isShare = jsonObject.optInt("isShare");
if (isShare == 0) {//表示需要分享
mHandler.sendEmptyMessage(0);
} else if (isShare == -1) { //表示不需要分享
mHandler.sendEmptyMessage(1);
}
} catch (JSONException e) {
Log.d(TAG, "解析异常");
}
}
首先要增加标识javascript的注解,@JavascriptInerface
解析传递过来的json字符串,通过Handler对象发送消息来控制分享按钮是否展示
在JsActivity方法中定义了mHandler,通过WebView的设置addJavascriprtInterface方法传递给了JsHost类中
JsActivty对应的不局文件:
activity_js.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/btn_share"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="分享" />
<WebView
android:id="@+id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/btn_share"></WebView>
</RelativeLayout>
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.what == 0) {//显示分享
btnShare.setVisibility(View.VISIBLE);//显示分享按钮
} else if (msg.what == 1) {//隐藏分享按钮
btnShare.setVisibility(View.GONE);//隐藏分享按钮
} else if (msg.what == 2) {//调用登录
Intent intent = new Intent(JsActivity.this, LoginActivity.class);
startActivityForResult(intent, JsActivity.RESULT_OK);
}
super.handleMessage(msg);
}
};
3.1点击登陆,如果没有登陆,弹起登陆界面
先看H5页面点击登陆,调用客户端的js方法
<input id="loginName" type="button" οnclick="isLogin()" value="登录">
function isLogin() {
var name = window.jsObject.requestToken();
document.getElementById("loginName").value = name;
}
点击"登录",调用了javascript中的isLogin()方法,在isLogin方法中调用客户端的requestToken()方法.此 requestToken()有返回值,返回值是当前登陆者的名字.
客户端的requestToken方法
/**
* 请求登陆者
*
* @return
*/
@JavascriptInterface
public String requestToken() {
if (TextUtils.isEmpty(App.getName())) {
mHandler.sendEmptyMessage(2);
}
Log.d(TAG, "登陆者名字" + "name=" + App.getName());
return TextUtils.isEmpty(App.getName()) ? "未登录" : App.getName();
}
如果App.getName()获取登陆者的名字,如果为空,则通过mHandelr方法调起登录界面的通知.同时将当前登陆者返回给H5页面.
Intent intent = new Intent(JsActivity.this, LoginActivity.class);
startActivityForResult(intent, JsActivity.RESULT_OK);
通过startActivityForResult方法开启登陆页面
startActivityForResult的使用方法请参考:点击
看一下登陆页面:
activity_login.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="10dp"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:id="@+id/name_des"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:text="name:" />
<EditText
android:id="@+id/edit_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toRightOf="@id/name_des" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginTop="20dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:id="@+id/pass_des"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:text="pass:" />
<EditText
android:id="@+id/edit_pass"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toRightOf="@id/pass_des" />
</RelativeLayout>
<Button
android:id="@+id/btn_login"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="Login" />
</LinearLayout>
当点击了login按钮,执行登陆操作
private void login() {
String name = editName.getText().toString().trim();
String pass = editPass.getText().toString().trim();
if (TextUtils.isEmpty(name)) {
Toast.makeText(getApplicationContext(), "name is empty", Toast.LENGTH_SHORT).show();
return;
} else if (TextUtils.isEmpty(pass)) {
Toast.makeText(getApplicationContext(), "pass is empty", Toast.LENGTH_SHORT).show();
return;
} else {
App.writeLoginInfo(name, pass);
setResult(JsActivity.RESULT_OK);
finish();
}
}
登陆成功后,把name和pass存到了App中
public class App extends Application {
private static SharedPreferences sharedPreferences;
@Override
public void onCreate() {
super.onCreate();
sharedPreferences = getApplicationContext().getSharedPreferences("login", Context.MODE_PRIVATE);
}
public static void writeLoginInfo(String name, String pass) {
sharedPreferences.edit().putString("name", name).putString("pass", pass).commit();
}
public static String getName() {
return sharedPreferences.getString("name", "");
}
}
同时在JsActivity中的onActivityResult方法中获取到通知,然后调用H5页面的loginSuccess方法,传递给H5客户端的登录者
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == RESULT_OK) {
String name = App.getName();
name = TextUtils.isEmpty(name) ? "未登录" : name;
Log.d(TAG, "onActivityResult:" + "name=" + name);
//调用H5的javascript中的loginSuccess方法
webview.loadUrl("javascript:loginSuccess('" + name + "')");
}
}
webview.loadUrl("javascript:loginSuccess('"+name+"')");
这是客户端调用H5中的javascript的方法.
function loginSuccess(name) {
document.getElementById("loginName").value = name;
}
讲name赋给id为loginName控件的value属性.
loginSuccess:是H5中的javascript方法
name:是方法参数
总结:
使用webview的addJavascriprtInterface(操作的对象,"javascript对象名称");
H5调用客户端方法:
无返回值: window.javascript对象.客户端js方法;
有返回值: var value=window.javascript对象.客户端js方法;
客户端调用H5的方法:
webview.loadUrl("javascript:方法名称(参数)");
webview.loadUrl("javascript:方法名称()");
到此WebView与javascript方法互相调用已经讲解完毕,希望对大家有帮助,有不足之处往大家指出.
源码下载: 服务器和客户端的源码