最近有个需求是这样的:在应用中添加一个商城,商城的实现是H5(包括登录)。需要将这个H5嵌到原生应用中,并在原生代码中添加支付功能。
接到这个需求的时候,想这不是很简单么,用WebView加载这个页面,通过Js回调原生方法,然后调用第三方支付,完工。
然而到实际开发的时候,问题就出现了。
首先的问题是:
1.在商城中,点击了一个商品,然后确认购买。
2.此时没有登录,会跳到登录界面。
3.没关系,那就登录一下。
4.登录完后,再次点击这个商品,然后去购买。
5.然后问题就出现了,前面不是登录过了吗?怎么还跳到登录界面了?
分析:
一开始以为是H5写的不对,然而我用浏览器打开的时候,是好的,跳转也正常,所以,还是WebView设置的有问题。
一通百度之后,初步断定是Cookie同步的问题,但是网络这一块一直不太懂,当下也没时间细细研究,所以就照着百度所得之后一步步尝试。下面是我的解决方法。
解决方法:
初始化WebView
private voidinitWebView() {
WebSettings webSettings=webview.getSettings();//设置编码
webSettings.setDefaultTextEncodingName("utf-8");
webSettings.setTextZoom(100);//自适应屏幕
webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
webSettings.setLoadWithOverviewMode(true);//支持js
webSettings.setJavaScriptEnabled(true);//设置本地调用对象及其接口
jsBridge = newJavaScriptBridge(getActivity(), webview);
webview.addJavascriptInterface(jsBridge,"Native");
CookieManager mCookieManager=CookieManager.getInstance();
mCookieManager.setAcceptCookie(true);
mCookieManager.setAcceptThirdPartyCookies(webview,true);
webview.setWebViewClient(newWebViewClient() {
@Overridepublic voidonPageStarted(WebView view, String url, Bitmap favicon) {super.onPageStarted(view, url, favicon);
}
@Overridepublic voidonPageFinished(WebView view, String url) {// //获取webview里面的cookie信息
CookieManager cookieManager =CookieManager.getInstance();
cookieManager.setAcceptCookie(true);
String cookieStr=cookieManager.getCookie(url);
saveCookies(cookieStr);
progressBar.setVisibility(View.GONE);
}
@Overridepublic void onReceivedError(WebView view, int errorCode, String description, finalString failingUrl) {
}public booleanshouldOverrideUrlLoading(WebView view, String url) {if (url.startsWith("http") || url.startsWith("https")) {if (url.startsWith("http://shop.yinm")) { //这个WebView是通用的,只对这个商城的链接做Cookie操作。
syncCookie(getContext(), url);
}
view.loadUrl(url);return false;
}else{//其他的URL则会开启一个Acitity然后去调用原生APP
try{
Intent in= newIntent(Intent.ACTION_VIEW, Uri.parse(url));
in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(in);
view.stopLoading();
}catch(Exception e) {
e.printStackTrace();
}return true;
}
}
});
}
View Code
在onPageFinished的时候,保存Cookie
private voidsaveCookies(String cookieString) {
sp.edit().putString("cook", cookieString).apply();
}
View Code
在loadUrl(url)前,同步Cookie
private voidsyncCookie(Context context, String url){try{
CookieSyncManager.createInstance(context);
CookieManager cookieManager=CookieManager.getInstance();
cookieManager.setAcceptCookie(true);
cookieManager.removeSessionCookie();//移除//log
String oldCookie =cookieManager.getCookie(url);if(oldCookie != null){
android.util.Log.i("zxy", "getCookie oldCookie " +oldCookie);
}
String cookie= sp.getString("cook", "");
String[] cookies= cookie.split(";");if (!TextUtils.isEmpty(cookie)) {for(String cook : cookies) {
cookieManager.setCookie(url, cook.trim());//一定要一个一个set, 如果是拼接的话,设置不成功。
}
}//最后一定要调用
CookieSyncManager.getInstance().sync();//log
String newCookie =cookieManager.getCookie(url);if(newCookie != null){
android.util.Log.i("zxy", "getCookie newCookie " +newCookie);
}
}catch(Exception e){
android.util.Log.i("zxy", "getCookie failed" +e.toString());
}
}
View Code
这样,就可以实现Cookie同步了。
(网路这一块,找个时间要好好补补)