2010-06-14 4 views
15

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

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

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 на локальной машине, и это не работает с этой настройкой.

Любые предложения?

ответ

1

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

Попробуйте эту идею от similar question.

0

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

+2

Уверен, но это пустая трата памяти для хранения всего 'DefaultHttpClient', когда вам просто нужен файл cookie. – rds

0

Незнайка, если вы все еще нужен ответ, но опять-таки здесь приходит некоторая дополнительная информация, которая может помочь

если вы хотите держать печенье синхронизированы

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

вы должны держать печенье от одного вызова к другому. Вместо создания нового 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 <[email protected]> 
*/ 
private HttpClient getHttpClient() { 
     final DefaultHttpClient httpClient = new DefaultHttpClient(); 
     synchronized (mLock) { 
       if (mCookie == null) { 
         mCookie = httpClient.getCookieStore(); 
       } else { 
         httpClient.setCookieStore(mCookie); 
       } 
     } 
     return httpClient; 
} 

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

0

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

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

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

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

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

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

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

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

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

1

Используйте это в 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(); 
    } 
0

Вы использовали эту линию -

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

Для того, чтобы убедиться, что вы получите новый куки каждый раз.

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

removeSessionCookie() issue of android (code.google.,com)

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

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

0

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

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

Am i clear?

Смежные вопросы