Revision 74a77186

View differences:

res/layout/activity_app_select.xml
1
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
2
    xmlns:tools="http://schemas.android.com/tools"
3
    android:layout_width="match_parent"
4
    android:layout_height="match_parent" >
5

  
6
    <fragment
7
        android:id="@+id/fragment_app_list"
8
        android:layout_width="fill_parent"
9
        android:layout_height="fill_parent"
10
        class="info.guardianproject.checkey.AppListFragment" />
11

  
12
</RelativeLayout>
res/layout/app_entry.xml
1
<?xml version="1.0" encoding="utf-8"?>
2
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3
    android:layout_width="fill_parent"
4
    android:layout_height="wrap_content"
5
    android:orientation="horizontal" >
6

  
7
    <ImageView
8
        android:id="@+id/icon"
9
        android:layout_width="48dip"
10
        android:layout_height="48dip"
11
        android:contentDescription="@string/icon" />
12

  
13
    <TextView
14
        android:id="@+id/text"
15
        android:layout_width="fill_parent"
16
        android:layout_height="wrap_content"
17
        android:gravity="left|center_vertical"
18
        android:textSize="24sp" />
19

  
20
</LinearLayout>
res/layout/fragment_main.xml
1
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
2
    xmlns:tools="http://schemas.android.com/tools"
3
    android:layout_width="match_parent"
4
    android:layout_height="match_parent"
5
    android:paddingBottom="@dimen/activity_vertical_margin"
6
    android:paddingLeft="@dimen/activity_horizontal_margin"
7
    android:paddingRight="@dimen/activity_horizontal_margin"
8
    android:paddingTop="@dimen/activity_vertical_margin"
9
    tools:context="info.guardianproject.checkey.MainActivity$PlaceholderFragment" >
10

  
11
    <TextView
12
        android:layout_width="wrap_content"
13
        android:layout_height="wrap_content"
14
        android:text="@string/hello_world" />
15

  
16
</RelativeLayout>
res/layout/select_local_apps_list_item.xml
1
<?xml version="1.0" encoding="utf-8"?>
2
<!--
3
     Copyright (C) 2010 The Android Open Source Project
4
     Licensed under the Apache License, Version 2.0 (the "License");
5
     you may not use this file except in compliance with the License.
6
     You may obtain a copy of the License at
7
          http://www.apache.org/licenses/LICENSE-2.0
8
     Unless required by applicable law or agreed to in writing, software
9
     distributed under the License is distributed on an "AS IS" BASIS,
10
     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
     See the License for the specific language governing permissions and
12
     limitations under the License.
13
-->
14

  
15
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
16
    xmlns:tools="http://schemas.android.com/tools"
17
    android:layout_width="match_parent"
18
    android:layout_height="wrap_content"
19
    android:background="?android:attr/activatedBackgroundIndicator"
20
    android:minHeight="?android:attr/listPreferredItemHeight"
21
    android:paddingBottom="2dip"
22
    android:paddingTop="2dip"
23
    tools:ignore="NewApi" >
24

  
25
    <!-- TODO remove NewApi ignore when appcompat-v7 is in place -->
26

  
27
    <ImageView
28
        android:id="@+id/icon"
29
        android:layout_width="48dip"
30
        android:layout_height="48dip"
31
        android:layout_marginLeft="?android:attr/listPreferredItemPaddingLeft"
32
        android:layout_marginStart="?android:attr/listPreferredItemPaddingLeft"
33
        android:layout_marginTop="6dip"
34
        tools:ignore="ContentDescription" />
35

  
36
    <TwoLineListItem
37
        android:layout_width="match_parent"
38
        android:layout_height="wrap_content"
39
        android:mode="twoLine" >
40

  
41
        <TextView
42
            android:id="@+id/application_label"
43
            android:layout_width="match_parent"
44
            android:layout_height="wrap_content"
45
            android:layout_marginLeft="?android:attr/listPreferredItemPaddingLeft"
46
            android:layout_marginStart="?android:attr/listPreferredItemPaddingLeft"
47
            android:layout_marginTop="6dip"
48
            android:textAppearance="?android:attr/textAppearanceListItem" />
49

  
50
        <TextView
51
            android:id="@+id/package_name"
52
            android:layout_width="match_parent"
53
            android:layout_height="wrap_content"
54
            android:layout_alignStart="@+id/application_label"
55
            android:layout_below="@+id/application_label"
56
            android:textAppearance="?android:attr/textAppearanceSmall" />
57
    </TwoLineListItem>
58

  
59
</LinearLayout>
res/menu/main.xml
5 5

  
6 6
    <item
7 7
        android:id="@+id/action_settings"
8
        android:icon="@android:drawable/ic_menu_preferences"
8 9
        android:orderInCategory="100"
9 10
        android:title="@string/action_settings"
10 11
        app:showAsAction="never"/>
11 12

  
12
</menu>
13
</menu>
res/values/strings.xml
2 2
<resources>
3 3

  
4 4
    <string name="app_name">ChecKey</string>
5
    <string name="hello_world">Hello world!</string>
5
    <string name="icon">icon</string>
6 6
    <string name="action_settings">Settings</string>
7
    <string name="no_applications_found">No applications found</string>
7 8

  
8
</resources>
9
</resources>
src/info/guardianproject/checkey/AppEntry.java
1
/*
2
 Licensed under the Apache License, Version 2.0 (the "License");
3
 you may not use this file except in compliance with the License.
4
You may obtain a copy of the License at
5

  
6
    http://www.apache.org/licenses/LICENSE-2.0
7

  
8
Unless required by applicable law or agreed to in writing, software
9
distributed under the License is distributed on an "AS IS" BASIS,
10
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
See the License for the specific language governing permissions and
12
limitations under the License.
13

  
14
Based on Paul Blundell's Tutorial:
15
http://blog.blundell-apps.com/tut-asynctask-loader-using-support-library/
16

  
17
which is originally based on:
18
https://developer.android.com/reference/android/content/AsyncTaskLoader.html
19
 */
20

  
21
package info.guardianproject.checkey;
22

  
23
import android.content.pm.ApplicationInfo;
24
import android.content.pm.PackageManager;
25
import android.graphics.drawable.Drawable;
26

  
27
import java.io.File;
28

  
29
public class AppEntry {
30
    public static final String TAG = "AppEntry";
31

  
32
    private final AppListLoader loader;
33
    private final ApplicationInfo info;
34
    private final File apkFile;
35
    private boolean enabled;
36
    private String label;
37
    private Drawable icon;
38
    private boolean mounted;
39

  
40
    public AppEntry(AppListLoader loader, ApplicationInfo info) {
41
        this.loader = loader;
42
        this.info = info;
43
        apkFile = new File(info.sourceDir);
44
    }
45

  
46
    public ApplicationInfo getApplicationInfo() {
47
        return info;
48
    }
49

  
50
    public String getPackageName() {
51
        return info.packageName;
52
    }
53

  
54
    public String getLabel() {
55
        return label;
56
    }
57

  
58
    public boolean isEnabled() {
59
        return enabled;
60
    }
61

  
62
    public void setEnabled(boolean enabled) {
63
        this.enabled = enabled;
64
    }
65

  
66
    public Drawable getIcon() {
67
        if (icon == null) {
68
            if (apkFile.exists()) {
69
                icon = info.loadIcon(loader.pm);
70
                return icon;
71
            } else {
72
                mounted = false;
73
            }
74
        } else if (!mounted) {
75
            // If the app wasn't mounted but is now mounted, reload its icon
76
            if (apkFile.exists()) {
77
                mounted = true;
78
                icon = info.loadIcon(loader.pm);
79
            }
80
        } else {
81
            return icon;
82
        }
83

  
84
        return loader.getContext().getResources().getDrawable(android.R.drawable.sym_def_app_icon);
85
    }
86

  
87
    @Override
88
    public String toString() {
89
        return label;
90
    }
91

  
92
    public void loadLabel(PackageManager pm) {
93
        if (label == null || !mounted) {
94
            if (apkFile.exists()) {
95
                mounted = true;
96
                CharSequence label = null;
97
                label = info.loadLabel(pm);
98
                this.label = label != null ? label.toString() : info.packageName;
99
            } else {
100
                mounted = false;
101
                label = info.packageName;
102
            }
103
        }
104
    }
105
}
src/info/guardianproject/checkey/AppListAdapter.java
1
/*
2
 Licensed under the Apache License, Version 2.0 (the "License");
3
 you may not use this file except in compliance with the License.
4
You may obtain a copy of the License at
5

  
6
    http://www.apache.org/licenses/LICENSE-2.0
7

  
8
Unless required by applicable law or agreed to in writing, software
9
distributed under the License is distributed on an "AS IS" BASIS,
10
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
See the License for the specific language governing permissions and
12
limitations under the License.
13

  
14
Based on Paul Blundell's Tutorial:
15
http://blog.blundell-apps.com/tut-asynctask-loader-using-support-library/
16

  
17
which is originally based on:
18
https://developer.android.com/reference/android/content/AsyncTaskLoader.html
19
 */
20

  
21
package info.guardianproject.checkey;
22

  
23
import android.content.Context;
24
import android.util.SparseArray;
25
import android.view.LayoutInflater;
26
import android.view.View;
27
import android.view.ViewGroup;
28
import android.widget.BaseAdapter;
29
import android.widget.ImageView;
30
import android.widget.TextView;
31

  
32
import java.util.List;
33

  
34
public class AppListAdapter extends BaseAdapter {
35

  
36
    private final LayoutInflater inflater;
37
    private List<AppEntry> data;
38

  
39
    public AppListAdapter(Context context) {
40
        inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
41
    }
42

  
43
    public void setData(List<AppEntry> data) {
44
        this.data = data;
45
        notifyDataSetChanged();
46
    }
47

  
48
    @Override
49
    public View getView(int position, View view, ViewGroup parent) {
50
        if (view == null)
51
            view = inflater.inflate(R.layout.select_local_apps_list_item, parent, false);
52

  
53
        AppEntry appEntry = data.get(position);
54
        ImageView iconView = ViewHolder.get(view, R.id.icon);
55
        iconView.setImageDrawable(appEntry.getIcon());
56
        TextView labelView = ViewHolder.get(view, R.id.application_label);
57
        labelView.setText(appEntry.getLabel());
58
        TextView packageView = ViewHolder.get(view, R.id.package_name);
59
        packageView.setText(appEntry.getPackageName());
60
        return view;
61
    }
62

  
63
    @Override
64
    public int getCount() {
65
        return data == null ? 0 : data.size();
66
    }
67

  
68
    @Override
69
    public Object getItem(int position) {
70
        return data == null ? null : data.get(position);
71
    }
72

  
73
    @Override
74
    public long getItemId(int position) {
75
        return position;
76
    }
77

  
78
    /* from http://www.piwai.info/android-adapter-good-practices/#Update */
79
    public static class ViewHolder {
80
        // a generic return type to reduce the casting noise in client code
81
        @SuppressWarnings("unchecked")
82
        public static <T extends View> T get(View view, int id) {
83
            SparseArray<View> viewHolder = (SparseArray<View>) view.getTag();
84
            if (viewHolder == null) {
85
                viewHolder = new SparseArray<View>();
86
                view.setTag(viewHolder);
87
            }
88
            View childView = viewHolder.get(id);
89
            if (childView == null) {
90
                childView = view.findViewById(id);
91
                viewHolder.put(id, childView);
92
            }
93
            return (T) childView;
94
        }
95
    }
96

  
97
}
src/info/guardianproject/checkey/AppListFragment.java
1
/*
2
 Licensed under the Apache License, Version 2.0 (the "License");
3
 you may not use this file except in compliance with the License.
4
You may obtain a copy of the License at
5

  
6
    http://www.apache.org/licenses/LICENSE-2.0
7

  
8
Unless required by applicable law or agreed to in writing, software
9
distributed under the License is distributed on an "AS IS" BASIS,
10
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
See the License for the specific language governing permissions and
12
limitations under the License.
13

  
14
Based on Paul Blundell's Tutorial:
15
http://blog.blundell-apps.com/tut-asynctask-loader-using-support-library/
16

  
17
which is originally based on:
18
https://developer.android.com/reference/android/content/AsyncTaskLoader.html
19
 */
20

  
21
package info.guardianproject.checkey;
22

  
23
import android.annotation.TargetApi;
24
import android.os.Bundle;
25
import android.support.v4.app.ListFragment;
26
import android.support.v4.app.LoaderManager.LoaderCallbacks;
27
import android.support.v4.content.Loader;
28
import android.view.View;
29
import android.widget.ListView;
30

  
31
import java.util.List;
32

  
33
public class AppListFragment extends ListFragment implements LoaderCallbacks<List<AppEntry>> {
34

  
35
    private AppListAdapter adapter;
36

  
37
    @Override
38
    public void onActivityCreated(Bundle savedInstanceState) {
39
        super.onActivityCreated(savedInstanceState);
40

  
41
        setEmptyText(getString(R.string.no_applications_found));
42

  
43
        adapter = new AppListAdapter(getActivity());
44
        setListAdapter(adapter);
45
        setListShown(false);
46

  
47
        // Prepare the loader
48
        // either reconnect with an existing one or start a new one
49
        getLoaderManager().initLoader(0, null, this);
50
    }
51

  
52
    @TargetApi(11)
53
    // TODO replace with appcompat-v7
54
    @Override
55
    public void onListItemClick(ListView l, View v, int position, long id) {
56
        AppEntry appEntry = (AppEntry) adapter.getItem(position);
57
        // TODO search androidobs here
58
    }
59

  
60
    @Override
61
    public Loader<List<AppEntry>> onCreateLoader(int id, Bundle args) {
62
        // This is called when a new loader needs to be created.
63
        // This sample only has one Loader with no arguments, so it is simple.
64
        return new AppListLoader(getActivity());
65
    }
66

  
67
    @Override
68
    public void onLoadFinished(Loader<List<AppEntry>> loader, List<AppEntry> data) {
69
        adapter.setData(data);
70

  
71
        // The list should now be shown
72
        if (isResumed()) {
73
            setListShown(true);
74
        } else {
75
            setListShownNoAnimation(true);
76
        }
77
    }
78

  
79
    @Override
80
    public void onLoaderReset(Loader<List<AppEntry>> loader) {
81
        // Clear the data in the adapter
82
        adapter.setData(null);
83
    }
84
}
src/info/guardianproject/checkey/AppListLoader.java
1
/*
2
 Licensed under the Apache License, Version 2.0 (the "License");
3
 you may not use this file except in compliance with the License.
4
You may obtain a copy of the License at
5

  
6
    http://www.apache.org/licenses/LICENSE-2.0
7

  
8
Unless required by applicable law or agreed to in writing, software
9
distributed under the License is distributed on an "AS IS" BASIS,
10
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
See the License for the specific language governing permissions and
12
limitations under the License.
13

  
14
Based on Paul Blundell's Tutorial:
15
http://blog.blundell-apps.com/tut-asynctask-loader-using-support-library/
16

  
17
which is originally based on:
18
https://developer.android.com/reference/android/content/AsyncTaskLoader.html
19
 */
20

  
21
package info.guardianproject.checkey;
22

  
23
import android.content.Context;
24
import android.content.pm.ApplicationInfo;
25
import android.content.pm.PackageManager;
26
import android.support.v4.content.AsyncTaskLoader;
27

  
28
import java.text.Collator;
29
import java.util.ArrayList;
30
import java.util.Collections;
31
import java.util.List;
32

  
33
public class AppListLoader extends AsyncTaskLoader<List<AppEntry>> {
34
    public final PackageManager pm;
35

  
36
    List<AppEntry> apps;
37
    PackageIntentReceiver packageObserver;
38

  
39
    public AppListLoader(Context context) {
40
        super(context);
41

  
42
        // Retrieve the package manager for later use; note we don't
43
        // use 'context' directly but instead the safe global application
44
        // context returned by getContext().
45
        pm = getContext().getPackageManager();
46
    }
47

  
48
    @Override
49
    protected void onStartLoading() {
50
        super.onStartLoading();
51
        // AsyncTaskLoader doesnt start unless you forceLoad
52
        // http://code.google.com/p/android/issues/detail?id=14944
53
        if (apps != null) {
54
            deliverResult(apps);
55
        }
56
        if (takeContentChanged() || apps == null) {
57
            forceLoad();
58
        }
59
    }
60

  
61
    /**
62
     * This is where the bulk of the work. This function is called in a
63
     * background thread and should generate a new set of data to be published
64
     * by the loader.
65
     */
66
    @Override
67
    public List<AppEntry> loadInBackground() {
68
        // Retrieve all known applications
69
        List<ApplicationInfo> apps = pm.getInstalledApplications(
70
                PackageManager.GET_UNINSTALLED_PACKAGES |
71
                        PackageManager.GET_DISABLED_COMPONENTS);
72

  
73
        if (apps == null) {
74
            apps = new ArrayList<ApplicationInfo>();
75
        }
76

  
77
        // Create corresponding array of entries and load their labels
78
        List<AppEntry> entries = new ArrayList<AppEntry>(apps.size());
79
        for (ApplicationInfo applicationInfo : apps) {
80
            AppEntry entry = new AppEntry(this, applicationInfo);
81
            entry.loadLabel(pm);
82
            entries.add(entry);
83
        }
84

  
85
        Collections.sort(entries, Comparator.ALPHA_COMPARATOR);
86

  
87
        return entries;
88
    }
89

  
90
    /**
91
     * Called when there is new data to deliver to the client. The super class
92
     * will take care of delivering it; the implementation just adds a little
93
     * more logic
94
     */
95
    @Override
96
    public void deliverResult(List<AppEntry> apps) {
97
        if (isReset()) {
98
            // An async query came in while the loader is stopped. We don't need
99
            // the result
100
            if (apps != null) {
101
                onReleaseResources(apps);
102
            }
103
        }
104
        List<AppEntry> oldApps = this.apps;
105
        this.apps = apps;
106

  
107
        if (isStarted()) {
108
            // If the loader is currently started, we can immediately deliver a
109
            // result
110
            super.deliverResult(apps);
111
        }
112

  
113
        // At this point we can release the resources associated with 'oldApps'
114
        // if needed;
115
        // now that the new result is delivered we know that it is no longer in
116
        // use
117
        if (oldApps != null) {
118
            onReleaseResources(oldApps);
119
        }
120
    }
121

  
122
    @Override
123
    protected void onStopLoading() {
124
        // Attempts to cancel the current load task if possible
125
        cancelLoad();
126
    }
127

  
128
    @Override
129
    public void onCanceled(List<AppEntry> apps) {
130
        super.onCanceled(apps);
131

  
132
        // At this point we can release the resources associated with 'apps' if
133
        // needed
134
        onReleaseResources(apps);
135
    }
136

  
137
    /**
138
     * Handles request to completely reset the loader
139
     */
140
    @Override
141
    protected void onReset() {
142
        super.onReset();
143

  
144
        // ensure the loader is stopped
145
        onStopLoading();
146

  
147
        // At this point we can release the resources associated with 'apps' if
148
        // needed
149
        if (apps != null) {
150
            onReleaseResources(apps);
151
            apps = null;
152
        }
153

  
154
        // Stop monitoring for changes
155
        if (packageObserver != null) {
156
            getContext().unregisterReceiver(packageObserver);
157
            packageObserver = null;
158
        }
159
    }
160

  
161
    /**
162
     * Helper function to take care of releasing resources associated with an
163
     * actively loaded data set
164
     */
165
    private void onReleaseResources(List<AppEntry> apps) {
166
        // For a simple list there is nothing to do
167
        // but for a Cursor we would close it here
168
    }
169

  
170
    /**
171
     * Perform alphabetical comparison on AppEntry objects
172
     */
173
    static class Comparator {
174
        static final java.util.Comparator<AppEntry> ALPHA_COMPARATOR = new java.util.Comparator<AppEntry>() {
175
            private final Collator collator = Collator.getInstance();
176

  
177
            @Override
178
            public int compare(AppEntry lhs, AppEntry rhs) {
179
                return collator.compare(lhs.getLabel(), rhs.getLabel());
180
            }
181
        };
182
    }
183
}
src/info/guardianproject/checkey/MainActivity.java
1 1

  
2 2
package info.guardianproject.checkey;
3 3

  
4
import android.support.v7.app.ActionBarActivity;
5
import android.support.v7.app.ActionBar;
6
import android.support.v4.app.Fragment;
4
import android.annotation.TargetApi;
7 5
import android.os.Bundle;
8
import android.view.LayoutInflater;
6
import android.support.v4.app.FragmentActivity;
9 7
import android.view.Menu;
10 8
import android.view.MenuItem;
11
import android.view.View;
12
import android.view.ViewGroup;
13
import android.os.Build;
14 9

  
15
public class MainActivity extends ActionBarActivity {
10
@TargetApi(11)
11
// TODO replace with appcompat-v7
12
public class MainActivity extends FragmentActivity {
13
    private final String TAG = "MainActivity";
14
    private AppListFragment appListFragment = null;
16 15

  
17 16
    @Override
18 17
    protected void onCreate(Bundle savedInstanceState) {
19 18
        super.onCreate(savedInstanceState);
20
        setContentView(R.layout.activity_main);
19
        setContentView(R.layout.activity_app_select);
20
    }
21 21

  
22
        if (savedInstanceState == null) {
23
            getSupportFragmentManager().beginTransaction()
24
                    .add(R.id.container, new PlaceholderFragment())
25
                    .commit();
26
        }
22
    @Override
23
    protected void onResume() {
24
        super.onResume();
25
        if (appListFragment == null)
26
            appListFragment = (AppListFragment) getSupportFragmentManager().findFragmentById(
27
                    R.id.fragment_app_list);
27 28
    }
28 29

  
29 30
    @Override
30 31
    public boolean onCreateOptionsMenu(Menu menu) {
31

  
32
        // Inflate the menu; this adds items to the action bar if it is present.
33 32
        getMenuInflater().inflate(R.menu.main, menu);
34 33
        return true;
35 34
    }
36 35

  
37 36
    @Override
38 37
    public boolean onOptionsItemSelected(MenuItem item) {
39
        // Handle action bar item clicks here. The action bar will
40
        // automatically handle clicks on the Home/Up button, so long
41
        // as you specify a parent activity in AndroidManifest.xml.
42
        int id = item.getItemId();
43
        if (id == R.id.action_settings) {
44
            return true;
38
        switch (item.getItemId()) {
39
            case android.R.id.home:
40
                setResult(RESULT_CANCELED);
41
                finish();
42
                return true;
43
            case R.id.action_settings:
44
                return true;
45 45
        }
46 46
        return super.onOptionsItemSelected(item);
47 47
    }
48

  
49
    /**
50
     * A placeholder fragment containing a simple view.
51
     */
52
    public static class PlaceholderFragment extends Fragment {
53

  
54
        public PlaceholderFragment() {
55
        }
56

  
57
        @Override
58
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
59
                Bundle savedInstanceState) {
60
            View rootView = inflater.inflate(R.layout.fragment_main, container, false);
61
            return rootView;
62
        }
63
    }
64

  
65 48
}
src/info/guardianproject/checkey/PackageIntentReceiver.java
1
/*
2
 Licensed under the Apache License, Version 2.0 (the "License");
3
 you may not use this file except in compliance with the License.
4
You may obtain a copy of the License at
5

  
6
    http://www.apache.org/licenses/LICENSE-2.0
7

  
8
Unless required by applicable law or agreed to in writing, software
9
distributed under the License is distributed on an "AS IS" BASIS,
10
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
See the License for the specific language governing permissions and
12
limitations under the License.
13

  
14
Based on Paul Blundell's Tutorial:
15
http://blog.blundell-apps.com/tut-asynctask-loader-using-support-library/
16

  
17
which is originally based on:
18
https://developer.android.com/reference/android/content/AsyncTaskLoader.html
19
 */
20

  
21
package info.guardianproject.checkey;
22

  
23
import android.content.BroadcastReceiver;
24
import android.content.Context;
25
import android.content.Intent;
26
import android.content.IntentFilter;
27

  
28
/**
29
 * Looks for changes to the installed apps so the loader can be updated
30
 */
31
public class PackageIntentReceiver extends BroadcastReceiver {
32
    final AppListLoader loader;
33

  
34
    public PackageIntentReceiver(AppListLoader loader) {
35
        this.loader = loader;
36
        IntentFilter filter = new IntentFilter();
37
        filter.addAction(Intent.ACTION_PACKAGE_ADDED);
38
        filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
39
        filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
40
        filter.addDataScheme("package");
41
        loader.getContext().registerReceiver(this, filter);
42
        // Register for events related to SD Card installation
43
        IntentFilter sdFilter = new IntentFilter();
44
        sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
45
        sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
46
        loader.getContext().registerReceiver(this, sdFilter);
47
    }
48

  
49
    @Override
50
    public void onReceive(Context context, Intent intent) {
51
        loader.onContentChanged();
52
    }
53

  
54
}

Also available in: Unified diff