Android Open Source - permissions Perm List Fragment






From Project

Back to project page permissions.

License

The source code is released under:

MIT License

If you think the Android project permissions listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package com.tellmas.android.permissions;
/*from   ww  w  .  j a  v  a2  s.c om*/
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import android.app.Activity;
import android.app.ListFragment;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PermissionInfo;
import android.content.pm.ResolveInfo;
import android.content.res.Resources.NotFoundException;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ExpandableListView;

import com.tellmas.android.permissions.AppListFragment.AppListFragmentListener;

/**
 * Fragment for the content View.
 * For installed apps with a launcher, obtains the permissions requested by said apps.
 * Displays:
 *   - each permission with its description
 *   - each app which requested it along with that app's label, icon and package
 */
public class PermListFragment extends ListFragment {

    private ArrayList<com.tellmas.android.permissions.PermissionInfo> thePermList;

    private Activity parentActivity;
    private AppListFragmentListener parentActivityListener;

    private ExpandableListView permListView;


    /**
     * Sets up the connection for callbacks to the parent Activity.
     *
     * @param activity the containing Activity
     * @throws ClassCastException
     * @see android.app.Fragment#onAttach(android.app.Activity)
     */
    @Override
    public void onAttach(Activity activity) {
        if (GlobalDefines.LOG_LOCAL) {
            Log.i(GlobalDefines.LOG_TAG, this.getClass().getSimpleName() + ": onAttach()");
        }
        super.onAttach(activity);

        try {
            this.parentActivityListener = (AppListFragmentListener) activity;
        } catch (ClassCastException cce) {
            throw new ClassCastException(activity.getClass().getName() + " did not implement PermListFragmentListener");
        }
    }


    /**
     * @param savedInstanceState data to start with
     * @see android.app.Fragment#onCreate(android.os.Bundle)
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        if (GlobalDefines.LOG_LOCAL) {
            Log.i(GlobalDefines.LOG_TAG, this.getClass().getSimpleName() + ": onCreate()");
        }
        super.onCreate(savedInstanceState);

        this.parentActivity = this.getActivity();

        if (savedInstanceState != null) {
            this.thePermList = savedInstanceState.getParcelableArrayList(GlobalDefines.BUNDLE_KEY_FOR_PERM_LIST);
        }
    }


    /**
     * Instantiates this Fragment's View.
     *
     * @param inflater the LayoutInflater object that can be used to inflate any views in the fragment
     * @param container the parent view that this fragment's UI should be attached to
     * @param savedInstanceState data used to restore the previous state
     * @return the main View for this Fragment
     * @see android.app.ListFragment#onCreateView(android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle)
     */
    @Override
    public View onCreateView(
            LayoutInflater inflater,
            ViewGroup container,
            Bundle savedInstanceState
    ) {
        if (GlobalDefines.LOG_LOCAL) {
            Log.i(GlobalDefines.LOG_TAG, this.getClass().getSimpleName() + ": onCreateView()");
        }
        super.onCreateView(inflater, container, savedInstanceState);

        return inflater.inflate(R.layout.fragment_permlist_layout, container, false);
    }


    /**
     * Sets up the main View for this Fragment and kicks off filling it with the data.
     * Also, kicks off the gathering of that data if needed.
     *
     * @param savedInstanceState data used to restore the previous state
     * @see android.app.Fragment#onActivityCreated(android.os.Bundle)
     */
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        if (GlobalDefines.LOG_LOCAL) {
            Log.i(GlobalDefines.LOG_TAG, this.getClass().getSimpleName() + ": onActivityCreated()");
        }
        super.onActivityCreated(savedInstanceState);

        this.permListView = (ExpandableListView) this.getView().findViewById(R.id.perms_list);

        if (this.thePermList == null) {
            this.getTheDataAndDisplayIt();
        } else {
            this.displayTheResults();
        }

        if (this.getRetainInstance() == true) {
            this.setRetainInstance(false);
        }
    }


    /**
     * Bundles up the list of apps and their data.
     *
     * @param outState where to store the data that will be restored later
     * @see android.app.Fragment#onSaveInstanceState(android.os.Bundle)
     */
    @Override
    public void onSaveInstanceState(Bundle outState) {
        if (GlobalDefines.LOG_LOCAL) {
            Log.i(GlobalDefines.LOG_TAG, this.getClass().getSimpleName() + ": onSaveInstanceState()");
        }
        super.onSaveInstanceState(outState);

        outState.putParcelableArrayList(GlobalDefines.BUNDLE_KEY_FOR_PERM_LIST, this.thePermList);
    }


    /**
     * Executes the AsyncTask inner-class.
     */
    public void getTheDataAndDisplayIt() {
        GetThePermsAsyncTask getThePerms = new GetThePermsAsyncTask();
        getThePerms.execute(this.parentActivity);
    }


    /*
     * Uses an expanded BaseExpandableListAdapter to display the permissions and the apps that request them.
     *
     * (non-Javadoc)
     */
    private void displayTheResults() {

        int numberOfApps = 0;
        try {
            numberOfApps = this.thePermList.size();

            // === Display all the permissions ===
            PermListExpandableListAdapter permListAdapter = new PermListExpandableListAdapter(this.parentActivity, this.thePermList);
            this.permListView.setAdapter(permListAdapter);
        // if 'this.thePermList' was null...
        } catch (NullPointerException npe) {
            Log.e(GlobalDefines.LOG_TAG, this.getClass().getSimpleName() + ": the list of permissions was null", npe);
        } finally {
            this.parentActivityListener.setFinished(numberOfApps, GlobalDefines.LIST_TYPE_PERMS);
        }
    }


    /* Uses an expanded BaseExpandableListAdapter to display the permissions and their apps.
     *
     * @param theList an ArrayList<ApplicationInfo> of the permissions
     * (non-Javadoc)
     */
    private void finalizeTheResults(ArrayList<com.tellmas.android.permissions.PermissionInfo> theList) {
        this.thePermList = theList;
        this.displayTheResults();
    }


    /*
     * Calls the parent Activity's callback to update the progress.
     *
     * @param soFar how far along the app list we are
     * @param total total number of apps in the list
     * (non-Javadoc)
     */
    private void setProgress(int soFar, int total) {
        this.parentActivityListener.updateProgress(soFar, total);
    }


    // -------------------------------------------------------------------------
    /**
     * Interface of callbacks to the containing Activity (which the containing
     *   Activity must implement).
     */
    public interface PermListFragmentListener {
        public void updateProgress(int soFar, int total);
        public void setFinished(int numOfApps, int itemType);
    }


    // -------------------------------------------------------------------------
    /* AsyncTask which obtains info on all the permissions which are requested
     *   by the apps on the device (which have a launcher)
     * @param contexts a single element array containing the outer class's instance (i.e. 'this')
     * @return a List<PermissionInfo> containing all the permissions
     * (non-Javadoc)
     */
    private class GetThePermsAsyncTask extends AsyncTask<Activity, Integer, ArrayList<com.tellmas.android.permissions.PermissionInfo>> {

        @Override
        protected ArrayList<com.tellmas.android.permissions.PermissionInfo> doInBackground(Activity... contexts) {

            final Activity context = contexts[0];
            final PackageManager pm = context.getPackageManager();
            Integer[] progress = {Integer.valueOf(0), Integer.valueOf(0)};

            // === List of apps which have a Launcher ===
            final Intent intentFilter = new Intent(Intent.ACTION_MAIN, null);
            intentFilter.addCategory(Intent.CATEGORY_LAUNCHER);
            final List<ResolveInfo> resolveInfoList = pm.queryIntentActivities(intentFilter, 0);

            // The permissions with corresponding apps.
            Map<String,HashSet<String>> permissionsWithTheirApps = new HashMap<String,HashSet<String>>();
            // === Iterate through the found apps to get their requested permissions. ===
            int appsFoundNum = resolveInfoList.size();
            for (int i=0; i < appsFoundNum; i++) {

                if (this.isCancelled()) {
                    return null;
                }

                // --- Get the package info. ---
                PackageInfo packageInfo = null;
                String packageName = null;
                try {
                    // Get the package name of an app found earlier.
                    try {
                        packageName = resolveInfoList.get(i).activityInfo.packageName;
                    // if no ActivityInfo...
                    } catch (NullPointerException npe) {
                        Log.w(GlobalDefines.LOG_TAG, this.getClass().getSimpleName() + ": No ActivityInfo for this ResolveInfo: " + resolveInfoList.get(i).toString() + ". Excluded from listing.");
                        // ...skip it.
                        continue;
                    }
                    packageInfo = pm.getPackageInfo(packageName, PackageManager.GET_PERMISSIONS);
                // if the package wasn't found on the system...
                } catch (NameNotFoundException nnfe) {
                    if (GlobalDefines.LOG_LOCAL) {
                        Log.e(GlobalDefines.LOG_TAG, this.getClass().getSimpleName() + ": " + packageName + " wasn't found on the system.");
                    }
                    // ...skip it.
                    continue;
                    /* This really shouldn't happen though, because the same
                     * package manager was used to get the list of activities. */
                }
                if (GlobalDefines.LOG_LOCAL) {
                    Log.v(GlobalDefines.LOG_TAG, this.getClass().getSimpleName() + ": " + packageName);
                }

                // === get the requested permissions for this app ===
                String[] permsRequestedByThisApp = packageInfo.requestedPermissions;
                // if this app requests one or more permissions...
                if (permsRequestedByThisApp != null) {
                    if (GlobalDefines.LOG_LOCAL) {
                        Log.v(GlobalDefines.LOG_TAG, this.getClass().getSimpleName() + ": requested permissions array length: " + Integer.toString(permsRequestedByThisApp.length));
                    }

                    // === Iterate through the permissions requested by the current app. ===
                    for (String perm : permsRequestedByThisApp) {

                        if (GlobalDefines.LOG_LOCAL) {
                            Log.v(GlobalDefines.LOG_TAG, this.getClass().getSimpleName() + ": current permission: " + perm);
                        }

                        if (this.isCancelled()) {
                            return null;
                        }

                        // Get the set of apps that requested this permission.
                        HashSet<String> appsForThisPermission = (HashSet<String>) permissionsWithTheirApps.get(perm);
                        try {
                            // if the app was not already listed...
                            if (!appsForThisPermission.contains(packageName)) {
                                // ...add it.
                                appsForThisPermission.add(packageName);
                                permissionsWithTheirApps.put(perm, appsForThisPermission);
                                if (GlobalDefines.LOG_LOCAL) {
                                    Log.v(GlobalDefines.LOG_TAG, this.getClass().getSimpleName() + ": Adding " + packageName + " to " + perm);
                                }
                            }
                            // else... this else case shouldn't happen.
                            // We're iterating through the apps, so this is the first time we've encountered this app.

                        // if we haven't encountered this permission yet...
                        } catch (NullPointerException npe) {
                            appsForThisPermission = new HashSet<String>();
                            appsForThisPermission.add(packageName);
                            permissionsWithTheirApps.put(perm, appsForThisPermission);
                            if (GlobalDefines.LOG_LOCAL) {
                                Log.v(GlobalDefines.LOG_TAG, this.getClass().getSimpleName() + ": First time encountering: " + perm + ". Adding it to the list.");
                                Log.v(GlobalDefines.LOG_TAG, this.getClass().getSimpleName() + ": Adding " + packageName + " to " + perm);
                            }
                        }
                    }
                // ...else the app didn't request any permissions...
                } else {
                    // ...so the permissions won't be listed.
                    if (GlobalDefines.LOG_LOCAL) {
                        Log.v(GlobalDefines.LOG_TAG, this.getClass().getSimpleName() + ": No permissions for this app.");
                    }
                }

                // set total number of permissions for the progress indicator
                progress[1] = Integer.valueOf(permissionsWithTheirApps.size());

            } // end of iterating through the apps in the ResolveInfo list


            // the List to return
            ArrayList<com.tellmas.android.permissions.PermissionInfo> theListOfPermissions =
                    new ArrayList<com.tellmas.android.permissions.PermissionInfo>(permissionsWithTheirApps.size());
            if (GlobalDefines.LOG_LOCAL) {
                Log.d(GlobalDefines.LOG_TAG, this.getClass().getSimpleName() + ": *** Construting the data which will be displayed. ***");
            }

            // === Iterate through the permissions to construct the data List which will be returned. ===
            Iterator<String> permissionsIterator = permissionsWithTheirApps.keySet().iterator();
            while (permissionsIterator.hasNext()) {

                String permission = permissionsIterator.next();

                if (GlobalDefines.LOG_LOCAL) {
                    Log.v(GlobalDefines.LOG_TAG, this.getClass().getSimpleName() + ": === Permission ===");
                }
                PermissionInfo permInfo = null; // android.content.pm.PermissionInfo
                try {
                    if (GlobalDefines.LOG_LOCAL) {
                        Log.v(GlobalDefines.LOG_TAG, this.getClass().getSimpleName() + ": " + permission);
                    }
                    permInfo = pm.getPermissionInfo(permission, PackageManager.GET_META_DATA);
                // if the package manager did not find the permission...
                } catch (NameNotFoundException nnfe) {
                    if (GlobalDefines.LOG_LOCAL) {
                        Log.e(GlobalDefines.LOG_TAG, this.getClass().getSimpleName() + ": Permission not found: " + permission);
                    }
                    // ...create a bare-bones PermissionInfo object to use instead.
                    permInfo = new PermissionInfo();
                    permInfo.labelRes = 0;
                    permInfo.descriptionRes = 0;
                }

                // --- permission Name ---
                String permissionName = null;
                try {
                    permissionName = context.getResources().getString(permInfo.labelRes);
                // if the Resource did not find the human readable name...
                } catch (NotFoundException nfe) {
                    permissionName = permInfo.name;
                    CharSequence nameCharSeq1 = permInfo.loadLabel(pm);
                    CharSequence nameCharSeq2 = permInfo.nonLocalizedLabel;
                    // if we already have a name...
                    if (permissionName != null) {
                        // ...just use it.
                    } else if (nameCharSeq1 != null) {
                        permissionName = nameCharSeq1.toString();
                    } else if (nameCharSeq2 != null) {
                        permissionName = nameCharSeq2.toString();
                    } else {
                        permissionName = permission;
                    }
                }
                if (GlobalDefines.LOG_LOCAL) {
                    Log.v(GlobalDefines.LOG_TAG, this.getClass().getSimpleName() + ": " + permissionName);
                }

                // --- permission Description ---
                String description = null;
                try {
                    description = context.getResources().getString(permInfo.descriptionRes);
                // if the Resource did not find the description...
                } catch (NotFoundException nfe) {
                    CharSequence descCharSeq1 = permInfo.loadDescription(pm);
                    CharSequence descCharSeq2 = permInfo.nonLocalizedDescription;
                    if (descCharSeq1 != null) {
                        description = descCharSeq1.toString();
                    } else if (descCharSeq2 != null) {
                        description = descCharSeq2.toString();
                    } else if (permInfo.descriptionRes == 0) {
                        description = context.getResources().getString(R.string.permission_defined_by_app);
                    // ...else if the permission is an 'android.permission.' permission...
                    } else if (permission.startsWith(GlobalDefines.ANDROID_PERMISSION_PREFIX, 0)) {
                        // ...but we didn't find the description earlier...
                        // ...log the permission.
                        if (GlobalDefines.LOG_LOCAL) {
                            Log.e(GlobalDefines.LOG_TAG,
                                    this.getClass().getSimpleName() +
                                    ": Error getting description for (the android.permission. permission): " +
                                    permission
                            );
                        }
                        description = null;
                    } else {
                        description = context.getResources().getString(R.string.permission_defined_elsewhere);
                    }
                }
                if (GlobalDefines.LOG_LOCAL) {
                    Log.v(GlobalDefines.LOG_TAG, this.getClass().getSimpleName() + ": " + description);
                }

                // the data for all the apps that use this permission
                List<ApplicationInfo> theAppsDataList = new LinkedList<ApplicationInfo>();
                // the set of app package names for this permission
                HashSet<String> theAppsPackages = permissionsWithTheirApps.get(permission);

                // === Iterate through each of the apps by package name. ===
                Iterator<String> appPackagesIterator = theAppsPackages.iterator();
                if (GlobalDefines.LOG_LOCAL) {
                    Log.v(GlobalDefines.LOG_TAG, this.getClass().getSimpleName() + ": --- Apps using this permission ---");
                }
                while (appPackagesIterator.hasNext()) {

                    if (this.isCancelled()) {
                        return theListOfPermissions;
                    }

                    String packageName = appPackagesIterator.next();
                    if (GlobalDefines.LOG_LOCAL) {
                        Log.v(GlobalDefines.LOG_TAG, this.getClass().getSimpleName() + ": " + packageName);
                    }

                    PackageInfo packageInfo = null;
                    try {
                        packageInfo = pm.getPackageInfo(packageName, 0);
                    // if the package wasn't found on the system...
                    } catch (NameNotFoundException nnfe) {
                        if (GlobalDefines.LOG_LOCAL) {
                            Log.e(GlobalDefines.LOG_TAG, this.getClass().getSimpleName() + ": " + packageName + " wasn't found on the system.");
                        }
                        // ...skip it.
                        continue;
                        /* This really shouldn't happen though, because the same
                         * package manager was used to get the list of activities. */
                    }

                    // --- app's Label ---
                    String appLabel = packageInfo.applicationInfo.loadLabel(pm).toString();
                    if (GlobalDefines.LOG_LOCAL) {
                        Log.v(GlobalDefines.LOG_TAG, this.getClass().getSimpleName() + ": " + appLabel);
                    }

                    // --- icon's Resource Id ---
                    int iconResourceId = packageInfo.applicationInfo.icon;
                    if (iconResourceId == 0) {
                        iconResourceId = packageInfo.applicationInfo.logo;
                    }
                    if (GlobalDefines.LOG_LOCAL) {
                        Log.v(GlobalDefines.LOG_TAG, this.getClass().getSimpleName() + ": icon resource id: " + Integer.toString(iconResourceId));
                    }

                    // Add this app's data to the List for the permission.
                    theAppsDataList.add(
                        new ApplicationInfo(appLabel, iconResourceId, packageName, null)
                    );

                }

                // Sort the apps data list.
                Collections.sort(theAppsDataList, new ApplicationInfoComparator());

                // Add the permission (with its apps' data) to the data List.
                theListOfPermissions.add(
                    new com.tellmas.android.permissions.PermissionInfo(
                        new Permission(permission, permissionName, description),
                        theAppsDataList
                    )
                );


                progress[0] = Integer.valueOf(progress[0].intValue() + 1);
                publishProgress(progress);

            } // end of iterating through the permissions

            // --- Sort the List of permissions ---
            Collections.sort(theListOfPermissions, new PermissionInfoComparator());

            return theListOfPermissions;
        } // end doInBackground


        /*
         * (non-Javadoc)
         * @see android.os.AsyncTask#onPostExecute(java.lang.Object)
         */
        @Override
        protected void onPostExecute(ArrayList<com.tellmas.android.permissions.PermissionInfo> theList) {
            finalizeTheResults(theList);
        }


        /*
         * (non-Javadoc)
         * @see android.os.AsyncTask#onProgressUpdate(Progress[])
         */
        @Override
        protected void onProgressUpdate(Integer... progress) {
            setProgress(progress[0].intValue(), progress[1].intValue());
        }


        /*
         * (non-Javadoc)
         * @see android.os.AsyncTask#onCancelled()
         */
        @Override
        protected void onCancelled() {
            // display nothing
            finalizeTheResults(null);
        }

    } // end getTheAppsAsyncTask


    /* ******************* Unused lifecycle methods *********************** */
    /*
    @Override
    public void onViewCreated (View view, Bundle savedInstanceState) {
        if (GlobalDefines.LOG_LOCAL) {
            Log.i(GlobalDefines.LOG_TAG, this.getClass().getSimpleName() + ": onViewCreated()");
        }
        super.onViewCreated(view, savedInstanceState);
    }
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
    @Override
    public void onViewStateRestored(Bundle savedInstanceState) {
        if (GlobalDefines.LOG_LOCAL) {
            Log.i(GlobalDefines.LOG_TAG, this.getClass().getSimpleName() + ": onViewStateRestored()");
        }
        super.onViewStateRestored(savedInstanceState);
    }
    @Override
    public void onStart() {
        if (GlobalDefines.LOG_LOCAL) {
            Log.i(GlobalDefines.LOG_TAG, this.getClass().getSimpleName() + ": onStart()");
        }
        super.onStart();
    }
    @Override
    public void onResume() {
        if (GlobalDefines.LOG_LOCAL) {
            Log.i(GlobalDefines.LOG_TAG, this.getClass().getSimpleName() + ": onResume()");
        }
        super.onResume();
    }
    @Override
    public void onPause() {
        if (GlobalDefines.LOG_LOCAL) {
            Log.i(GlobalDefines.LOG_TAG, this.getClass().getSimpleName() + ": onPause()");
        }
        super.onPause();
    }
    @Override
    public void onStop() {
        if (GlobalDefines.LOG_LOCAL) {
            Log.i(GlobalDefines.LOG_TAG, this.getClass().getSimpleName() + ": onStop()");
        }
        super.onStop();
    }
    @Override
    public void onTrimMemory(int level) {
        if (GlobalDefines.LOG_LOCAL) {
            Log.i(GlobalDefines.LOG_TAG, this.getClass().getSimpleName() + ": onTrimMemory()");
        }
        super.onTrimMemory(level);
    }
    @Override
    public void onDestroyView() {
        if (GlobalDefines.LOG_LOCAL) {
            Log.i(GlobalDefines.LOG_TAG, this.getClass().getSimpleName() + ": onDestroyView()");
        }
        super.onDestroyView();
    }
    @Override
    public void onDestroy() {
        if (GlobalDefines.LOG_LOCAL) {
            Log.i(GlobalDefines.LOG_TAG, this.getClass().getSimpleName() + ": onDestroy()");
        }
        super.onDestroy();
    }
    @Override
    public void onDetach() {
        if (GlobalDefines.LOG_LOCAL) {
            Log.i(GlobalDefines.LOG_TAG, this.getClass().getSimpleName() + ": onDetach()");
        }
        super.onDetach();
    }
    */
    /* ****************** END Unused lifecycle methods ******************** */
}




Java Source Code List

com.tellmas.android.permissions.AppListExpandableListAdapter.java
com.tellmas.android.permissions.AppListFragment.java
com.tellmas.android.permissions.ApplicationInfoComparator.java
com.tellmas.android.permissions.ApplicationInfo.java
com.tellmas.android.permissions.GlobalDefines.java
com.tellmas.android.permissions.MainActivity.java
com.tellmas.android.permissions.PermListExpandableListAdapter.java
com.tellmas.android.permissions.PermListFragment.java
com.tellmas.android.permissions.PermissionInfoComparator.java
com.tellmas.android.permissions.PermissionInfo.java
com.tellmas.android.permissions.Permission.java