2 * The MIT License (MIT)
4 * Copyright 2016 Arnab Chakraborty. http://arnab.ch
6 * Permission is hereby granted, free of charge, to any person obtaining a copy of this
7 * software and associated documentation files (the "Software"), to deal in the Software
8 * without restriction, including without limitation the rights to use, copy, modify,
9 * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to the following
13 * The above copyright notice and this permission notice shall be included in all copies
14 * or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
17 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
18 * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
20 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
21 * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 package org.anbox.appmgr;
26 import android.content.Context;
27 import android.content.pm.ApplicationInfo;
28 import android.content.pm.PackageManager;
29 import android.support.v4.content.AsyncTaskLoader;
31 import java.text.Collator;
32 import java.util.ArrayList;
33 import java.util.Collections;
34 import java.util.List;
35 import java.util.Comparator;
38 * @credit http://developer.android.com/reference/android/content/AsyncTaskLoader.html
40 public class AppsLoader extends AsyncTaskLoader<ArrayList<AppModel>> {
41 ArrayList<AppModel> mInstalledApps;
43 final PackageManager mPm;
44 PackageIntentReceiver mPackageObserver;
46 public AppsLoader(Context context) {
49 mPm = context.getPackageManager();
53 public ArrayList<AppModel> loadInBackground() {
54 // retrieve the list of installed applications
55 List<ApplicationInfo> apps = mPm.getInstalledApplications(0);
58 apps = new ArrayList<ApplicationInfo>();
61 final Context context = getContext();
63 // create corresponding apps and load their labels
64 ArrayList<AppModel> items = new ArrayList<AppModel>(apps.size());
65 for (int i = 0; i < apps.size(); i++) {
66 String pkg = apps.get(i).packageName;
68 // only apps which are launchable
69 if (context.getPackageManager().getLaunchIntentForPackage(pkg) != null) {
70 AppModel app = new AppModel(context, apps.get(i));
71 app.loadLabel(context);
77 Collections.sort(items, ALPHA_COMPARATOR);
83 public void deliverResult(ArrayList<AppModel> apps) {
85 // An async query came in while the loader is stopped. We
86 // don't need the result.
88 onReleaseResources(apps);
92 ArrayList<AppModel> oldApps = apps;
93 mInstalledApps = apps;
96 // If the Loader is currently started, we can immediately
97 // deliver its results.
98 super.deliverResult(apps);
101 // At this point we can release the resources associated with
102 // 'oldApps' if needed; now that the new result is delivered we
103 // know that it is no longer in use.
104 if (oldApps != null) {
105 onReleaseResources(oldApps);
110 protected void onStartLoading() {
111 if (mInstalledApps != null) {
112 // If we currently have a result available, deliver it
114 deliverResult(mInstalledApps);
117 // watch for changes in app install and uninstall operation
118 if (mPackageObserver == null) {
119 mPackageObserver = new PackageIntentReceiver(this);
122 if (takeContentChanged() || mInstalledApps == null ) {
123 // If the data has changed since the last time it was loaded
124 // or is not currently available, start a load.
130 protected void onStopLoading() {
131 // Attempt to cancel the current load task if possible.
136 public void onCanceled(ArrayList<AppModel> apps) {
137 super.onCanceled(apps);
139 // At this point we can release the resources associated with 'apps'
141 onReleaseResources(apps);
145 protected void onReset() {
146 // Ensure the loader is stopped
149 // At this point we can release the resources associated with 'apps'
151 if (mInstalledApps != null) {
152 onReleaseResources(mInstalledApps);
153 mInstalledApps = null;
156 // Stop monitoring for changes.
157 if (mPackageObserver != null) {
158 getContext().unregisterReceiver(mPackageObserver);
159 mPackageObserver = null;
164 * Helper method to do the cleanup work if needed, for example if we're
165 * using Cursor, then we should be closing it here
169 protected void onReleaseResources(ArrayList<AppModel> apps) {
175 * Perform alphabetical comparison of application entry objects.
177 public static final Comparator<AppModel> ALPHA_COMPARATOR = new Comparator<AppModel>() {
178 private final Collator sCollator = Collator.getInstance();
180 public int compare(AppModel object1, AppModel object2) {
181 return sCollator.compare(object1.getLabel(), object2.getLabel());