Launcher的启动

Launcher的启动

手机开机的时候启动systemservice,systemservice启动ActivityManagerService,PMS等,启动Launcher首先分析ActivityManagerService

Created with Raphaël 2.1.2ActivityManagerServiceActivityManagerServiceActivityStackSupervisorActivityStackSupervisorLauncherLauncherLauncherModelLauncherModelstartHomeActivityLockedstartHomeActivitymoveHomeStackTaskToTopstartActivityLockedonCreatestartLoaderrunloadAndBindWorkspaceloadAndBindAllAppsloadAllAppsbindAllApplications

代码具体实现:

   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();
        ActivityInfo aInfo =
            resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
        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) {
                intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
                mStackSupervisor.startHomeActivity(intent, aInfo, reason);
            }
        }

        return true;
    }

startHomeActivityLocked方法首先通过调用getHomeIntent()方法来构建一个CATEGORY_HOME类型的intent,然后调用PackageManagerService的resolveActivityInfo()方法来查询category类型为HOME的Activity,然后调用getProcessRecordLocked()方法获得Activity的进程信息,由于是第一次启动Activity,Activity代表的进程还没有启动,所以这里返回的ProcessRecord为null,接下来调用mStackSupervisor对象的startHomeActivity()方法启动Launcher,而mStackSupervisor是一个ActivityStackSupervisor类型的对象,接下来看一下getHomeIntent方法怎么构建一个CATEGORY_HOME类型的intent

 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;
    }

getHomeIntent方法通过addCategory方法添加一个CATEGORY_HOME类型的Intent,并返回

 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();
        }
    }

startHomeActivity方法中调用moveHomeStackTaskToTop()方法把Launcher放进HomeStack里,Stack分为2种:
Stack #0 专门放Launcher和SystemUI
Stack #1 放其他应用程序
回到startHomeActivity方法中,然后调用startActivityLocked方法去真正的启动Launcher这个Activity,这个启动很复杂,这里只要知道,startActivityLocked方法会把Launcher这个activity启动起来,当Activity启动之后,就会进入它的onCreate方法中,因此,接下来看Launcher的onCreate方法

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        ...

        super.onCreate(savedInstanceState);

        initializeDynamicGrid(false);

        ...
        setContentView(R.layout.launcher);

        if (!mRestoring) {
            if (DISABLE_SYNCHRONOUS_BINDING_CURRENT_PAGE) {
                // If the user leaves launcher, then we should just load items asynchronously when
                // they return.
                mModel.startLoader(true, PagedView.INVALID_RESTORE_PAGE);
            } 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.getRestorePage());
            }
        }

       ....
    }

onCreate方法中做了一些与UI有关的操作,这里主要关心在Launcher里面加载应用图标操作,即把安装的所有的应用图标加载到桌面上,当点击某个应用图标的时候,就会启动这个应用程序,此处通过调用mModel对象的startLoader方法来进一步处理

 public void startLoader(boolean isLaunching, int synchronousBindPage, int loadFlags) {
        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.
            synchronized (mDeferredBindRunnables) {
                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.getContext(), isLaunching, loadFlags);
                if (synchronousBindPage != PagedView.INVALID_RESTORE_PAGE
                        && mAllAppsLoaded && mWorkspaceLoaded) {
                    mLoaderTask.runBindSynchronousPage(synchronousBindPage);
                } else {
                    sWorkerThread.setPriority(Thread.NORM_PRIORITY);
                    sWorker.post(mLoaderTask);
                }
            }
        }
    }

startLoader方法中new了一个LoaderTask,LoaderTask实现了Runnable,先到run方法中去看一下

  public void run() {
            ...
                isUpgrade = loadAndBindWorkspace();
             ....
                loadAndBindAllApps();
        }

run方法首先调用loadAndBindWorkspace加载workspace,然后调用loadAndBindAllApps方法加载应用程序图标

private void loadAndBindAllApps() {
            if (DEBUG_LOADERS) {
                Log.d(TAG, "loadAndBindAllApps mAllAppsLoaded=" + mAllAppsLoaded);
            }
            if (!mAllAppsLoaded) {
                loadAllApps();
                synchronized (LoaderTask.this) {
                    if (mStopped) {
                        return;
                    }
                    mAllAppsLoaded = true;
                }
            } else {
                onlyBindAllApps();
            }
        }

loadAndBindAllApps方法中调用了loadAllApps方法继续处理

  private void loadAllApps() {
        ....
            // Post callback on main thread
            mHandler.post(new Runnable() {
                public void run() {
                    final long bindTime = SystemClock.uptimeMillis();
                    final Callbacks callbacks = tryGetCallbacks(oldCallbacks);
                    if (callbacks != null) {
                        callbacks.bindAllApplications(added);
                        if (DEBUG_LOADERS) {
                            Log.d(TAG, "bound " + added.size() + " apps in "
                                + (SystemClock.uptimeMillis() - bindTime) + "ms");
                        }
                    } else {
                        Log.i(TAG, "not binding apps: no Launcher activity");
                    }
                }
            });
        }

loadAllApps方法中回调了bindAllApplications方法

 public void bindAllApplications(final ArrayList<AppInfo> apps) {
        if (LauncherAppState.isDisableAllApps()) {
            if (mIntentsOnWorkspaceFromUpgradePath != null) {
                if (LauncherModel.UPGRADE_USE_MORE_APPS_FOLDER) {
                    getHotseat().addAllAppsFolder(mIconCache, apps,
                            mIntentsOnWorkspaceFromUpgradePath, Launcher.this, mWorkspace);
                }
                mIntentsOnWorkspaceFromUpgradePath = null;
            }
            if (mAppsCustomizeContent != null) {
                mAppsCustomizeContent.onPackagesUpdated(
                        LauncherModel.getSortedWidgetsAndShortcuts(this));
            }
        } else {
            if (mAppDrawerAdapter != null) {
                mAppDrawerAdapter.setApps(apps);
            }
            if (mAppsCustomizeContent != null) {
                mAppsCustomizeContent.setApps(apps);
                mAppsCustomizeContent.onPackagesUpdated(
                        LauncherModel.getSortedWidgetsAndShortcuts(this));
            }
        }
    }

到这里Launcher的启动和加载应用图标就介绍完了,当点击某个图标的时候,怎么启动应用程序呢

public boolean startActivitySafely(View v, Intent intent, Object tag) {
        boolean success = false;
        if (mIsSafeModeEnabled && !Utilities.isSystemApp(this, intent)) {
            Toast.makeText(this, R.string.safemode_shortcut_error, Toast.LENGTH_SHORT).show();
            return false;
        }
        for (int i = 0; i < TRIGGER_INTENT.length; i++) {
            if (intent.getAction().equals(TRIGGER_INTENT[i])) {
                final String requiredPermission = REQUIRED_PERMISSIONS[i];
                int hasCallPhonePermission = ContextCompat.checkSelfPermission(Launcher.this,
                        requiredPermission);
                if (hasCallPhonePermission != PackageManager.PERMISSION_GRANTED) {
                    mPermissionIntent = intent;
                    mPermissionTag = tag;
                    mPermissionView = v;
                    if (!ActivityCompat.shouldShowRequestPermissionRationale(Launcher.this,
                            requiredPermission)) {
                        String message = getString(R.string.no_permission_hint) +
                                getString(ACCESS_PERMISSION_HINT[i]);
                        showMessageOKCancel(message,
                                new DialogInterface.OnClickListener() {
                                    @Override
                                    public void onClick(DialogInterface dialog, int which) {
                                        ActivityCompat.requestPermissions(Launcher.this,
                                                new String[]{requiredPermission},
                                                REQUEST_CODE_ASK_PERMISSIONS);
                                    }
                                });
                        return false;
                    }
                    ActivityCompat.requestPermissions(Launcher.this,
                            new String[]{requiredPermission},
                            REQUEST_CODE_ASK_PERMISSIONS);
                    return 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;
    }

当点击某个应用图标时,就会通过调用startActivity方法来把对应的Activity启动起来

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值