編輯:關於Android編程
前幾天,項目組有個技術問題,想用本地加載html, js寫cookie的方法,繞過去。
想法是沒有問題的, 但是測試的時候發現, 每次重新打開App, 都取不到以前Cookie裡面設的值。
後來去App/data下面找WebView.db,打開來一看,cookie情報根本沒有存。
原因是js寫cookie的時候,沒有指明expire, WebKit默認把它當成臨時cookie, webview終了之後就丟失了。
這個問題本身不復雜,不過趁機我看了一把Andorid底層讀取Cookie的source root:
以下source root,轉載請注明出自《南湖邊上的小木屋》
1. 取Cookie的API
[java]
CookieManager.getInstance().getCookie(url);
2.CookieManager的getInstance()
[java]
/**
* Gets the singleton CookieManager instance. If this method is used
* before the application instantiates a {@link WebView} instance,
* {@link CookieSyncManager#createInstance(Context)} must be called
* first.
*
* @return the singleton CookieManager instance
*/
public static synchronized CookieManager getInstance() {
return WebViewFactory.getProvider().getCookieManager();
}
3.WebViewFactory是個工廠模式,額
[java]
static synchronized WebViewFactoryProvider getProvider() {
// For now the main purpose of this function (and the factory abstraction) is to keep
// us honest and minimize usage of WebViewClassic internals when binding the proxy.
if (sProviderInstance != null) return sProviderInstance;
sProviderInstance = getFactoryByName(DEFAULT_WEB_VIEW_FACTORY);
if (sProviderInstance == null) {
if (DEBUG) Log.v(LOGTAG, "Falling back to explicit linkage");
sProviderInstance = new WebViewClassic.Factory();
}
return sProviderInstance;
}
4.層層嵌套,最後生成的instance是CookieManagerClassic
[java]
@Override
public CookieManager getCookieManager() {
return CookieManagerClassic.getInstance();
}
5. getCookie方法 實現在CookieManagerClassic上
[java]
@Override
public String getCookie(String url) {
return getCookie(url, false);
}
@Override
public String getCookie(String url, boolean privateBrowsing) {
WebAddress uri;
try {
uri = new WebAddress(url);
} catch (ParseException ex) {
Log.e(LOGTAG, "Bad address: " + url);
return null;
}
return nativeGetCookie(uri.toString(), privateBrowsing);
}
6. nativeGetCookie定義在CookieManager.cpp裡, 恩。。。。JNI。。。
[java]
static jstring getCookie(JNIEnv* env, jobject, jstring url, jboolean privateBrowsing)
{
GURL gurl(jstringToStdString(env, url));
CookieOptions options;
options.set_include_httponly();
std::string cookies = WebCookieJar::get(privateBrowsing)->cookieStore()->GetCookieMonster()->GetCookiesWithOptions(gurl, options);
return stdStringToJstring(env, cookies);
}
7. WebCookieJar.cpp中,定義了從哪裡去取得Cookie情報
[java]
WebCookieJar* WebCookieJar::get(bool isPrivateBrowsing)
{
MutexLocker lock(instanceMutex);
if (!isFirstInstanceCreated && fileSchemeCookiesEnabled)
net::CookieMonster::EnableFileScheme();
isFirstInstanceCreated = true;
scoped_refptr<WebCookieJar>* instancePtr = instance(isPrivateBrowsing);
if (!instancePtr->get())
*instancePtr = new WebCookieJar(databaseDirectory(isPrivateBrowsing));
return instancePtr->get();
}
[java]
static std::string databaseDirectory(bool isPrivateBrowsing)
{
static const char* const kDatabaseFilename = "/webviewCookiesChromium.db";
static const char* const kDatabaseFilenamePrivateBrowsing = "/webviewCookiesChromiumPrivate.db";
std::string databaseFilePath = databaseDirectory();
databaseFilePath.append(isPrivateBrowsing ? kDatabaseFilenamePrivateBrowsing : kDatabaseFilename);
return databaseFilePath;
}
※Android3.0以上是webviewCookiesChromium.db, 以下是WebView.db文件
8.最後讀取Cookie情報發生在cookie_monster.cc。 額,最後調到C++, 去讀.db文件,無敵了
[java]
std::string CookieMonster::GetCookiesWithOptions(const GURL& url,
const CookieOptions& options) {
base::AutoLock autolock(lock_);
InitIfNecessary();
if (!HasCookieableScheme(url)) {
return std::string();
}
TimeTicks start_time(TimeTicks::Now());
// Get the cookies for this host and its domain(s).
std::vector<CanonicalCookie*> cookies;
FindCookiesForHostAndDomain(url, options, true, &cookies);
std::sort(cookies.begin(), cookies.end(), CookieSorter);
std::string cookie_line;
for (std::vector<CanonicalCookie*>::const_iterator it = cookies.begin();
it != cookies.end(); ++it) {
if (it != cookies.begin())
cookie_line += "; ";
// In Mozilla if you set a cookie like AAAA, it will have an empty token
// and a value of AAAA. When it sends the cookie back, it will send AAAA,
// so we need to avoid sending =AAAA for a blank token value.
if (!(*it)->Name().empty())
cookie_line += (*it)->Name() + "=";
cookie_line += (*it)->Value();
}
histogram_time_get_->AddTime(TimeTicks::Now() - start_time);
VLOG(kVlogGetCookies) << "GetCookies() result: " << cookie_line;
return cookie_line;
}
#以上#
TableLayout經常用到的屬性有:android:collapseColumns:以第0行為序,隱藏指定的列:android:collapseColumns該屬性為
在Android開發中,我們經常會遇到這樣一種情況:在UI界面上進行某項操作後要執行一段很耗時的代碼,比如我們在界面上點擊了一個”下載“按鈕,那麼我們需要執行網絡請求,這
本文介紹了ListView給每個Item上面的按鈕添加事件,具體如下:1.先看下效果圖:在這裡僅供測試,我把數據都寫死了,根據需要可以自己進行修改,此外實現ListVie
Service 是一個可以在後台執行長時間運行操作而不使用用戶界面的應用組件。 例如,服務可以處理網絡事務、播放音樂,執行文件 I/O 或與內容提供程序交互,而所有這一切