LoaderCustomSupport.java revision aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8
1aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn/* 2aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn * Copyright (C) 2010 The Android Open Source Project 3aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn * 4aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn * Licensed under the Apache License, Version 2.0 (the "License"); 5aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn * you may not use this file except in compliance with the License. 6aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn * You may obtain a copy of the License at 7aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn * 8aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn * http://www.apache.org/licenses/LICENSE-2.0 9aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn * 10aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn * Unless required by applicable law or agreed to in writing, software 11aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn * distributed under the License is distributed on an "AS IS" BASIS, 12aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn * See the License for the specific language governing permissions and 14aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn * limitations under the License. 15aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn */ 16aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 17aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornpackage com.example.android.supportv4.app; 18aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 19aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornimport com.example.android.supportv4.R; 20aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 21aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornimport java.io.File; 22aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornimport java.text.Collator; 23aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornimport java.util.ArrayList; 24aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornimport java.util.Collections; 25aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornimport java.util.Comparator; 26aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornimport java.util.List; 27aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 28aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornimport android.content.BroadcastReceiver; 29aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornimport android.content.Context; 30aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornimport android.content.Intent; 31aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornimport android.content.IntentFilter; 32aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornimport android.content.pm.ActivityInfo; 33aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornimport android.content.pm.ApplicationInfo; 34aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornimport android.content.pm.PackageManager; 35aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornimport android.content.res.Configuration; 36aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornimport android.content.res.Resources; 37aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornimport android.graphics.drawable.Drawable; 38aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornimport android.os.Bundle; 39aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornimport android.support.v4.app.FragmentActivity; 40aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornimport android.support.v4.app.FragmentManager; 41aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornimport android.support.v4.app.ListFragment; 42aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornimport android.support.v4.app.LoaderManager; 43aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornimport android.support.v4.content.AsyncTaskLoader; 44aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornimport android.support.v4.content.Loader; 45aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornimport android.text.TextUtils; 46aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornimport android.util.Log; 47aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornimport android.view.LayoutInflater; 48aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornimport android.view.Menu; 49aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornimport android.view.MenuInflater; 50aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornimport android.view.MenuItem; 51aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornimport android.view.View; 52aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornimport android.view.ViewGroup; 53aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornimport android.widget.ArrayAdapter; 54aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornimport android.widget.ImageView; 55aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornimport android.widget.ListView; 56aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornimport android.widget.SearchView; 57aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornimport android.widget.TextView; 58aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornimport android.widget.SearchView.OnQueryTextListener; 59aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 60aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn/** 61aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn * Demonstration of the implementation of a custom Loader. 62aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn */ 63aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornpublic class LoaderCustomSupport extends FragmentActivity { 64aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 65aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn @Override 66aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn protected void onCreate(Bundle savedInstanceState) { 67aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn super.onCreate(savedInstanceState); 68aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 69aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn FragmentManager fm = getSupportFragmentManager(); 70aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 71aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // Create the list fragment and add it as our sole content. 72aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn if (fm.findFragmentById(android.R.id.content) == null) { 73aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn AppListFragment list = new AppListFragment(); 74aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn fm.beginTransaction().add(android.R.id.content, list).commit(); 75aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 76aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 77aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 78aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn//BEGIN_INCLUDE(loader) 79aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn /** 80aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn * This class holds the per-item data in our Loader. 81aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn */ 82aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn public static class AppEntry { 83aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn public AppEntry(AppListLoader loader, ApplicationInfo info) { 84aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn mLoader = loader; 85aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn mInfo = info; 86aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn mApkFile = new File(info.sourceDir); 87aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 88aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 89aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn public ApplicationInfo getApplicationInfo() { 90aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn return mInfo; 91aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 92aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 93aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn public String getLabel() { 94aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn return mLabel; 95aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 96aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 97aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn public Drawable getIcon() { 98aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn if (mIcon == null) { 99aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn if (mApkFile.exists()) { 100aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn mIcon = mInfo.loadIcon(mLoader.mPm); 101aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn return mIcon; 102aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } else { 103aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn mMounted = false; 104aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 105aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } else if (!mMounted) { 106aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // If the app wasn't mounted but is now mounted, reload 107aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // its icon. 108aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn if (mApkFile.exists()) { 109aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn mMounted = true; 110aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn mIcon = mInfo.loadIcon(mLoader.mPm); 111aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn return mIcon; 112aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 113aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } else { 114aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn return mIcon; 115aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 116aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 117aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn return mLoader.getContext().getResources().getDrawable( 118aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn android.R.drawable.sym_def_app_icon); 119aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 120aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 121aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn @Override public String toString() { 122aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn return mLabel; 123aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 124aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 125aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn void loadLabel(Context context) { 126aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn if (mLabel == null || !mMounted) { 127aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn if (!mApkFile.exists()) { 128aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn mMounted = false; 129aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn mLabel = mInfo.packageName; 130aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } else { 131aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn mMounted = true; 132aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn CharSequence label = mInfo.loadLabel(context.getPackageManager()); 133aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn mLabel = label != null ? label.toString() : mInfo.packageName; 134aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 135aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 136aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 137aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 138aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn private final AppListLoader mLoader; 139aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn private final ApplicationInfo mInfo; 140aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn private final File mApkFile; 141aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn private String mLabel; 142aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn private Drawable mIcon; 143aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn private boolean mMounted; 144aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 145aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 146aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn /** 147aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn * Perform alphabetical comparison of application entry objects. 148aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn */ 149aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn public static final Comparator<AppEntry> ALPHA_COMPARATOR = new Comparator<AppEntry>() { 150aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn private final Collator sCollator = Collator.getInstance(); 151aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn @Override 152aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn public int compare(AppEntry object1, AppEntry object2) { 153aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn return sCollator.compare(object1.getLabel(), object2.getLabel()); 154aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 155aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn }; 156aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 157aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn /** 158aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn * Helper for determining if the configuration has changed in an interesting 159aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn * way so we need to rebuild the app list. 160aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn */ 161aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn public static class InterestingConfigChanges { 162aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn final Configuration mLastConfiguration = new Configuration(); 163aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn int mLastDensity; 164aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 165aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn boolean applyNewConfig(Resources res) { 166aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn int configChanges = mLastConfiguration.updateFrom(res.getConfiguration()); 167aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn boolean densityChanged = mLastDensity != res.getDisplayMetrics().densityDpi; 168aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn if (densityChanged || (configChanges&(ActivityInfo.CONFIG_LOCALE 169aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn |ActivityInfo.CONFIG_UI_MODE|ActivityInfo.CONFIG_SCREEN_LAYOUT)) != 0) { 170aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn mLastDensity = res.getDisplayMetrics().densityDpi; 171aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn return true; 172aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 173aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn return false; 174aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 175aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 176aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 177aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn /** 178aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn * Helper class to look for interesting changes to the installed apps 179aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn * so that the loader can be updated. 180aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn */ 181aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn public static class PackageIntentReceiver extends BroadcastReceiver { 182aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn final AppListLoader mLoader; 183aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 184aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn public PackageIntentReceiver(AppListLoader loader) { 185aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn mLoader = loader; 186aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED); 187aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn filter.addAction(Intent.ACTION_PACKAGE_REMOVED); 188aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn filter.addAction(Intent.ACTION_PACKAGE_CHANGED); 189aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn filter.addDataScheme("package"); 190aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn mLoader.getContext().registerReceiver(this, filter); 191aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // Register for events related to sdcard installation. 192aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn IntentFilter sdFilter = new IntentFilter(); 193aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE); 194aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE); 195aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn mLoader.getContext().registerReceiver(this, sdFilter); 196aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 197aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 198aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn @Override public void onReceive(Context context, Intent intent) { 199aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // Tell the loader about the change. 200aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn mLoader.onContentChanged(); 201aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 202aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 203aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 204aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn /** 205aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn * A custom Loader that loads all of the installed applications. 206aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn */ 207aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn public static class AppListLoader extends AsyncTaskLoader<List<AppEntry>> { 208aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn final InterestingConfigChanges mLastConfig = new InterestingConfigChanges(); 209aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn final PackageManager mPm; 210aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 211aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn List<AppEntry> mApps; 212aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn PackageIntentReceiver mPackageObserver; 213aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 214aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn public AppListLoader(Context context) { 215aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn super(context); 216aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 217aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // Retrieve the package manager for later use; note we don't 218aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // use 'context' directly but instead the save global application 219aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // context returned by getContext(). 220aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn mPm = getContext().getPackageManager(); 221aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 222aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 223aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn /** 224aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn * This is where the bulk of our work is done. This function is 225aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn * called in a background thread and should generate a new set of 226aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn * data to be published by the loader. 227aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn */ 228aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn @Override public List<AppEntry> loadInBackground() { 229aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // Retrieve all known applications. 230aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn List<ApplicationInfo> apps = mPm.getInstalledApplications( 231aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn PackageManager.GET_UNINSTALLED_PACKAGES | 232aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn PackageManager.GET_DISABLED_COMPONENTS); 233aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn if (apps == null) { 234aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn apps = new ArrayList<ApplicationInfo>(); 235aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 236aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 237aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn final Context context = getContext(); 238aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 239aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // Create corresponding array of entries and load their labels. 240aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn List<AppEntry> entries = new ArrayList<AppEntry>(apps.size()); 241aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn for (int i=0; i<apps.size(); i++) { 242aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn AppEntry entry = new AppEntry(this, apps.get(i)); 243aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn entry.loadLabel(context); 244aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn entries.add(entry); 245aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 246aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 247aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // Sort the list. 248aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn Collections.sort(entries, ALPHA_COMPARATOR); 249aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 250aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // Done! 251aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn return entries; 252aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 253aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 254aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn /** 255aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn * Called when there is new data to deliver to the client. The 256aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn * super class will take care of delivering it; the implementation 257aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn * here just adds a little more logic. 258aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn */ 259aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn @Override public void deliverResult(List<AppEntry> apps) { 260aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn if (isReset()) { 261aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // An async query came in while the loader is stopped. We 262aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // don't need the result. 263aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn if (apps != null) { 264aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn onReleaseResources(apps); 265aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 266aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 267aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn List<AppEntry> oldApps = apps; 268aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn mApps = apps; 269aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 270aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn if (isStarted()) { 271aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // If the Loader is currently started, we can immediately 272aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // deliver its results. 273aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn super.deliverResult(apps); 274aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 275aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 276aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // At this point we can release the resources associated with 277aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // 'oldApps' if needed; now that the new result is delivered we 278aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // know that it is no longer in use. 279aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn if (oldApps != null) { 280aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn onReleaseResources(oldApps); 281aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 282aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 283aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 284aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn /** 285aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn * Handles a request to start the Loader. 286aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn */ 287aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn @Override protected void onStartLoading() { 288aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn if (mApps != null) { 289aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // If we currently have a result available, deliver it 290aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // immediately. 291aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn deliverResult(mApps); 292aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 293aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 294aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // Start watching for changes in the app data. 295aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn if (mPackageObserver == null) { 296aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn mPackageObserver = new PackageIntentReceiver(this); 297aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 298aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 299aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // Has something interesting in the configuration changed since we 300aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // last built the app list? 301aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn boolean configChange = mLastConfig.applyNewConfig(getContext().getResources()); 302aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 303aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn if (takeContentChanged() || mApps == null || configChange) { 304aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // If the data has changed since the last time it was loaded 305aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // or is not currently available, start a load. 306aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn forceLoad(); 307aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 308aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 309aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 310aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn /** 311aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn * Handles a request to stop the Loader. 312aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn */ 313aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn @Override protected void onStopLoading() { 314aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // Attempt to cancel the current load task if possible. 315aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn cancelLoad(); 316aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 317aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 318aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn /** 319aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn * Handles a request to cancel a load. 320aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn */ 321aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn @Override public void onCanceled(List<AppEntry> apps) { 322aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn super.onCanceled(apps); 323aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 324aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // At this point we can release the resources associated with 'apps' 325aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // if needed. 326aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn onReleaseResources(apps); 327aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 328aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 329aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn /** 330aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn * Handles a request to completely reset the Loader. 331aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn */ 332aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn @Override protected void onReset() { 333aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn super.onReset(); 334aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 335aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // Ensure the loader is stopped 336aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn onStopLoading(); 337aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 338aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // At this point we can release the resources associated with 'apps' 339aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // if needed. 340aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn if (mApps != null) { 341aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn onReleaseResources(mApps); 342aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn mApps = null; 343aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 344aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 345aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // Stop monitoring for changes. 346aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn if (mPackageObserver != null) { 347aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn getContext().unregisterReceiver(mPackageObserver); 348aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn mPackageObserver = null; 349aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 350aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 351aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 352aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn /** 353aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn * Helper function to take care of releasing resources associated 354aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn * with an actively loaded data set. 355aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn */ 356aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn protected void onReleaseResources(List<AppEntry> apps) { 357aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // For a simple List<> there is nothing to do. For something 358aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // like a Cursor, we would close it here. 359aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 360aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 361aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn//END_INCLUDE(loader) 362aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 363aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn//BEGIN_INCLUDE(fragment) 364aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn public static class AppListAdapter extends ArrayAdapter<AppEntry> { 365aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn private final LayoutInflater mInflater; 366aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 367aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn public AppListAdapter(Context context) { 368aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn super(context, android.R.layout.simple_list_item_2); 369aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 370aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 371aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 372aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn public void setData(List<AppEntry> data) { 373aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn clear(); 374aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn if (data != null) { 375aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn addAll(data); 376aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 377aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 378aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 379aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn /** 380aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn * Populate new items in the list. 381aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn */ 382aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn @Override public View getView(int position, View convertView, ViewGroup parent) { 383aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn View view; 384aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 385aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn if (convertView == null) { 386aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn view = mInflater.inflate(R.layout.list_item_icon_text, parent, false); 387aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } else { 388aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn view = convertView; 389aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 390aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 391aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn AppEntry item = getItem(position); 392aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn ((ImageView)view.findViewById(R.id.icon)).setImageDrawable(item.getIcon()); 393aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn ((TextView)view.findViewById(R.id.text)).setText(item.getLabel()); 394aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 395aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn return view; 396aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 397aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 398aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 399aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn public static class AppListFragment extends ListFragment 400aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn implements OnQueryTextListener, LoaderManager.LoaderCallbacks<List<AppEntry>> { 401aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 402aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // This is the Adapter being used to display the list's data. 403aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn AppListAdapter mAdapter; 404aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 405aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // If non-null, this is the current filter the user has provided. 406aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn String mCurFilter; 407aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 408aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn @Override public void onActivityCreated(Bundle savedInstanceState) { 409aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn super.onActivityCreated(savedInstanceState); 410aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 411aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // Give some text to display if there is no data. In a real 412aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // application this would come from a resource. 413aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn setEmptyText("No applications"); 414aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 415aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // We have a menu item to show in action bar. 416aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn setHasOptionsMenu(true); 417aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 418aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // Create an empty adapter we will use to display the loaded data. 419aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn mAdapter = new AppListAdapter(getActivity()); 420aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn setListAdapter(mAdapter); 421aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 422aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // Start out with a progress indicator. 423aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn setListShown(false); 424aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 425aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // Prepare the loader. Either re-connect with an existing one, 426aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // or start a new one. 427aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn getLoaderManager().initLoader(0, null, this); 428aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 429aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 430aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { 431aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // Place an action bar item for searching. 432aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn MenuItem item = menu.add("Search"); 433aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn item.setIcon(android.R.drawable.ic_menu_search); 434aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); 435aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn SearchView sv = new SearchView(getActivity()); 436aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn sv.setOnQueryTextListener(this); 437aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn item.setActionView(sv); 438aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 439aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 440aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn @Override public boolean onQueryTextChange(String newText) { 441aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // Called when the action bar search text has changed. Since this 442aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // is a simple array adapter, we can just have it do the filtering. 443aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn mCurFilter = !TextUtils.isEmpty(newText) ? newText : null; 444aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn mAdapter.getFilter().filter(mCurFilter); 445aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn return true; 446aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 447aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 448aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn @Override public boolean onQueryTextSubmit(String query) { 449aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // Don't care about this. 450aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn return true; 451aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 452aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 453aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn @Override public void onListItemClick(ListView l, View v, int position, long id) { 454aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // Insert desired behavior here. 455aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn Log.i("LoaderCustom", "Item clicked: " + id); 456aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 457aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 458aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn @Override public Loader<List<AppEntry>> onCreateLoader(int id, Bundle args) { 459aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // This is called when a new Loader needs to be created. This 460aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // sample only has one Loader with no arguments, so it is simple. 461aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn return new AppListLoader(getActivity()); 462aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 463aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 464aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn @Override public void onLoadFinished(Loader<List<AppEntry>> loader, List<AppEntry> data) { 465aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // Set the new data in the adapter. 466aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn mAdapter.setData(data); 467aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 468aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // The list should now be shown. 469aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn if (isResumed()) { 470aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn setListShown(true); 471aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } else { 472aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn setListShownNoAnimation(true); 473aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 474aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 475aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 476aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn @Override public void onLoaderReset(Loader<List<AppEntry>> loader) { 477aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // Clear the data in the adapter. 478aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn mAdapter.setData(null); 479aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 480aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 481aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn//END_INCLUDE(fragment) 482aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn} 483