Поддерживать сеанс cookie в Android

Хорошо, у меня есть приложение для Android, в котором есть форма, два EditText, spinner и кнопка входа. Пользователь выбирает услугу со счетчика, вводит имя пользователя и пароль и нажимает логин. Данные отправляются через POST, возвращается ответ, обрабатываются, запускается новый WebView, загружается строка html, генерируемая из ответа, и у меня есть домашняя страница любой выбранной пользователем службы.

Это все хорошо и хорошо. Теперь, когда пользователь нажимает на ссылку, информация для входа не может быть найдена, и страница просит пользователя снова войти в систему. Мой сеанс регистрации куда-то куда-то удаляется, и я не уверен, как передать информацию из класса, который контролирует основную часть моего приложения, в класс, который только запускает активность веб-просмотра.

Обработчик 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. Кажется, что работает для одной службы, в которую я вхожу, что я знаю, хранит файлы cookie на сервере (старые, архаичные, но это работает, и они не хотят его менять). Служба, которую я пытаюсь сейчас, требует от пользователя сохранения Cookie на локальной машине, и это не работает с этой настройкой.

Какие-либо предложения?

Вам нужно сохранить cookie от одного вызова другому. Вместо создания нового DefaultHttpClient используйте этот построитель:

 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; } 

И сохраните класс Builder как область вашего приложения.

Вы можете хранить файлы cookie в общих предпочтениях и загружать их по мере необходимости в другие действия.

Или попробуйте эту идею по аналогичному вопросу .

Использовать это при входе в URL-адрес

  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(); } 

Когда запускается любое новое действие (поэтому я предполагаю, что это то же самое, когда вы запускаете новый веб-просмотр), он эффективно запускает новую программу с нуля. Это новое действие не будет иметь доступа к данным из любой предыдущей деятельности (если только эти данные не будут переданы путем присоединения к намерению).

2 возможных решения:

1) putExtra может использоваться только для передачи примитивных данных, поэтому, чтобы передать что-то более сложное, вам нужно либо

  • A) Оберните более сложную структуру в классе, который реализует
    Удобный интерфейс, который может быть сохранен дополнительно.

    B) Оберните более сложную структуру в классе, который реализует
    Интерфейс Serializable, который может быть сохранен дополнительно.

Любой из этих подходов является довольно сложным и справедливым.

2) Лично я предпочитаю подход, предложенный rds. Чтобы уточнить, когда rds говорит:

Сохраните класс Builder как поле вашего приложения.

Я думаю, что он означает расширение класса приложения. Все хранящиеся там объекты доступны во всем мире для всех видов деятельности. В этой статье очень четко объясняется, как это сделать: http://www.screaming-penguin.com/node/7746 Вы можете игнорировать материал об AsyncTask (хотя я уверен, что в какой-то момент вам это понадобится) И просто сосредоточиться на части о расширении класса приложения.

У меня эта знакомая проблема несколько недель назад, потому что вы создаете новый DefaultHttpClient каждый раз, когда вы нажимаете кнопку. Попробуйте создать один DefaultHttpClient и используя тот же DefaultHttpClient для каждого запроса, который вы пытаетесь отправить. Он решил мою проблему

Вы использовали эту строку –

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

Чтобы каждый раз получать новый cookie.

Похоже, вы прошли через ту же проблему, что и я, проверьте ниже ссылку –

RemoveSessionCookie () проблема android (code.google., Com)

Он говорит, что removeSessionCookie() реализуется в потоке, поэтому всякий раз, когда он вызывается; Начинается поток и после вашего setCookie(url, cookieString); , Он удаляет новый cookie, который вы только что установили. Поэтому для некоторых устройств он работает хорошо, поскольку removeSessionCookie() уже выполнен, а для некоторых он удаляет файл cookie, и мы получаем эту проблему.

Я предлагаю удалить этот removeSessionCookie(); Поскольку вы устанавливаете только один файл cookie, поэтому он не будет конфликтовать с другими файлами cookie. Ваш код будет работать без проблем.

Sever использует sessionID, хранящийся в файлах cookie, чтобы идентифицировать specfic пользователя. Каждый язык имеет другое имя sessionID в заголовках http. Вы можете использовать какой-либо сетевой инструмент или браузер, чтобы узнать, как называется имя sessionID.

И другим способом, я УГАДАЮ, facebook и твиттер, вы удалите весь код, связанный с сеансом, на сервере используется токен доступа для идентификации пользователя.

Я чист?