Android6.0 Launcher2应用解析
在之前我们分析了Android6.0系统在启动时安装应用程序的过程,这些应用程序安装好之后,Launcher应用就负责把它们在桌面上展示出来。
一、AMS启动Launcher
Launcher应用是在AMS的systemReady方法中直接调用startHomeActivityLocked启动的,下面是systemReady启动Launcher的代码。
startHomeActivityLocked(mCurrentUserId,"systemReady");我们来看下这个函数,先调用了getHomeIntent方法来获取Intent,然后也是调用resolveActivityInfo函数从PKMS获取ActivityInfo,接着当进程没有启动的话,调用ActivityStackSupervisor的startHomeActivity函数
booleanstartHomeActivityLocked(intuserId,Stringreason){ if(mFactoryTest==FactoryTest.FACTORY_TEST_LOW_LEVEL &&mTopAction==null){ //Wearerunninginfactorytestmode,butunabletofind //thefactorytestapp,sojustsitarounddisplayingthe //errormessageanddon'ttrytostartanything. returnfalse; } Intentintent=getHomeIntent();//获取intent ActivityInfoaInfo= resolveActivityInfo(intent,STOCK_PM_FLAGS,userId);//获取ActivityInfo if(aInfo!=null){ intent.setComponent(newComponentName( aInfo.applicationInfo.packageName,aInfo.name)); //Don'tdothisifthehomeappiscurrentlybeing //instrumented. aInfo=newActivityInfo(aInfo); aInfo.applicationInfo=getAppInfoForUser(aInfo.applicationInfo,userId); ProcessRecordapp=getProcessRecordLocked(aInfo.processName, aInfo.applicationInfo.uid,true); if(app==null||app.instrumentationClass==null){//进程没有启动调用 EventLog.writeEvent(EventLogTags.AM_PROC_START,"AMS->startHomeActivityLockedstartHomeActivitythenstartActivityLock:"+aInfo.processName); intent.setFlags(intent.getFlags()|Intent.FLAG_ACTIVITY_NEW_TASK); mStackSupervisor.startHomeActivity(intent,aInfo,reason); } } returntrue; }
我们先来看看getHomeIntent这个函数。
IntentgetHomeIntent(){ Intentintent=newIntent(mTopAction,mTopData!=null?Uri.parse(mTopData):null); intent.setComponent(mTopComponent); if(mFactoryTest!=FactoryTest.FACTORY_TEST_LOW_LEVEL){ intent.addCategory(Intent.CATEGORY_HOME); } returnintent; }
然后我们来看下ActivityStackSupervisor的startHomeActivity函数,它也是调用了startActivityLocked来启动Activity的,在之前的博客分析过这个函数这里我们就不介绍了。
voidstartHomeActivity(Intentintent,ActivityInfoaInfo,Stringreason){ 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){ //Ifweareinresumesectionalready,homeactivitywillbeinitialized,butnot //resumed(toavoidrecursiveresume)andwillstaythatwayuntilsomethingpokesit //again.Weneedtoscheduleanotherresume. 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> <actionandroid:name="android.intent.action.MAIN"/> <categoryandroid:name="android.intent.category.HOME"/> <categoryandroid:name="android.intent.category.DEFAULT"/> <categoryandroid:name="android.intent.category.MONKEY"/> </intent-filter> </activity> ......
在Launcher.java的onCreate函数中调用了mModel.startLoader函数
protectedvoidonCreate(BundlesavedInstanceState){ ...... if(!mRestoring){ if(sPausedFromUserAction){ //Iftheuserleaveslauncher,thenweshouldjustloaditemsasynchronouslywhen //theyreturn. mModel.startLoader(true,-1); }else{ //Weonlyloadthepagesynchronouslyiftheuserrotates(ortriggersa //configurationchange)whilelauncherisintheforeground mModel.startLoader(true,mWorkspace.getCurrentPage()); } } ......
startLoader函数会post一个Runnable消息,我们来看下它的run方法
publicvoidstartLoader(booleanisLaunching,intsynchronousBindPage){ synchronized(mLock){ if(DEBUG_LOADERS){ Log.d(TAG,"startLoaderisLaunching="+isLaunching); } //Clearanydeferredbind-runnablesfromthesynchronizedloadprocess //Wemustdothisbeforeanyloading/bindingisscheduledbelow. mDeferredBindRunnables.clear(); //Don'tbothertostartthethreadifweknowit'snotgoingtodoanything if(mCallbacks!=null&&mCallbacks.get()!=null){ //Ifthereisalreadyonerunning,tellittostop. //also,don'tdowngradeisLaunchingifwe'realreadyrunning isLaunching=isLaunching||stopLoaderLocked(); mLoaderTask=newLoaderTask(mApp,isLaunching); if(synchronousBindPage>-1&&mAllAppsLoaded&&mWorkspaceLoaded){ mLoaderTask.runBindSynchronousPage(synchronousBindPage); }else{ sWorkerThread.setPriority(Thread.NORM_PRIORITY); sWorker.post(mLoaderTask); } } } }
在它的run方法中会调用loadAndBindAllApps函数,在loadAndBindAllApps函数中又会调用loadAllAppsByBatch函数
publicvoidrun(){ synchronized(mLock){ mIsLoaderTaskRunning=true; } finalCallbackscbk=mCallbacks.get(); finalbooleanloadWorkspaceFirst=cbk!=null?(!cbk.isAllAppsVisible()):true; keep_running:{ //ElevateprioritywhenHomelaunchesforthefirsttimetoavoid //starvingatboottime.Staringatablankhomeisnotcool. synchronized(mLock){ if(DEBUG_LOADERS)Log.d(TAG,"Settingthreadpriorityto"+ (mIsLaunching?"DEFAULT":"BACKGROUND")); Process.setThreadPriority(mIsLaunching ?Process.THREAD_PRIORITY_DEFAULT:Process.THREAD_PRIORITY_BACKGROUND); } //Firststep.Loadworkspacefirst,thisisnecessarysinceaddingofappsfrom //managedprofileinallappsisdeferreduntilonResume.Seehttp://b/17336902. if(loadWorkspaceFirst){ if(DEBUG_LOADERS)Log.d(TAG,"step1:loadingworkspace"); loadAndBindWorkspace(); }else{ Log.d(TAG,"step1:special:loadingallapps"); loadAndBindAllApps(); }
我们先来看下loadAndBindAllApps函数,这个函数先进入while循环,然后调用了LauncherApps的getActivityList函数,后面又会调用callbacks的bindAllApplications
privatevoidloadAllAppsByBatch(){ finallongt=DEBUG_LOADERS?SystemClock.uptimeMillis():0; ...... mBgAllAppsList.clear(); finalintprofileCount=profiles.size(); for(intp=0;p<profileCount;p++){ ...... while(i<N&&!mStopped){ if(i==0){ finallongqiaTime=DEBUG_LOADERS?SystemClock.uptimeMillis():0; apps=mLauncherApps.getActivityList(null,user); ...... mHandler.post(newRunnable(){ publicvoidrun(){ finallongt=SystemClock.uptimeMillis(); if(callbacks!=null){ if(firstProfile){ callbacks.bindAllApplications(added); }else{ callbacks.bindAppsAdded(added); } if(DEBUG_LOADERS){ Log.d(TAG,"bound"+added.size()+"appsin" +(SystemClock.uptimeMillis()-t)+"ms"); } }else{ Log.i(TAG,"notbindingapps:noLauncheractivity"); } } }); ......
我们先来看LauncherApps的getActivityList函数,它先用mService成员变量调用getLauncherActivities函数获取到list<ResolveInfo>,然后封装在ArrayList<LauncherActivityInfo>中。
publicList<LauncherActivityInfo>getActivityList(StringpackageName,UserHandleuser){ List<ResolveInfo>activities=null; try{ activities=mService.getLauncherActivities(packageName,user); }catch(RemoteExceptionre){ thrownewRuntimeException("FailedtocallLauncherAppsService"); } if(activities==null){ returnCollections.EMPTY_LIST; } ArrayList<LauncherActivityInfo>lais=newArrayList<LauncherActivityInfo>(); finalintcount=activities.size(); for(inti=0;i<count;i++){ ResolveInfori=activities.get(i); longfirstInstallTime=0; try{ firstInstallTime=mPm.getPackageInfo(ri.activityInfo.packageName, PackageManager.GET_UNINSTALLED_PACKAGES).firstInstallTime; }catch(NameNotFoundExceptionnnfe){ //Sorry,can'tfindpackage } LauncherActivityInfolai=newLauncherActivityInfo(mContext,ri,user, firstInstallTime); if(DEBUG){ Log.v(TAG,"Returningactivityforprofile"+user+":" +lai.getComponentName()); } lais.add(lai); } returnlais; }
其service是classLauncherAppsImplextendsILauncherApps.Stub下面是getLauncherActivities函数,肯定也是通过PKMS来获取相关Activity的ResolveInfo的。
@Override publicList<ResolveInfo>getLauncherActivities(StringpackageName,UserHandleuser) throwsRemoteException{ ensureInUserProfiles(user,"Cannotretrieveactivitiesforunrelatedprofile"+user); if(!isUserEnabled(user)){ returnnewArrayList<ResolveInfo>(); } finalIntentmainIntent=newIntent(Intent.ACTION_MAIN,null); mainIntent.addCategory(Intent.CATEGORY_LAUNCHER); mainIntent.setPackage(packageName); longident=Binder.clearCallingIdentity(); try{ List<ResolveInfo>apps=mPm.queryIntentActivitiesAsUser(mainIntent,0/*flags*/, user.getIdentifier()); returnapps; }finally{ Binder.restoreCallingIdentity(ident); } }
最后回调Launcher.java的bindAllApplications函数,最后在这个函数中可以在桌面上展示系统中所有的应用程序了。
publicvoidbindAllApplications(finalArrayList<ApplicationInfo>apps){ RunnablesetAllAppsRunnable=newRunnable(){ publicvoidrun(){ if(mAppsCustomizeContent!=null){ mAppsCustomizeContent.setApps(apps); } } }; //Removetheprogressbarentirely;wecouldalsomakeitGONE //butbettertoremoveitsinceweknowit'snotgoingtobeused ViewprogressBar=mAppsCustomizeTabHost. findViewById(R.id.apps_customize_progress_bar); if(progressBar!=null){ ((ViewGroup)progressBar.getParent()).removeView(progressBar); //WejustpostthecalltosetAppssotheuserseestheprogressbar //disappear--otherwise,itjustlooksliketheprogressbarfroze //whichdoesn'tlookgreat mAppsCustomizeTabHost.post(setAllAppsRunnable); }else{ //IfwedidnotinitializethespinnerinonCreate,thenwecandirectlysetthe //listofapplicationswithoutwaitingforanyprogressbarsviewstobehidden. setAllAppsRunnable.run(); } }
三、显示应用图标
我们再来看下Launcher的onClick函数,当调用showWorkspace可以显示所有应用的图标。
publicvoidonClick(Viewv){ //Makesurethatrogueclicksdon'tgetthroughwhileallappsislaunching,orafterthe //viewhasdetached(it'spossibleforthistohappeniftheviewisremovedmidtouch). if(v.getWindowToken()==null){ return; } if(!mWorkspace.isFinishedSwitchingState()){ return; } Objecttag=v.getTag(); if(taginstanceofShortcutInfo){ //Openshortcut finalIntentintent=((ShortcutInfo)tag).intent; int[]pos=newint[2]; v.getLocationOnScreen(pos); intent.setSourceBounds(newRect(pos[0],pos[1], pos[0]+v.getWidth(),pos[1]+v.getHeight())); booleansuccess=startActivitySafely(v,intent,tag); if(success&&vinstanceofBubbleTextView){ mWaitingForResume=(BubbleTextView)v; mWaitingForResume.setStayPressed(true); } }elseif(taginstanceofFolderInfo){ if(vinstanceofFolderIcon){ FolderIconfi=(FolderIcon)v; handleFolderClick(fi); } }elseif(v==mAllAppsButton){ if(isAllAppsVisible()){ showWorkspace(true); }else{ onClickAllAppsButton(v); } } }
在showWorkspace中会显示所有的图标
voidshowWorkspace(booleananimated,RunnableonCompleteRunnable){ if(mState!=State.WORKSPACE){ booleanwasInSpringLoadedMode=(mState==State.APPS_CUSTOMIZE_SPRING_LOADED); mWorkspace.setVisibility(View.VISIBLE); hideAppsCustomizeHelper(State.WORKSPACE,animated,false,onCompleteRunnable); //Showthesearchbar(onlyanimateifwewereshowingthedroptargetbarinspring //loadedmode) if(mSearchDropTargetBar!=null){ mSearchDropTargetBar.showSearchBar(wasInSpringLoadedMode); } //Weonlyneedtoanimateinthedockdividerifwe'regoingfromspringloadedmode showDockDivider(animated&&wasInSpringLoadedMode); //SetfocustotheAppsCustomizebutton if(mAllAppsButton!=null){ mAllAppsButton.requestFocus(); } } mWorkspace.flashScrollingIndicator(animated); //Changethestate*after*we'vecalledallthetransitioncode mState=State.WORKSPACE; //Resumetheauto-advanceofwidgets mUserPresent=true; updateRunning(); //Sendanaccessibilityeventtoannouncethecontextchange getWindow().getDecorView() .sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); }
而点击应用图标,最终会调用Launcher.java的startActivitySafely来启动应用。这里调用的startActivity就是Activity的startActivity函数。
booleanstartActivitySafely(Viewv,Intentintent,Objecttag){ booleansuccess=false; try{ success=startActivity(v,intent,tag); }catch(ActivityNotFoundExceptione){ Toast.makeText(this,R.string.activity_not_found,Toast.LENGTH_SHORT).show(); Log.e(TAG,"Unabletolaunch.tag="+tag+"intent="+intent,e); } returnsuccess; }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。