LoaderCustomSupport.java revision ddffc06960e054e3e4f4eb468360e73053c7cbab
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; 38109979ea9794aa98665d125ebe6a90448ff65f1fSvetoslav Ganovimport android.support.v4.view.MenuItemCompat; 39109979ea9794aa98665d125ebe6a90448ff65f1fSvetoslav Ganovimport android.support.v4.widget.SearchViewCompat; 40aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornimport android.text.TextUtils; 41aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornimport android.util.Log; 42aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornimport android.view.LayoutInflater; 43aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornimport android.view.Menu; 44aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornimport android.view.MenuInflater; 45aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornimport android.view.MenuItem; 46aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornimport android.view.View; 47aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornimport android.view.ViewGroup; 48aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornimport android.widget.ArrayAdapter; 49aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornimport android.widget.ImageView; 50aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornimport android.widget.ListView; 51aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornimport android.widget.TextView; 52109979ea9794aa98665d125ebe6a90448ff65f1fSvetoslav Ganov 53109979ea9794aa98665d125ebe6a90448ff65f1fSvetoslav Ganovimport com.example.android.supportv4.R; 54109979ea9794aa98665d125ebe6a90448ff65f1fSvetoslav Ganov 55109979ea9794aa98665d125ebe6a90448ff65f1fSvetoslav Ganovimport java.io.File; 56109979ea9794aa98665d125ebe6a90448ff65f1fSvetoslav Ganovimport java.text.Collator; 57109979ea9794aa98665d125ebe6a90448ff65f1fSvetoslav Ganovimport java.util.ArrayList; 58109979ea9794aa98665d125ebe6a90448ff65f1fSvetoslav Ganovimport java.util.Collections; 59109979ea9794aa98665d125ebe6a90448ff65f1fSvetoslav Ganovimport java.util.Comparator; 60109979ea9794aa98665d125ebe6a90448ff65f1fSvetoslav Ganovimport java.util.List; 61aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 62aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn/** 63aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn * Demonstration of the implementation of a custom Loader. 64aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn */ 65aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackbornpublic class LoaderCustomSupport extends FragmentActivity { 66aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 67aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn @Override 68aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn protected void onCreate(Bundle savedInstanceState) { 69aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn super.onCreate(savedInstanceState); 70aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 71aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn FragmentManager fm = getSupportFragmentManager(); 72aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 73aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // Create the list fragment and add it as our sole content. 74aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn if (fm.findFragmentById(android.R.id.content) == null) { 75aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn AppListFragment list = new AppListFragment(); 76aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn fm.beginTransaction().add(android.R.id.content, list).commit(); 77aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 78aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 79aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 80aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn//BEGIN_INCLUDE(loader) 81aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn /** 82aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn * This class holds the per-item data in our Loader. 83aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn */ 84aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn public static class AppEntry { 85aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn public AppEntry(AppListLoader loader, ApplicationInfo info) { 86aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn mLoader = loader; 87aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn mInfo = info; 88aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn mApkFile = new File(info.sourceDir); 89aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 90aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 91aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn public ApplicationInfo getApplicationInfo() { 92aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn return mInfo; 93aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 94aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 95aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn public String getLabel() { 96aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn return mLabel; 97aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 98aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 99aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn public Drawable getIcon() { 100aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn if (mIcon == null) { 101aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn if (mApkFile.exists()) { 102aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn mIcon = mInfo.loadIcon(mLoader.mPm); 103aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn return mIcon; 104aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } else { 105aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn mMounted = false; 106aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 107aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } else if (!mMounted) { 108aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // If the app wasn't mounted but is now mounted, reload 109aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // its icon. 110aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn if (mApkFile.exists()) { 111aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn mMounted = true; 112aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn mIcon = mInfo.loadIcon(mLoader.mPm); 113aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn return mIcon; 114aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 115aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } else { 116aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn return mIcon; 117aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 118aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 11967949f5f3bc1f721fa5f63250f0fd74a44f5381fAurimas Liutikas return ContextCompat.getDrawable( 12067949f5f3bc1f721fa5f63250f0fd74a44f5381fAurimas Liutikas mLoader.getContext(), android.R.drawable.sym_def_app_icon); 121aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 122aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 123aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn @Override public String toString() { 124aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn return mLabel; 125aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 126aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 127aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn void loadLabel(Context context) { 128aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn if (mLabel == null || !mMounted) { 129aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn if (!mApkFile.exists()) { 130aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn mMounted = false; 131aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn mLabel = mInfo.packageName; 132aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } else { 133aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn mMounted = true; 134aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn CharSequence label = mInfo.loadLabel(context.getPackageManager()); 135aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn mLabel = label != null ? label.toString() : mInfo.packageName; 136aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 137aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 138aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 139aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 140aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn private final AppListLoader mLoader; 141aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn private final ApplicationInfo mInfo; 142aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn private final File mApkFile; 143aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn private String mLabel; 144aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn private Drawable mIcon; 145aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn private boolean mMounted; 146aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 147aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 148aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn /** 149aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn * Perform alphabetical comparison of application entry objects. 150aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn */ 151aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn public static final Comparator<AppEntry> ALPHA_COMPARATOR = new Comparator<AppEntry>() { 152aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn private final Collator sCollator = Collator.getInstance(); 153aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn @Override 154aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn public int compare(AppEntry object1, AppEntry object2) { 155aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn return sCollator.compare(object1.getLabel(), object2.getLabel()); 156aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 157aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn }; 158aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 159aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn /** 160aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn * Helper for determining if the configuration has changed in an interesting 161aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn * way so we need to rebuild the app list. 162aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn */ 163aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn public static class InterestingConfigChanges { 164aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn final Configuration mLastConfiguration = new Configuration(); 165aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn int mLastDensity; 166aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 167aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn boolean applyNewConfig(Resources res) { 168aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn int configChanges = mLastConfiguration.updateFrom(res.getConfiguration()); 169aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn boolean densityChanged = mLastDensity != res.getDisplayMetrics().densityDpi; 170aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn if (densityChanged || (configChanges&(ActivityInfo.CONFIG_LOCALE 171109979ea9794aa98665d125ebe6a90448ff65f1fSvetoslav Ganov |ActivityInfoCompat.CONFIG_UI_MODE|ActivityInfo.CONFIG_SCREEN_LAYOUT)) != 0) { 172aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn mLastDensity = res.getDisplayMetrics().densityDpi; 173aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn return true; 174aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 175aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn return false; 176aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 177aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 178aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 179aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn /** 180aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn * Helper class to look for interesting changes to the installed apps 181aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn * so that the loader can be updated. 182aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn */ 183aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn public static class PackageIntentReceiver extends BroadcastReceiver { 184aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn final AppListLoader mLoader; 185aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 186aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn public PackageIntentReceiver(AppListLoader loader) { 187aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn mLoader = loader; 188aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED); 189aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn filter.addAction(Intent.ACTION_PACKAGE_REMOVED); 190aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn filter.addAction(Intent.ACTION_PACKAGE_CHANGED); 191aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn filter.addDataScheme("package"); 192aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn mLoader.getContext().registerReceiver(this, filter); 193aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // Register for events related to sdcard installation. 194aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn IntentFilter sdFilter = new IntentFilter(); 195ddffc06960e054e3e4f4eb468360e73053c7cbabAurimas Liutikas sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE); 196ddffc06960e054e3e4f4eb468360e73053c7cbabAurimas Liutikas sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE); 197aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn mLoader.getContext().registerReceiver(this, sdFilter); 198aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 199aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 200aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn @Override public void onReceive(Context context, Intent intent) { 201aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // Tell the loader about the change. 202aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn mLoader.onContentChanged(); 203aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 204aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 205aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 206aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn /** 207aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn * A custom Loader that loads all of the installed applications. 208aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn */ 209aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn public static class AppListLoader extends AsyncTaskLoader<List<AppEntry>> { 210aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn final InterestingConfigChanges mLastConfig = new InterestingConfigChanges(); 211aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn final PackageManager mPm; 212aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 213aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn List<AppEntry> mApps; 214aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn PackageIntentReceiver mPackageObserver; 215aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 216aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn public AppListLoader(Context context) { 217aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn super(context); 218aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 219aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // Retrieve the package manager for later use; note we don't 220aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // use 'context' directly but instead the save global application 221aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // context returned by getContext(). 222aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn mPm = getContext().getPackageManager(); 223aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 224aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 225aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn /** 226aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn * This is where the bulk of our work is done. This function is 227aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn * called in a background thread and should generate a new set of 228aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn * data to be published by the loader. 229aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn */ 230aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn @Override public List<AppEntry> loadInBackground() { 231aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // Retrieve all known applications. 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); 4386a8875b9abd9914c20d28ccd8eb483da4ff9e4a5Dianne Hackborn MenuItemCompat.setShowAsAction(item, MenuItemCompat.SHOW_AS_ACTION_IF_ROOM 4396a8875b9abd9914c20d28ccd8eb483da4ff9e4a5Dianne Hackborn | MenuItemCompat.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW); 4409243026743939a62a1db9e759e471c16ecb5c51dDianne Hackborn final View searchView = SearchViewCompat.newSearchView(getActivity()); 441109979ea9794aa98665d125ebe6a90448ff65f1fSvetoslav Ganov if (searchView != null) { 442109979ea9794aa98665d125ebe6a90448ff65f1fSvetoslav Ganov SearchViewCompat.setOnQueryTextListener(searchView, 4439c76e9550ada0475f1c750e5672128630d2a028cAurimas Liutikas new SearchViewCompat.OnQueryTextListener() { 4449c76e9550ada0475f1c750e5672128630d2a028cAurimas Liutikas @Override 4459c76e9550ada0475f1c750e5672128630d2a028cAurimas Liutikas public boolean onQueryTextChange(String newText) { 4469c76e9550ada0475f1c750e5672128630d2a028cAurimas Liutikas // Called when the action bar search text has changed. Since this 4479c76e9550ada0475f1c750e5672128630d2a028cAurimas Liutikas // is a simple array adapter, we can just have it do the filtering. 4489c76e9550ada0475f1c750e5672128630d2a028cAurimas Liutikas mCurFilter = !TextUtils.isEmpty(newText) ? newText : null; 4499c76e9550ada0475f1c750e5672128630d2a028cAurimas Liutikas mAdapter.getFilter().filter(mCurFilter); 4509c76e9550ada0475f1c750e5672128630d2a028cAurimas Liutikas return true; 4519c76e9550ada0475f1c750e5672128630d2a028cAurimas Liutikas } 4529c76e9550ada0475f1c750e5672128630d2a028cAurimas Liutikas 4539c76e9550ada0475f1c750e5672128630d2a028cAurimas Liutikas @Override 4549c76e9550ada0475f1c750e5672128630d2a028cAurimas Liutikas public boolean onQueryTextSubmit(String query) { 4559c76e9550ada0475f1c750e5672128630d2a028cAurimas Liutikas return false; 4569c76e9550ada0475f1c750e5672128630d2a028cAurimas Liutikas } 4579c76e9550ada0475f1c750e5672128630d2a028cAurimas Liutikas }); 4589243026743939a62a1db9e759e471c16ecb5c51dDianne Hackborn SearchViewCompat.setOnCloseListener(searchView, 4599c76e9550ada0475f1c750e5672128630d2a028cAurimas Liutikas new SearchViewCompat.OnCloseListener() { 4609243026743939a62a1db9e759e471c16ecb5c51dDianne Hackborn @Override 4619243026743939a62a1db9e759e471c16ecb5c51dDianne Hackborn public boolean onClose() { 4629243026743939a62a1db9e759e471c16ecb5c51dDianne Hackborn if (!TextUtils.isEmpty(SearchViewCompat.getQuery(searchView))) { 4639243026743939a62a1db9e759e471c16ecb5c51dDianne Hackborn SearchViewCompat.setQuery(searchView, null, true); 4649243026743939a62a1db9e759e471c16ecb5c51dDianne Hackborn } 4659243026743939a62a1db9e759e471c16ecb5c51dDianne Hackborn return true; 4669243026743939a62a1db9e759e471c16ecb5c51dDianne Hackborn } 4679c76e9550ada0475f1c750e5672128630d2a028cAurimas Liutikas }); 468109979ea9794aa98665d125ebe6a90448ff65f1fSvetoslav Ganov MenuItemCompat.setActionView(item, searchView); 469109979ea9794aa98665d125ebe6a90448ff65f1fSvetoslav Ganov } 470aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 471aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 472aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn @Override public void onListItemClick(ListView l, View v, int position, long id) { 473aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // Insert desired behavior here. 474aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn Log.i("LoaderCustom", "Item clicked: " + id); 475aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 476aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 477aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn @Override public Loader<List<AppEntry>> onCreateLoader(int id, Bundle args) { 478aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // This is called when a new Loader needs to be created. This 479aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // sample only has one Loader with no arguments, so it is simple. 480aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn return new AppListLoader(getActivity()); 481aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 482aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 483aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn @Override public void onLoadFinished(Loader<List<AppEntry>> loader, List<AppEntry> data) { 484aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // Set the new data in the adapter. 485aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn mAdapter.setData(data); 486aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 487aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // The list should now be shown. 488aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn if (isResumed()) { 489aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn setListShown(true); 490aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } else { 491aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn setListShownNoAnimation(true); 492aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 493aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 494aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn 495aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn @Override public void onLoaderReset(Loader<List<AppEntry>> loader) { 496aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn // Clear the data in the adapter. 497aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn mAdapter.setData(null); 498aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 499aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn } 500aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn//END_INCLUDE(fragment) 501aefd2819f5d9f972a6c6dc33a3c66d6d2891d4e8Dianne Hackborn} 502