com.github.michalbednarski.intentslab.editor.ComponentPickerDialogFragment.java Source code

Java tutorial

Introduction

Here is the source code for com.github.michalbednarski.intentslab.editor.ComponentPickerDialogFragment.java

Source

/*
 * IntentsLab - Android app for playing with Intents and Binder IPC
 * Copyright (C) 2014 Micha Bednarski
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY 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 com.github.michalbednarski.intentslab.editor;

import android.app.Dialog;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import com.github.michalbednarski.intentslab.R;
import com.github.michalbednarski.intentslab.SingleFragmentActivity;
import com.github.michalbednarski.intentslab.Utils;
import com.github.michalbednarski.intentslab.browser.ComponentInfoFragment;

import java.util.ArrayList;
import java.util.List;

/**
 * Fragment for choosing component for intent
 *
 * Must be in {@link IntentEditorActivity}
 * and have target fragment set to {@link IntentGeneralFragment}
 */
public class ComponentPickerDialogFragment extends DialogFragment
        implements OnItemClickListener, OnItemLongClickListener {

    private ResolveInfo[] mChoices;
    private int mEnabledChoicesCount;

    public ComponentPickerDialogFragment() {
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(true);

        // Get edited intent
        IntentEditorActivity intentEditor = (IntentEditorActivity) getActivity();
        Intent intent = new Intent(intentEditor.getEditedIntent());
        intent.setComponent(null);

        // Get components
        PackageManager pm = intentEditor.getPackageManager();
        List<ResolveInfo> ri = null;

        switch (intentEditor.getComponentType()) {
        case IntentEditorConstants.ACTIVITY:
            ri = pm.queryIntentActivities(intent, PackageManager.GET_DISABLED_COMPONENTS);
            break;
        case IntentEditorConstants.BROADCAST:
            ri = pm.queryBroadcastReceivers(intent, PackageManager.GET_DISABLED_COMPONENTS);
            break;
        case IntentEditorConstants.SERVICE:
            ri = pm.queryIntentServices(intent, PackageManager.GET_DISABLED_COMPONENTS);
            break;
        }

        // Cancel if no components
        if (ri.isEmpty()) {
            Toast.makeText(getActivity(), R.string.no_matching_components_found, Toast.LENGTH_SHORT).show();
            dismiss();
            return;
        }

        // Split enabled and disabled choices
        ArrayList<ResolveInfo> choices = new ArrayList<ResolveInfo>();
        ArrayList<ResolveInfo> disabledChoices = new ArrayList<ResolveInfo>();
        for (ResolveInfo resolveInfo : ri) {
            (isComponentEnabled(pm, resolveInfo) ? choices : disabledChoices).add(resolveInfo);
        }

        mEnabledChoicesCount = choices.size();
        choices.addAll(disabledChoices);
        mChoices = choices.toArray(new ResolveInfo[choices.size()]);
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        Dialog dialog = super.onCreateDialog(savedInstanceState);
        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
        return dialog;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        // Abort if nothing found, onCreate called dismiss()
        if (mChoices == null) {
            return null;
        }

        // Create list
        ListView lv = new ListView(getActivity(), null);
        lv.setId(android.R.id.list);
        lv.setAdapter(new Adapter());
        Utils.fixListViewInDialogBackground(lv);
        lv.setOnItemClickListener(this);
        lv.setOnItemLongClickListener(this);
        return lv;
    }

    private String getComponentName(ResolveInfo info) {
        boolean isService = info.activityInfo == null;
        return new ComponentName(isService ? info.serviceInfo.packageName : info.activityInfo.packageName,
                isService ? info.serviceInfo.name : info.activityInfo.name).flattenToShortString();
    }

    private static boolean isComponentEnabled(PackageManager pm, ResolveInfo info) {
        final boolean defaultEnabled;
        final ComponentName componentName;

        ActivityInfo activityInfo = info.activityInfo;
        if (activityInfo != null) {
            if (!activityInfo.applicationInfo.enabled) {
                return false;
            }
            defaultEnabled = activityInfo.enabled;
            componentName = new ComponentName(activityInfo.packageName, activityInfo.name);
        } else {
            ServiceInfo serviceInfo = info.serviceInfo;
            if (!serviceInfo.applicationInfo.enabled) {
                return false;
            }
            defaultEnabled = serviceInfo.enabled;
            componentName = new ComponentName(serviceInfo.packageName, serviceInfo.name);
        }

        int enabledSetting = pm.getComponentEnabledSetting(componentName);
        if (enabledSetting == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
            return defaultEnabled;
        } else {
            return enabledSetting != PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
        }
    }

    private class Adapter extends ArrayAdapter<ResolveInfo> {
        private LayoutInflater mInflater;
        private PackageManager mPm;

        Adapter() {
            super(getActivity(), 0, mChoices);
            FragmentActivity activity = getActivity();
            mInflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            mPm = activity.getPackageManager();
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            if (convertView == null) {
                convertView = mInflater.inflate(R.layout.simple_list_item_2_with_icon, parent, false);
            }

            ResolveInfo info = getItem(position);
            ((TextView) convertView.findViewById(android.R.id.text1)).setText(info.loadLabel(mPm));
            ((TextView) convertView.findViewById(android.R.id.text2)).setText(getComponentName(info));

            ((ImageView) convertView.findViewById(R.id.app_icon)).setImageDrawable(info.loadIcon(mPm));

            setTextViewsEnabled(convertView, position < mEnabledChoicesCount);

            return convertView;
        }
    }

    /**
     * Fill component name field on item click
     */
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        ((IntentGeneralFragment) getTargetFragment()).setComponentText(getComponentName(mChoices[position]));
        dismiss();
    }

    /**
     * Show item info on long click
     */
    @Override
    public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
        ResolveInfo info = mChoices[position];
        boolean isService = info.activityInfo == null;
        startActivity(new Intent(getActivity(), SingleFragmentActivity.class)
                .putExtra(SingleFragmentActivity.EXTRA_FRAGMENT, ComponentInfoFragment.class.getName())
                .putExtra(ComponentInfoFragment.ARG_PACKAGE_NAME,
                        isService ? info.serviceInfo.packageName : info.activityInfo.packageName)
                .putExtra(ComponentInfoFragment.ARG_COMPONENT_NAME,
                        isService ? info.serviceInfo.name : info.activityInfo.name)
                .putExtra(ComponentInfoFragment.ARG_LAUNCHED_FROM_INTENT_EDITOR, true));
        return true;
    }

    private static void setTextViewsEnabled(View v, boolean enabled) {
        if (v instanceof TextView) {
            v.setEnabled(enabled);
        }

        if (v instanceof ViewGroup) {
            final ViewGroup vg = (ViewGroup) v;
            for (int i = vg.getChildCount() - 1; i >= 0; i--) {
                setTextViewsEnabled(vg.getChildAt(i), enabled);
            }
        }
    }
}