android客戶端經過httpClient或者httpUrlConnection進行登陸後,爲了把登陸狀態同步到webView中,這時須要進行cookie的同步
javascript
參考:http://segmentfault.com/a/1190000002877843 php
一.cookie同步方式java
下面是登陸線程:android
public class LoginThread extends Thread{ private Handler loginHandler; public LoginThread(Handler loginHandler) { this.loginHandler = loginHandler; } @Override public void run() { List<String> cookieLst = new ArrayList<String>(); HttpParams httpParams = new BasicHttpParams(); ConnManagerParams.setMaxTotalConnections(httpParams, 5); ConnManagerParams.setTimeout(httpParams, 15*1000); HttpConnectionParams.setSoTimeout(httpParams, 10*1000); HttpConnectionParams.setTcpNoDelay(httpParams, true); HttpPost httpPost = new HttpPost("http://192.168.1.107/cookie/login.php"); List<NameValuePair> nvPairs = new ArrayList<NameValuePair>(); nvPairs.add(new BasicNameValuePair("name", "lisi")); nvPairs.add(new BasicNameValuePair("age","22")); nvPairs.add(new BasicNameValuePair("gender", "男")); try { UrlEncodedFormEntity entity = new UrlEncodedFormEntity(nvPairs, HTTP.UTF_8); httpPost.setEntity(entity); HttpClient httpClient = new DefaultHttpClient(); //Cookie可能獲取不到,所以有必要調用瀏覽器兼容模式 HttpClientParams.setCookiePolicy(httpClient.getParams(), CookiePolicy.BROWSER_COMPATIBILITY); HttpResponse httpResponse = httpClient.execute(httpPost); if(httpResponse!=null && httpResponse.getStatusLine().getStatusCode()==HttpStatus.SC_OK) { String content = EntityUtils.toString(httpResponse.getEntity()); Log.d("LOGIN", content); Header[] allHeaders = httpResponse.getAllHeaders(); if(allHeaders!=null) { //獲取cookie的第一種方式 for (Header header : allHeaders) { Log.d("LOGIN", header.getName()+"="+header.getValue()); if("Set-Cookie".equalsIgnoreCase(header.getName())) { cookieLst.add(header.getValue()); } } } //獲取cookie的第二種方式 AbstractHttpClient abstractHttpClient = (AbstractHttpClient) httpClient; CookieStore cookieStore = abstractHttpClient.getCookieStore(); List<Cookie> cookies = cookieStore.getCookies(); for (Cookie cookie : cookies) { Log.d("LOGIN-COOKIE", cookie.getName()+"="+cookie.getValue()+",path="+cookie.getPath()+",domain="+cookie.getDomain()+",expires="+cookie.getExpiryDate()); } if(loginHandler!=null) { Message msg = new Message(); msg.obj = cookieLst; msg.what = 200; msg.setTarget(loginHandler); msg.sendToTarget(); } } } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
下面是WebView主頁面Activityweb
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) public class Main extends Activity implements DownloadListener { private WebView mWebView; //extraHeaders經測試不能夠同步cookie private Map<String, String> extraHeaders; private final String TAG = "WEB_VIEW"; private final Handler loginHandler = new Handler(){ @Override public void handleMessage(Message msg) { if(msg.what==200) { List<String> cookies = (List<String>) msg.obj; if(cookies!=null) { syncCookieToWebView(cookies); mWebView.loadUrl("http://192.168.1.107/cookie/read.php"); } }else{ super.handleMessage(msg); } } }; @SuppressLint("SetJavaScriptEnabled") @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mWebView = (WebView) findViewById(R.id.main_webview); WebSettings settings = mWebView.getSettings(); settings.setAppCacheEnabled(true); settings.setCacheMode(WebSettings.LOAD_DEFAULT); settings.setGeolocationEnabled(true); settings.setUseWideViewPort(true); settings.setSaveFormData(true); settings.setSavePassword(true); settings.setSupportZoom(false); settings.setLoadsImagesAutomatically(true); settings.setBlockNetworkImage(false); if(android.os.Build.VERSION.SDK_INT>=11) { settings.setEnableSmoothTransition(true); } settings.setJavaScriptCanOpenWindowsAutomatically(false); settings.setAllowFileAccess(false); settings.setJavaScriptEnabled(true); String userAgent = settings.getUserAgentString(); Log.d(TAG, userAgent); if(android.os.Build.VERSION.SDK_INT>=14) { mWebView.setFitsSystemWindows(true); } if(mWebView.isHardwareAccelerated()) { mWebView.setLayerType(View.LAYER_TYPE_HARDWARE, null); } mWebView.setKeepScreenOn(true); extraHeaders = new IdentityHashMap<String, String>(); mWebView.setWebViewClient(new WebViewClient(){ @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { if(view!=null && !TextUtils.isEmpty(url)) { extraHeaders.put("control-cache", "no-cache,private"); extraHeaders.put("pragma", "no-cache,no-store"); extraHeaders.put("expires", "0"); view.loadUrl(url, extraHeaders); return true; } return super.shouldOverrideUrlLoading(view, url); } }); mWebView.setDownloadListener(this); //mWebView.loadUrl("http://shouji.baidu.com/software/?from=web_alad_multi"); new LoginThread(loginHandler).start(); } //銷燬webView @Override protected void onDestroy() { super.onDestroy(); mWebView.clearFormData(); mWebView.clearHistory(); mWebView.destroy(); } //監聽文件下載,WebView不會自動下載,須要咱們本身構建下載代碼 @Override public void onDownloadStart(String url, String userAgent,String contentDisposition, String mimetype, long contentLength) { Log.d(TAG, "url="+url); Log.d(TAG, "userAgent="+url); Log.d(TAG, "contentDisposition="+contentDisposition); Log.d(TAG, "mimetype="+mimetype); Log.d(TAG, "contentLength="+contentLength); //第一種下載方式是 自定義的http工具類 //new DownloadThread(url,contentDisposition,mimetype,contentLength).start(); //第二種下載方式是調用系統的webView,具備默認的進度條 Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse(url)); startActivity(intent); } /** * cookie同步 */ private void syncCookieToWebView(List<String> cookies) { CookieSyncManager.createInstance(Main.this); CookieManager cm = CookieManager.getInstance(); cm.setAcceptCookie(true); if(cookies!=null) { for (String cookie : cookies) { cm.setCookie("http://192.168.1.107:80",cookie);//注意端口號和域名,這種方式能夠同步全部cookie,包括sessionid } } CookieSyncManager.getInstance().sync(); } }
二.注意:平時開發中Cookie同步是最佳選項,但這並不意味着必定須要使用cookie同步,咱們可使用 token+用戶id+登陸時間校驗碼 進行同步登陸segmentfault
三.對於使用javaInterface進行同步登陸的問題瀏覽器
javaInterface風險性很高,若是android平臺是 4.2+比較安全,但4.2如下版本,安全性不容樂觀,好比經過反射形成硬盤被讀寫的可能性很高!安全
在android 4.2中增長了 @javainterface註解,而且將公開的方法異步化,這樣有效的控制了某些不必公開的方法被無心間做爲接口公開,致使js發射到硬盤的讀寫io類,從而發生文件被竊取,垃圾文件堆積,有害文件被下載等問題!cookie
四.目前來講讓全部人使用 4.2+以上版本可能性不大,但儘可能少使用javainterface,轉而使用 協議的方式,所謂協議,就是通訊協議,咱們能夠分析url參數,從而進行webView和native代碼的通訊session
mWebView.setWebViewClient(new WebViewClient(){ @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { //捕獲url的參數值 if(url.indexOf("login")>=0) { //客戶端代碼執行某部分操做----->執行完畢後經過url參數把執行結果返回webView }else if(url.indexOf("userCenter")>=0){ //客戶端代碼執行某部分操做----->執行完畢後經過url參數把執行結果返回webView } return super.shouldOverrideUrlLoading(view, url); } });
固然,javainterface不推薦,但徹底可使用
view.loadUrl("javascript:dosometing("+"'參數'"+")");
-------------------------------2015-04-30-更新,從webView讀取cookie--------------------------------
private class MyWebViewClient extends WebViewClient { public boolean shouldOverrideUrlLoading(WebView view, String url) { webview.loadUrl(url); return true; } public void onPageFinished(WebView view, String url) { CookieManager cookieManager = CookieManager.getInstance(); String CookieStr = cookieManager.getCookie(url); Log.e("sunzn", "Cookies = " + CookieStr); super.onPageFinished(view, url); } }