最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

 更新時間:2016年09月15日 09:12:47   作者:kc58236582  
這篇文章主要為大家詳細(xì)介紹了Android6.0 Launcher2應(yīng)用,具有一定的參考價值,感興趣的小伙伴們可以參考一下

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

一、AMS啟動Launcher 

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

startHomeActivityLocked(mCurrentUserId, "systemReady");我們來看下這個函數(shù),先調(diào)用了getHomeIntent方法來獲取Intent,然后也是調(diào)用resolveActivityInfo函數(shù)從PKMS獲取ActivityInfo,接著當(dāng)進(jìn)程沒有啟動的話,調(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)程沒有啟動調(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這個函數(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來啟動Activity的,在之前的博客分析過這個函數(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啟動 

接著我們來看下Launcher的AndroidManifest.xml,我們看下其主Activity有一個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ù)會post一個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方法中會調(diào)用loadAndBindAllApps函數(shù),在loadAndBindAllApps函數(shù)中又會調(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ù),這個函數(shù)先進(jìn)入while循環(huán),然后調(diào)用了LauncherApps的getActivityList函數(shù),后面又會調(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ù),最后在這個函數(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中會顯示所有的圖標(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);
  } 

而點擊應(yīng)用圖標(biāo),最終會調(diào)用Launcher.java的startActivitySafely來啟動應(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í)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 解決Android調(diào)用系統(tǒng)分享給微信,出現(xiàn)分享失敗,分享多文件必須為圖片格式的問題

    解決Android調(diào)用系統(tǒng)分享給微信,出現(xiàn)分享失敗,分享多文件必須為圖片格式的問題

    這篇文章主要介紹了解決Android調(diào)用系統(tǒng)分享給微信,出現(xiàn)分享失敗,分享多文件必須為圖片格式的問題,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-09-09
  • Android BroadcastReceiver廣播簡單使用

    Android BroadcastReceiver廣播簡單使用

    這篇文章主要為大家詳細(xì)介紹了Android BroadcastReceiver廣播簡單的使用,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-04-04
  • Flutter移動端進(jìn)行多渠道打包發(fā)布的全過程

    Flutter移動端進(jìn)行多渠道打包發(fā)布的全過程

    在使用flutter開發(fā)的過程中,需要根據(jù)不同的環(huán)境,不同的包名來打包,下面這篇文章主要給大家介紹了關(guān)于Flutter移動端進(jìn)行多渠道打包發(fā)布的相關(guān)資料,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-06-06
  • android從資源文件中讀取文件流并顯示的方法

    android從資源文件中讀取文件流并顯示的方法

    這篇文章主要介紹了android從資源文件中讀取文件流并顯示的方法,涉及Android針對文件的讀取及顯示技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-07-07
  • Android自帶的四種線程池使用總結(jié)

    Android自帶的四種線程池使用總結(jié)

    本篇文章主要介紹了Android自帶的四種線程池使用總結(jié),詳細(xì)的介紹了4種線程池的用法,具有一定的參考價值,有興趣的小伙伴可以了解一下
    2017-07-07
  • adb wireless進(jìn)行Android手機調(diào)試詳解

    adb wireless進(jìn)行Android手機調(diào)試詳解

    這篇文章給大家講解了在Android手機上使用adb wireless進(jìn)行調(diào)試的步驟以及問題解決辦法,有需要的跟著學(xué)習(xí)下吧。
    2017-12-12
  • android view轉(zhuǎn)Bitmap生成截圖的方法

    android view轉(zhuǎn)Bitmap生成截圖的方法

    這篇文章主要介紹了android view轉(zhuǎn)Bitmap生成截圖的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-09-09
  • Android?Room數(shù)據(jù)庫加密詳解

    Android?Room數(shù)據(jù)庫加密詳解

    這篇文章主要為大家詳細(xì)介紹了Android?Room數(shù)據(jù)庫加密,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • Android TCP 文件客戶端與服務(wù)器DEMO介紹

    Android TCP 文件客戶端與服務(wù)器DEMO介紹

    首先是服務(wù)器,服務(wù)器是在PC機上,JAVA運行環(huán)境,主要參考網(wǎng)上的代碼,自己做了支持多線程處理,代碼如下所示。需要的朋友可以過來參考下,希望對大家有所幫助
    2013-11-11
  • Android Studio提示inotify大小不足的解決辦法

    Android Studio提示inotify大小不足的解決辦法

    大家在使用Android Studio導(dǎo)入AOSP源碼的時候,可能會遇到inotify大小不足的問題,這篇文章就給大家介紹了怎么解決這個問題的方法,有需要的朋友們可以參考借鑒。
    2016-09-09

最新評論

孟州市| 元氏县| 聂荣县| 满洲里市| 辽源市| 龙江县| 黄龙县| 开封县| 元朗区| 博兴县| 河东区| 射洪县| 广平县| 奉化市| 老河口市| 改则县| 四子王旗| 克拉玛依市| 佛山市| 富顺县| 扎囊县| 德钦县| 台南县| 谢通门县| 荆门市| 丹寨县| 当雄县| 铜陵市| 郎溪县| 柳林县| 贡山| 科尔| 延寿县| 辉南县| 江山市| 嘉定区| 宿松县| 兴安县| 商城县| 台中县| 聂荣县|