部落格搬家啦——為了更好地經營部落格,本人已經將部落格遷移至www.ijavaboy.com。這裡已經不再更新,給您帶來的不便,深感抱歉!這篇文章的新地址:點擊我
上篇中,講到了第一個功能中需要擷取應用程式的資訊,然後添加到案頭。這裡,先記錄下如何擷取Android中的應用程式資訊。
一、調用系統捷徑列表
Intent pickIntent = new Intent(Intent.ACTION_PICK_ACTIVITY); pickIntent.putExtra(Intent.EXTRA_INTENT, new Intent(Intent.ACTION_CREATE_SHORTCUT)); pickIntent.putExtra(Intent.EXTRA_TITLE, res.getString(R.string.title_select_app)); pickIntent.putExtras(bundle); startActivityForResult(pickIntent, REQUEST_PICK_SHORTCUT);
這個擷取到的就是所有可以建立的捷徑,但是我們需要在這個列表中加入其他項怎麼辦呢?因為我們知道,我需要在這個列表中加入“應用程式”,這一項,這樣當我們點擊應用程式的時候,就可以顯示應用程式列表。這個時候,我們只需要傳入額外的資訊就可以了,如下:
Resources res = getResources();/** * 用一個Bundle對象,傳遞兩個list資訊 * 一個list中存放需要附加到快捷列表中的項的文字 * 一個list中存放每一個對應的表徵圖資訊 */ Bundle bundle = new Bundle(); ArrayList<String> shortcutNames = new ArrayList<String>(); shortcutNames.add(res.getString(R.string.group_application)); shortcutNames.add("其他"); //顯示在List第一個的應用捷徑的名字 bundle.putStringArrayList(Intent.EXTRA_SHORTCUT_NAME, shortcutNames); //顯示表徵圖 ArrayList<ShortcutIconResource> shortcutIcons = new ArrayList<ShortcutIconResource>(); shortcutIcons.add(ShortcutIconResource.fromContext(UorderLauncher.this, R.drawable.icon)); shortcutIcons.add(ShortcutIconResource.fromContext(UorderLauncher.this, R.drawable.icon)); bundle.putParcelableArrayList(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, shortcutIcons); Intent pickIntent = new Intent(Intent.ACTION_PICK_ACTIVITY); pickIntent.putExtra(Intent.EXTRA_INTENT, new Intent(Intent.ACTION_CREATE_SHORTCUT)); pickIntent.putExtra(Intent.EXTRA_TITLE, res.getString(R.string.title_select_app)); //將附加資訊加入到pickIntent pickIntent.putExtras(bundle); startActivityForResult(pickIntent, REQUEST_PICK_SHORTCUT);
二、調用應用程式列表
當我們點擊我們附加的項“應用程式”時,我們希望彈出應用程式列表,這個也可以條用系統內建列表,也可以使用自己定義的列表。
1、調用系統應用資訊列表
在上面我們加上了一個附加項“應用程式”,那麼我們怎麼知道,當前點擊的是“應用程式”這一項呢?注意上面我們啟動的時候是startActivityForResult(pickIntent, REQUEST_PICK_SHORTCUT);
在onActivityResult中處理該請求對應的邏輯:如果使用者選擇的是“應用程式”,則調用系統應用程式列表,否則,直接請求建立捷徑
private void addShortcut(Intent data){Resources res = getResources();final String appName = res.getString(R.string.group_application);final String shortcutName = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);if(appName.equals(shortcutName)){//說明使用者選擇的是應用程式,進入應用程式列表Intent mainIntent = new Intent(Intent.ACTION_MAIN,null);mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);Intent pickIntent = new Intent(Intent.ACTION_PICK_ACTIVITY);pickIntent.putExtra(Intent.EXTRA_INTENT, mainIntent);startActivityForResult(pickIntent, REQUEST_PICK_APPLICATION);}else{//否則,直接建立捷徑startActivityForResult(data, REQUEST_CREATE_SHORTCUT);}}
這樣,就實現點擊“應用程式”則顯示應用程式列表,否則,建立捷徑
2、擷取所有應用程式資訊,實現自訂的應用程式列表
其實,對於系統中所有應用程式的資訊,程式中都是可以擷取到的。在案頭點擊的時候用的是系統內建的應用程式列表。但是,當點擊案頭下方的應用程式圖示的時候,就需要顯示一個GridView顯示所有的應用程式資訊,這裡,就需要擷取應用程式資訊,然後放入每一個item中。這裡就順帶實現一下。布局和效果略過,只記錄如果擷取應用程式資訊。
/** * 同樣,以ACTION_MAIN和CATEGORY_LAUNCHER作為過濾條件 * 查詢所有符合的應用資訊(ResolveInfo) * ResolveInfo中就包含了我們需要的主要資訊。 * 當然還有其他的方式擷取應用資訊,如PackageInfo,關於這些資訊,可以參看 * http://android.tgbus.com/Android/tutorial/201108/364210.shtml */final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);final PackageManager pManager = this.getPackageManager();/** * queryIntentActivities通過解析所有應用程式中含有如下Intent-filter的App * <intent-filter> * <action android:name="android.intent.action.MAIN" /> * <category android:name="android.intent.category.LAUNCHER" /> * </intent-filter> */final List<ResolveInfo> infoList = pManager.queryIntentActivities(mainIntent, 0);if(infoList != null){ArrayList<AppInfo> appList = new ArrayList<AppInfo>();for(ResolveInfo info : infoList){AppInfo app = makeAppInfo(pManager, info);appList.add(app);}return appList;}return null;
程式還包含了一個makeAppInfo(pManager, info);這個方法源碼是:
private AppInfo makeAppInfo(PackageManager pManager, ResolveInfo info) {//有了ComponentName,就可以儲存每個應用程式的啟動資訊//下次我們可以直接啟動它ComponentName component = new ComponentName(info.activityInfo.applicationInfo.packageName,info.activityInfo.name);//這個是自己定義的一個用來封裝我們需要的應用程式的資訊AppInfo app = new AppInfo();//擷取應用的名稱CharSequence appName = info.loadLabel(pManager);if(appName == null){//如果沒有成功擷取到,則用其主Activity的名字作為應用程式名稱appName = info.activityInfo.name;}app.name = appName.toString();//擷取應用程式的表徵圖Drawable draw = info.activityInfo.loadIcon(pManager);//應用程式圖片可以大小不一,這裡需要將他們的size限定在一定的大小app.icon = BitmapUtils.createIconThumbnail(draw, getApplicationContext());//將啟動資訊儲存在AppInfo中,在我們的應用中啟動另一個應用程式,使用FLAG_ACTIVITY_NEW_TASKapp.setActivity(component, Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);return app;}
這樣就得到了所有的應用程式資訊。系統Launcher在其GridView中列出的所有應用就是這麼擷取的。
三、擷取應用程式資訊的其他方式:
下面這個擷取到的應用資訊,你會發現比上面的方法多了很多,因為其獲得的是系統中所有的安裝包資訊
List<PackageInfo> packageList = this.getPackageManager().getInstalledPackages(0);appList = new ArrayList<AppInfo>();for(PackageInfo info : packageList){CharSequence appName = info.applicationInfo.loadLabel(getPackageManager());if(TextUtils.isEmpty(appName)){appName = info.packageName;}//加上下面這個if條件就把系統內建的應用給過濾掉了,擷取到的僅僅是我們自己安裝的if((info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM)<=0){ComponentName comp = getComponentName(info.packageName);AppInfo appInfo = new AppInfo();appInfo.icon = info.applicationInfo.loadIcon(getPackageManager());appInfo.name = appName.toString();appInfo.setActivity(comp, Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);appList.add(appInfo);}}
程式中調用了getComponentName,其源碼是:
private ComponentName getComponentName(String packageName) {Intent intent = new Intent(Intent.ACTION_MAIN, null);intent.addCategory(Intent.CATEGORY_LAUNCHER);intent.setPackage(packageName);List<ResolveInfo> infoList = getPackageManager().queryIntentActivities(intent, 0);if(infoList != null && infoList.size()>0){ResolveInfo info = infoList.get(0);if(info != null){String pkgName = info.activityInfo.packageName;String clsName = info.activityInfo.name;return new ComponentName(pkgName, clsName);}}return null;}
到處,也就很清楚Launcher中長按案頭,應用程式是如何選擇和在GridView中的應用程式資訊是如何擷取到的了。
下一篇,將繼續介紹CellLayout自訂控制項的實現原理!