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;
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。