Android 浏览器的研究(四)--- Apk的启动和主页的加载过程

当我们在Launcher中点击浏览器的图标时,浏览器的窗口会打开并显示主页(HomePage)。这里我们对这一场景进行分析,研究浏览器如何启动,取得缺省主页并将它布局和显示的。


根据前边对WebView 类的学习,大概可以预期我们在主ActivityonCreate方法里从设置里面取得缺省主页的配置,创建一个WebView类,并使用setContentView将它添加到主窗口中。下面我们从浏览器的代码看看它是如何实现的。

首先,研究AndroidManifest文件,从<application>标签的内容看到该Apk实现了自己的Applicaton Browser

<application   android:name="Browser"
               android:label="@string/application_name"
               android:icon="@mipmap/ic_launcher_browser"
               android:backupAgent=".BrowserBackupAgent"
               android:hardwareAccelerated="true"
               android:taskAffinity="android.task.browser" >
另外,该Apk的主Activity为BrowserActivity:

<activity android:name="BrowserActivity"
          android:label="@string/application_name"
          android:launchMode="singleTask"
          android:alwaysRetainTaskState="true"
          android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale"
          android:theme="@style/BrowserTheme"
          android:windowSoftInputMode="adjustResize" >

。。。

<!-- We are also the main entry point of the browser. -->
<intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.LAUNCHER" />
    <category android:name="android.intent.category.BROWSABLE" />
    <category android:name="android.intent.category.APP_BROWSER" />
</intent-filter>


Apk的启动,首先是ApplicationBrowser类的onCreate方法,主要工作:

   // create CookieSyncManager with current Context

   CookieSyncManager.createInstance(this);

   BrowserSettings.initialize(getApplicationContext());

   Preloader.initialize(getApplicationContext());

这里涉及到三个工作:Cookie同步管理,浏览器设置和预加载。

然后是ActivityonCreate方法,与我们的研究相关的代码:

@Override
public void onCreate(Bundle icicle) {
    if (LOGV_ENABLED) {
        Log.v(LOGTAG, this + " onStart, has state: "
                + (icicle == null ? "false" : "true"));
    }
    super.onCreate(icicle);
    mController = createController();
    Intent intent = (icicle == null) ? getIntent() : null;
    mController.start(intent);
}


createController方法:
private Controller createController() {
    Controller controller = new Controller(this);
    boolean xlarge = isTablet(this);
    UI ui = null;
    if (xlarge) {
        ui = new XLargeUi(this, controller);
    } else {
        ui = new PhoneUi(this, controller);
    }
    controller.setUi(ui);
    return controller;
}

主要的工作是Controller的创建,PhoneUi的创建和Controllerstart


Controller的构造方法主要涉及到以下几个相关类:

BrowserSettings

TabControl

CrashRecoveryHandler

UrlHandler

BrowserWebViewFactory

IntentHandler

PageDialogHandler

BookMarksContentObserver

NetworkStateHandler

SystemAllowGeolocationOrigins

IconDataBase

PhoneUi的构造:

   BaseUi的构造:

FrameLayout frameLayout = (FrameLayout) mActivity.getWindow()
        .getDecorView().findViewById(android.R.id.content);
LayoutInflater.from(mActivity)
        .inflate(R.layout.custom_screen, frameLayout);
mFixedTitlebarContainer = (FrameLayout) frameLayout.findViewById(
        R.id.fixed_titlebar_container);
mContentView = (FrameLayout) frameLayout.findViewById(
        R.id.main_content);
mCustomViewContainer = (FrameLayout) frameLayout.findViewById(
        R.id.fullscreen_custom_content);
mErrorConsoleContainer = (LinearLayout) frameLayout
        .findViewById(R.id.error_console);


Custom_screenlayout文件:

<merge
    xmlns:android="http://schemas.android.com/apk/res/android">
    <FrameLayout android:id="@+id/fullscreen_custom_content"
        android:visibility="gone"
        android:background="@color/black"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
    />
    <com.android.browser.view.CustomScreenLinearLayout
        android:orientation="vertical"
        android:id="@+id/vertical_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <LinearLayout android:id="@+id/error_console"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
        />
        <FrameLayout android:id="@+id/fixed_titlebar_container"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
        />
        <FrameLayout android:id="@+id/main_content"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
        />
    </com.android.browser.view.CustomScreenLinearLayout>
</merge>


可以看出这个是浏览器主界面的布局,浏览器的布局已经准备好,后面我们创建的WebView应该是添加到main_content里面。


Controller start 方法执行了CrashRecoveryHandlerstartRecovery().

CrashRecoveryHandler相关操作:

首先是initialize(),创建了CrashRecoveryHandler实例,CrashRecoveryHandler实例构造了foregroundHandlerbackgroundHandler

CrashRecoveryHandlerpreloadCrashState方法,在backgroundHandler的处理中执行loadCrashState(),该方法将CrashStateSTATE_FILE读入到mRecoveryState中。

CrashRecoveryHandlerstartRecovery方法,调用ControllerdoStart()

ControllerdoStart方法调用onPreloginFinished().

currentTabId is -1, thenopenTabToHomePage().

openTabToHomePage

createNewTabthen loadUrl.

createNewTab的实现:

TabControl::createNewTab

createNewWebView:

new BrowserWebView;该类主要用来管理WebView滚动条事件。

initWebViewSettings

setActiveTab

TabControl::setCurrentTab

PhoneUi::setActiveTab

attachTabToContentView

至此,我们看完Apk启动并加载HomePage的过程,简单总结如下:

1.浏览器实现了自己的Application类(Browser,在其onCreate方法中进行了一些初始化工作(Cookie同步管理,浏览器设置和预加载);

2.浏览器的主ActivityBrowserActivity,在其onCreate方法中构建了ControllerPhoneUi,并调用Controller::start方法启动Controller

a)Controller在其构造方法中实例化和初始化一些协助对象,其中一个重要的类是CrashRecoveryHandler

b)PhoneUi的构造方法加载custom_screen布局文件,并将它作为Activity窗口的ContentView.

c)Controller::start方法执行了CrashRecoveryHandlerstartRecovery(),该方法又调用ControllerdoStart()方法

i.ControllerdoStart方法调用onPreloginFinished(),该方法执行openTabToHomePage,打开浏览器主页。具体将WebView加到ContentView的方法是BaseUiattachTabToContentView方法。





Android 浏览器的研究(四)--- Apk的启动和主页的加载过程

上一篇:PL-SQL


下一篇:Multilingual App Toolkit v2.2 release