com.google.android.apps.dashclock.configuration.PackageChooserPreference.java Source code

Java tutorial

Introduction

Here is the source code for com.google.android.apps.dashclock.configuration.PackageChooserPreference.java

Source

/*
 * Copyright 2013 Google 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.
 */

package com.google.android.apps.dashclock.configuration;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.preference.Preference;
import android.support.v4.view.ViewPager;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.Checkable;
import android.widget.CheckedTextView;
import android.widget.CompoundButton;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

import com.google.android.apps.dashclock.ui.SimplePagedTabsHelper;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import me.barrasso.android.volume.LogUtils;
import me.barrasso.android.volume.R;

/**
 * A preference that allows the user to choose a set of applications.
 */
public class PackageChooserPreference extends Preference {

    public PackageChooserPreference(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public PackageChooserPreference(Context context) {
        super(context);
    }

    public PackageChooserPreference(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    private static final TextUtils.SimpleStringSplitter COLON_SPLITTER = new TextUtils.SimpleStringSplitter(':');

    public void setPackages(Set<String> packages) {
        if (null == packages) {
            setValue("");
            return;
        }
        setValue((packages.size() == 0) ? "" : TextUtils.join(":", packages));
    }

    public Set<String> getPackages(String value, String defaultValue) {
        String listVal = value;
        if (TextUtils.isEmpty(value)) {
            listVal = defaultValue;
        }

        Set<String> packages = new HashSet<String>();
        TextUtils.SimpleStringSplitter splitter = COLON_SPLITTER;
        splitter.setString(listVal);
        while (splitter.hasNext()) {
            packages.add(splitter.next());
        }

        return packages;
    }

    public Set<String> getPackages() {
        return getPackages(getPersistedString(""), "");
    }

    public void setValue(String value) {
        if (callChangeListener(value)) {
            persistString(value);
            notifyChanged();
        }
    }

    @Override
    protected void onClick() {
        super.onClick();

        AppChooserDialogFragment fragment = AppChooserDialogFragment.newInstance();
        fragment.setPreference(this);

        Activity activity = (Activity) getContext();
        activity.getFragmentManager().beginTransaction().add(fragment, getFragmentTag()).commit();
    }

    @Override
    protected void onAttachedToActivity() {
        super.onAttachedToActivity();

        Activity activity = (Activity) getContext();
        AppChooserDialogFragment fragment = (AppChooserDialogFragment) activity.getFragmentManager()
                .findFragmentByTag(getFragmentTag());
        if (fragment != null) {
            // re-bind preference to fragment
            fragment.setPreference(this);
        }
    }

    @Override
    protected Object onGetDefaultValue(TypedArray a, int index) {
        return a.getString(index);
    }

    @Override
    protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
        setValue(restoreValue ? getPersistedString("") : (String) defaultValue);
    }

    public String getFragmentTag() {
        return "app_chooser_" + getKey();
    }

    public static class AppChooserDialogFragment extends DialogFragment {
        public static int REQUEST_CREATE_SHORTCUT = 1;

        private PackageChooserPreference mPreference;
        private Set<String> appPackages;

        private ActivityListAdapter mAppsAdapter;

        private ListView mAppsList;

        public AppChooserDialogFragment() {
        }

        public static AppChooserDialogFragment newInstance() {
            return new AppChooserDialogFragment();
        }

        public void setPreference(PackageChooserPreference preference) {
            mPreference = preference;
            tryBindLists();
            appPackages = mPreference.getPackages();
        }

        @Override
        public void onAttach(Activity activity) {
            super.onAttach(activity);
            tryBindLists();
        }

        static DialogInterface.OnClickListener dismissListener = new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                dialogInterface.dismiss();
            }
        };

        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            // Force Holo Light since ?android:actionBarXX would use dark action bar
            Context layoutContext = new ContextThemeWrapper(getActivity(), android.R.style.Theme_Holo_Light);

            LayoutInflater layoutInflater = LayoutInflater.from(layoutContext);
            View rootView = layoutInflater.inflate(R.layout.dialog_app_chooser, null);
            final ViewGroup tabWidget = (ViewGroup) rootView.findViewById(android.R.id.tabs);
            final ViewPager pager = (ViewPager) rootView.findViewById(R.id.pager);
            pager.setPageMargin((int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 16,
                    getResources().getDisplayMetrics()));

            SimplePagedTabsHelper helper = new SimplePagedTabsHelper(layoutContext, tabWidget, pager);
            helper.addTab(R.string.title_apps, R.id.apps_list);

            // Set up apps
            mAppsList = (ListView) rootView.findViewById(R.id.apps_list);
            mAppsList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> listView, View view, int position, long itemId) {
                    Log.i("PackageChooserPreference", "onItemClick(" + position + ")");
                    String appPackage = mAppsAdapter.getPackageName(position);
                    Checkable checker = (Checkable) view;
                    checker.setChecked(!checker.isChecked());
                    if (checker.isChecked()) {
                        appPackages.add(appPackage);
                    } else {
                        appPackages.remove(appPackage);
                    }
                    mPreference.setPackages(appPackages);
                }
            });

            tryBindLists();

            return new AlertDialog.Builder(getActivity()).setView(rootView)
                    .setPositiveButton(android.R.string.ok, dismissListener).create();
        }

        private void tryBindLists() {
            if (mPreference == null) {
                return;
            }

            if (isAdded() && mAppsAdapter == null) {
                mAppsAdapter = new ActivityListAdapter(
                        new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_LAUNCHER));
            }

            if (mAppsAdapter != null && mAppsList != null) {
                mAppsList.setAdapter(mAppsAdapter);
            }
        }

        static class ActivityInfo {
            CharSequence label;
            Drawable icon;
            ComponentName componentName;
        }

        private class ActivityListAdapter extends BaseAdapter {
            private Intent mQueryIntent;
            private LayoutInflater inflater;
            private List<ActivityInfo> mInfos;

            private ActivityListAdapter(Intent queryIntent) {
                mQueryIntent = queryIntent;
                inflater = LayoutInflater.from(getActivity());
                PackageManager mPackageManager = getActivity().getPackageManager();

                mInfos = new ArrayList<ActivityInfo>();
                List<ResolveInfo> resolveInfos = mPackageManager.queryIntentActivities(queryIntent, 0);
                for (ResolveInfo ri : resolveInfos) {
                    ActivityInfo ai = new ActivityInfo();
                    try {
                        ai.icon = ri.loadIcon(mPackageManager);
                    } catch (OutOfMemoryError ome) {
                        LogUtils.LOGE("AppChooserPreference", "Ran out of memory displaying icon.", ome);
                    }
                    ai.label = ri.loadLabel(mPackageManager);
                    ai.componentName = new ComponentName(ri.activityInfo.packageName, ri.activityInfo.name);
                    mInfos.add(ai);
                }

                // Make sure to sort by alphabetical order (not comparing capitalization).
                Collections.sort(mInfos, new Comparator<ActivityInfo>() {
                    @Override
                    public int compare(ActivityInfo activityInfo, ActivityInfo activityInfo2) {
                        return String.valueOf(activityInfo.label).toUpperCase()
                                .compareTo(String.valueOf(activityInfo2.label).toUpperCase());
                    }
                });
            }

            @Override
            public int getCount() {
                return mInfos.size();
            }

            @Override
            public boolean isEnabled(int position) {
                return true;
            }

            @Override
            public boolean areAllItemsEnabled() {
                return true;
            }

            @Override
            public Object getItem(int position) {
                return mInfos.get(position);
            }

            public String getPackageName(int position) {
                return mInfos.get(position).componentName.getPackageName();
            }

            public Intent getIntent(int position) {
                return new Intent(mQueryIntent).setComponent(mInfos.get(position).componentName);
            }

            @Override
            public long getItemId(int position) {
                return mInfos.get(position).componentName.hashCode();
            }

            @Override
            public View getView(int position, View convertView, ViewGroup container) {
                if (convertView == null) {
                    convertView = inflater.inflate(R.layout.list_item_intent_check, container, false);
                }

                ActivityInfo ai = mInfos.get(position);
                TextView title = (TextView) convertView;
                title.setText(ai.label);
                int iconSize = Resources.getSystem().getDimensionPixelSize(android.R.dimen.app_icon_size);
                ai.icon.setBounds(0, 0, iconSize, iconSize);
                title.setCompoundDrawablesRelative(ai.icon, null, null, null);

                if (title instanceof Checkable) {
                    Checkable checker = (Checkable) title;
                    checker.setChecked(appPackages.contains(ai.componentName.getPackageName()));
                }

                return convertView;
            }
        }
    }
}