Implement simple activity to show all launchable applications
This commit is contained in:
parent
7f564c55eb
commit
9c9eb48bf0
12 changed files with 1106 additions and 2 deletions
|
|
@ -6,14 +6,18 @@
|
|||
<application
|
||||
android:name="org.anbox.appmgr.MainApplication">
|
||||
<activity
|
||||
android:name=".LauncherActivity"
|
||||
android:launchMode="singleTask">
|
||||
android:name=".LauncherActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.HOME"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".AppViewActivity"
|
||||
android:label="@string/app_name"
|
||||
android:excludeFromRecents="true">
|
||||
</activity>
|
||||
<service
|
||||
android:name=".LauncherService"
|
||||
android:exported="false">
|
||||
|
|
|
|||
17
android/appmgr/res/layout/app_view.xml
Normal file
17
android/appmgr/res/layout/app_view.xml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingLeft="@dimen/activity_horizontal_margin"
|
||||
android:paddingRight="@dimen/activity_horizontal_margin"
|
||||
android:paddingTop="@dimen/activity_vertical_margin"
|
||||
android:paddingBottom="@dimen/activity_vertical_margin"
|
||||
tools:context=".AppViewActivity">
|
||||
|
||||
<fragment
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:name="org.anbox.appmgr.AppsGridFragment"
|
||||
android:id="@+id/apps_grid" />
|
||||
|
||||
</RelativeLayout>
|
||||
38
android/appmgr/res/layout/list_item_icon_text.xml
Normal file
38
android/appmgr/res/layout/list_item_icon_text.xml
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2007 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ImageView android:id="@+id/icon"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_gravity="center_horizontal"/>
|
||||
|
||||
<TextView android:id="@+id/text"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:singleLine="true"
|
||||
android:gravity="center"
|
||||
android:textColor="@android:color/black"
|
||||
android:textSize="14sp"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
5
android/appmgr/res/values/dimens.xml
Normal file
5
android/appmgr/res/values/dimens.xml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<resources>
|
||||
<!-- Default screen margins, per the Android Design guidelines. -->
|
||||
<dimen name="activity_horizontal_margin">16dp</dimen>
|
||||
<dimen name="activity_vertical_margin">16dp</dimen>
|
||||
</resources>
|
||||
89
android/appmgr/src/org/anbox/appmgr/AppListAdapter.java
Normal file
89
android/appmgr/src/org/anbox/appmgr/AppListAdapter.java
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright 2016 Arnab Chakraborty. http://arnab.ch
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
* software and associated documentation files (the "Software"), to deal in the Software
|
||||
* without restriction, including without limitation the rights to use, copy, modify,
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies
|
||||
* or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
|
||||
* THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package org.anbox.appmgr;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Created by Arnab Chakraborty
|
||||
*/
|
||||
public class AppListAdapter extends ArrayAdapter<AppModel> {
|
||||
private final LayoutInflater mInflater;
|
||||
|
||||
public AppListAdapter (Context context) {
|
||||
super(context, android.R.layout.simple_list_item_2);
|
||||
|
||||
mInflater = LayoutInflater.from(context);
|
||||
}
|
||||
|
||||
public void setData(ArrayList<AppModel> data) {
|
||||
clear();
|
||||
if (data != null) {
|
||||
addAll(data);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
|
||||
public void addAll(Collection<? extends AppModel> items) {
|
||||
//If the platform supports it, use addAll, otherwise add in loop
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
|
||||
super.addAll(items);
|
||||
}else{
|
||||
for(AppModel item: items){
|
||||
super.add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate new items in the list.
|
||||
*/
|
||||
@Override public View getView(int position, View convertView, ViewGroup parent) {
|
||||
View view;
|
||||
|
||||
if (convertView == null) {
|
||||
view = mInflater.inflate(R.layout.list_item_icon_text, parent, false);
|
||||
} else {
|
||||
view = convertView;
|
||||
}
|
||||
|
||||
AppModel item = getItem(position);
|
||||
((ImageView)view.findViewById(R.id.icon)).setImageDrawable(item.getIcon());
|
||||
((TextView)view.findViewById(R.id.text)).setText(item.getLabel());
|
||||
|
||||
return view;
|
||||
}
|
||||
}
|
||||
74
android/appmgr/src/org/anbox/appmgr/AppListFragment.java
Normal file
74
android/appmgr/src/org/anbox/appmgr/AppListFragment.java
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright 2016 Arnab Chakraborty. http://arnab.ch
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
* software and associated documentation files (the "Software"), to deal in the Software
|
||||
* without restriction, including without limitation the rights to use, copy, modify,
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies
|
||||
* or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
|
||||
* THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package org.anbox.appmgr;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.ListFragment;
|
||||
import android.support.v4.app.LoaderManager;
|
||||
import android.support.v4.content.Loader;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Created by Arnab Chakraborty
|
||||
*/
|
||||
public class AppListFragment extends ListFragment implements LoaderManager.LoaderCallbacks<ArrayList<AppModel>> {
|
||||
AppListAdapter mAdapter;
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
|
||||
setEmptyText("No Applications");
|
||||
|
||||
mAdapter = new AppListAdapter(getActivity());
|
||||
setListAdapter(mAdapter);
|
||||
|
||||
// till the data is loaded display a spinner
|
||||
setListShown(false);
|
||||
|
||||
// create the loader to load the apps list in background
|
||||
getLoaderManager().initLoader(0, null, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Loader<ArrayList<AppModel>> onCreateLoader(int id, Bundle bundle) {
|
||||
return new AppsLoader(getActivity());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadFinished(Loader<ArrayList<AppModel>> loader, ArrayList<AppModel> apps) {
|
||||
mAdapter.setData(apps);
|
||||
|
||||
if (isResumed()) {
|
||||
setListShown(true);
|
||||
} else {
|
||||
setListShownNoAnimation(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoaderReset(Loader<ArrayList<AppModel>> loader) {
|
||||
mAdapter.setData(null);
|
||||
}
|
||||
}
|
||||
101
android/appmgr/src/org/anbox/appmgr/AppModel.java
Normal file
101
android/appmgr/src/org/anbox/appmgr/AppModel.java
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright 2016 Arnab Chakraborty. http://arnab.ch
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
* software and associated documentation files (the "Software"), to deal in the Software
|
||||
* without restriction, including without limitation the rights to use, copy, modify,
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies
|
||||
* or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
|
||||
* THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package org.anbox.appmgr;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* @credit http://developer.android.com/reference/android/content/AsyncTaskLoader.html
|
||||
*/
|
||||
public class AppModel {
|
||||
|
||||
private final Context mContext;
|
||||
private final ApplicationInfo mInfo;
|
||||
|
||||
private String mAppLabel;
|
||||
private Drawable mIcon;
|
||||
|
||||
private boolean mMounted;
|
||||
private final File mApkFile;
|
||||
|
||||
public AppModel(Context context, ApplicationInfo info) {
|
||||
mContext = context;
|
||||
mInfo = info;
|
||||
|
||||
mApkFile = new File(info.sourceDir);
|
||||
}
|
||||
|
||||
public ApplicationInfo getAppInfo() {
|
||||
return mInfo;
|
||||
}
|
||||
|
||||
public String getApplicationPackageName() {
|
||||
return getAppInfo().packageName;
|
||||
}
|
||||
|
||||
public String getLabel() {
|
||||
return mAppLabel;
|
||||
}
|
||||
|
||||
public Drawable getIcon() {
|
||||
if (mIcon == null) {
|
||||
if (mApkFile.exists()) {
|
||||
mIcon = mInfo.loadIcon(mContext.getPackageManager());
|
||||
return mIcon;
|
||||
} else {
|
||||
mMounted = false;
|
||||
}
|
||||
} else if (!mMounted) {
|
||||
// If the app wasn't mounted but is now mounted, reload
|
||||
// its icon.
|
||||
if (mApkFile.exists()) {
|
||||
mMounted = true;
|
||||
mIcon = mInfo.loadIcon(mContext.getPackageManager());
|
||||
return mIcon;
|
||||
}
|
||||
} else {
|
||||
return mIcon;
|
||||
}
|
||||
|
||||
return mContext.getResources().getDrawable(android.R.drawable.sym_def_app_icon);
|
||||
}
|
||||
|
||||
|
||||
void loadLabel(Context context) {
|
||||
if (mAppLabel == null || !mMounted) {
|
||||
if (!mApkFile.exists()) {
|
||||
mMounted = false;
|
||||
mAppLabel = mInfo.packageName;
|
||||
} else {
|
||||
mMounted = true;
|
||||
CharSequence label = mInfo.loadLabel(context.getPackageManager());
|
||||
mAppLabel = label != null ? label.toString() : mInfo.packageName;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
41
android/appmgr/src/org/anbox/appmgr/AppViewActivity.java
Normal file
41
android/appmgr/src/org/anbox/appmgr/AppViewActivity.java
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3, as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.anbox.appmgr;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
|
||||
public final class AppViewActivity extends FragmentActivity {
|
||||
private static final String TAG = "AnboxAppView";
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle info) {
|
||||
super.onCreate(info);
|
||||
|
||||
setContentView(R.layout.app_view);
|
||||
|
||||
Log.i(TAG, "Created application view activity");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
Log.i(TAG, "Destroying application view activity");
|
||||
super.onDestroy();
|
||||
}
|
||||
}
|
||||
90
android/appmgr/src/org/anbox/appmgr/AppsGridFragment.java
Normal file
90
android/appmgr/src/org/anbox/appmgr/AppsGridFragment.java
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright 2016 Arnab Chakraborty. http://arnab.ch
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
* software and associated documentation files (the "Software"), to deal in the Software
|
||||
* without restriction, including without limitation the rights to use, copy, modify,
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies
|
||||
* or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
|
||||
* THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package org.anbox.appmgr;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.LoaderManager;
|
||||
import android.support.v4.content.Loader;
|
||||
import android.view.View;
|
||||
import android.widget.GridView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Created by Arnab Chakraborty
|
||||
*/
|
||||
public class AppsGridFragment extends GridFragment implements LoaderManager.LoaderCallbacks<ArrayList<AppModel>> {
|
||||
|
||||
AppListAdapter mAdapter;
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
|
||||
setEmptyText("No Applications");
|
||||
|
||||
mAdapter = new AppListAdapter(getActivity());
|
||||
setGridAdapter(mAdapter);
|
||||
|
||||
// till the data is loaded display a spinner
|
||||
setGridShown(false);
|
||||
|
||||
// create the loader to load the apps list in background
|
||||
getLoaderManager().initLoader(0, null, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Loader<ArrayList<AppModel>> onCreateLoader(int id, Bundle bundle) {
|
||||
return new AppsLoader(getActivity());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadFinished(Loader<ArrayList<AppModel>> loader, ArrayList<AppModel> apps) {
|
||||
mAdapter.setData(apps);
|
||||
|
||||
if (isResumed()) {
|
||||
setGridShown(true);
|
||||
} else {
|
||||
setGridShownNoAnimation(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoaderReset(Loader<ArrayList<AppModel>> loader) {
|
||||
mAdapter.setData(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGridItemClick(GridView g, View v, int position, long id) {
|
||||
AppModel app = (AppModel) getGridAdapter().getItem(position);
|
||||
if (app != null) {
|
||||
Intent intent = getActivity().getPackageManager().getLaunchIntentForPackage(app.getApplicationPackageName());
|
||||
|
||||
if (intent != null) {
|
||||
startActivity(intent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
184
android/appmgr/src/org/anbox/appmgr/AppsLoader.java
Normal file
184
android/appmgr/src/org/anbox/appmgr/AppsLoader.java
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright 2016 Arnab Chakraborty. http://arnab.ch
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
* software and associated documentation files (the "Software"), to deal in the Software
|
||||
* without restriction, including without limitation the rights to use, copy, modify,
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies
|
||||
* or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
|
||||
* THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package org.anbox.appmgr;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.support.v4.content.AsyncTaskLoader;
|
||||
|
||||
import java.text.Collator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Comparator;
|
||||
|
||||
/**
|
||||
* @credit http://developer.android.com/reference/android/content/AsyncTaskLoader.html
|
||||
*/
|
||||
public class AppsLoader extends AsyncTaskLoader<ArrayList<AppModel>> {
|
||||
ArrayList<AppModel> mInstalledApps;
|
||||
|
||||
final PackageManager mPm;
|
||||
PackageIntentReceiver mPackageObserver;
|
||||
|
||||
public AppsLoader(Context context) {
|
||||
super(context);
|
||||
|
||||
mPm = context.getPackageManager();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<AppModel> loadInBackground() {
|
||||
// retrieve the list of installed applications
|
||||
List<ApplicationInfo> apps = mPm.getInstalledApplications(0);
|
||||
|
||||
if (apps == null) {
|
||||
apps = new ArrayList<ApplicationInfo>();
|
||||
}
|
||||
|
||||
final Context context = getContext();
|
||||
|
||||
// create corresponding apps and load their labels
|
||||
ArrayList<AppModel> items = new ArrayList<AppModel>(apps.size());
|
||||
for (int i = 0; i < apps.size(); i++) {
|
||||
String pkg = apps.get(i).packageName;
|
||||
|
||||
// only apps which are launchable
|
||||
if (context.getPackageManager().getLaunchIntentForPackage(pkg) != null) {
|
||||
AppModel app = new AppModel(context, apps.get(i));
|
||||
app.loadLabel(context);
|
||||
items.add(app);
|
||||
}
|
||||
}
|
||||
|
||||
// sort the list
|
||||
Collections.sort(items, ALPHA_COMPARATOR);
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deliverResult(ArrayList<AppModel> apps) {
|
||||
if (isReset()) {
|
||||
// An async query came in while the loader is stopped. We
|
||||
// don't need the result.
|
||||
if (apps != null) {
|
||||
onReleaseResources(apps);
|
||||
}
|
||||
}
|
||||
|
||||
ArrayList<AppModel> oldApps = apps;
|
||||
mInstalledApps = apps;
|
||||
|
||||
if (isStarted()) {
|
||||
// If the Loader is currently started, we can immediately
|
||||
// deliver its results.
|
||||
super.deliverResult(apps);
|
||||
}
|
||||
|
||||
// At this point we can release the resources associated with
|
||||
// 'oldApps' if needed; now that the new result is delivered we
|
||||
// know that it is no longer in use.
|
||||
if (oldApps != null) {
|
||||
onReleaseResources(oldApps);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStartLoading() {
|
||||
if (mInstalledApps != null) {
|
||||
// If we currently have a result available, deliver it
|
||||
// immediately.
|
||||
deliverResult(mInstalledApps);
|
||||
}
|
||||
|
||||
// watch for changes in app install and uninstall operation
|
||||
if (mPackageObserver == null) {
|
||||
mPackageObserver = new PackageIntentReceiver(this);
|
||||
}
|
||||
|
||||
if (takeContentChanged() || mInstalledApps == null ) {
|
||||
// If the data has changed since the last time it was loaded
|
||||
// or is not currently available, start a load.
|
||||
forceLoad();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStopLoading() {
|
||||
// Attempt to cancel the current load task if possible.
|
||||
cancelLoad();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCanceled(ArrayList<AppModel> apps) {
|
||||
super.onCanceled(apps);
|
||||
|
||||
// At this point we can release the resources associated with 'apps'
|
||||
// if needed.
|
||||
onReleaseResources(apps);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onReset() {
|
||||
// Ensure the loader is stopped
|
||||
onStopLoading();
|
||||
|
||||
// At this point we can release the resources associated with 'apps'
|
||||
// if needed.
|
||||
if (mInstalledApps != null) {
|
||||
onReleaseResources(mInstalledApps);
|
||||
mInstalledApps = null;
|
||||
}
|
||||
|
||||
// Stop monitoring for changes.
|
||||
if (mPackageObserver != null) {
|
||||
getContext().unregisterReceiver(mPackageObserver);
|
||||
mPackageObserver = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to do the cleanup work if needed, for example if we're
|
||||
* using Cursor, then we should be closing it here
|
||||
*
|
||||
* @param apps
|
||||
*/
|
||||
protected void onReleaseResources(ArrayList<AppModel> apps) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Perform alphabetical comparison of application entry objects.
|
||||
*/
|
||||
public static final Comparator<AppModel> ALPHA_COMPARATOR = new Comparator<AppModel>() {
|
||||
private final Collator sCollator = Collator.getInstance();
|
||||
@Override
|
||||
public int compare(AppModel object1, AppModel object2) {
|
||||
return sCollator.compare(object1.getLabel(), object2.getLabel());
|
||||
}
|
||||
};
|
||||
}
|
||||
399
android/appmgr/src/org/anbox/appmgr/GridFragment.java
Normal file
399
android/appmgr/src/org/anbox/appmgr/GridFragment.java
Normal file
|
|
@ -0,0 +1,399 @@
|
|||
package org.anbox.appmgr;
|
||||
|
||||
/*
|
||||
* Created by Thomas Barrasso on 9/11/12.
|
||||
* Copyright (c) 2012 Loupe Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.GridView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ListAdapter;
|
||||
import android.widget.ListView;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
/**
|
||||
* Based on {@link android.app.ListFragment} but adapted for {@link GridView}.
|
||||
*/
|
||||
public class GridFragment extends Fragment {
|
||||
|
||||
static final int INTERNAL_EMPTY_ID = 0x00ff0001;
|
||||
static final int INTERNAL_PROGRESS_CONTAINER_ID = 0x00ff0002;
|
||||
static final int INTERNAL_LIST_CONTAINER_ID = 0x00ff0003;
|
||||
|
||||
final private Handler mHandler = new Handler();
|
||||
|
||||
final private Runnable mRequestFocus = new Runnable() {
|
||||
public void run() {
|
||||
mGrid.focusableViewAvailable(mGrid);
|
||||
}
|
||||
};
|
||||
|
||||
final private AdapterView.OnItemClickListener mOnClickListener
|
||||
= new AdapterView.OnItemClickListener() {
|
||||
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
|
||||
onGridItemClick((GridView) parent, v, position, id);
|
||||
}
|
||||
};
|
||||
|
||||
ListAdapter mAdapter;
|
||||
GridView mGrid;
|
||||
View mEmptyView;
|
||||
TextView mStandardEmptyView;
|
||||
View mProgressContainer;
|
||||
View mGridContainer;
|
||||
CharSequence mEmptyText;
|
||||
boolean mGridShown;
|
||||
|
||||
public GridFragment() { }
|
||||
|
||||
/**
|
||||
* Provide default implementation to return a simple grid view. Subclasses
|
||||
* can override to replace with their own layout. If doing so, the
|
||||
* returned view hierarchy <em>must</em> have a GridView whose id
|
||||
* is {@link android.R.id#list android.R.id.list} and can optionally
|
||||
* have a sibling view id {@link android.R.id#empty android.R.id.empty}
|
||||
* that is to be shown when the grid is empty.
|
||||
*
|
||||
* <p>If you are overriding this method with your own custom content,
|
||||
* consider including the standard layout {@link android.R.layout#list_content}
|
||||
* in your layout file, so that you continue to retain all of the standard
|
||||
* behavior of ListFragment. In particular, this is currently the only
|
||||
* way to have the built-in indeterminant progress state be shown.
|
||||
*/
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
final Context context = getActivity();
|
||||
|
||||
FrameLayout root = new FrameLayout(context);
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
LinearLayout pframe = new LinearLayout(context);
|
||||
pframe.setId(INTERNAL_PROGRESS_CONTAINER_ID);
|
||||
pframe.setOrientation(LinearLayout.VERTICAL);
|
||||
pframe.setVisibility(View.GONE);
|
||||
pframe.setGravity(Gravity.CENTER);
|
||||
|
||||
ProgressBar progress = new ProgressBar(context, null,
|
||||
android.R.attr.progressBarStyleLarge);
|
||||
pframe.addView(progress, new FrameLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
root.addView(pframe, new FrameLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
FrameLayout lframe = new FrameLayout(context);
|
||||
lframe.setId(INTERNAL_LIST_CONTAINER_ID);
|
||||
|
||||
TextView tv = new TextView(getActivity());
|
||||
tv.setId(INTERNAL_EMPTY_ID);
|
||||
tv.setGravity(Gravity.CENTER);
|
||||
lframe.addView(tv, new FrameLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
|
||||
|
||||
GridView lv = new GridView(getActivity());
|
||||
lv.setId(android.R.id.list);
|
||||
lv.setDrawSelectorOnTop(false);
|
||||
lv.setColumnWidth(convertDpToPixels(60, getActivity()));
|
||||
lv.setStretchMode(GridView.STRETCH_COLUMN_WIDTH);
|
||||
lv.setNumColumns(GridView.AUTO_FIT);
|
||||
lv.setHorizontalSpacing(convertDpToPixels(20, getActivity()));
|
||||
lv.setVerticalSpacing(convertDpToPixels(20, getActivity()));
|
||||
lv.setSmoothScrollbarEnabled(true);
|
||||
|
||||
// disable overscroll
|
||||
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
|
||||
lv.setOverScrollMode(ListView.OVER_SCROLL_NEVER);
|
||||
}
|
||||
|
||||
lframe.addView(lv, new FrameLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
|
||||
|
||||
root.addView(lframe, new FrameLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
root.setLayoutParams(new FrameLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach to grid view once the view hierarchy has been created.
|
||||
*/
|
||||
@Override
|
||||
public void onViewCreated(View view, Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
ensureGrid();
|
||||
}
|
||||
|
||||
/**
|
||||
* Detach from {@link GridView}
|
||||
*/
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
mHandler.removeCallbacks(mRequestFocus);
|
||||
mGrid = null;
|
||||
mGridShown = false;
|
||||
mEmptyView = mProgressContainer = mGridContainer = null;
|
||||
mStandardEmptyView = null;
|
||||
super.onDestroyView();
|
||||
}
|
||||
|
||||
public static int convertDpToPixels(float dp, Context context){
|
||||
Resources resources = context.getResources();
|
||||
return (int) TypedValue.applyDimension(
|
||||
TypedValue.COMPLEX_UNIT_DIP,
|
||||
dp,
|
||||
resources.getDisplayMetrics()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will be called when an item in the grid is selected.
|
||||
* Subclasses should override. Subclasses can call
|
||||
* getGridView().getItemAtPosition(position) if they need to access the
|
||||
* data associated with the selected item.
|
||||
*
|
||||
* @param g The {@link GridView} where the click happened
|
||||
* @param v The view that was clicked within the {@link GridView}
|
||||
* @param position The position of the view in the grid
|
||||
* @param id The row id of the item that was clicked
|
||||
*/
|
||||
public void onGridItemClick(GridView g, View v, int position, long id) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide the cursor for the {@link GridView}.
|
||||
*/
|
||||
public void setGridAdapter(ListAdapter adapter) {
|
||||
final boolean hadAdapter = (mAdapter != null);
|
||||
mAdapter = adapter;
|
||||
if (mGrid != null) {
|
||||
mGrid.setAdapter(adapter);
|
||||
if (!mGridShown && !hadAdapter) {
|
||||
// The grid was hidden, and previously didn't have an
|
||||
// adapter. It is now time to show it.
|
||||
setGridShown(true, (getView().getWindowToken() != null));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the currently selected grid item to the specified
|
||||
* position with the adapter's data
|
||||
*
|
||||
* @param position
|
||||
*/
|
||||
public void setSelection(int position) {
|
||||
ensureGrid();
|
||||
mGrid.setSelection(position);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the position of the currently selected grid item.
|
||||
*/
|
||||
public int getSelectedItemPosition() {
|
||||
ensureGrid();
|
||||
return mGrid.getSelectedItemPosition();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the cursor row ID of the currently selected grid item.
|
||||
*/
|
||||
public long getSelectedItemId() {
|
||||
ensureGrid();
|
||||
return mGrid.getSelectedItemId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the activity's {@link GridView} widget.
|
||||
*/
|
||||
public GridView getGridView() {
|
||||
ensureGrid();
|
||||
return mGrid;
|
||||
}
|
||||
|
||||
/**
|
||||
* The default content for a ListFragment has a TextView that can
|
||||
* be shown when the grid is empty. If you would like to have it
|
||||
* shown, call this method to supply the text it should use.
|
||||
*/
|
||||
public void setEmptyText(CharSequence text) {
|
||||
ensureGrid();
|
||||
if (mStandardEmptyView == null) {
|
||||
throw new IllegalStateException("Can't be used with a custom content view");
|
||||
}
|
||||
mStandardEmptyView.setText(text);
|
||||
if (mEmptyText == null) {
|
||||
mGrid.setEmptyView(mStandardEmptyView);
|
||||
}
|
||||
mEmptyText = text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Control whether the grid is being displayed. You can make it not
|
||||
* displayed if you are waiting for the initial data to show in it. During
|
||||
* this time an indeterminant progress indicator will be shown instead.
|
||||
*
|
||||
* <p>Applications do not normally need to use this themselves. The default
|
||||
* behavior of ListFragment is to start with the grid not being shown, only
|
||||
* showing it once an adapter is given with {@link #setGridAdapter(ListAdapter)}.
|
||||
* If the grid at that point had not been shown, when it does get shown
|
||||
* it will be do without the user ever seeing the hidden state.
|
||||
*
|
||||
* @param shown If true, the grid view is shown; if false, the progress
|
||||
* indicator. The initial value is true.
|
||||
*/
|
||||
public void setGridShown(boolean shown) {
|
||||
setGridShown(shown, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Like {@link #setGridShown(boolean)}, but no animation is used when
|
||||
* transitioning from the previous state.
|
||||
*/
|
||||
public void setGridShownNoAnimation(boolean shown) {
|
||||
setGridShown(shown, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Control whether the grid is being displayed. You can make it not
|
||||
* displayed if you are waiting for the initial data to show in it. During
|
||||
* this time an indeterminant progress indicator will be shown instead.
|
||||
*
|
||||
* @param shown If true, the grid view is shown; if false, the progress
|
||||
* indicator. The initial value is true.
|
||||
* @param animate If true, an animation will be used to transition to the
|
||||
* new state.
|
||||
*/
|
||||
private void setGridShown(boolean shown, boolean animate) {
|
||||
ensureGrid();
|
||||
if (mProgressContainer == null) {
|
||||
throw new IllegalStateException("Can't be used with a custom content view");
|
||||
}
|
||||
if (mGridShown == shown) {
|
||||
return;
|
||||
}
|
||||
mGridShown = shown;
|
||||
if (shown) {
|
||||
if (animate) {
|
||||
mProgressContainer.startAnimation(AnimationUtils.loadAnimation(
|
||||
getActivity(), android.R.anim.fade_out));
|
||||
mGridContainer.startAnimation(AnimationUtils.loadAnimation(
|
||||
getActivity(), android.R.anim.fade_in));
|
||||
} else {
|
||||
mProgressContainer.clearAnimation();
|
||||
mGridContainer.clearAnimation();
|
||||
}
|
||||
mProgressContainer.setVisibility(View.GONE);
|
||||
mGridContainer.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
if (animate) {
|
||||
mProgressContainer.startAnimation(AnimationUtils.loadAnimation(
|
||||
getActivity(), android.R.anim.fade_in));
|
||||
mGridContainer.startAnimation(AnimationUtils.loadAnimation(
|
||||
getActivity(), android.R.anim.fade_out));
|
||||
} else {
|
||||
mProgressContainer.clearAnimation();
|
||||
mGridContainer.clearAnimation();
|
||||
}
|
||||
mProgressContainer.setVisibility(View.VISIBLE);
|
||||
mGridContainer.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ListAdapter associated with this activity's {@link GridView}.
|
||||
*/
|
||||
public ListAdapter getGridAdapter() {
|
||||
return mAdapter;
|
||||
}
|
||||
|
||||
private void ensureGrid() {
|
||||
if (mGrid != null) {
|
||||
return;
|
||||
}
|
||||
View root = getView();
|
||||
if (root == null) {
|
||||
throw new IllegalStateException("Content view not yet created");
|
||||
}
|
||||
if (root instanceof GridView) {
|
||||
mGrid = (GridView) root;
|
||||
} else {
|
||||
mStandardEmptyView = (TextView)root.findViewById(INTERNAL_EMPTY_ID);
|
||||
if (mStandardEmptyView == null) {
|
||||
mEmptyView = root.findViewById(android.R.id.empty);
|
||||
} else {
|
||||
mStandardEmptyView.setVisibility(View.GONE);
|
||||
}
|
||||
mProgressContainer = root.findViewById(INTERNAL_PROGRESS_CONTAINER_ID);
|
||||
mGridContainer = root.findViewById(INTERNAL_LIST_CONTAINER_ID);
|
||||
View rawGridView = root.findViewById(android.R.id.list);
|
||||
if (!(rawGridView instanceof GridView)) {
|
||||
if (rawGridView == null) {
|
||||
throw new RuntimeException(
|
||||
"Your content must have a GridView whose id attribute is " +
|
||||
"'android.R.id.list'");
|
||||
}
|
||||
throw new RuntimeException(
|
||||
"Content has view with id attribute 'android.R.id.list' "
|
||||
+ "that is not a GridView class");
|
||||
}
|
||||
mGrid = (GridView) rawGridView;
|
||||
if (mEmptyView != null) {
|
||||
mGrid.setEmptyView(mEmptyView);
|
||||
} else if (mEmptyText != null) {
|
||||
mStandardEmptyView.setText(mEmptyText);
|
||||
mGrid.setEmptyView(mStandardEmptyView);
|
||||
}
|
||||
}
|
||||
mGridShown = true;
|
||||
mGrid.setOnItemClickListener(mOnClickListener);
|
||||
if (mAdapter != null) {
|
||||
ListAdapter adapter = mAdapter;
|
||||
mAdapter = null;
|
||||
setGridAdapter(adapter);
|
||||
} else {
|
||||
// We are starting without an adapter, so assume we won't
|
||||
// have our data right away and start with the progress indicator.
|
||||
if (mProgressContainer != null) {
|
||||
setGridShown(false, false);
|
||||
}
|
||||
}
|
||||
mHandler.post(mRequestFocus);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright 2016 Arnab Chakraborty. http://arnab.ch
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
* software and associated documentation files (the "Software"), to deal in the Software
|
||||
* without restriction, including without limitation the rights to use, copy, modify,
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies
|
||||
* or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
|
||||
* THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package org.anbox.appmgr;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
|
||||
/**
|
||||
* Helper class to look for interesting changes to the installed apps
|
||||
* so that the loader can be updated.
|
||||
*
|
||||
* @Credit http://developer.android.com/reference/android/content/AsyncTaskLoader.html
|
||||
*/
|
||||
public class PackageIntentReceiver extends BroadcastReceiver {
|
||||
|
||||
final AppsLoader mLoader;
|
||||
|
||||
public PackageIntentReceiver(AppsLoader loader) {
|
||||
mLoader = loader;
|
||||
|
||||
IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
|
||||
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
|
||||
filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
|
||||
filter.addDataScheme("package");
|
||||
mLoader.getContext().registerReceiver(this, filter);
|
||||
|
||||
// Register for events related to sdcard installation.
|
||||
IntentFilter sdFilter = new IntentFilter();
|
||||
sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
|
||||
sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
|
||||
mLoader.getContext().registerReceiver(this, sdFilter);
|
||||
}
|
||||
|
||||
@Override public void onReceive(Context context, Intent intent) {
|
||||
// Tell the loader about the change.
|
||||
mLoader.onContentChanged();
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue