在Android中维护Cookie会话

好吧,我有一个Android应用程序,它有一个窗体,两个EditText,一个微调和一个loginbutton。 用户从微调器中select服务,键入他们的用户名和密码,然后单击login。 通过POST发送数据,返回响应,处理数据,启动新的WebView,从响应中生成的htmlstring被加载,并且我拥有用户select的任何服务的主页。

这一切都很好。 现在,当用户点击一个链接时,找不到login信息,页面会要求用户重新login。 我的login会话正在放弃某处,我不确定如何将控制我的应用程序的主要部分的类的信息传递给刚刚启动webview活动的类。

来自表单loginbutton的onClick处理程序:

private class FormOnClickListener implements View.OnClickListener { public void onClick(View v) { String actionURL, user, pwd, user_field, pwd_field; actionURL = "thePageURL"; user_field = "username"; //this changes based on selections in a spinner pwd_field = "password"; //this changes based on selections in a spinner user = "theUserLogin"; pwd = "theUserPassword"; List<NameValuePair> myList = new ArrayList<NameValuePair>(); myList.add(new BasicNameValuePair(user_field, user)); myList.add(new BasicNameValuePair(pwd_field, pwd)); HttpParams params = new BasicHttpParams(); DefaultHttpClient client = new DefaultHttpClient(params); HttpPost post = new HttpPost(actionURL); HttpResponse response = null; BasicResponseHandler myHandler = new BasicResponseHandler(); String endResult = null; try { post.setEntity(new UrlEncodedFormEntity(myList)); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } try { response = client.execute(post); } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } try { endResult = myHandler.handleResponse(response); } catch (HttpResponseException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } List<Cookie> cookies = client.getCookieStore().getCookies(); if (!cookies.isEmpty()) { for (int i = 0; i < cookies.size(); i++) { cookie = cookies.get(i); } } Intent myWebViewIntent = new Intent(MsidePortal.this, MyWebView.class); myWebViewIntent.putExtra("htmlString", endResult); myWebViewIntent.putExtra("actionURL", actionURL); startActivity(myWebViewIntent); } } 

这里是处理响应显示的WebView类:

 public class MyWebView extends android.app.Activity { private class MyWebViewClient extends WebViewClient { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { view.loadUrl(url); return true; } } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.web); MyWebViewClient myClient = new MyWebViewClient(); WebView webview = (WebView)findViewById(R.id.mainwebview); webview.getSettings().setBuiltInZoomControls(true); webview.getSettings().setJavaScriptEnabled(true); webview.setWebViewClient(myClient); Bundle extras = getIntent().getExtras(); if(extras != null) { // Get endResult String htmlString = extras.getString("htmlString"); String actionURL = extras.getString("actionURL"); Cookie sessionCookie = MsidePortal.cookie; CookieSyncManager.createInstance(this); CookieManager cookieManager = CookieManager.getInstance(); if (sessionCookie != null) { cookieManager.removeSessionCookie(); String cookieString = sessionCookie.getName() + "=" + sessionCookie.getValue() + "; domain=" + sessionCookie.getDomain(); cookieManager.setCookie(actionURL, cookieString); CookieSyncManager.getInstance().sync(); } webview.loadDataWithBaseURL(actionURL, htmlString, "text/html", "utf-8", actionURL);} } } } 

我已经混合成功实施该cookie解决scheme。 它似乎工作,我login到一个服务,我知道保持在服务器上的cookie(旧的,古老的,但它的工作,他们不想改变它。)我现在尝试的服务需要用户保持cookie在他们的本地机器上,而且不能用这个设置。

有什么build议么?

Related of "在Android中维护Cookie会话"

你需要保持cookie从一个电话到另一个。 而不是创build一个新的DefaultHttpClient,使用这个构build器:

 private Object mLock = new Object(); private CookieStore mCookie = null; /** * Builds a new HttpClient with the same CookieStore than the previous one. * This allows to follow the http session, without keeping in memory the * full DefaultHttpClient. * @author Régis Décamps <decamps@users.sf.net> */ private HttpClient getHttpClient() { final DefaultHttpClient httpClient = new DefaultHttpClient(); synchronized (mLock) { if (mCookie == null) { mCookie = httpClient.getCookieStore(); } else { httpClient.setCookieStore(mCookie); } } return httpClient; } 

并保持生成器类作为您的应用程序的领域。

您可以将Cookie存储在共享首选项中,并根据需要将其加载到其他活动中。

或者从类似的问题尝试这个想法。

在urllogin活动中使用这个

  List<Cookie> cookies = client.getCookieStore().getCookies(); if (!cookies.isEmpty()) { for (int i = 0; i < cookies.size(); i++) { cookie = cookies.get(i); } } Cookie sessionCookie = cookie; if (sessionCookie != null) { String cookieString = sessionCookie.getName() + "=" + sessionCookie.getValue() + "; domain=" + sessionCookie.getDomain(); cookieManager .setCookie("www.mydomain.com", cookieString); CookieSyncManager.getInstance().sync(); } 

不知道如果你仍然需要一个答案,但这里又来了一些额外的信息,可能会有所帮助

如果你想保持cookie同步

 // ensure any cookies set by the dialog are saved CookieSyncManager.getInstance().sync(); 

如果你想清除Cookies

 public static void clearCookies(Context context) { // Edge case: an illegal state exception is thrown if an instance of // CookieSyncManager has not be created. CookieSyncManager is normally // created by a WebKit view, but this might happen if you start the // app, restore saved state, and click logout before running a UI // dialog in a WebView -- in which case the app crashes @SuppressWarnings("unused") CookieSyncManager cookieSyncMngr = CookieSyncManager.createInstance(context); CookieManager cookieManager = CookieManager.getInstance(); cookieManager.removeAllCookie(); } 

当任何新的活动启动(所以我认为这是相同的,当你启动一个新的web视图),它是从头开始有效地启动一个新的程序。 这个新的活动将不能访问任何先前活动的数据(除非该数据是通过附加到该意图传递的)。

2可能的解决scheme

1)putExtra只能用来传递原始数据,所以要传递一些更复杂的东西

  • a)将更复杂的结构包装在一个实现该类的类中
    Parcelable接口,可以存储在一个额外的。

    b)把更复杂的结构包装在一个实现这个过程的类中
    可串行化的接口,可以存储在一个额外的。

这两种方法中的任何一种都相当复杂,而且工作量相当大。

2)我个人更喜欢rdsbuild议的方法。 为了澄清,当rds说:

保持Builder类作为你的应用程序的一个字段。

我认为他的意思是扩展应用程序类。 存储在那里的任何属性都可用于全部活动。 这篇文章非常清楚地解释了如何做到这一点: http : //www.screaming-penguin.com/node/7746你可以忽略关于AsyncTask的东西(虽然我相信你会发现在某些时候需要)只关注扩展应用程序类的部分。

我几个星期前就有这个类似的问题,那是因为每次单击button时都会创build一个新的DefaultHttpClient。尝试创build一个DefaultHttpClient,并为每个要发送的请求使用相同的DefaultHttpClient。 它解决了我的问题

你已经使用这一行 –

  if (sessionCookie != null) { cookieManager.removeSessionCookie(); } 

确保您每次都收到新的cookie。

似乎你已经经历了同样的问题,我面临,检查下面的链接 –

android(code.google。com)的removeSessionCookie()问题

它说removeSessionCookie()是在一个线程中实现的,所以每当它被调用的时候; 一个线程启动后,你的setCookie(url, cookieString); 被调用,它将删除刚刚设置的新cookie。 所以对于一些设备来说它工作得很好,因为removeSessionCookie()已经被执行了,而对于一些设备,它会删除cookie,并且我们会遇到这个问题。

我build议你删除这个removeSessionCookie(); 因为您只设置一个cookie,所以不会与其他cookie冲突。 您的代码将无缝工作。

Sever使用cookie中存储的sessionID来标识特定用户。每个语言在http头文件中都有一个不同的sessionID名称。您可以使用一些networking工具或浏览器来查看sessionID所称的名称。

还有其他一些方式,我用GUESS,facebook和twitter的方式,你会删除所有会话相关的代码,这是服务器使用Access Token来识别用户。

我清楚了吗?