Android系统默认Home应用程序(Launcher)的启动过程源代码分析

简介: 转自 :http://blog.csdn.net/luoshengyang/article/details/6767736    在前面一篇文章中,我们分析了Android系统在启动时安装应用程序的过程,这些应用程序安装好之后,还需要有一个Home应用程序来负责把它们在桌面上展示出来,在Android系统中,这个默认的Home应用程序就是Launcher了,本文将详细分析Laun

转自 :http://blog.csdn.net/luoshengyang/article/details/6767736

   在前面一篇文章中,我们分析了Android系统在启动时安装应用程序的过程,这些应用程序安装好之后,还需要有一个Home应用程序来负责把它们在桌面上展示出来,在Android系统中,这个默认的Home应用程序就是Launcher了,本文将详细分析Launcher应用程序的启动过程。

        Android系统的Home应用程序Launcher是由ActivityManagerService启动的,而ActivityManagerService和PackageManagerService一样,都是在开机时由SystemServer组件启动的,SystemServer组件首先是启动ePackageManagerServic,由它来负责安装系统的应用程序,具体可以参考前面一篇文章Android应用程序安装过程源代码分析,系统中的应用程序安装好了以后,SystemServer组件接下来就要通过ActivityManagerService来启动Home应用程序Launcher了,Launcher在启动的时候便会通过PackageManagerServic把系统中已经安装好的应用程序以快捷图标的形式展示在桌面上,这样用户就可以使用这些应用程序了,整个过程如下图所示:


点击查看大图

        下面详细分析每一个步骤。

        Step 1. SystemServer.main

        这个函数定义在frameworks/base/services/java/com/android/server/SystemServer.java文件中,具体可以参考前面一篇文章Android应用程序安装过程源代码分析的Step 1。

        Step 2. SystemServer.init1

        这个函数是一个JNI方法,实现在 frameworks/base/services/jni/com_android_server_SystemServer.cpp文件中,具体可以参考前面一篇文章Android应用程序安装过程源代码分析的Step 2。

        Step 3. libsystem_server.system_init

        函数system_init实现在libsystem_server库中,源代码位于frameworks/base/cmds/system_server/library/system_init.cpp文件中,具体可以参考前面一篇文章Android应用程序安装过程源代码分析的Step 3。

        Step 4. AndroidRuntime.callStatic

        这个函数定义在frameworks/base/core/jni/AndroidRuntime.cpp文件中,具体可以参考前面一篇文章Android应用程序安装过程源代码分析的Step 4。

        Step 5. SystemServer.init2

        这个函数定义在frameworks/base/services/java/com/android/server/SystemServer.java文件中,具体可以参考前面一篇文章Android应用程序安装过程源代码分析的Step 5。

        Step 6. ServerThread.run

        这个函数定义在frameworks/base/services/java/com/android/server/SystemServer.java文件中,具体可以参考前面一篇文章Android应用程序安装过程源代码分析的Step 6。

        Step 7. ActivityManagerService.main

        这个函数定义在frameworks/base/services/java/com/android/server/am/ActivityManagerServcie.java文件中:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public final class ActivityManagerService extends ActivityManagerNative  
  2.         implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {  
  3.     ......  
  4.   
  5.     public static final Context main(int factoryTest) {  
  6.         AThread thr = new AThread();  
  7.         thr.start();  
  8.   
  9.         synchronized (thr) {  
  10.             while (thr.mService == null) {  
  11.                 try {  
  12.                     thr.wait();  
  13.                 } catch (InterruptedException e) {  
  14.                 }  
  15.             }  
  16.         }  
  17.   
  18.         ActivityManagerService m = thr.mService;  
  19.         mSelf = m;  
  20.         ActivityThread at = ActivityThread.systemMain();  
  21.         mSystemThread = at;  
  22.         Context context = at.getSystemContext();  
  23.         m.mContext = context;  
  24.         m.mFactoryTest = factoryTest;  
  25.         m.mMainStack = new ActivityStack(m, context, true);  
  26.   
  27.         m.mBatteryStatsService.publish(context);  
  28.         m.mUsageStatsService.publish(context);  
  29.   
  30.         synchronized (thr) {  
  31.             thr.mReady = true;  
  32.             thr.notifyAll();  
  33.         }  
  34.   
  35.         m.startRunning(nullnullnullnull);  
  36.   
  37.         return context;  
  38.     }  
  39.   
  40.     ......  
  41. }  
        这个函数首先通过AThread线程对象来内部创建了一个ActivityManagerService实例,然后将这个实例保存其成员变量mService中,接着又把这个ActivityManagerService实例保存在ActivityManagerService类的静态成员变量mSelf中,最后初始化其它成员变量,就结束了。

        Step 8. PackageManagerService.main

        这个函数定义在frameworks/base/services/java/com/android/server/PackageManagerService.java文件中,具体可以参考前面一篇文章Android应用程序安装过程源代码分析的Step 7。执行完这一步之后,系统中的应用程序的所有信息都保存在PackageManagerService中了,后面Home应用程序Launcher启动起来后,就会把PackageManagerService中的应用程序信息取出来,然后以快捷图标的形式展示在桌面上,后面我们将会看到这个过程。

        Step 9. ActivityManagerService.setSystemProcess

        这个函数定义在frameworks/base/services/java/com/android/server/am/ActivityManagerServcie.java文件中:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public final class ActivityManagerService extends ActivityManagerNative  
  2.         implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {  
  3.     ......  
  4.   
  5.     public static void setSystemProcess() {  
  6.         try {  
  7.             ActivityManagerService m = mSelf;  
  8.   
  9.             ServiceManager.addService("activity", m);  
  10.             ServiceManager.addService("meminfo"new MemBinder(m));  
  11.             if (MONITOR_CPU_USAGE) {  
  12.                 ServiceManager.addService("cpuinfo"new CpuBinder(m));  
  13.             }  
  14.             ServiceManager.addService("permission"new PermissionController(m));  
  15.   
  16.             ApplicationInfo info =  
  17.                 mSelf.mContext.getPackageManager().getApplicationInfo(  
  18.                 "android", STOCK_PM_FLAGS);  
  19.             mSystemThread.installSystemApplicationInfo(info);  
  20.   
  21.             synchronized (mSelf) {  
  22.                 ProcessRecord app = mSelf.newProcessRecordLocked(  
  23.                     mSystemThread.getApplicationThread(), info,  
  24.                     info.processName);  
  25.                 app.persistent = true;  
  26.                 app.pid = MY_PID;  
  27.                 app.maxAdj = SYSTEM_ADJ;  
  28.                 mSelf.mProcessNames.put(app.processName, app.info.uid, app);  
  29.                 synchronized (mSelf.mPidsSelfLocked) {  
  30.                     mSelf.mPidsSelfLocked.put(app.pid, app);  
  31.                 }  
  32.                 mSelf.updateLruProcessLocked(app, truetrue);  
  33.             }  
  34.         } catch (PackageManager.NameNotFoundException e) {  
  35.             throw new RuntimeException(  
  36.                 "Unable to find android system package", e);  
  37.         }  
  38.     }  
  39.     ......  
  40. }  
        这个函数首先是将这个ActivityManagerService实例添加到ServiceManager中去托管,这样其它地方就可以通过ServiceManager.getService接口来访问这个全局唯一的ActivityManagerService实例了,接着又通过调用mSystemThread.installSystemApplicationInfo函数来把应用程序框架层下面的android包加载进来 ,这里的mSystemThread是一个ActivityThread类型的实例变量,它是在上面的Step 7中创建的,后面就是一些其它的初始化工作了。

        Step 10.  ActivityManagerService.systemReady

        这个函数是在上面的Step 6中的ServerThread.run函数在将系统中的一系列服务都初始化完毕之后才调用的,它定义在frameworks/base/services/java/com/android/server/am/ActivityManagerServcie.java文件中:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public final class ActivityManagerService extends ActivityManagerNative  
  2.         implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {  
  3.     ......  
  4.   
  5.     public void systemReady(final Runnable goingCallback) {  
  6.         ......  
  7.   
  8.         synchronized (this) {  
  9.             ......  
  10.   
  11.             mMainStack.resumeTopActivityLocked(null);  
  12.         }  
  13.     }  
  14.   
  15.     ......  
  16. }  
        这个函数的内容比较多,这里省去无关的部分,主要关心启动Home应用程序的逻辑,这里就是通过mMainStack.resumeTopActivityLocked函数来启动Home应用程序的了,这里的mMainStack是一个ActivityStack类型的实例变量。

        Step 11. ActivityStack.resumeTopActivityLocked

        这个函数定义在frameworks/base/services/java/com/android/server/am/ActivityStack.java文件中:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public class ActivityStack {  
  2.     ......  
  3.   
  4.     final boolean resumeTopActivityLocked(ActivityRecord prev) {  
  5.         // Find the first activity that is not finishing.  
  6.         ActivityRecord next = topRunningActivityLocked(null);  
  7.   
  8.         ......  
  9.   
  10.         if (next == null) {  
  11.             // There are no more activities!  Let's just start up the  
  12.             // Launcher...  
  13.             if (mMainStack) {  
  14.                 return mService.startHomeActivityLocked();  
  15.             }  
  16.         }  
  17.   
  18.         ......  
  19.     }  
  20.   
  21.     ......  
  22. }  
        这里调用函数topRunningActivityLocked返回的是当前系统Activity堆栈最顶端的Activity,由于此时还没有Activity被启动过,因此,返回值为null,即next变量的值为null,于是就调用mService.startHomeActivityLocked语句,这里的mService就是前面在Step 7中创建的ActivityManagerService实例了。

        Step 12. ActivityManagerService.startHomeActivityLocked

        这个函数定义在frameworks/base/services/java/com/android/server/am/ActivityManagerServcie.java文件中:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public final class ActivityManagerService extends ActivityManagerNative  
  2.         implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {  
  3.     ......  
  4.   
  5.     boolean startHomeActivityLocked() {  
  6.         ......  
  7.   
  8.         Intent intent = new Intent(  
  9.             mTopAction,  
  10.             mTopData != null ? Uri.parse(mTopData) : null);  
  11.         intent.setComponent(mTopComponent);  
  12.         if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {  
  13.             intent.addCategory(Intent.CATEGORY_HOME);  
  14.         }  
  15.         ActivityInfo aInfo =  
  16.             intent.resolveActivityInfo(mContext.getPackageManager(),  
  17.             STOCK_PM_FLAGS);  
  18.         if (aInfo != null) {  
  19.             intent.setComponent(new ComponentName(  
  20.                 aInfo.applicationInfo.packageName, aInfo.name));  
  21.             // Don't do this if the home app is currently being  
  22.             // instrumented.  
  23.             ProcessRecord app = getProcessRecordLocked(aInfo.processName,  
  24.                 aInfo.applicationInfo.uid);  
  25.             if (app == null || app.instrumentationClass == null) {  
  26.                 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);  
  27.                 mMainStack.startActivityLocked(null, intent, nullnull0, aInfo,  
  28.                     nullnull000falsefalse);  
  29.             }  
  30.         }  
  31.   
  32.         return true;  
  33.     }  
  34.   
  35.     ......  
  36. }  
        函数首先创建一个CATEGORY_HOME类型的Intent,然后通过Intent.resolveActivityInfo函数向PackageManagerService查询Category类型为HOME的Activity,这里我们假设只有系统自带的Launcher应用程序注册了HOME类型的Activity(见packages/apps/Launcher2/AndroidManifest.xml文件):

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. <manifest  
  2.     xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     package="com.android.launcher"  
  4.     android:sharedUserId="@string/sharedUserId"  
  5.     >  
  6.   
  7.     ......  
  8.   
  9.     <application  
  10.         android:name="com.android.launcher2.LauncherApplication"  
  11.         android:process="@string/process"  
  12.         android:label="@string/application_name"  
  13.         android:icon="@drawable/ic_launcher_home">  
  14.   
  15.         <activity  
  16.             android:name="com.android.launcher2.Launcher"  
  17.             android:launchMode="singleTask"  
  18.             android:clearTaskOnLaunch="true"  
  19.             android:stateNotNeeded="true"  
  20.             android:theme="@style/Theme"  
  21.             android:screenOrientation="nosensor"  
  22.             android:windowSoftInputMode="stateUnspecified|adjustPan">  
  23.             <intent-filter>  
  24.                 <action android:name="android.intent.action.MAIN" />  
  25.                 <category android:name="android.intent.category.HOME" />  
  26.                 <category android:name="android.intent.category.DEFAULT" />  
  27.                 <category android:name="android.intent.category.MONKEY"/>  
  28.                 </intent-filter>  
  29.         </activity>  
  30.   
  31.         ......  
  32.     </application>  
  33. </manifest>  

        因此,这里就返回com.android.launcher2.Launcher这个Activity了。由于是第一次启动这个Activity,接下来调用函数getProcessRecordLocked返回来的ProcessRecord值为null,于是,就调用mMainStack.startActivityLocked函数启动com.android.launcher2.Launcher这个Activity了,这里的mMainStack是一个ActivityStack类型的成员变量。

        Step 13.  ActivityStack.startActivityLocked

        这个函数定义在frameworks/base/services/java/com/android/server/am/ActivityStack.java文件中,具体可以参考Android应用程序启动过程源代码分析一文,这里就不详述了,在我们这个场景中,调用这个函数的最后结果就是把com.android.launcher2.Launcher启动起来,接着调用它的onCreate函数。

        Step 14. Launcher.onCreate

        这个函数定义在packages/apps/Launcher2/src/com/android/launcher2/Launcher.java文件中:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public final class Launcher extends Activity  
  2.         implements View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks, AllAppsView.Watcher {  
  3.     ......  
  4.   
  5.     @Override  
  6.     protected void onCreate(Bundle savedInstanceState) {  
  7.         ......  
  8.   
  9.         if (!mRestoring) {  
  10.             mModel.startLoader(thistrue);  
  11.         }  
  12.   
  13.         ......  
  14.     }  
  15.   
  16.     ......  
  17. }  
        这里的mModel是一个LauncherModel类型的成员变量,这里通过调用它的startLoader成员函数来执行加应用程序的操作。

        Step 15. LauncherModel.startLoader

        这个函数定义在packages/apps/Launcher2/src/com/android/launcher2/LauncherModel.java文件中:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public class LauncherModel extends BroadcastReceiver {  
  2.     ......  
  3.   
  4.     public void startLoader(Context context, boolean isLaunching) {  
  5.         ......  
  6.   
  7.                 synchronized (mLock) {  
  8.                      ......  
  9.   
  10.                      // Don't bother to start the thread if we know it's not going to do anything  
  11.                      if (mCallbacks != null && mCallbacks.get() != null) {  
  12.                          // If there is already one running, tell it to stop.  
  13.                          LoaderTask oldTask = mLoaderTask;  
  14.                          if (oldTask != null) {  
  15.                              if (oldTask.isLaunching()) {  
  16.                                  // don't downgrade isLaunching if we're already running  
  17.                                  isLaunching = true;  
  18.                              }  
  19.                              oldTask.stopLocked();  
  20.                  }  
  21.                  mLoaderTask = new LoaderTask(context, isLaunching);  
  22.                  sWorker.post(mLoaderTask);  
  23.                 }  
  24.            }  
  25.     }  
  26.   
  27.     ......  
  28. }  
        这里不是直接加载应用程序,而是把加载应用程序的操作作为一个消息来处理。这里的sWorker是一个Handler,通过它的post方式把一个消息放在消息队列中去,然后系统就会调用传进去的参数mLoaderTask的run函数来处理这个消息,这个mLoaderTask是LoaderTask类型的实例,于是,下面就会执行LoaderTask类的run函数了。

        Step 16. LoaderTask.run

        这个函数定义在packages/apps/Launcher2/src/com/android/launcher2/LauncherModel.java文件中:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public class LauncherModel extends BroadcastReceiver {  
  2.     ......  
  3.   
  4.     private class LoaderTask implements Runnable {  
  5.         ......  
  6.   
  7.         public void run() {  
  8.             ......  
  9.   
  10.             keep_running: {  
  11.                 ......  
  12.   
  13.                 // second step  
  14.                 if (loadWorkspaceFirst) {  
  15.                     ......  
  16.                     loadAndBindAllApps();  
  17.                 } else {  
  18.                     ......  
  19.                 }  
  20.   
  21.                 ......  
  22.             }  
  23.   
  24.             ......  
  25.         }  
  26.   
  27.         ......  
  28.     }  
  29.   
  30.     ......  
  31. }  
        这里调用loadAndBindAllApps成员函数来进一步操作。

        Step 17. LoaderTask.loadAndBindAllApps
        这个函数定义在packages/apps/Launcher2/src/com/android/launcher2/LauncherModel.java文件中:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public class LauncherModel extends BroadcastReceiver {  
  2.     ......  
  3.   
  4.     private class LoaderTask implements Runnable {  
  5.         ......  
  6.   
  7.         private void loadAndBindAllApps() {  
  8.             ......  
  9.   
  10.             if (!mAllAppsLoaded) {  
  11.                 loadAllAppsByBatch();  
  12.                 if (mStopped) {  
  13.                     return;  
  14.                 }  
  15.                 mAllAppsLoaded = true;  
  16.             } else {  
  17.                 onlyBindAllApps();  
  18.             }  
  19.         }  
  20.   
  21.   
  22.         ......  
  23.     }  
  24.   
  25.     ......  
  26. }  
        由于还没有加载过应用程序,这里的mAllAppsLoaded为false,于是就继续调用loadAllAppsByBatch函数来进一步操作了。

        Step 18. LoaderTask.loadAllAppsByBatch
        这个函数定义在packages/apps/Launcher2/src/com/android/launcher2/LauncherModel.java文件中:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public class LauncherModel extends BroadcastReceiver {  
  2.     ......  
  3.   
  4.     private class LoaderTask implements Runnable {  
  5.         ......  
  6.   
  7.         private void loadAllAppsByBatch() {   
  8.             ......  
  9.   
  10.             final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);  
  11.             mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);  
  12.   
  13.             final PackageManager packageManager = mContext.getPackageManager();  
  14.             List<ResolveInfo> apps = null;  
  15.   
  16.             int N = Integer.MAX_VALUE;  
  17.   
  18.             int startIndex;  
  19.             int i=0;  
  20.             int batchSize = -1;  
  21.             while (i < N && !mStopped) {  
  22.                 if (i == 0) {  
  23.                     mAllAppsList.clear();  
  24.                     ......  
  25.                     apps = packageManager.queryIntentActivities(mainIntent, 0);  
  26.                       
  27.                     ......  
  28.   
  29.                     N = apps.size();  
  30.                       
  31.                     ......  
  32.   
  33.                     if (mBatchSize == 0) {  
  34.                         batchSize = N;  
  35.                     } else {  
  36.                         batchSize = mBatchSize;  
  37.                     }  
  38.   
  39.                     ......  
  40.   
  41.                     Collections.sort(apps,  
  42.                         new ResolveInfo.DisplayNameComparator(packageManager));  
  43.                 }  
  44.   
  45.                 startIndex = i;  
  46.                 for (int j=0; i<N && j<batchSize; j++) {  
  47.                     // This builds the icon bitmaps.  
  48.                     mAllAppsList.add(new ApplicationInfo(apps.get(i), mIconCache));  
  49.                     i++;  
  50.                 }  
  51.   
  52.                 final boolean first = i <= batchSize;  
  53.                 final Callbacks callbacks = tryGetCallbacks(oldCallbacks);  
  54.                 final ArrayList<ApplicationInfo> added = mAllAppsList.added;  
  55.                 mAllAppsList.added = new ArrayList<ApplicationInfo>();  
  56.               
  57.                 mHandler.post(new Runnable() {  
  58.                     public void run() {  
  59.                         final long t = SystemClock.uptimeMillis();  
  60.                         if (callbacks != null) {  
  61.                             if (first) {  
  62.                                 callbacks.bindAllApplications(added);  
  63.                             } else {  
  64.                                 callbacks.bindAppsAdded(added);  
  65.                             }  
  66.                             ......  
  67.                         } else {  
  68.                             ......  
  69.                         }  
  70.                     }  
  71.                 });  
  72.   
  73.                 ......  
  74.             }  
  75.   
  76.             ......  
  77.         }  
  78.   
  79.         ......  
  80.     }  
  81.   
  82.     ......  
  83. }  
        函数首先构造一个CATEGORY_LAUNCHER类型的Intent:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);  
  2. mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);  
        接着从mContext变量中获得PackageManagerService的接口:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. final PackageManager packageManager = mContext.getPackageManager();  

       下一步就是通过这个PackageManagerService.queryIntentActivities接口来取回所有Action类型为Intent.ACTION_MAIN,并且Category类型为Intent.CATEGORY_LAUNCHER的Activity了。

       我们先进入到PackageManagerService.queryIntentActivities函数中看看是如何获得这些Activity的,然后再回到这个函数中来看其余操作。

       Step 19. PackageManagerService.queryIntentActivities

       这个函数定义在frameworks/base/services/java/com/android/server/PackageManagerService.java文件中:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. class PackageManagerService extends IPackageManager.Stub {  
  2.     ......  
  3.   
  4.     public List<ResolveInfo> queryIntentActivities(Intent intent,  
  5.             String resolvedType, int flags) {  
  6.         ......  
  7.   
  8.         synchronized (mPackages) {  
  9.             String pkgName = intent.getPackage();  
  10.             if (pkgName == null) {  
  11.                 return (List<ResolveInfo>)mActivities.queryIntent(intent,  
  12.                         resolvedType, flags);  
  13.             }  
  14.   
  15.             ......  
  16.         }  
  17.   
  18.         ......  
  19.     }  
  20.   
  21.     ......  
  22. }  

        回忆前面一篇文章Android应用程序安装过程源代码分析,系统在前面的Step 8中启动PackageManagerService时,会把系统中的应用程序都解析一遍,然后把解析得到的Activity都保存在mActivities变量中,这里通过这个mActivities变量的queryIntent函数返回符合条件intent的Activity,这里要返回的便是Action类型为Intent.ACTION_MAIN,并且Category类型为Intent.CATEGORY_LAUNCHER的Activity了。

        回到Step 18中的 LoaderTask.loadAllAppsByBatch函数中,从queryIntentActivities函数调用处返回所要求的Activity后,便调用函数tryGetCallbacks(oldCallbacks)得到一个返CallBack接口,这个接口是由Launcher类实现的,接着调用这个接口的.bindAllApplications函数来进一步操作。注意,这里又是通过消息来处理加载应用程序的操作的。

        Step 20. Launcher.bindAllApplications

        这个函数定义在packages/apps/Launcher2/src/com/android/launcher2/Launcher.java文件中:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public final class Launcher extends Activity  
  2.         implements View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks, AllAppsView.Watcher {  
  3.     ......  
  4.   
  5.     private AllAppsView mAllAppsGrid;  
  6.   
  7.     ......  
  8.   
  9.     public void bindAllApplications(ArrayList<ApplicationInfo> apps) {  
  10.         mAllAppsGrid.setApps(apps);  
  11.     }  
  12.   
  13.     ......  
  14. }  
        这里的mAllAppsGrid是一个AllAppsView类型的变量,它的实际类型一般就是AllApps2D了。

        Step 21. AllApps2D.setApps

        这个函数定义在packages/apps/Launcher2/src/com/android/launcher2/AllApps2D.java文件中:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public class AllApps2D  
  2.     extends RelativeLayout  
  3.     implements AllAppsView,  
  4.         AdapterView.OnItemClickListener,  
  5.         AdapterView.OnItemLongClickListener,  
  6.         View.OnKeyListener,  
  7.         DragSource {  
  8.   
  9.     ......  
  10.   
  11.     public void setApps(ArrayList<ApplicationInfo> list) {  
  12.         mAllAppsList.clear();  
  13.         addApps(list);  
  14.     }  
  15.   
  16.     public void addApps(ArrayList<ApplicationInfo> list) {  
  17.         final int N = list.size();  
  18.   
  19.         for (int i=0; i<N; i++) {  
  20.             final ApplicationInfo item = list.get(i);  
  21.             int index = Collections.binarySearch(mAllAppsList, item,  
  22.                 LauncherModel.APP_NAME_COMPARATOR);  
  23.             if (index < 0) {  
  24.                 index = -(index+1);  
  25.             }  
  26.             mAllAppsList.add(index, item);  
  27.         }  
  28.         mAppsAdapter.notifyDataSetChanged();  
  29.     }  
  30.   
  31.     ......  
  32. }  
        函数setApps首先清空mAllAppsList列表,然后调用addApps函数来为上一步得到的每一个应用程序创建一个ApplicationInfo实例了,有了这些ApplicationInfo实例之后,就可以在桌面上展示系统中所有的应用程序了。

        到了这里,系统默认的Home应用程序Launcher就把PackageManagerService中的应用程序加载进来了,当我们在屏幕上点击下面这个图标时,就会把刚才加载好的应用程序以图标的形式展示出来了:

        点击这个按钮时,便会响应Launcher.onClick函数:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public final class Launcher extends Activity  
  2.         implements View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks, AllAppsView.Watcher {  
  3.     ......  
  4.   
  5.     public void onClick(View v) {  
  6.         Object tag = v.getTag();  
  7.         if (tag instanceof ShortcutInfo) {  
  8.             ......  
  9.         } else if (tag instanceof FolderInfo) {  
  10.             ......  
  11.         } else if (v == mHandleView) {  
  12.             if (isAllAppsVisible()) {  
  13.                 ......  
  14.             } else {  
  15.                 showAllApps(true);  
  16.             }  
  17.         }  
  18.     }  
  19.   
  20.     ......  
  21. }  
        接着就会调用showAllApps函数显示应用程序图标:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public final class Launcher extends Activity  
  2.         implements View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks, AllAppsView.Watcher {  
  3.     ......  
  4.   
  5.     void showAllApps(boolean animated) {  
  6.         mAllAppsGrid.zoom(1.0f, animated);  
  7.   
  8.         ((View) mAllAppsGrid).setFocusable(true);  
  9.         ((View) mAllAppsGrid).requestFocus();  
  10.   
  11.         // TODO: fade these two too  
  12.         mDeleteZone.setVisibility(View.GONE);  
  13.     }  
  14.   
  15.     ......  
  16. }  
        这样我们就可以看到系统中的应用程序了:



        当点击上面的这些应用程序图标时,便会响应AllApps2D.onItemClick函数:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public class AllApps2D  
  2.     extends RelativeLayout  
  3.     implements AllAppsView,  
  4.         AdapterView.OnItemClickListener,  
  5.         AdapterView.OnItemLongClickListener,  
  6.         View.OnKeyListener,  
  7.         DragSource {  
  8.   
  9.     ......  
  10.   
  11.     public void onItemClick(AdapterView parent, View v, int position, long id) {  
  12.         ApplicationInfo app = (ApplicationInfo) parent.getItemAtPosition(position);  
  13.         mLauncher.startActivitySafely(app.intent, app);  
  14.     }  
  15.   
  16.   
  17.     ......  
  18. }<span style="font-family:Arial, Verdana, sans-serif;"><span style="white-space: normal;">  
  19. </span></span>  

        这里的成员变量mLauncher的类型为Launcher,于是就调用Launcher.startActivitySafely函数来启动应用程序了,这个过程具体可以参考Android应用程序启动过程源代码分析一文。


目录
相关文章
|
12天前
|
安全 Android开发 数据安全/隐私保护
深入探讨iOS与Android系统安全性对比分析
在移动操作系统领域,iOS和Android无疑是两大巨头。本文从技术角度出发,对这两个系统的架构、安全机制以及用户隐私保护等方面进行了详细的比较分析。通过深入探讨,我们旨在揭示两个系统在安全性方面的差异,并为用户提供一些实用的安全建议。
|
12天前
|
算法 JavaScript Android开发
|
14天前
|
安全 搜索推荐 Android开发
揭秘安卓与iOS系统的差异:技术深度对比
【10月更文挑战第27天】 本文深入探讨了安卓(Android)与iOS两大移动操作系统的技术特点和用户体验差异。通过对比两者的系统架构、应用生态、用户界面、安全性等方面,揭示了为何这两种系统能够在市场中各占一席之地,并为用户提供不同的选择。文章旨在为读者提供一个全面的视角,理解两种系统的优势与局限,从而更好地根据自己的需求做出选择。
36 2
|
13天前
|
安全 搜索推荐 程序员
深入探索Android系统的碎片化问题及其解决方案
在移动操作系统的世界中,Android以其开放性和灵活性赢得了广泛的市场份额。然而,这种开放性也带来了一个众所周知的问题——系统碎片化。本文旨在探讨Android系统碎片化的现状、成因以及可能的解决方案,为开发者和用户提供一种全新的视角来理解这一现象。通过分析不同版本的Android系统分布、硬件多样性以及更新机制的影响,我们提出了一系列针对性的策略,旨在减少碎片化带来的影响,提升用户体验。
|
13天前
|
安全 Android开发 iOS开发
深入探索iOS与Android系统的差异性及优化策略
在当今数字化时代,移动操作系统的竞争尤为激烈,其中iOS和Android作为市场上的两大巨头,各自拥有庞大的用户基础和独特的技术特点。本文旨在通过对比分析iOS与Android的核心差异,探讨各自的优势与局限,并提出针对性的优化策略,以期为用户提供更优质的使用体验和为开发者提供有价值的参考。
|
3天前
|
搜索推荐 Android开发 开发者
探索安卓开发中的自定义视图:打造个性化UI组件
【10月更文挑战第39天】在安卓开发的世界中,自定义视图是实现独特界面设计的关键。本文将引导你理解自定义视图的概念、创建流程,以及如何通过它们增强应用的用户体验。我们将从基础出发,逐步深入,最终让你能够自信地设计和实现专属的UI组件。
|
5天前
|
Android开发 Swift iOS开发
探索安卓与iOS开发的差异和挑战
【10月更文挑战第37天】在移动应用开发的广阔舞台上,安卓和iOS这两大操作系统扮演着主角。它们各自拥有独特的特性、优势以及面临的开发挑战。本文将深入探讨这两个平台在开发过程中的主要差异,从编程语言到用户界面设计,再到市场分布的不同影响,旨在为开发者提供一个全面的视角,帮助他们更好地理解并应对在不同平台上进行应用开发时可能遇到的难题和机遇。
|
7天前
|
XML 存储 Java
探索安卓开发之旅:从新手到专家
【10月更文挑战第35天】在数字化时代,安卓应用的开发成为了一个热门话题。本文旨在通过浅显易懂的语言,带领初学者了解安卓开发的基础知识,同时为有一定经验的开发者提供进阶技巧。我们将一起探讨如何从零开始构建第一个安卓应用,并逐步深入到性能优化和高级功能的实现。无论你是编程新手还是希望提升技能的开发者,这篇文章都将为你提供有价值的指导和灵感。