Android--browser java部分
7530 ワード
本文は主にbrowserのjava部分コードについて簡単に説明し、主線は基本的にbrowserを初めて開いてウェブページをロードする流れをめぐって展開され、ついでにApp層のいくつかの主要クラスの関係を述べた.browserの上位コードをより速く理解し、webkitの一部コードに注目する時間を割くことができます.webkitの一部のコードはとても多いですよ.まずlogcatのログ情報やbrowerアプリケーションのAndroidmanifest.xmlに基づいて、browserの最初のインタフェースを開くのはBrowserActivity.javaです.この中にはコードが少ないので、oncreate()の初期化動作に注目すればいいのですが、ここではまずクラスの関係を整理します.
2、現在のデバイスがphoneかpadかによってIを初期化し、
3.mUIをmControllerに渡し、後でUIを操作できるようにControllerにUIの参照を持たせます.
もう少し下を見て、controllerとUIの中に何があるか見てみましょう.Controllerのコンストラクション関数:
では、ここでまとめてみましょう.framework層のbrowserに対して、webview.java、CallBackproxy.java、BrowserFrame.java、WebCoreFrameBridgeといういくつかのクラスに重点を置いてみましょう.他のクラスはまだ気づいていません.ネット漏れの魚もいるに違いありませんが、まずこれらの主線クラスをつかんでから、細部のものはゆっくりしてください.
本文の物語もこれで終わり、説明する上ではandroidオリジナルブラウザjava部分コード呼び出しの流れの簡単な分析にすぎないが、実際にはアプリケーション層コード機能はウェブページ(webview)の管理と表示に偏っており、webkit自体とはあまりつながりがなく、例えばwebkitに興味があるだけで、webkit部分だけを見ることは完全に可能である.もちろんコードの規模は大きいので、理解するのに時間がかかります.
PS:現在のbrowser設定には実験室のオプションがあります.それは高速制御オプションがあります.それを開くと円形のメニュー機能が開きます.android 3.0のバージョンからこの機能があるようです.対応するコード実装はPieで始まるクラスコードです.これは動的制御で、固定座標のようなものではありません.興味のあるものは見てください.
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
if (IntentHandler.handleWebSearchIntent(this, null, getIntent())) {
finish();
return;
}
mController = new Controller(this, icicle == null);
boolean xlarge = isTablet(this);
if (xlarge) {
mUi = new XLargeUi(this, mController);
} else {
mUi = new PhoneUi(this, mController);
}
mController.setUi(mUi);
Bundle state = getIntent().getBundleExtra(EXTRA_STATE);
if (state != null && icicle == null) {
icicle = state;
}
mController.start(icicle, getIntent());
上のコードは以下のことをしました:1、新しいコントロールオブジェクト、2、現在のデバイスがphoneかpadかによってIを初期化し、
3.mUIをmControllerに渡し、後でUIを操作できるようにControllerにUIの参照を持たせます.
もう少し下を見て、controllerとUIの中に何があるか見てみましょう.Controllerのコンストラクション関数:
public Controller(Activity browser, boolean preloadCrashState) {
mActivity = browser;
mSettings = BrowserSettings.getInstance();
mTabControl = new TabControl(this);
mSettings.setController(this);
……….
mFactory = new BrowserWebViewFactory(browser);
……..
}
ここにTabを管理するTabcontrolがありますが、このTabは何ですか?これは、前のUIというインタフェースの実装を見ると、UIインタフェースの実装クラスはBaseUIであり、phoneUIとXlargerUIはBaseUI(ここでは典型的なオブジェクト向け設計)に継承されている.BaseUIはTitlebarとTabの2つの部分から構成されており、Titlebarは私たちがウェブサイトを見て入力した部分であり、Tabは次のページ部分であり、Tab.javaのコードの中で、私たちはwebviewオブジェクトを見つけることができ、Tabがwebviewを1層包装したと理解できる.またcontrollerというクラスに戻って、controllerはwebviewCotrollerを実現したことに注意して、UiControllerインタフェースの(tabcontrollerはインタフェースではありませんて、それはただ1つの普通のクラスです)、ここまでcontroller.javaというクラスがとても強くて、Tabcontrollerを借りてTabのグループを管理して、Tabはwebviewの実例があって、コントローラはさらに具体的なTabオブジェクトに基づいて各webviewを制御している.こいつはbrowser app層の総管だろう.controllerの参照さえ得られれば、インタフェースのwebviewの制御を完了することができる.クラスの関係はまずこれについて、次はやはりホームページを開く流れを見て、OnCeate()の中のmControl.start(icicle,getIntent()に接続しましょう. 具体的なコードは以下の通りです. void start(final Bundle icicle, final Intent intent) {
boolean noCrashRecovery = intent.getBooleanExtra(NO_CRASH_RECOVERY, false);
if (icicle != null || noCrashRecovery) {
doStart(icicle, intent, false);
} else {
mCrashRecoveryHandler.startRecovery(intent);
}
}
どのブランチを行っても、最後に同じクラスのdoStart(final Bundle icicle,final Intent intent,final boolean fromCrash)に来ます.doStart()のコードは私たちが関心を持っています. GoogleAccountLogin.startLoginIfNeeded(mActivity,
new Runnable() {
@Override public void run() {
onPreloginFinished(icicle, intent, currentTabId, restoreIncognitoTabs,
fromCrash); } });
ここでスレッドを開いてloadページの内容を開始し、スレッドstart動作はstartLoginIfNeeded()の中にあります.onPreloginFinishedの中に入ってみましょう、 private void onPreloginFinished(Bundle icicle, Intent intent, long currentTabId,
boolean restoreIncognitoTabs, boolean fromCrash) {
//
if (currentTabId == -1) {
Tab t = null;
if (urlData.isEmpty()) {
t = openTabToHomePage();// url
} else {
t = openTab(urlData);// url
}
} else {
}
}
上のコードに沿っていくつかのステップを追跡すると、openTabToHomePageでもopenTabでもcreateNewTab()が実行され、loadUrl()関数が実行され、loadUrl()が最終的に機能するコードはTab.javaで、下のコードは public void loadUrl(String url, Map<String, String> headers) {
if (mMainView != null) {
mPageLoadProgress = INITIAL_PROGRESS;
mInPageLoad = true;
mCurrentState = new PageState(mContext, false, url, null);
mWebViewController.onPageStarted(this, mMainView, null);
mMainView.loadUrl(url, headers);
}
}
mMainViewはwebviewの例なので、ここまでpackages層のコードフローも終わりframework層に移行し始め、間違いなくwebview.javaはこの層のコアのコードの一つに違いない.WebviewのloadUrl()の方法を見てみましょう. public void loadUrl(String url, Map<String, String> additionalHttpHeaders) {
checkThread();
loadUrlImpl(url, additionalHttpHeaders);
}
private void loadUrlImpl(String url, Map<String, String> extraHeaders) {
switchOutDrawHistory();
WebViewCore.GetUrlData arg = new WebViewCore.GetUrlData();
arg.mUrl = url;
arg.mExtraHeaders = extraHeaders;
mWebViewCore.sendMessage(EventHub.LOAD_URL, arg);// TAG。
clearHelpers();
}
上のTAG:EventHub.LOAD_URLの追跡では、コードがWebCoreViewに来ていることがわかります case LOAD_URL: {
CookieManager.getInstance().waitForCookieOperationsToComplete();
GetUrlData param = (GetUrlData) msg.obj;
loadUrl(param.mUrl, param.mExtraHeaders);
break;
}
では、ここのloadUrl()はどこを指しているのでしょうか.続けて見るとすぐに見つかりますが、IDEツールを利用してこのような関係を整理するのは速いです. private void loadUrl(String url, Map<String, String> extraHeaders) {
if (DebugFlags.WEB_VIEW_CORE) Log.v(LOGTAG, " CORE loadUrl " + url);
mBrowserFrame.loadUrl(url, extraHeaders);
}
また新しい変数mBrowserFrameが出てきて、タイプ宣言を見てBrowserFrameの例であることを知って、sourceInsightのジャンプ機能を利用して直接行ってみましょう. public void loadUrl(String url, Map<String, String> extraHeaders) {
mLoadInitFromJava = true;
if (URLUtil.isJavaScriptUrl(url)) {
stringByEvaluatingJavaScriptFromString(
url.substring("javascript:".length()));
} else {
nativeLoadUrl(url, extraHeaders);
}
mLoadInitFromJava = false;
}
ここでnativeLoadUrlを見て、JNIの知識を使うようになりました.次の言葉は私たちに次にどこに行くかを教えてくれます. { "nativeLoadUrl", "(Ljava/lang/String;Ljava/util/Map;)V", (void*) LoadUrl },
WebCoreFrameBridge.cpp(externalwebkitsourcewebkitandroidjni)のloadUrl関数は、ここまでc層のwebkitをリクエストすることになりますが、現在もここまでしか付いていません.後はコールバックメッセージを待っています.前述のクラスのほかにCallBackproxy.javaにも関連しています.こいつは非常に重要な橋です.私たちのBrowserFrameはCallbackProxyを通じてメインスレッドにメッセージを送信します.つまり、それは重要です.webkit部分のコード理解はまだぼんやりしていて、どこから手をつけるか分かりません.だから、この後の流れはさらに掘り起こしなければなりません.同時に、指の高さを求めます.では、ここでまとめてみましょう.framework層のbrowserに対して、webview.java、CallBackproxy.java、BrowserFrame.java、WebCoreFrameBridgeといういくつかのクラスに重点を置いてみましょう.他のクラスはまだ気づいていません.ネット漏れの魚もいるに違いありませんが、まずこれらの主線クラスをつかんでから、細部のものはゆっくりしてください.
本文の物語もこれで終わり、説明する上ではandroidオリジナルブラウザjava部分コード呼び出しの流れの簡単な分析にすぎないが、実際にはアプリケーション層コード機能はウェブページ(webview)の管理と表示に偏っており、webkit自体とはあまりつながりがなく、例えばwebkitに興味があるだけで、webkit部分だけを見ることは完全に可能である.もちろんコードの規模は大きいので、理解するのに時間がかかります.
PS:現在のbrowser設定には実験室のオプションがあります.それは高速制御オプションがあります.それを開くと円形のメニュー機能が開きます.android 3.0のバージョンからこの機能があるようです.対応するコード実装はPieで始まるクラスコードです.これは動的制御で、固定座標のようなものではありません.興味のあるものは見てください.