# JSBridge实现篇-安卓
# web端代码
先写一下web端的代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<input type="button" value="js调用android方法1" onclick="onAndroidFunction1('js调用android方法1')">
<input type="button" value="js调用android方法2" onclick="onAndroidFunction2()">
<script>
// 调用 Android 方法1
function onAndroidFunction1(str) {
window.AndroidJSBridge.androidTestFunction1(str);
}
// 调用 Android 方法2
function onAndroidFunction2() {
var result = window.AndroidJSBridge.androidTestFunction2();
alert(result);
}
// Android 调用 onFunction 方法
window.onFunction = function (str) {
alert(str);
return 'onFunction 方法已经调用完成';
}
</script>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
onAndroidFunction1是h5调用安卓的androidTestFunction1的方法onAndroidFunction2是h5调用安卓的androidTestFunction2的方法window.onFunction是安卓主动调用 h5的方法
# 使用腾讯的 X5 webview
package cn.sunday.hybridappdemo;
import android.app.Application;
import com.tencent.smtt.sdk.QbSdk;
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
// TODO Auto-generated method stub
super.onCreate();
//搜集本地tbs内核信息并上报服务器,服务器返回结果决定使用哪个内核。
QbSdk.PreInitCallback cb = new QbSdk.PreInitCallback() {
@Override
public void onViewInitFinished(boolean arg0) {
// TODO Auto-generated method stub
//x5內核初始化完成的回调,为true表示x5内核加载成功,否则表示x5内核加载失败,会自动切换到系统内核。
}
@Override
public void onCoreInitFinished() {
// TODO Auto-generated method stub
}
};
//x5内核初始化接口
QbSdk.initX5Environment(getApplicationContext(), cb);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# android app 页面构建
package cn.sunday.hybridappdemo;
import android.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import com.tencent.smtt.sdk.ValueCallback;
import cn.sunday.hybridappdemo.constants.Constants;
import cn.sunday.hybridappdemo.views.X5WebView;
public class MainActivity extends AppCompatActivity {
private X5WebView mWebView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
}
/**
* 初始化 webview
*/
private void init () {
mWebView = findViewById(R.id.web_view);
mWebView.loadUrl(Constants.WEB_URL);
}
/**
* 原生端调用 web 方法,方法必须是挂载到 web 端 window 对象下面的方法。
* 调用 JS 中的方法:onFunction1
*/
public void onJSFunction1 (View v) {
mWebView.evaluateJavascript("javascript:onFunction('android调用JS方法')", new ValueCallback<String>() {
@Override
public void onReceiveValue(String s) {
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setMessage(s);
builder.setNegativeButton("确定", null);
builder.create().show();
}
});
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# onJSFunction1方法
- 调用 JS 中的方法:onFunction1
- 原生端调用 web 方法,方法必须是挂载到 web 端 window 对象下面的方法。
# webview 配置
package cn.sunday.hybridappdemo.views;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.content.Context;
import android.util.AttributeSet;
import com.tencent.smtt.export.external.interfaces.JsResult;
import com.tencent.smtt.sdk.WebChromeClient;
import com.tencent.smtt.sdk.WebSettings;
import com.tencent.smtt.sdk.WebView;
import com.tencent.smtt.sdk.WebViewClient;
import java.util.Map;
import cn.sunday.hybridappdemo.jsInterface.MyJaveScriptInterface;
public class X5WebView extends WebView {
private Context mContext;
public X5WebView(Context context) {
super(context);
init(context);
}
public X5WebView(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
init(context);
}
public X5WebView(Context context, AttributeSet attributeSet, int i) {
super(context, attributeSet, i);
init(context);
}
public X5WebView(Context context, AttributeSet attributeSet, int i, boolean b) {
super(context, attributeSet, i, b);
init(context);
}
public X5WebView(Context context, AttributeSet attributeSet, int i, Map<String, Object> map, boolean b) {
super(context, attributeSet, i, map, b);
init(context);
}
private void init (Context context) {
this.mContext = context;
/**
* 基础配置
*/
initWebViewSettings();
initWebViewClient();
initChromeClient();
/**
* 构建 JSBridge 对象,这里提供的 JSBridge 字符串会被挂载到
* 网页中的 window 对象下面。
*
* window.AndroidJSBridge
*/
addJavascriptInterface(
new MyJaveScriptInterface(mContext, this),
"AndroidJSBridge");
}
/**
* 对 webview 进行基础配置
*/
private void initWebViewSettings () {
WebSettings webSettings = getSettings();
/**
* 允许加载的网页执行 JavaScript 方法
*/
webSettings.setJavaScriptEnabled(true);
/**
* 设置网页不允许缩放
*/
webSettings.setSupportZoom(false);
webSettings.setBuiltInZoomControls(false);
webSettings.setDisplayZoomControls(true);
/**
* 设置网页缓存方式为不缓存,方便我们的调试
*/
webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);
}
/**
* 设置 webviewClient ,如果不进行这层设置,则网页打开默认会使用
* 系统中的浏览器进行打开,而不是在本 APP 中进行打开。
*/
private void initWebViewClient () {
setWebViewClient(new WebViewClient(){
});
}
/**
* 监听网页中的url加载事件
*/
private void initChromeClient () {
setWebChromeClient(new WebChromeClient(){
/**
* alert()
* 监听alert弹出框,使用原生弹框代替alert。
*/
@Override
public boolean onJsAlert(WebView webView, String s, String s1, JsResult jsResult) {
AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
builder.setMessage(s1);
builder.setNegativeButton("确定", null);
builder.create().show();
jsResult.confirm();
return true;
}
});
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# 可以被网页端调用的方法
package cn.sunday.hybridappdemo.jsInterface;
import android.app.AlertDialog;
import android.content.Context;
import android.webkit.JavascriptInterface;
import com.tencent.smtt.sdk.ValueCallback;
import java.util.Timer;
import java.util.TimerTask;
import cn.sunday.hybridappdemo.views.X5WebView;
public class MyJaveScriptInterface {
private Context mContext;
private X5WebView mWebView;
public MyJaveScriptInterface(Context context, X5WebView x5WebView) {
this.mContext = context;
this.mWebView = x5WebView;
}
/**
*
* window.AndroidJSBridge.androidTestFunction1('xxxx')
* 调用该方法,APP 会弹出一个 Alert 对话框,
* 对话框中的内容为 JavaScript 传入的字符串
* @param str android 只能接收基本数据类型参数
* ,不能接收引用类型的数据(Object、Array)。
* JSON.stringify(Object) -> String
*/
@JavascriptInterface
public void androidTestFunction1 (String str) {
AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
builder.setMessage(str);
builder.setNegativeButton("确定", null);
builder.create().show();
}
/**
* 调用该方法,方法会返回一个返回值给 javaScript 端
* @return 返回值的内容为:"androidTestFunction2方法的返回值"
*/
@JavascriptInterface
public String androidTestFunction2 () {
return "androidTestFunction2方法的返回值";
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53