我已经查看了许多不同的代码变体,了解如何获取已安装的应用程序列表并将它们显示在ListView中给用户,但没有一个对我成功。我想知道的是如何做到这一点以及我如何添加标志(?)以便我可以列出具有不同意图过滤器的幕布应用程序,例如LONG_SEARCH_BUTTON,并且能够查看包和启动器那个应用程序的类......如果这样做的话?
我想要一个完整的java类,如果有人不介意分享他们的知识,因为试图拼凑一些代码变得非常紧张!我已经为Android编写了几个月的代码,所以我知道大部分基本的东西(我想想......)但是之前没有这样的事情。
答案 0 :(得分:2)
我写了一个简短的应用程序,确切地说......检查出here。
答案 1 :(得分:0)
以下是Android文档中的示例代码。请根据您的要求发挥创意。
/ ** *此类包含我们的Loader中的每项数据。 */ 上市 static class AppEntry { public AppEntry(AppListLoader loader,ApplicationInfo info){ mLoader =装载机; mInfo = info; mApkFile =新文件(info.sourceDir); }
public ApplicationInfo getApplicationInfo() { return mInfo; } public String getLabel() { return mLabel; } public Drawable getIcon() { if (mIcon == null) { if (mApkFile.exists()) { mIcon = mInfo.loadIcon(mLoader.mPm); return mIcon; } else { mMounted = false; } } else if (!mMounted) { // If the app wasn't mounted but is now mounted, reload // its icon. if (mApkFile.exists()) { mMounted = true; mIcon = mInfo.loadIcon(mLoader.mPm); return mIcon; } } else { return mIcon; } return mLoader.getContext().getResources().getDrawable( android.R.drawable.sym_def_app_icon); } @Override public String toString() { return mLabel; } void loadLabel(Context context) { if (mLabel == null || !mMounted) { if (!mApkFile.exists()) { mMounted = false; mLabel = mInfo.packageName; } else { mMounted = true; CharSequence label = mInfo.loadLabel(context.getPackageManager()); mLabel = label != null ? label.toString() : mInfo.packageName; } } } private final AppListLoader mLoader; private final ApplicationInfo mInfo; private final File mApkFile; private String mLabel; private Drawable mIcon; private boolean mMounted; }
/ ** *执行应用程序输入对象的字母比较。 * / public static final Comparator ALPHA_COMPARATOR = new Comparator(){ private final Collator sCollator = Collator.getInstance(); @覆盖 public int compare(AppEntry object1,AppEntry object2){ return sCollator.compare(object1.getLabel(),object2.getLabel()); }};
/ ** *帮助确定配置是否已更改 有趣的*方式,所以我们需要重建应用程序列表。 */ 上市 static class InterestingConfigChanges { 最终配置mLastConfiguration = new Configuration(); int mLastDensity;
boolean applyNewConfig(Resources res) { int configChanges = mLastConfiguration.updateFrom(res.getConfiguration()); boolean densityChanged = mLastDensity != res.getDisplayMetrics().densityDpi; if (densityChanged || (configChanges&(ActivityInfo.CONFIG_LOCALE |ActivityInfo.CONFIG_UI_MODE|ActivityInfo.CONFIG_SCREEN_LAYOUT)) != 0)
{ mLastDensity = res.getDisplayMetrics()。densityDpi; 返回true; } 返回false; }}
/ ** * Helper类,用于查找已安装的有趣更改 apps *以便加载程序可以更新。 * / public static class PackageIntentReceiver扩展BroadcastReceiver { 最终AppListLoader mLoader;
public PackageIntentReceiver(AppListLoader loader) { mLoader = loader; IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED); filter.addAction(Intent.ACTION_PACKAGE_REMOVED); filter.addAction(Intent.ACTION_PACKAGE_CHANGED); filter.addDataScheme("package"); mLoader.getContext().registerReceiver(this, filter); // Register for events related to sdcard installation. IntentFilter sdFilter = new IntentFilter(); sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE); sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE); mLoader.getContext().registerReceiver(this, sdFilter); } @Override public void onReceive(Context context, Intent intent) { // Tell the loader about the change. mLoader.onContentChanged(); } }
/ ** *加载所有已安装应用程序的自定义Loader。 * / public static class AppListLoader extends AsyncTaskLoader> { final InterestingConfigChanges mLastConfig = new InterestingConfigChanges(); 最终的PackageManager mPm;
List<AppEntry> mApps; PackageIntentReceiver mPackageObserver; public AppListLoader(Context context) { super(context); // Retrieve the package manager for later use; note we don't // use 'context' directly but instead the save global application // context returned by getContext(). mPm = getContext().getPackageManager(); } /** * This is where the bulk of our work is done. This function is * called in a background thread and should generate a new set of * data to be published by the loader. */ @Override public List<AppEntry> loadInBackground() { // Retrieve all known applications. List<ApplicationInfo> apps = mPm.getInstalledApplications( PackageManager.GET_UNINSTALLED_PACKAGES | PackageManager.GET_DISABLED_COMPONENTS); if (apps == null) { apps = new ArrayList<ApplicationInfo>(); } final Context context = getContext(); // Create corresponding array of entries and load their labels. List<AppEntry> entries = new ArrayList<AppEntry>(apps.size()); for (int i=0; i<apps.size(); i++) { AppEntry entry = new AppEntry(this, apps.get(i)); entry.loadLabel(context); entries.add(entry); } // Sort the list. Collections.sort(entries, ALPHA_COMPARATOR); // Done! return entries; } /** * Called when there is new data to deliver to the client. The * super class will take care of delivering it; the implementation * here just adds a little more logic. */ @Override public void deliverResult(List<AppEntry> apps) { if (isReset()) { // An async query came in while the loader is stopped. We // don't need the result. if (apps != null) { onReleaseResources(apps); } } List<AppEntry> oldApps = apps; mApps = apps; if (isStarted()) { // If the Loader is currently started, we can immediately // deliver its results. super.deliverResult(apps); } // At this point we can release the resources associated with // 'oldApps' if needed; now that the new result is delivered we // know that it is no longer in use. if (oldApps != null) { onReleaseResources(oldApps); } } /** * Handles a request to start the Loader. */ @Override protected void onStartLoading() { if (mApps != null) { // If we currently have a result available, deliver it // immediately. deliverResult(mApps); } // Start watching for changes in the app data. if (mPackageObserver == null) { mPackageObserver = new PackageIntentReceiver(this); } // Has something interesting in the configuration changed since we // last built the app list? boolean configChange = mLastConfig.applyNewConfig(getContext().getResources()); if (takeContentChanged() || mApps == null || configChange) { // If the data has changed since the last time it was loaded // or is not currently available, start a load. forceLoad(); } } /** * Handles a request to stop the Loader. */ @Override protected void onStopLoading() { // Attempt to cancel the current load task if possible. cancelLoad(); } /** * Handles a request to cancel a load. */ @Override public void onCanceled(List<AppEntry> apps) { super.onCanceled(apps); // At this point we can release the resources associated with 'apps' // if needed. onReleaseResources(apps); } /** * Handles a request to completely reset the Loader. */ @Override protected void onReset() { super.onReset(); // Ensure the loader is stopped onStopLoading(); // At this point we can release the resources associated with 'apps' // if needed. if (mApps != null) { onReleaseResources(mApps); mApps = null; } // Stop monitoring for changes. if (mPackageObserver != null) { getContext().unregisterReceiver(mPackageObserver); mPackageObserver = null; } } /** * Helper function to take care of releasing resources associated * with an actively loaded data set. */ protected void onReleaseResources(List<AppEntry> apps) { // For a simple List<> there is nothing to do. For something // like a Cursor, we would close it here. } }
使用上述加载程序显示列表中当前安装的应用程序的片段的示例实现如下所示。
public static class AppListAdapter extends ArrayAdapter { private final LayoutInflater mInflater;
public AppListAdapter(Context context) { super(context, android.R.layout.simple_list_item_2); mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); } public void setData(List<AppEntry> data) { clear(); if (data != null) { addAll(data); } } /** * Populate new items in the list. */ @Override public View getView(int position, View convertView, ViewGroup parent) { View view; if (convertView == null) { view = mInflater.inflate(R.layout.list_item_icon_text, parent, false); } else { view = convertView; } AppEntry item = getItem(position); ((ImageView)view.findViewById(R.id.icon)).setImageDrawable(item.getIcon()); ((TextView)view.findViewById(R.id.text)).setText(item.getLabel()); return view; } }
public static class AppListFragment扩展了ListFragment 实现OnQueryTextListener,LoaderManager.LoaderCallbacks&gt; {
// This is the Adapter being used to display the list's data. AppListAdapter mAdapter; // If non-null, this is the current filter the user has provided. String mCurFilter; @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); // Give some text to display if there is no data. In a real // application this would come from a resource. setEmptyText("No applications"); // We have a menu item to show in action bar. setHasOptionsMenu(true); // Create an empty adapter we will use to display the loaded data. mAdapter = new AppListAdapter(getActivity()); setListAdapter(mAdapter); // Start out with a progress indicator. setListShown(false); // Prepare the loader. Either re-connect with an existing one, // or start a new one. getLoaderManager().initLoader(0, null, this); } @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { // Place an action bar item for searching. MenuItem item = menu.add("Search"); item.setIcon(android.R.drawable.ic_menu_search); item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW); SearchView sv = new SearchView(getActivity()); sv.setOnQueryTextListener(this); item.setActionView(sv); } @Override public boolean onQueryTextChange(String newText) { // Called when the action bar search text has changed. Since this // is a simple array adapter, we can just have it do the filtering. mCurFilter = !TextUtils.isEmpty(newText) ? newText : null; mAdapter.getFilter().filter(mCurFilter); return true; } @Override public boolean onQueryTextSubmit(String query) { // Don't care about this. return true; } @Override public void onListItemClick(ListView l, View v, int position, long id) { // Insert desired behavior here. Log.i("LoaderCustom", "Item clicked: " + id); } @Override public Loader<List<AppEntry>> onCreateLoader(int id, Bundle args) { // This is called when a new Loader needs to be created. This // sample only has one Loader with no arguments, so it is simple. return new AppListLoader(getActivity()); } @Override public void onLoadFinished(Loader<List<AppEntry>> loader, List<AppEntry> data) { // Set the new data in the adapter. mAdapter.setData(data); // The list should now be shown. if (isResumed()) { setListShown(true); } else { setListShownNoAnimation(true); } } @Override public void onLoaderReset(Loader<List<AppEntry>> loader) { // Clear the data in the adapter. mAdapter.setData(null); } }