网页与Android原生页交互越来越多,遇到的问题也越来越多。
问题描述1:用户在app端登录成功,然后在app端打开一个需要登录信息(用来识别用户)的web页。
解决方案:app端发送js消息给web端,将用户登录的token值传递给web页。web页在调用需要登录信息的接口时设置请求头信息。关于Android如何传递参数给web请参照上一篇h5与Android原生交互这里Android端将token值发送到web页,web页处理如下:
<script>
function connectWebViewJavascriptBridge(callback) {
if (window.WebViewJavascriptBridge) {
callback(WebViewJavascriptBridge)
}else{ document.addEventListener('WebViewJavascriptBridgeReady', function () {
callback(WebViewJavascriptBridge)
}, false)
}
}
connectWebViewJavascriptBridge(function (bridge) {
bridge.init(function (message, responseCallback) {
alert("message"+message)
document.cookie="token="+message;
// alert('token\ \ '+message);
$.ajax({
url:'/xxxx/xxxxx/xxxxx/',
type:'GET',
beforeSend:function(xhr){
alert("beforeSend "+message)
xhr.setRequestHeader('Authorization','token\ \ '+message)
},
success:function(resp){
alert("success "+message)
dealResp(resp,message)
},
error:function(err){
// alert("err")
console.log(err)
}
})
var data = {'Javascript Responds': 'Wee!'}
new Vue({
el: "#vue-app",
template: "#app-template",
data:{
tab: 1,
},
events: {
'bridgeEvt': function(obj) {
bridge.send(JSON.stringify(obj),function(responseData){
console.log(responseData);
})
}
},
ready: function(){
if(/notice_type=2/.test(location.href)) {
this.tab = 2
}
},
});
responseCallback(data)
})
})
</script>
这里主要看一下对message的处理,首先吧token值存到cookie里面,这样其他的页面都可以通过cookie来获取到登录token了。然后ajax get请求的时候设置请求头信息xhr.setRequestHeader(‘Authorization’,’token\ \ ‘+message)这个键值对是需要后台来识别登录信息的。
问题描述2:app端打开的web页又跳转了好几个web页,点击返回键所有的页面都被关闭了,直接返回到了原生页面。(老版本的微信的公众号推出的文章就有这个问题,现在已经修复了)
解决方案:
1.Android端
重写当前web所在的activity的onBackPressed()方法
@Override
public void onBackPressed() {
if(null != mWebView && mWebView.canGoBack()){
mWebView.goBack();
}else{
super.onBackPressed();
}
}
这样可以实现网页的后退。
but
没那么简单。问题并不是这么简单就解决了。你会发现当你返回到上一个web页面的时候你的ajax请求的数据不会变!(比如在第一个页面你是要认证,第二个页面处理完认证,第一个页面的认证需要变成已认证)这里数据不能重新获取的原因是,通过webView.goBack()方法是不会发送js数据的。因此不会去执行请求数据的ajax请求。
2web端
因为cookie值是网页通用的(同网段),所以在接收js数据的web页面也通过cookie获取一次token。
<script>
function connectWebViewJavascriptBridge(callback) {
if (window.WebViewJavascriptBridge) {
callback(WebViewJavascriptBridge)
} else {
document.addEventListener('WebViewJavascriptBridgeReady', function () {
callback(WebViewJavascriptBridge)
}, false)
}
}
connectWebViewJavascriptBridge(function (bridge) {
var cookieToken = document.cookie.split(";")[0].split("token=")[1];
alert("cookieToken = "+cookieToken);
if(cookieToken){
$.ajax({
url:'/xxxxx/xxxx/xxxxxx/',
type:'GET',
beforeSend:function(xhr){
// alert("beforeSend")
xhr.setRequestHeader('Authorization','token\ \ '+cookieToken)
},
success:function(resp){
// alert("success")
dealResp(resp,cookieToken)
},
error:function(err){
// alert("err")
console.log(err)
}
})
}
bridge.init(function (message, responseCallback) {
alert("message"+message)
document.cookie="token="+message;
// alert('token\ \ '+message);
$.ajax({
url:'/xxxxx/xxx/xxxxxx/',
type:'GET',
beforeSend:function(xhr){
alert("beforeSend "+message)
xhr.setRequestHeader('Authorization','token\ \ '+message)
},
success:function(resp){
alert("success "+message)
dealResp(resp,message)
},
error:function(err){
// alert("err")
console.log(err)
}
})
var data = {'Javascript Responds': 'Wee!'}
new Vue({
el: "#vue-app",
template: "#app-template",
data:{
tab: 1,
},
events: {
'bridgeEvt': function(obj) {
bridge.send(JSON.stringify(obj),function(responseData){
console.log(responseData);
})
}
},
ready: function(){
if(/notice_type=2/.test(location.href)) {
this.tab = 2
}
},
});
responseCallback(data)
})
})
</script>
至此web页返回上一页即可刷新数据了。
你以为Android与web的缠绵就此结束了吗?请看下面的问题
问题描述3:用户退出当前账号,换一个账号之后,web页获取的信息是前一个用户的信息??
解决方案:原因:前一个用户打开了web页,cookie被赋值了,后一个用户登录再打开web页时依然使用的是前一个用户的cookie所以web页获取的信息依然是前一个用户的信息。解决方法:在web页返回到Android原生页面的时候将webView的cookie值清除。
Android代码重写onBackPressed()方法。
@Override
public void onBackPressed() {
if(null != mWebView && mWebView.canGoBack()){
mWebView.goBack();
}else{
CookieSyncManager.createInstance(mContext);
CookieManager.getInstance().removeAllCookie();
super.onBackPressed();
}
}
并且需要让webView不留缓存。
mWebView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
暂时遇到的问题就这么多,还有问题会再补充。如果有更好的解决方案,还望各路大神指点。