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