前言睹簇,最近有個(gè)項(xiàng)目要做一個(gè)安卓和iOS的App,實(shí)質(zhì)上是通過調(diào)用webview來加載網(wǎng)頁膨桥,但是需要實(shí)現(xiàn)微信掃一掃類似的功能钟哥,那就只能通過js來調(diào)用安卓/iOS中暴露出來調(diào)用掃一掃的接口,不過通過搜網(wǎng)上的一些關(guān)于安卓和js互調(diào)的文章达舒,都只是介紹了一些關(guān)于安卓系統(tǒng)和js互調(diào)的基本原理和實(shí)現(xiàn)值朋,并沒有類似于實(shí)現(xiàn)像微信掃一掃一樣的通過回調(diào)函數(shù)來處理微信掃一掃的結(jié)果的相關(guān)教程。那么咱們就得自力更生巩搏,來研究下怎樣才能實(shí)現(xiàn)微信掃一掃類似的功能昨登。
我們就拿安卓的來說。
第一步:
mainfest.xml中加入網(wǎng)絡(luò)權(quán)限
<uses-permission android:name="android.permission.INTERNET" />
第二步:
加載本地寫好的html文件(定義好js中提供給android調(diào)用的方法 funFromjs(),和android提供給js調(diào)用的對(duì)象接口fun1FromAndroid(String name)),放在 assets目錄下贯底。
<body>
<a>js中調(diào)用本地方法</a>
<script>
function funFromjs(){
document.getElementById("helloweb").innerHTML="HelloWebView,i'm from js";
}
var aTag = document.getElementsByTagName('a')[0];
aTag.addEventListener('click', function(){
//調(diào)用android本地方法
myObj.fun1FromAndroid("調(diào)用android本地方法fun1FromAndroid(String name)7崂薄!");
return false;
}, false);
</script>
<p></p>
<div id="helloweb">
</div>
</body>
第三步:
實(shí)現(xiàn)android工程與js交互的相關(guān)代碼,其中l(wèi)oadUrl()是實(shí)現(xiàn)安卓將js代碼注入到webview里的關(guān)鍵
android代碼:
@SuppressLint({ "JavascriptInterface", "SetJavaScriptEnabled" })
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化
initViews();
//設(shè)置編碼
mWebView.getSettings().setDefaultTextEncodingName("utf-8");
//支持js
mWebView.getSettings().setJavaScriptEnabled(true);
//設(shè)置背景顏色 透明
mWebView.setBackgroundColor(Color.argb(0, 0, 0, 0));
//設(shè)置本地調(diào)用對(duì)象及其接口
mWebView.addJavascriptInterface(new JavaScriptObject(mContext), "myObj");
//載入js
mWebView.loadUrl("file:///android_asset/test.html");
//點(diǎn)擊調(diào)用js中方法
mBtn1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mWebView.loadUrl("javascript:funFromjs()");
Toast.makeText(mContext, "調(diào)用javascript:funFromjs()", Toast.LENGTH_LONG).show();
}
});
}
js調(diào)用的android對(duì)象方法定義
public class JavaScriptObject {
Context mContxt;
@JavascriptInterface //sdk17版本以上加上注解
public JavaScriptObject(Context mContxt) {
this.mContxt = mContxt;
}
public void fun1FromAndroid(String name) {
Toast.makeText(mContxt, name, Toast.LENGTH_LONG).show();
}
public void fun2(String name) {
Toast.makeText(mContxt, "調(diào)用fun2:" + name, Toast.LENGTH_SHORT).show();
}
}
以上代碼借鑒了網(wǎng)友們一些代碼_~
下面開始本文的核心代碼,我們將html的代碼改造下
<body>
<a>js中調(diào)用本地方法</a>
<script>
function funFromjs(){
document.getElementById("helloweb").innerHTML="HelloWebView,i'm from js";
}
//先定義一個(gè)scan函數(shù)禽捆,參數(shù)cb
function scan(cb){
if(typeof cb == "function"){
//將cb強(qiáng)制類型轉(zhuǎn)化成字符串類型,cb就是回調(diào)函數(shù)
cb = String(cb);
}else{
cb = String(cb);
}
myObj.fun1FromAndroid(cb);
}
var aTag = document.getElementsByTagName('a')[0];
aTag.addEventListener('click', function(){
//調(diào)用android本地方法
//下面我們來調(diào)用這個(gè)scan函數(shù)并傳入回調(diào)函數(shù)
scan(function(str){
alert(str);
});
return false;
}, false);
</script>
<p></p>
<div id="helloweb">
</div>
</body>
//然后再改造安卓的java代碼:
public class JavaScriptObject {
Context mContxt;
@JavascriptInterface //sdk17版本以上加上注解
public JavaScriptObject(Context mContxt) {
this.mContxt = mContxt;
}
public void fun1FromAndroid(String name) {
//這里將name的數(shù)據(jù)暫存起來笙什,方便loadUrl注入js的時(shí)候調(diào)用,具體的代碼就不展示了
Toast.makeText(mContxt, name, Toast.LENGTH_LONG).show();
}
public void fun2(String name) {
Toast.makeText(mContxt, "調(diào)用fun2:" + name, Toast.LENGTH_SHORT).show();
}
}
然后是安卓activity里的代碼改造:
@SuppressLint({ "JavascriptInterface", "SetJavaScriptEnabled" })
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化
initViews();
//設(shè)置編碼
mWebView.getSettings().setDefaultTextEncodingName("utf-8");
//支持js
mWebView.getSettings().setJavaScriptEnabled(true);
//設(shè)置背景顏色 透明
mWebView.setBackgroundColor(Color.argb(0, 0, 0, 0));
//設(shè)置本地調(diào)用對(duì)象及其接口
mWebView.addJavascriptInterface(new JavaScriptObject(mContext), "myObj");
//載入js
mWebView.loadUrl("file:///android_asset/test.html");
//點(diǎn)擊調(diào)用js中方法
mBtn1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mWebView.loadUrl("javascript:funFromjs()");
Toast.makeText(mContext, "調(diào)用javascript:funFromjs()", Toast.LENGTH_LONG).show();
}
});
}
//我們現(xiàn)在考慮的是掃一掃的功能胚想,需要在另一個(gè)頁面實(shí)現(xiàn)調(diào)用攝像頭琐凭,并讀取到二維碼的信息,并存儲(chǔ)下來浊服,在攝像頭頁面銷毀后淘正,回到上個(gè)頁面
@Override
protected void onResume(Bundle savedInstanceState) {
//具體的數(shù)據(jù)代碼就不寫了
String jsCode;//假設(shè)這個(gè)是webview里傳進(jìn)來回調(diào)函數(shù)的字符串
String scanResualt;//假設(shè)這個(gè)是掃碼之后的結(jié)果
mWebView.loadUrl("javascript:var app = "+jsCode+";app(' "+scanResualt+" ');");//解釋:這里將前臺(tái)傳遞回調(diào)函數(shù)字符串賦值給一個(gè)變量app摆马,接著再調(diào)用這個(gè)剛定義的app函數(shù),并將掃碼結(jié)果以參數(shù)形式傳遞給app這個(gè)函數(shù)鸿吆;這樣我們能實(shí)現(xiàn)類似微信掃一掃這樣從html端的js傳遞匿名函數(shù)(帶參數(shù)),并以js傳遞不同的回調(diào)函數(shù)來處理安卓系統(tǒng)返回的字符串
}
結(jié)語:上面的代碼可能不夠嚴(yán)謹(jǐn)囤采,只是提供了這樣的一個(gè)思路,可能還有其他更好的實(shí)現(xiàn)方法惩淳,iOS中webview的實(shí)現(xiàn)方式跟安卓的差不多蕉毯,如果有什么疑問可以留言或者私信。