越來越多的應用采用原生代碼與Html混合開發(fā)的方式,對于這種類型的應用导坟,Android如何與JS進行交互呢溃论?本篇就對交互方式進行總結。
這邊先列下各種交互方式:
一色解、WebView加載Html
加載Html的方式這里簡單列一下茂嗓,webview的設置這邊不做詳細講解。
//加載assets里的test.html
mWebView.loadUrl("file:///android_asset/test.html");
//加載網(wǎng)頁
mWebView.loadUrl("https://www.baidu.com/");
二科阎、Android調用Html里的JS方法
1述吸、通過WebView的loadUrl () 方法調用JS方法
調用方式:WebView.loadUrl("javascript:<方法名>(<有參數(shù)時傳參>)");
具體代碼:
public class MainActivity extends AppCompatActivity {
WebView mWebView;
Button mButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mWebView = findViewById(R.id.wv);
mButton = findViewById(R.id.btn);
// 獲取WebSetting對象
WebSettings webSettings = mWebView.getSettings();
// 設置支持javascript
webSettings.setJavaScriptEnabled(true);
// 設置允許JS彈窗
webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
mWebView.setWebChromeClient(new WebChromeClient());
//加載assets里的test.html
mWebView.loadUrl("file:///android_asset/test.html");
//加載網(wǎng)頁
//mWebView.loadUrl("https://www.baidu.com/");
mButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//調用js要在webview加載完才可以調用
mWebView.post(new Runnable() {
@Override
public void run() {
//方法名fucn1要寫對,傳入的參數(shù)要用單引號或雙引號引用锣笨,雙引號注意要用轉義字符
mWebView.loadUrl("javascript:func1('a1a')");
}
});
}
});
}
}
test.html代碼:
<html>
<body>
<script type="text/javascript">
document.write("<h1>Hello World!</h1>")
function func1(str){
alert("Android調用了JS的func1方法--"+str);
}
</script>
</body>
</html>
該種方式簡單但是獲取JS返回值較麻煩蝌矛。
2道批、通過WebView的evaluateJavascript ()方法調用JS方法(可以獲取返回值)
只需要將loadUrl()換成下面該方法即可
mWebView.evaluateJavascript("javascript:func1('a1a')", new ValueCallback<String>() {
@Override
public void onReceiveValue(String value) {//value為 js 返回的值
}
});
該方法在android版本19以下不能使用,所以最好配合方法1使用朴读,如下:
if(Build.VERSION.SDK_INT<Build.VERSION_CODES.KITKAT) {
//方法名fucn1要寫對屹徘,傳入的參數(shù)要用單引號或雙引號引用,雙引號注意要用轉義字符
mWebView.loadUrl("javascript:func1('a1a')");
}else {
mWebView.evaluateJavascript("javascript:func1('a1a')", new ValueCallback<String>() {
@Override
public void onReceiveValue(String value) {//value為 js 返回的值
}
});
}
三衅金、JS調用Android代碼
1噪伊、通過WebView的addJavascriptInterface () 進行對象映射
首先,定義一個要被JS調用的類氮唯,被調用的方法加@JavascriptInterface注解鉴吹。
public class CallByJS{
// 被JS調用的方法必須加@JavascriptInterface注解
@JavascriptInterface
public void callByJS(String str) {
Log.e("web_test",str);
}
}
然后在WebView里通過addJavascriptInterface()將Java對象映射到JS對象。
// 通過addJavascriptInterface()將Java對象映射到JS對象
mWebView.addJavascriptInterface(new CallByJS(), "androidObj");
接下來JS就可以通過androidObj調用CallByJS對象的方法了惩琉。
<html>
<body>
<script type="text/javascript">
<!--document.write("<h1>Hello World!</h1>")-->
function func1(str){
alert("Android調用了JS的func1方法--"+str);
return "jsjs";
}
function clickBtn(){
androidObj.callByJS("JS調用了Android的方法");
}
</script>
<button type="button" id="btn" onclick="clickBtn()">點擊調用Android代碼</button>
</body>
</html>
運行豆励,點擊調用按鈕
Logcat里日志如下,說明JS調用了android的代碼瞒渠。
2良蒸、通過 WebViewClient 的shouldOverrideUrlLoading ()方法攔截 url。
這種方式就是Android通過 WebViewClient 的回調方法shouldOverrideUrlLoading ()攔截 url伍玖,解析該 url 的協(xié)議嫩痰,如果檢測到是預先約定好的協(xié)議,就執(zhí)行相應方法 窍箍。
mWebView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// 根據(jù)協(xié)議的參數(shù)進行攔截,下面攔截"callandroid://test"
// 一般根據(jù)scheme & authority判斷
Uri uri = Uri.parse(url);
// 如果 scheme = callAndroid串纺,即代表都符合約定的協(xié)議
if (uri.getScheme().equals("callandroid")) {
// 如果 authority = test,即代表都符合約定的協(xié)議
if (uri.getAuthority().equals("test")) {// 攔截url,下面開始執(zhí)行Android的方法
Toast.makeText(MainActivity.this, "js通過攔截調用了Android的方法", Toast.LENGTH_SHORT).show();
// 可以獲取參數(shù)
HashMap<String, String> params = new HashMap<>();
Set<String> paramNames = uri.getQueryParameterNames();
for (String name : paramNames) {
params.put(name, uri.getQueryParameter(name));
}
Log.e("web-test", params.toString());
}
return true;
}
return super.shouldOverrideUrlLoading(view, url);
}
});
接下來在Html里調用椰棘,下面的clickBtn2()方法:
<html>
<body>
<script type="text/javascript">
<!--document.write("<h1>Hello World!</h1>")-->
function func1(str){
alert("Android調用了JS的func1方法--"+str);
return "jsjs";
}
function clickBtn(){
androidObj.callByJS("JS調用了Android的方法");
}
function clickBtn2(){
document.location = "callandroid://test?arg1=abc&arg2=202";
}
</script>
<button type="button" id="btn" onclick="clickBtn()">點擊調用Android代碼</button>
<button type="button" id="btn2" onclick="clickBtn2()">通過攔截調用Android代碼</button>
</body>
</html>
運行程序纺棺,點擊第二個按鈕,執(zhí)行shouldOverrideUrlLoading方法邪狞,鏈接被攔截祷蝌,開始執(zhí)行對應的業(yè)務邏輯代碼:
也可以獲取參數(shù),Logcat打印出參數(shù)如下:
該方法JS無法直接獲取android代碼的返回值帆卓,需要android調用JS方法的方式把返回值傳給JS杆逗。
3、通過 WebChromeClient 的onJsAlert ()鳞疲、onJsConfirm ()、onJsPrompt ()方法攔截JS對話框alert ()蠕蚜、confirm ()尚洽、prompt ()消息
該方式就是Android通過 WebChromeClient 的onJsAlert()、onJsConfirm()靶累、onJsPrompt()方法分別攔截JS的alert()腺毫,confirm()癣疟,prompt()彈出框。
下面寫個onJsPrompt()攔截prompt()的例子潮酒。
首先重寫onJsPrompt方法睛挚,攔截方式與方式2類似。
mWebView.setWebChromeClient(new WebChromeClient(){
@Override
public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
return super.onJsAlert(view, url, message, result);
}
@Override
public boolean onJsConfirm(WebView view, String url, String message, JsResult result) {
return super.onJsConfirm(view, url, message, result);
}
@Override
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
// 根據(jù)協(xié)議的參數(shù)進行攔截,下面攔截"callandroid://test"
// 一般根據(jù)scheme & authority判斷
Uri uri = Uri.parse(message);//message是由JS的prompt()傳來的
// 如果 scheme = callAndroid急黎,即代表都符合約定的協(xié)議
if (uri.getScheme().equals("callandroid")) {
// 如果 authority = test扎狱,即代表都符合約定的協(xié)議
if (uri.getAuthority().equals("test")) {// 攔截url,下面開始執(zhí)行Android的方法
// 可以獲取參數(shù)
HashMap<String, String> params = new HashMap<>();
Set<String> paramNames = uri.getQueryParameterNames();
for (String name : paramNames) {
params.put(name, uri.getQueryParameter(name));
}
//將返回值返回給JS
result.confirm("攔截Prompt成功啦,傳進來的參數(shù)是:"+params.toString());
}
return true;
}
return super.onJsPrompt(view, url, message, defaultValue, result);
}
});
接下來在Html用JS調用
<html>
<body>
<script type="text/javascript">
<!--document.write("<h1>Hello World!</h1>")-->
function func1(str){
alert("Android調用了JS的func1方法--"+str);
return "jsjs";
}
function clickBtn(){
androidObj.callByJS("JS調用了Android的方法");
}
function clickBtn2(){
document.location = "callandroid://test?arg1=abc&arg2=202";
}
function clickBtn3(){
<!--這邊會被攔截,可以取得返回值-->
var str = prompt("callandroid://test?arg1=btn3");
alert(str);
}
</script>
<button type="button" id="btn" onclick="clickBtn()">點擊調用Android代碼</button>
<button type="button" id="btn2" onclick="clickBtn2()">通過攔截調用Android代碼</button>
<Br/>
<button type="button" id="btn3" onclick="clickBtn3()">攔截prompt</button>
</body>
</html>
執(zhí)行代碼勃教,點擊按鈕3:
其他兩個方法攔截也類似淤击,只不過alert ()沒有返回值,confirm ()返回值是boolean類型故源。