ANDROID : 在 Webview 和 httpclient 之间共享会话

Posted

技术标签:

【中文标题】ANDROID : 在 Webview 和 httpclient 之间共享会话【英文标题】:ANDROID : Share session between Webview and httpclient 【发布时间】:2012-06-28 18:45:23 【问题描述】:

我实际上在我的 WebView 中有一个记录的会话。 但我也使用 httpclient 从网络发送和获取数据。我在网上看到无法获取 WebView 的内容,所以我需要使用我的 httpclient 从 webservice 获取数据。

问题是这个网络服务使用了会话……而我的会话在我的 WebView 中,所以 httpclient 没有它,我无法访问网络服务的内容。

我看到很多关于这个问题的帖子,但我不明白解决方案。

这是我在 onPageStarted 上所做的:

CookieManager mgr = CookieManager.getInstance();
Log.i( "URL", url );
Log.i("Cookie",mgr.getCookie("mywebsite.com"));
String cookie_string = mgr.getCookie("mywebsite.com");
if(cookie_string.length() > 1)                     
    Data.instance().getPref().edit().putString("cookie",cookie_string).commit();

我看到我有这种东西,所以我希望那些也包括会话: (我删除了号码)

__utma=......(number)......; 

__utmc=number;

__utmz=number.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); 

wt3_eid=%number%number; 

wt3_sid=%number

然后我不知道该怎么做才能在我的 httpclient 中设置这个 cookie。我试了一下,没有成功:

HttpClient client = new DefaultHttpClient();
BasicCookieStore cookieStore = new BasicCookieStore();
String login_cookie_string = Data.instance().getPref().getString("cookie", "");
String[] cookie_parts = null;
if(login_cookie_string.length()> 0)


    //debug_view.setText(login_cookie_string);
    Log.d("COOKIE", login_cookie_string);
    cookie_parts = login_cookie_string.split(";");

    for(int t=0;t < cookie_parts.length;t++)
    
        String[] cookieContent = cookie_parts[t].split("=");
        Cookie login_cookie = new BasicClientCookie(cookieContent[0],cookieContent[1]);
        ((BasicClientCookie) login_cookie).setDomain("mywebsite.com");
        cookieStore.addCookie(login_cookie);
    


((AbstractHttpClient) client).setCookieStore(cookieStore);

【问题讨论】:

通过 WebScarab 或 Fiddler 等代理路由流量,以找出 WebView 和 httpclient 请求之间的剩余差异。 【参考方案1】:

所以,这就是我所做的,它对我有用 -

HttpRequestBase request = new HttpGet(uri);
request.addHeader("Cookie", getCookieFromAppCookieManager(uri.toString()));

现在getCookieFromAppCookieManager的实现如下- 该方法从应用程序 CookieManager 获取给定 URL 的 cookie。应用程序 CookieManager 管理应用程序的 WebView 实例使用的 cookie。

@param url the URL for which the cookies are requested
@return value the cookies as a string, using the format of the 'Cookie' HTTP request header
@throws MalformedURLException


public static String getCookieFromAppCookieManager(String url) throws MalformedURLException 
    CookieManager cookieManager = CookieManager.getInstance();
    if (cookieManager == null)
        return null;
    String rawCookieHeader = null;
    URL parsedURL = new URL(url);

    // Extract Set-Cookie header value from android app CookieManager for this URL
    rawCookieHeader = cookieManager.getCookie(parsedURL.getHost());
    if (rawCookieHeader == null)
        return null;
    return rawCookieHeader;

【讨论】:

如果您只想与本机代码(即 httpclient)共享 webview cookie,对我来说效果很好 我无法取回 sessionid cookie。为什么? 如果你使用 https,你会发现这很有用: rawCookieHeader = cookieManager.getCookie("https://" + parsedURL.getHost());和工作!【参考方案2】:

按照这个教程:

http://metatroid.com/article/Android:%20handling%20web%20service%20authentication

================================这里网页的内容=====

您可能会发现自己在 Android 中所做的事情是 Web 身份验证。 大多数网站都会发布一个 cookie 来跟踪会话 ID 并保持用户登录。为了保持这种身份验证,您需要在活动之间以及 http 客户端和 webview 之间保持 cookie 同步。

我最终采用的方法似乎运行良好,它是创建一个扩展 Application 的类,然后定义一个 HttpClient 以在整个 Application 的其余部分中使用。该代码如下所示:

public class AppSettings extends Application 
    private static final DefaultHttpClient client = createClient();

    @Override
    public void onCreate()
    

    static DefaultHttpClient getClient()
            return client;
    
    private static DefaultHttpClient createClient()
            BasicHttpParams params = new BasicHttpParams();
            SchemeRegistry schemeRegistry = new SchemeRegistry();
            schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
            final SSLSocketFactory sslSocketFactory = SSLSocketFactory.getSocketFactory();
            schemeRegistry.register(new Scheme("https", sslSocketFactory, 443));
            ClientConnectionManager cm = new ThreadSafeClientConnManager(params, schemeRegistry);
            DefaultHttpClient httpclient = new DefaultHttpClient(cm, params);
            httpclient.getCookieStore().getCookies();
            return httpclient;
    

该类还创建了一个适用于 AsyncTasks 并同时发出多个 http 请求的 HttpClient。为 ClientConnectionManager 使用 ThreadSafeClientConnManager 可以让您在 AsyncTasks 中运行 http 请求,而不会在您按下后退按钮并开始第二个或第三个时导致强制关闭。

它还会创建一个可以在您的所有活动中访问的默认 cookie 存储。您可以通过调用 getClient() 方法在其他活动中使用它。

例如

public class SomeActivity extends Activity 
        static DefaultHttpClient mClient = AppSettings.getClient();
        ...
        try 

            HttpGet httpget = new HttpGet('URL');
            HttpResponse response;
            response = mClient.execute(httpget);
            ...
        
        ...
    

如果您发现有必要使用 web 视图并需要它来访问和使用与您的客户端相同的 cookie。您可以使用 CookieManager 同步客户端的 cookie 存储:(在 onPageStarted 方法中)

DefaultHttpClient mClient = AppSettings.getClient();


Cookie sessionInfo;
List<Cookie> cookies = mClient.getCookieStore().getCookies();

if (! cookies.isEmpty())
        CookieSyncManager.createInstance(getApplicationContext());
        CookieManager cookieManager = CookieManager.getInstance();

        for(Cookie cookie : cookies)
                sessionInfo = cookie;
                String cookieString = sessionInfo.getName() + "=" + sessionInfo.getValue() + "; domain=" + sessionInfo.getDomain();
                cookieManager.setCookie("example.com", cookieString);
                CookieSyncManager.getInstance().sync();
        

您需要将 example.com 切换到正确的域。

【讨论】:

以上是关于ANDROID : 在 Webview 和 httpclient 之间共享会话的主要内容,如果未能解决你的问题,请参考以下文章

Android 下的 WebView 中数据如何保存

ANDROID : 在 Webview 和 httpclient 之间共享会话

WebView在android中加载缓慢?

Android Webview 和Javascript交互,实现Android和JavaScript相互调用

在 android 应用中处理 textview 和 webview 链接

在 webView 和 CordovaWebView android 之间共享 localStorage