国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統(tǒng) > Android > 正文

Android6.0 Launcher2應(yīng)用解析

2019-12-12 05:16:17
字體:
供稿:網(wǎng)友

在之前我們分析了Android6.0系統(tǒng)在啟動(dòng)時(shí)安裝應(yīng)用程序的過程,這些應(yīng)用程序安裝好之后,Launcher應(yīng)用就負(fù)責(zé)把它們在桌面上展示出來。

一、AMS啟動(dòng)Launcher 

Launcher應(yīng)用是在AMS的systemReady方法中直接調(diào)用startHomeActivityLocked啟動(dòng)的,下面是systemReady啟動(dòng)Launcher的代碼。 

startHomeActivityLocked(mCurrentUserId, "systemReady");我們來看下這個(gè)函數(shù),先調(diào)用了getHomeIntent方法來獲取Intent,然后也是調(diào)用resolveActivityInfo函數(shù)從PKMS獲取ActivityInfo,接著當(dāng)進(jìn)程沒有啟動(dòng)的話,調(diào)用ActivityStackSupervisor的startHomeActivity函數(shù)

   boolean startHomeActivityLocked(int userId, String reason) {    if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL        && mTopAction == null) {      // We are running in factory test mode, but unable to find      // the factory test app, so just sit around displaying the      // error message and don't try to start anything.      return false;    }    Intent intent = getHomeIntent();//獲取intent    ActivityInfo aInfo =      resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);//獲取ActivityInfo    if (aInfo != null) {      intent.setComponent(new ComponentName(          aInfo.applicationInfo.packageName, aInfo.name));      // Don't do this if the home app is currently being      // instrumented.      aInfo = new ActivityInfo(aInfo);      aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);      ProcessRecord app = getProcessRecordLocked(aInfo.processName,          aInfo.applicationInfo.uid, true);      if (app == null || app.instrumentationClass == null) {//進(jìn)程沒有啟動(dòng)調(diào)用        EventLog.writeEvent(EventLogTags.AM_PROC_START,"AMS -> startHomeActivityLocked startHomeActivity then startActivityLock : "+ aInfo.processName);        intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);        mStackSupervisor.startHomeActivity(intent, aInfo, reason);      }    }    return true;  } 

我們先來看看getHomeIntent這個(gè)函數(shù)。

Intent getHomeIntent() {    Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);    intent.setComponent(mTopComponent);    if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {      intent.addCategory(Intent.CATEGORY_HOME);    }    return intent;  }

然后我們來看下ActivityStackSupervisor的startHomeActivity函數(shù),它也是調(diào)用了startActivityLocked來啟動(dòng)Activity的,在之前的博客分析過這個(gè)函數(shù)這里我們就不介紹了。

   void startHomeActivity(Intent intent, ActivityInfo aInfo, String reason) {    moveHomeStackTaskToTop(HOME_ACTIVITY_TYPE, reason);    startActivityLocked(null /* caller */, intent, null /* resolvedType */, aInfo,        null /* voiceSession */, null /* voiceInteractor */, null /* resultTo */,        null /* resultWho */, 0 /* requestCode */, 0 /* callingPid */, 0 /* callingUid */,        null /* callingPackage */, 0 /* realCallingPid */, 0 /* realCallingUid */,        0 /* startFlags */, null /* options */, false /* ignoreTargetSecurity */,        false /* componentSpecified */,        null /* outActivity */, null /* container */, null /* inTask */);    if (inResumeTopActivity) {      // If we are in resume section already, home activity will be initialized, but not      // resumed (to avoid recursive resume) and will stay that way until something pokes it      // again. We need to schedule another resume.      scheduleResumeTopActivities();    }  }

二、Launcher啟動(dòng) 

接著我們來看下Launcher的AndroidManifest.xml,我們看下其主Activity有一個(gè)category為android.intent.category.HOME 

  <application    android:name="com.android.launcher2.LauncherApplication"    android:label="@string/application_name"    android:icon="@mipmap/ic_launcher_home"    android:hardwareAccelerated="true"    android:largeHeap="@bool/config_largeHeap"    android:supportsRtl="true">    <activity      android:name="com.android.launcher2.Launcher"      android:launchMode="singleTask"      android:clearTaskOnLaunch="true"      android:stateNotNeeded="true"      android:resumeWhilePausing="true"      android:theme="@style/Theme"      android:windowSoftInputMode="adjustPan"      android:screenOrientation="nosensor">       <intent-filter>        <action android:name="android.intent.action.MAIN" />        <category android:name="android.intent.category.HOME" />        <category android:name="android.intent.category.DEFAULT" />        <category android:name="android.intent.category.MONKEY"/>      </intent-filter>    </activity>    ...... 

在Launcher.java的onCreate函數(shù)中調(diào)用了mModel.startLoader函數(shù)

   protected void onCreate(Bundle savedInstanceState) {    ......    if (!mRestoring) {      if (sPausedFromUserAction) {        // If the user leaves launcher, then we should just load items asynchronously when        // they return.        mModel.startLoader(true, -1);      } else {        // We only load the page synchronously if the user rotates (or triggers a        // configuration change) while launcher is in the foreground        mModel.startLoader(true, mWorkspace.getCurrentPage());      }    }    ...... 

startLoader函數(shù)會(huì)post一個(gè)Runnable消息,我們來看下它的run方法 

  public void startLoader(boolean isLaunching, int synchronousBindPage) {    synchronized (mLock) {      if (DEBUG_LOADERS) {        Log.d(TAG, "startLoader isLaunching=" + isLaunching);      }      // Clear any deferred bind-runnables from the synchronized load process      // We must do this before any loading/binding is scheduled below.      mDeferredBindRunnables.clear();      // Don't bother to start the thread if we know it's not going to do anything      if (mCallbacks != null && mCallbacks.get() != null) {        // If there is already one running, tell it to stop.        // also, don't downgrade isLaunching if we're already running        isLaunching = isLaunching || stopLoaderLocked();        mLoaderTask = new LoaderTask(mApp, isLaunching);        if (synchronousBindPage > -1 && mAllAppsLoaded && mWorkspaceLoaded) {          mLoaderTask.runBindSynchronousPage(synchronousBindPage);        } else {          sWorkerThread.setPriority(Thread.NORM_PRIORITY);          sWorker.post(mLoaderTask);        }      }    }  }

 在它的run方法中會(huì)調(diào)用loadAndBindAllApps函數(shù),在loadAndBindAllApps函數(shù)中又會(huì)調(diào)用loadAllAppsByBatch函數(shù) 

    public void run() {      synchronized (mLock) {        mIsLoaderTaskRunning = true;      }      final Callbacks cbk = mCallbacks.get();      final boolean loadWorkspaceFirst = cbk != null ? (!cbk.isAllAppsVisible()) : true;      keep_running: {        // Elevate priority when Home launches for the first time to avoid        // starving at boot time. Staring at a blank home is not cool.        synchronized (mLock) {          if (DEBUG_LOADERS) Log.d(TAG, "Setting thread priority to " +              (mIsLaunching ? "DEFAULT" : "BACKGROUND"));          Process.setThreadPriority(mIsLaunching              ? Process.THREAD_PRIORITY_DEFAULT : Process.THREAD_PRIORITY_BACKGROUND);        }        // First step. Load workspace first, this is necessary since adding of apps from        // managed profile in all apps is deferred until onResume. See http://b/17336902.        if (loadWorkspaceFirst) {          if (DEBUG_LOADERS) Log.d(TAG, "step 1: loading workspace");          loadAndBindWorkspace();        } else {          Log.d(TAG, "step 1: special: loading all apps");          loadAndBindAllApps();        } 

我們先來看下loadAndBindAllApps函數(shù),這個(gè)函數(shù)先進(jìn)入while循環(huán),然后調(diào)用了LauncherApps的getActivityList函數(shù),后面又會(huì)調(diào)用callbacks的bindAllApplications

    private void loadAllAppsByBatch() {      final long t = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;      ......      mBgAllAppsList.clear();      final int profileCount = profiles.size();      for (int p = 0; p < profileCount; p++) {        ......        while (i < N && !mStopped) {          if (i == 0) {            final long qiaTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;            apps = mLauncherApps.getActivityList(null, user);            ......                                 mHandler.post(new Runnable() {            public void run() {              final long t = SystemClock.uptimeMillis();              if (callbacks != null) {                if (firstProfile) {                  callbacks.bindAllApplications(added);                } else {                  callbacks.bindAppsAdded(added);                }                if (DEBUG_LOADERS) {                  Log.d(TAG, "bound " + added.size() + " apps in "                    + (SystemClock.uptimeMillis() - t) + "ms");                }              } else {                Log.i(TAG, "not binding apps: no Launcher activity");              }            }          });          ......

我們先來看LauncherApps的getActivityList函數(shù),它先用mService成員變量調(diào)用getLauncherActivities函數(shù)獲取到list<ResolveInfo>,然后封裝在ArrayList<LauncherActivityInfo> 中。

  public List<LauncherActivityInfo> getActivityList(String packageName, UserHandle user) {    List<ResolveInfo> activities = null;    try {      activities = mService.getLauncherActivities(packageName, user);    } catch (RemoteException re) {      throw new RuntimeException("Failed to call LauncherAppsService");    }    if (activities == null) {      return Collections.EMPTY_LIST;    }    ArrayList<LauncherActivityInfo> lais = new ArrayList<LauncherActivityInfo>();    final int count = activities.size();    for (int i = 0; i < count; i++) {      ResolveInfo ri = activities.get(i);      long firstInstallTime = 0;      try {        firstInstallTime = mPm.getPackageInfo(ri.activityInfo.packageName,          PackageManager.GET_UNINSTALLED_PACKAGES).firstInstallTime;      } catch (NameNotFoundException nnfe) {        // Sorry, can't find package      }      LauncherActivityInfo lai = new LauncherActivityInfo(mContext, ri, user,          firstInstallTime);      if (DEBUG) {        Log.v(TAG, "Returning activity for profile " + user + " : "            + lai.getComponentName());      }      lais.add(lai);    }    return lais;  } 

其service是class LauncherAppsImpl extends ILauncherApps.Stub 下面是getLauncherActivities函數(shù),肯定也是通過PKMS來獲取相關(guān)Activity的ResolveInfo的。 

    @Override    public List<ResolveInfo> getLauncherActivities(String packageName, UserHandle user)        throws RemoteException {      ensureInUserProfiles(user, "Cannot retrieve activities for unrelated profile " + user);      if (!isUserEnabled(user)) {        return new ArrayList<ResolveInfo>();      }      final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);      mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);      mainIntent.setPackage(packageName);      long ident = Binder.clearCallingIdentity();      try {        List<ResolveInfo> apps = mPm.queryIntentActivitiesAsUser(mainIntent, 0 /* flags */,            user.getIdentifier());        return apps;      } finally {        Binder.restoreCallingIdentity(ident);      }    } 

最后回調(diào)Launcher.java的bindAllApplications函數(shù),最后在這個(gè)函數(shù)中可以在桌面上展示系統(tǒng)中所有的應(yīng)用程序了。

  public void bindAllApplications(final ArrayList<ApplicationInfo> apps) {    Runnable setAllAppsRunnable = new Runnable() {      public void run() {        if (mAppsCustomizeContent != null) {          mAppsCustomizeContent.setApps(apps);        }      }    };    // Remove the progress bar entirely; we could also make it GONE    // but better to remove it since we know it's not going to be used    View progressBar = mAppsCustomizeTabHost.      findViewById(R.id.apps_customize_progress_bar);    if (progressBar != null) {      ((ViewGroup)progressBar.getParent()).removeView(progressBar);      // We just post the call to setApps so the user sees the progress bar      // disappear-- otherwise, it just looks like the progress bar froze      // which doesn't look great      mAppsCustomizeTabHost.post(setAllAppsRunnable);    } else {      // If we did not initialize the spinner in onCreate, then we can directly set the      // list of applications without waiting for any progress bars views to be hidden.      setAllAppsRunnable.run();    }  }

三、顯示應(yīng)用圖標(biāo) 

我們再來看下Launcher的onClick函數(shù),當(dāng)調(diào)用showWorkspace可以顯示所有應(yīng)用的圖標(biāo)。

   public void onClick(View v) {    // Make sure that rogue clicks don't get through while allapps is launching, or after the    // view has detached (it's possible for this to happen if the view is removed mid touch).    if (v.getWindowToken() == null) {      return;    }    if (!mWorkspace.isFinishedSwitchingState()) {      return;    }    Object tag = v.getTag();    if (tag instanceof ShortcutInfo) {      // Open shortcut      final Intent intent = ((ShortcutInfo) tag).intent;      int[] pos = new int[2];      v.getLocationOnScreen(pos);      intent.setSourceBounds(new Rect(pos[0], pos[1],          pos[0] + v.getWidth(), pos[1] + v.getHeight()));      boolean success = startActivitySafely(v, intent, tag);      if (success && v instanceof BubbleTextView) {        mWaitingForResume = (BubbleTextView) v;        mWaitingForResume.setStayPressed(true);      }    } else if (tag instanceof FolderInfo) {      if (v instanceof FolderIcon) {        FolderIcon fi = (FolderIcon) v;        handleFolderClick(fi);      }    } else if (v == mAllAppsButton) {      if (isAllAppsVisible()) {        showWorkspace(true);      } else {        onClickAllAppsButton(v);      }    }  } 

在showWorkspace中會(huì)顯示所有的圖標(biāo)

   void showWorkspace(boolean animated, Runnable onCompleteRunnable) {    if (mState != State.WORKSPACE) {      boolean wasInSpringLoadedMode = (mState == State.APPS_CUSTOMIZE_SPRING_LOADED);      mWorkspace.setVisibility(View.VISIBLE);      hideAppsCustomizeHelper(State.WORKSPACE, animated, false, onCompleteRunnable);      // Show the search bar (only animate if we were showing the drop target bar in spring      // loaded mode)      if (mSearchDropTargetBar != null) {        mSearchDropTargetBar.showSearchBar(wasInSpringLoadedMode);      }      // We only need to animate in the dock divider if we're going from spring loaded mode      showDockDivider(animated && wasInSpringLoadedMode);      // Set focus to the AppsCustomize button      if (mAllAppsButton != null) {        mAllAppsButton.requestFocus();      }    }    mWorkspace.flashScrollingIndicator(animated);    // Change the state *after* we've called all the transition code    mState = State.WORKSPACE;    // Resume the auto-advance of widgets    mUserPresent = true;    updateRunning();    // Send an accessibility event to announce the context change    getWindow().getDecorView()        .sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);  } 

而點(diǎn)擊應(yīng)用圖標(biāo),最終會(huì)調(diào)用Launcher.java的startActivitySafely來啟動(dòng)應(yīng)用。這里調(diào)用的startActivity就是Activity的startActivity函數(shù)。 

  boolean startActivitySafely(View v, Intent intent, Object tag) {    boolean success = false;    try {      success = startActivity(v, intent, tag);    } catch (ActivityNotFoundException e) {      Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();      Log.e(TAG, "Unable to launch. tag=" + tag + " intent=" + intent, e);    }    return success;  }

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持武林網(wǎng)。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 体育| 武威市| 睢宁县| 纳雍县| 纳雍县| 怀化市| 东港市| 仙游县| 汉阴县| 桓仁| 竹北市| 固原市| 祥云县| 鄯善县| 离岛区| 大荔县| 谷城县| 鄢陵县| 滨海县| 新民市| 保亭| 威海市| 宁武县| 台东县| 靖宇县| 三亚市| 东兰县| 门头沟区| 深圳市| 万源市| 高平市| 广水市| 平阳县| 台前县| 洛阳市| 老河口市| 呼伦贝尔市| 长治县| 晋城| 新泰市| 马尔康县|