正文  UI设计 > Launcher >

launcher修改--获取应用列表

在home节面上,当我们点击中间按键的时候,会跳转到一个下图,在代码中是如何实现的呢?我们来找一下:源码copy to clipboard打印?mHandleView = (HandleView) findViewById(R.id.all_apps_button);mHandl......

在home节面上,当我们点击中间按键的时候,会跳转到一个下图,

在代码中是如何实现的呢?我们来找一下:

 

源码copy to clipboard打印?
  1. mHandleView = (HandleView) findViewById(R.id.all_apps_button);
  2. mHandleView.setLauncher(this);
  3. mHandleView.setOnClickListener(this);
  4. mHandleView.setOnLongClickListener(this);
mHandleView = (HandleView) findViewById(R.id.all_apps_button);
        mHandleView.setLauncher(this);
        mHandleView.setOnClickListener(this);
        mHandleView.setOnLongClickListener(this);
再看onclick()方法:在onclick方法中,有一下代码

 

 

源码copy to clipboard打印?
  1. else if (v == mHandleView) {
  2. if (isAllAppsVisible()) {
  3. closeAllApps(true);
  4. } else {
  5. showAllApps(true);
  6. }
else if (v == mHandleView) {
            if (isAllAppsVisible()) {
                closeAllApps(true);
            } else {
                showAllApps(true);
            }
我们再找一下 showAllApps()方法

 

 

源码copy to clipboard打印?
  1. void showAllApps(boolean animated) {
  2. mAllAppsGrid.zoom(1.0f, animated);
  3.  
  4. ((View) mAllAppsGrid).setFocusable(true);
  5. ((View) mAllAppsGrid).requestFocus();
  6.  
  7. // TODO: fade these two too
  8. mDeleteZone.setVisibility(View.GONE);
  9. mHandleView.setVisibility(View.GONE);
  10. mPreviousView.setVisibility(View.GONE);
  11. mNextView.setVisibility(View.GONE);
  12. hotseatLeft.setVisibility(View.GONE);
  13. hotseatRight.setVisibility(View.GONE);
  14. }
void showAllApps(boolean animated) {
        mAllAppsGrid.zoom(1.0f, animated);

        ((View) mAllAppsGrid).setFocusable(true);
        ((View) mAllAppsGrid).requestFocus();
        
        // TODO: fade these two too
        mDeleteZone.setVisibility(View.GONE);
        mHandleView.setVisibility(View.GONE);
        mPreviousView.setVisibility(View.GONE);
        mNextView.setVisibility(View.GONE);
	hotseatLeft.setVisibility(View.GONE);
	hotseatRight.setVisibility(View.GONE);
    }
在上面用到了mAllAppsGrid,我们找一下这个控件:

 

 

源码copy to clipboard打印?
  1. private AllAppsView mAllAppsGrid;
  2.  
  3. mAllAppsGrid = (AllAppsView)dragLayer.findViewById(R.id.all_apps_view);
  4. mAllAppsGrid.setLauncher(this);
  5. mAllAppsGrid.setDragController(dragController);
  6. ((View) mAllAppsGrid).setWillNotDraw(false); // We don't want a hole punched in our window.
  7. // Manage focusability manually since this thing is always visible
  8. ((View) mAllAppsGrid).setFocusable(false);
private AllAppsView mAllAppsGrid;

        mAllAppsGrid = (AllAppsView)dragLayer.findViewById(R.id.all_apps_view);
        mAllAppsGrid.setLauncher(this);
        mAllAppsGrid.setDragController(dragController);
        ((View) mAllAppsGrid).setWillNotDraw(false); // We don't want a hole punched in our window.
        // Manage focusability manually since this thing is always visible
        ((View) mAllAppsGrid).setFocusable(false);
上面代码是在Launcher.java中的setupview()方法中定义
all_apps_view是在all_app_2d.xml中定义。

 

你想找到AllApp2D.java中,可以找到mAllAppsGrid使用的方法,如addApps,removeApps,zoom这几个方法:

 

源码copy to clipboard打印?
  1. public void addApps(ArrayList<ApplicationInfo> list) {
  2. // Log.d(TAG, "addApps: " + list.size() + " apps: " + list.toString());
  3.  
  4. final int N = list.size();
  5.  
  6. for (int i=0; i<N; i++) {
  7. final ApplicationInfo item = list.get(i);
  8. int index = Collections.binarySearch(mAllAppsList, item,
  9. LauncherModel.APP_NAME_COMPARATOR);
  10. if (index < 0) {
  11. index = -(index+1);
  12. }
  13. mAllAppsList.add(index, item);
  14. }
  15. mAppsAdapter.notifyDataSetChanged();
  16. }
  17.  
  18. public void removeApps(ArrayList<ApplicationInfo> list) {
  19. final int N = list.size();
  20. for (int i=0; i<N; i++) {
  21. final ApplicationInfo item = list.get(i);
  22. int index = findAppByComponent(mAllAppsList, item);
  23. if (index >= 0) {
  24. mAllAppsList.remove(index);
  25. } else {
  26. Log.w(TAG, "couldn't find a match for item \"" + item + "\"");
  27. // Try to recover. This should keep us from crashing for now.
  28. }
  29. }
  30. mAppsAdapter.notifyDataSetChanged();
  31. }
  32.  
  33. public void zoom(float zoom, boolean animate) {
  34. // Log.d(TAG, "zooming " + ((zoom == 1.0) ? "open" : "closed"));
  35. cancelLongPress();
  36.  
  37. mZoom = zoom;
  38.  
  39. if (isVisible()) {
  40. getParent().bringChildToFront(this);
  41. setVisibility(View.VISIBLE);
  42. mGrid.setAdapter(mAppsAdapter);
  43. if (animate) {
  44. startAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.all_apps_2d_fade_in));
  45. } else {
  46. onAnimationEnd();
  47. }
  48. } else {
  49. if (animate) {
  50. startAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.all_apps_2d_fade_out));
  51. } else {
  52. onAnimationEnd();
  53. }
  54. }
  55. }
public void addApps(ArrayList<ApplicationInfo> list) {
//        Log.d(TAG, "addApps: " + list.size() + " apps: " + list.toString());

        final int N = list.size();

        for (int i=0; i<N; i++) {
            final ApplicationInfo item = list.get(i);
            int index = Collections.binarySearch(mAllAppsList, item,
                    LauncherModel.APP_NAME_COMPARATOR);
            if (index < 0) {
                index = -(index+1);
            }
            mAllAppsList.add(index, item);
        }
        mAppsAdapter.notifyDataSetChanged();
    }

    public void removeApps(ArrayList<ApplicationInfo> list) {
        final int N = list.size();
        for (int i=0; i<N; i++) {
            final ApplicationInfo item = list.get(i);
            int index = findAppByComponent(mAllAppsList, item);
            if (index >= 0) {
                mAllAppsList.remove(index);
            } else {
                Log.w(TAG, "couldn't find a match for item \"" + item + "\"");
                // Try to recover.  This should keep us from crashing for now.
            }
        }
        mAppsAdapter.notifyDataSetChanged();
    }

     public void zoom(float zoom, boolean animate) {
//        Log.d(TAG, "zooming " + ((zoom == 1.0) ? "open" : "closed"));
        cancelLongPress();

        mZoom = zoom;

        if (isVisible()) {
            getParent().bringChildToFront(this);
            setVisibility(View.VISIBLE);
            mGrid.setAdapter(mAppsAdapter);
            if (animate) {
                startAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.all_apps_2d_fade_in));
            } else {
                onAnimationEnd();
            }
        } else {
            if (animate) {
                startAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.all_apps_2d_fade_out));
            } else {
                onAnimationEnd();
            }
        }
    }
在zoom()方法里面有mGrid.setAdapter(mAppsAdapter),在构造方法中,给adapter已经赋值。

 

 

源码copy to clipboard打印?
  1. public AllApps2D(Context context, AttributeSet attrs) {
  2. super(context, attrs);
  3. setVisibility(View.GONE);
  4. setSoundEffectsEnabled(false);
  5.  
  6. mAppsAdapter = new AppsAdapter(getContext(), mAllAppsList);
  7. mAppsAdapter.setNotifyOnChange(false);
  8. }
public AllApps2D(Context context, AttributeSet attrs) {
        super(context, attrs);
        setVisibility(View.GONE);
        setSoundEffectsEnabled(false);

        mAppsAdapter = new AppsAdapter(getContext(), mAllAppsList);
        mAppsAdapter.setNotifyOnChange(false);
    }
那是如何获取应用列表的呢?我们再回到Launcher.java中,在loadHotseats()中:

 

 

源码copy to clipboard打印?
  1. private void loadHotseats() {
  2. if (mHotseatConfig == null) {
  3. mHotseatConfig = getResources().getStringArray(R.array.hotseats);
  4. if (mHotseatConfig.length > 0) {
  5. mHotseats = new Intent[mHotseatConfig.length];
  6. mHotseatLabels = new CharSequence[mHotseatConfig.length];
  7. mHotseatIcons = new Drawable[mHotseatConfig.length];
  8. } else {
  9. mHotseats = null;
  10. mHotseatIcons = null;
  11. mHotseatLabels = null;
  12. }
  13.  
  14. TypedArray hotseatIconDrawables = getResources().obtainTypedArray(R.array.hotseat_icons);
  15. for (int i=0; i<mHotseatConfig.length; i++) {
  16. // load icon for this slot; currently unrelated to the actual activity
  17. try {
  18. mHotseatIcons[i] = hotseatIconDrawables.getDrawable(i);
  19. } catch (ArrayIndexOutOfBoundsException ex) {
  20. Log.w(TAG, "Missing hotseat_icons array item #" + i);
  21. mHotseatIcons[i] = null;
  22. }
  23. }
  24. hotseatIconDrawables.recycle();
  25. }
  26.  
  27. PackageManager pm = getPackageManager();
  28. for (int i=0; i<mHotseatConfig.length; i++) {
  29. Intent intent = null;
  30. if (mHotseatConfig[i].equals("*BROWSER*")) {
  31. // magic value meaning "launch user's default web browser"
  32. // replace it with a generic web request so we can see if there is indeed a default
  33. String defaultUri = getString(R.string.default_browser_url);
  34. intent = new Intent(
  35. Intent.ACTION_VIEW,
  36. ((defaultUri != null)
  37. ? Uri.parse(defaultUri)
  38. : getDefaultBrowserUri())
  39. ).addCategory(Intent.CATEGORY_BROWSABLE);
  40. // note: if the user launches this without a default set, she
  41. // will always be taken to the default URL above; this is
  42. // unavoidable as we must specify a valid URL in order for the
  43. // chooser to appear, and once the user selects something, that
  44. // URL is unavoidably sent to the chosen app.
  45. } else {
  46. try {
  47. intent = Intent.parseUri(mHotseatConfig[i], 0);
  48. } catch (java.net.URISyntaxException ex) {
  49. Log.w(TAG, "Invalid hotseat intent: " + mHotseatConfig[i]);
  50. // bogus; leave intent=null
  51. }
  52. }
  53.  
  54. if (intent == null) {
  55. mHotseats[i] = null;
  56. mHotseatLabels[i] = getText(R.string.activity_not_found);
  57. continue;
  58. }
  59.  
  60. if (LOGD) {
  61. Log.d(TAG, "loadHotseats: hotseat " + i
  62. + " initial intent=["
  63. + intent.toUri(Intent.URI_INTENT_SCHEME)
  64. + "]");
  65. }
  66.  
  67. ResolveInfo bestMatch = pm.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
  68. List<ResolveInfo> allMatches = pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
  69. if (LOGD) {
  70. Log.d(TAG, "Best match for intent: " + bestMatch);
  71. Log.d(TAG, "All matches: ");
  72. for (ResolveInfo ri : allMatches) {
  73. Log.d(TAG, " --> " + ri);
  74. }
  75. }
  76. // did this resolve to a single app, or the resolver?
  77. if (allMatches.size() == 0 || bestMatch == null) {
  78. // can't find any activity to handle this. let's leave the
  79. // intent as-is and let Launcher show a toast when it fails
  80. // to launch.
  81. mHotseats[i] = intent;
  82.  
  83. // set accessibility text to "Not installed"
  84. mHotseatLabels[i] = getText(R.string.activity_not_found);
  85. } else {
  86. boolean found = false;
  87. for (ResolveInfo ri : allMatches) {
  88. if (bestMatch.activityInfo.name.equals(ri.activityInfo.name)
  89. && bestMatch.activityInfo.applicationInfo.packageName
  90. .equals(ri.activityInfo.applicationInfo.packageName)) {
  91. found = true;
  92. break;
  93. }
  94. }
  95.  
  96. if (!found) {
  97. if (LOGD) Log.d(TAG, "Multiple options, no default yet");
  98. // the bestMatch is probably the ResolveActivity, meaning the
  99. // user has not yet selected a default
  100. // so: we'll keep the original intent for now
  101. mHotseats[i] = intent;
  102.  
  103. // set the accessibility text to "Select shortcut"
  104. mHotseatLabels[i] = getText(R.string.title_select_shortcut);
  105. } else {
  106. // we have an app!
  107. // now reconstruct the intent to launch it through the front
  108. // door
  109. ComponentName com = new ComponentName(
  110. bestMatch.activityInfo.applicationInfo.packageName,
  111. bestMatch.activityInfo.name);
  112. mHotseats[i] = new Intent(Intent.ACTION_MAIN).setComponent(com);
  113.  
  114. // load the app label for accessibility
  115. mHotseatLabels[i] = bestMatch.activityInfo.loadLabel(pm);
  116. }
  117. }
  118.  
  119. if (LOGD) {
  120. Log.d(TAG, "loadHotseats: hotseat " + i
  121. + " final intent=["
  122. + ((mHotseats[i] == null)
  123. ? "null"
  124. : mHotseats[i].toUri(Intent.URI_INTENT_SCHEME))
  125. + "] label=[" + mHotseatLabels[i]
  126. + "]"
  127. );
  128. }
  129. }
  130. }
private void loadHotseats() {
        if (mHotseatConfig == null) {
            mHotseatConfig = getResources().getStringArray(R.array.hotseats);
            if (mHotseatConfig.length > 0) {
                mHotseats = new Intent[mHotseatConfig.length];
                mHotseatLabels = new CharSequence[mHotseatConfig.length];
                mHotseatIcons = new Drawable[mHotseatConfig.length];
            } else {
                mHotseats = null;
                mHotseatIcons = null;
                mHotseatLabels = null;
            }

            TypedArray hotseatIconDrawables = getResources().obtainTypedArray(R.array.hotseat_icons);
            for (int i=0; i<mHotseatConfig.length; i++) {
                // load icon for this slot; currently unrelated to the actual activity
                try {
                    mHotseatIcons[i] = hotseatIconDrawables.getDrawable(i);
                } catch (ArrayIndexOutOfBoundsException ex) {
                    Log.w(TAG, "Missing hotseat_icons array item #" + i);
                    mHotseatIcons[i] = null;
                }
            }
            hotseatIconDrawables.recycle();
        }

        PackageManager pm = getPackageManager();
        for (int i=0; i<mHotseatConfig.length; i++) {
            Intent intent = null;
            if (mHotseatConfig[i].equals("*BROWSER*")) {
                // magic value meaning "launch user's default web browser"
                // replace it with a generic web request so we can see if there is indeed a default
                String defaultUri = getString(R.string.default_browser_url);
                intent = new Intent(
                        Intent.ACTION_VIEW,
                        ((defaultUri != null)
                            ? Uri.parse(defaultUri)
                            : getDefaultBrowserUri())
                    ).addCategory(Intent.CATEGORY_BROWSABLE);
                // note: if the user launches this without a default set, she
                // will always be taken to the default URL above; this is
                // unavoidable as we must specify a valid URL in order for the
                // chooser to appear, and once the user selects something, that 
                // URL is unavoidably sent to the chosen app.
            } else {
                try {
                    intent = Intent.parseUri(mHotseatConfig[i], 0);
                } catch (java.net.URISyntaxException ex) {
                    Log.w(TAG, "Invalid hotseat intent: " + mHotseatConfig[i]);
                    // bogus; leave intent=null
                }
            }
            
            if (intent == null) {
                mHotseats[i] = null;
                mHotseatLabels[i] = getText(R.string.activity_not_found);
                continue;
            }

            if (LOGD) {
                Log.d(TAG, "loadHotseats: hotseat " + i 
                    + " initial intent=[" 
                    + intent.toUri(Intent.URI_INTENT_SCHEME)
                    + "]");
            }

            ResolveInfo bestMatch = pm.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
            List<ResolveInfo> allMatches = pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
            if (LOGD) { 
                Log.d(TAG, "Best match for intent: " + bestMatch);
                Log.d(TAG, "All matches: ");
                for (ResolveInfo ri : allMatches) {
                    Log.d(TAG, "  --> " + ri);
                }
            }
            // did this resolve to a single app, or the resolver?
            if (allMatches.size() == 0 || bestMatch == null) {
                // can't find any activity to handle this. let's leave the 
                // intent as-is and let Launcher show a toast when it fails 
                // to launch.
                mHotseats[i] = intent;

                // set accessibility text to "Not installed"
                mHotseatLabels[i] = getText(R.string.activity_not_found);
            } else {
                boolean found = false;
                for (ResolveInfo ri : allMatches) {
                    if (bestMatch.activityInfo.name.equals(ri.activityInfo.name)
                        && bestMatch.activityInfo.applicationInfo.packageName
                            .equals(ri.activityInfo.applicationInfo.packageName)) {
                        found = true;
                        break;
                    }
                }
                
                if (!found) {
                    if (LOGD) Log.d(TAG, "Multiple options, no default yet");
                    // the bestMatch is probably the ResolveActivity, meaning the
                    // user has not yet selected a default
                    // so: we'll keep the original intent for now
                    mHotseats[i] = intent;

                    // set the accessibility text to "Select shortcut"
                    mHotseatLabels[i] = getText(R.string.title_select_shortcut);
                } else {
                    // we have an app!
                    // now reconstruct the intent to launch it through the front
                    // door
                    ComponentName com = new ComponentName(
                        bestMatch.activityInfo.applicationInfo.packageName,
                        bestMatch.activityInfo.name);
                    mHotseats[i] = new Intent(Intent.ACTION_MAIN).setComponent(com);

                    // load the app label for accessibility
                    mHotseatLabels[i] = bestMatch.activityInfo.loadLabel(pm);
                }
            }

            if (LOGD) {
                Log.d(TAG, "loadHotseats: hotseat " + i 
                    + " final intent=[" 
                    + ((mHotseats[i] == null)
                        ? "null"
                        : mHotseats[i].toUri(Intent.URI_INTENT_SCHEME))
                    + "] label=[" + mHotseatLabels[i]
                    + "]"
                    );
            }
        }
    }

有点复杂,主要代码其实如下:

 

 

源码copy to clipboard打印?
  1. PackageManager pm = getPackageManager();
  2. ResolveInfo bestMatch = pm.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
  3. List<ResolveInfo> allMatches = pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
PackageManager pm = getPackageManager();
ResolveInfo bestMatch = pm.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
List<ResolveInfo> allMatches = pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
这样就获取了。下面以一个简单的例子结束, 获取在sd卡中安装的程序列表:

 

 

源码copy to clipboard打印?
  1. private void getSdcardApps(){
  2. mSdcardAppsList.clear();
  3. ActivityManager am = (ActivityManager)mLauncher.getSystemService(Activity.ACTIVITY_SERVICE);
  4. PackageManager pm =mLauncher.getPackageManager();
  5. List<android.content.pm.ApplicationInfo> list = pm.getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES);
  6. for (android.content.pm.ApplicationInfo appInfo : list) {
  7. if((appInfo.flags & android.content.pm.ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0){
  8. for (ApplicationInfo applicationInfo : mAllAppsList) {
  9. if(appInfo.packageName.equals(applicationInfo.componentName.getPackageName())){
  10. mSdcardAppsList.add(applicationInfo);
  11. break;
  12. }
  13. }
  14. }
  15. }
  16. mAppsAdapter = new AppsAdapter(getContext(), mSdcardAppsList);
  17. mAppsAdapter.notifyDataSetChanged();
  18. mGrid.setAdapter(mAppsAdapter);
  19. text.setVisibility(View.VISIBLE);
  20. text.setBackgroundResource(R.drawable.tab_mmenu_b3_normal);
  21. }
private void getSdcardApps(){
		mSdcardAppsList.clear();
		ActivityManager am = (ActivityManager)mLauncher.getSystemService(Activity.ACTIVITY_SERVICE);
		PackageManager pm =mLauncher.getPackageManager();  
		List<android.content.pm.ApplicationInfo> list = pm.getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES);
		for (android.content.pm.ApplicationInfo appInfo : list) {
				if((appInfo.flags & android.content.pm.ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0){
					for (ApplicationInfo applicationInfo : mAllAppsList) {
						if(appInfo.packageName.equals(applicationInfo.componentName.getPackageName())){
							mSdcardAppsList.add(applicationInfo);
							break;
						}
					}
				}
		}
		mAppsAdapter = new AppsAdapter(getContext(), mSdcardAppsList);
		mAppsAdapter.notifyDataSetChanged();
		mGrid.setAdapter(mAppsAdapter);
		text.setVisibility(View.VISIBLE);
		text.setBackgroundResource(R.drawable.tab_mmenu_b3_normal);
	}