1. 程式人生 > >Android Launcher分析和修改3 Launcher啟動和初始化

Android Launcher分析和修改3 Launcher啟動和初始化

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow

也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!

               

前面兩篇文章都是寫有關Launcher配置檔案的修改,程式碼方面涉及不多,今天開始進入Launcher程式碼分析。

 

我們開機啟動Launcher,Launcher是由Activity Manager啟動的,而Activity Manager是由system server啟動。

 

原創博文,轉載請標明出處:http://www.cnblogs.com/mythou/p/3157452.html 

 

1、Launcher程序啟動過程

 

可以由下面圖看到Launcher程序是如何被建立啟動:

 

 

Activity Manager通過傳送Intend來啟動Launcher。

    
Intent intent = new Intent(mTopAction, mTopData != null ? 
  Uri.parse(mTopData) : null
);intent.setComponent(mTopComponent);if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL)
{    intent.addCategory(Intent.CATEGORY_HOME);}
startActivityLocked(
null, intent, null, null, 0, aInfo,  null, null, 0, 0, 0, false, false);
   

因此,如果你要開機啟動一個替換Launcher的程式,只要在程式<intent-filter>裡面加入action.MAIN 、

 

category.HOME、category.DEFAULT就可以。如果出現多個程式都加入這種intent,系統會彈出讓你選擇

 

哪個作為啟動器。

 

 

 

2、Launcher初始化——LauncherApplication。

 

Application類,我想大部分做Android應用的朋友都用過,每個Android應用預設都有一個Application類,

 

你也可以繼承Application類,然後加入自己程式碼。Application是一個全域性的應用類,在AndroidManifest.xml

 

我們也可以找到Application標籤。

    
   <application        android:name="com.android.launcher2.LauncherApplication"        android:label="@string/application_name"          android:icon="@drawable/ic_launcher_home"        android:hardwareAccelerated="@bool/config_hardwareAccelerated"        android:largeHeap="@bool/config_largeHeap"        android:configChanges="locale">  </application>    
   

Android四大元件的宣告都需要放到application標籤裡面,預設使用的是系統的Application類,如果你在專案

 

裡面過載了它。就需要在標籤,name屬性下寫上你的新的Application類名。Launcher裡面就是繼承了Application

 

LauncherApplication。應用啟動的時候首先會載入Application。

 

我們可以看到Launcher主類Launcher.java的onCreate函式裡面,第一個就是獲取Application的例項。

    
LauncherApplication app = ((LauncherApplication)getApplication());
   

 

 

接下來我們看看LauncherApplication裡面初始化,LauncherApplication大部分工作就是在初始化完成,剩下都是

 

一些返回介面。

    
    @Override    public void onCreate() 
    {        super.onCreate();       
//獲取螢幕大小,主要用來區分手機還是平板        final int screenSize = getResources().getConfiguration().screenLayout &                Configuration.SCREENLAYOUT_SIZE_MASK;        sIsScreenLarge = screenSize == Configuration.SCREENLAYOUT_SIZE_LARGE ||            screenSize == Configuration.SCREENLAYOUT_SIZE_XLARGE;
//螢幕密度        sScreenDensity
= getResources().getDisplayMetrics().density;     //IconCahe裡面儲存了介面所有應用圖示的繪畫需要的資料,這個到時候具體分析再說。
        //加入這東西的主要原因是為了提高繪畫介面的效率        mIconCache
= new IconCache(this);        //資料庫載入類,LauncherModel是Launcher裡面非常重要的一個類,相當於MVC模式裡面的
     //Model功能,管理資料和初始化資料
        mModel = new LauncherModel(this, mIconCache);        //下面註冊了一些監聽器,主要包含APK檔案更新刪除等資料變化的時候接收的通知
          //接收通知後,主要是用來更新Launcher裡面的資料庫。因為桌面應用圖示資料,只會載入一次        IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);        filter.addAction(Intent.ACTION_PACKAGE_REMOVED);        filter.addAction(Intent.ACTION_PACKAGE_CHANGED);        filter.addDataScheme("package");        registerReceiver(mModel, filter);        filter = new IntentFilter();        filter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);        filter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);        filter.addAction(Intent.ACTION_LOCALE_CHANGED);        filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);        registerReceiver(mModel, filter);        filter = new IntentFilter();        filter.addAction(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED);        registerReceiver(mModel, filter);        filter = new IntentFilter();        filter.addAction(SearchManager.INTENT_ACTION_SEARCHABLES_CHANGED);        registerReceiver(mModel, filter);
    
//contentresolver則是用於管理所有程式的contentprovider例項        ContentResolver resolver = getContentResolver();        //註冊內容觀察者,監聽application資料庫變化,回撥        resolver.registerContentObserver(LauncherSettings.Favorites.CONTENT_URI, true, mFavoritesObserver);    }
   

上面是LauncherApplication最主要的工作,初始化整個Launcher的一些關鍵類,和註冊一些監聽器。主要都是用

 

來監聽應用的安裝更新刪除等導致Launcher資料庫變化的操作。Launcher資料都是使用contentprovider來提供資料。

 

其中註冊的監聽介面是

    
    private final ContentObserver mFavoritesObserver = new ContentObserver(new Handler())     {        @Override        public void onChange(boolean selfChange)         {
       //重新載入介面資料            mModel.startLoader(LauncherApplication.
this, false);        }    };
   
LauncherSettings.Favorites.CONTENT_URI裡面資料發生變化的時候,都會呼叫mModel.startLoader()介面,
重新載入Launcher的資料。startLoader的具體操作,我後面分析LauncherModel類的時候會分析。這一塊涉及
Launcher所有資料載入。
剩下的接都是返回初始化時候建立的物件或者獲取螢幕密度、獲取是否大螢幕。
後面很多處理都需要判斷是否是大螢幕,4.0以後手機平板都共用一套系統,導致多了很多處理。
 

 

 

3、Launcher.java初始化

 

Launcher.java是Launcher裡面最主要的類,是一個Activity。啟動的第一個元件。既然是Activity,我們要分析它

 

初始化,毫無疑問,需要找到onCreate()裡面分析。把主要一些分析用註釋方式寫在程式碼裡面,這樣比較方便閱讀。

 

 

    
    @Override    protected void onCreate(Bundle savedInstanceState) 
  {        super.onCreate(savedInstanceState);       
//獲取Application 例項        LauncherApplication app = ((LauncherApplication)getApplication());
     //LauncherModel類裡面獲取Launcher的物件引用        mModel
= app.setLauncher(this);
//獲取IconCache,IconCache在Application裡面初始化            mIconCache
= app.getIconCache();        mDragController = new DragController(this);        mInflater = getLayoutInflater();        mAppWidgetManager = AppWidgetManager.getInstance(this);        //監聽widget改變,以後在Model裡面回撥處理的結果        mAppWidgetHost = new LauncherAppWidgetHost(this, APPWIDGET_HOST_ID);        mAppWidgetHost.startListening();
     //這個是設定Launcher的跟蹤除錯檔案,下面很多資訊會寫到這個檔案裡面。       
if (PROFILE_STARTUP)
     {            android.os.Debug.startMethodTracing(                    Environment.getExternalStorageDirectory()
+ "/launcher");        }        //讀取本地配置,儲存更新配置,清空IconCache        checkForLocaleChange();        setContentView(R.layout.launcher);                //對所有的UI控制元件進行載入和配置        setupViews();                //顯示操作提示,第一次啟動的時候才會顯示        showFirstRunWorkspaceCling();        //註冊監控Launcher資料庫變化        registerContentObservers();     //鎖住APP,初始化不能操作。        lockAllApps();        mSavedState = savedInstanceState;        restoreState(mSavedState);        // Update customization drawer _after_ restoring the states        if (mAppsCustomizeContent != null)
     {            mAppsCustomizeContent.onPackagesUpdated();        }       
if (PROFILE_STARTUP)
     {            android.os.Debug.stopMethodTracing();        }       
//載入啟動資料,所有介面資料(快捷方式、folder、widget、allApp)等在loader裡面載入,這部分後面我會詳細分析。        if (!mRestoring) {            mModel.startLoader(this, true);        }        if (!mModel.isAllAppsLoaded())
     {            ViewGroup appsCustomizeContentParent
= (ViewGroup) mAppsCustomizeContent.getParent();            mInflater.inflate(R.layout.apps_customize_progressbar, appsCustomizeContentParent);        }        // For handling default keys        mDefaultKeySsb = new SpannableStringBuilder();        Selection.setSelection(mDefaultKeySsb, 0);        IntentFilter filter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);        registerReceiver(mCloseSystemDialogsReceiver, filter);
     //下面這幾個就是Android原生介面上的Market、搜尋、聲音輸入按鈕的預設圖示顯示。        boolean searchVisible
= false;        boolean voiceVisible = false;        // If we have a saved version of these external icons, we load them up immediately        int coi = getCurrentOrientationIndexForGlobalIcons();        if (sGlobalSearchIcon[coi] == null || sVoiceSearchIcon[coi] == null ||                sAppMarketIcon[coi] == null) {            updateAppMarketIcon();            searchVisible = updateGlobalSearchIcon();            voiceVisible = updateVoiceSearchIcon(searchVisible);        }        if (sGlobalSearchIcon[coi] != null) {             updateGlobalSearchIcon(sGlobalSearchIcon[coi]);             searchVisible = true;        }        if (sVoiceSearchIcon[coi] != null)
      {            updateVoiceSearchIcon(sVoiceSearchIcon[coi]);            voiceVisible
= true;        }        if (sAppMarketIcon[coi] != null)
    {            updateAppMarketIcon(sAppMarketIcon[coi]);        }        mSearchDropTargetBar.onSearchPackagesChanged(searchVisible, voiceVisible);       
// On large interfaces, we want the screen to auto-rotate based on the current orientation        if (LauncherApplication.isScreenLarge() || Build.TYPE.contentEquals("eng"))
     {            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);        }         Log.i(TAG,
"------------------------>Launcher init over") ;   }
   

 上面就是Launcher.java的初始化,大部分我都寫了註釋。其實這裡最主要的工作是載入介面資料:

 

mModel.startLoader(this, true); 這塊實現是在LauncherModel裡面實現的。下一篇文章,我會詳細

 

說明如何載入和獲取管理系統裡面的APP相關資料。

 

 

 

今天就講到這裡,如發現問題,請留言指出,歡迎留言討論。

 

 

 

 相關係列文章:

 

Android Launcher分析和修改1——Launcher預設介面配置(default_workspace)

 

Android Launcher分析和修改2——Icon修改、介面佈局調整、桌布設定

 

 

 

 

 

 


<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>           

給我老師的人工智慧教程打call!http://blog.csdn.net/jiangjunshow

這裡寫圖片描述