com.mokee.permissionsmanager.fragments.AppOpsCategory.java Source code

Java tutorial

Introduction

Here is the source code for com.mokee.permissionsmanager.fragments.AppOpsCategory.java

Source

/**
 * Copyright (C) 2013 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.
 */

package com.mokee.permissionsmanager.fragments;

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

import android.app.ListFragment;
import android.app.LoaderManager;
import android.content.AsyncTaskLoader;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.Loader;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

import com.mokee.permissionsmanager.R;
import com.mokee.permissionsmanager.activites.MainActivity;
import com.mokee.permissionsmanager.common.AppOpsState;
import com.mokee.permissionsmanager.common.AppOpsState.AppOpEntry;

public class AppOpsCategory extends ListFragment implements LoaderManager.LoaderCallbacks<List<AppOpEntry>> {

    private static final int RESULT_APP_DETAILS = 1;
    private int flag = 0;//0app1system
    private AppOpsState mState;
    private LocalBroadcastManager localBroadcastManager;
    // This is the Adapter being used to display the list's data.
    private AppListAdapter mAdapter;
    private static AppOpsState.OpsTemplate template;
    private String mCurrentPkgName;

    public AppOpsCategory() {
    }

    public AppOpsCategory(AppOpsState.OpsTemplate template, int flag) {
        this.template = template;
        Bundle args = new Bundle();
        args.putParcelable("template", template);
        setArguments(args);
        this.flag = flag;
    }

    /**
     * Helper for determining if the configuration has changed in an interesting way so we need to rebuild the app list.
     */
    public static class InterestingConfigChanges {
        final Configuration mLastConfiguration = new Configuration();
        int mLastDensity;

        boolean applyNewConfig(Resources res) {
            int configChanges = mLastConfiguration.updateFrom(res.getConfiguration());
            boolean densityChanged = mLastDensity != res.getDisplayMetrics().densityDpi;
            if (densityChanged || (configChanges & (ActivityInfo.CONFIG_LOCALE | ActivityInfo.CONFIG_UI_MODE
                    | ActivityInfo.CONFIG_SCREEN_LAYOUT)) != 0) {
                mLastDensity = res.getDisplayMetrics().densityDpi;
                return true;
            }
            return false;
        }
    }

    /**
     * Helper class to look for interesting changes to the installed apps so that the loader can be updated.
     */
    public static class PackageIntentReceiver extends BroadcastReceiver {
        final AppListLoader mLoader;

        public PackageIntentReceiver(AppListLoader 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();
        }
    }

    /**
     * A custom Loader that loads all of the installed applications.
     */
    public static class AppListLoader extends AsyncTaskLoader<List<AppOpEntry>> {
        final InterestingConfigChanges mLastConfig = new InterestingConfigChanges();
        final AppOpsState mState;
        final AppOpsState.OpsTemplate mTemplate;

        List<AppOpEntry> mApps;
        PackageIntentReceiver mPackageObserver;

        public AppListLoader(Context context, AppOpsState state, AppOpsState.OpsTemplate template) {
            super(context);
            mState = state;
            mTemplate = template;
        }

        @Override
        public List<AppOpEntry> loadInBackground() {
            return mState.buildState(template);//loading applist
        }

        /**
         * Called when there is new data to deliver to the client. The super class will take care of delivering it; the
         * implementation here just adds a little more logic.
         */
        @Override
        public void deliverResult(List<AppOpEntry> apps) {
            if (isReset()) {
                // An async query came in while the loader is stopped. We
                // don't need the result.
                if (apps != null) {
                    onReleaseResources(apps);
                }
            }
            List<AppOpEntry> oldApps = apps;
            mApps = 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);
            }
        }

        /**
         * Handles a request to start the Loader.
         */
        @Override
        protected void onStartLoading() {
            // We don't monitor changed when loading is stopped, so need
            // to always reload at this point.
            onContentChanged();

            if (mApps != null) {
                // If we currently have a result available, deliver it
                // immediately.
                deliverResult(mApps);
            }

            // Start watching for changes in the app data.
            if (mPackageObserver == null) {
                mPackageObserver = new PackageIntentReceiver(this);
            }

            // Has something interesting in the configuration changed since we
            // last built the app list?
            boolean configChange = mLastConfig.applyNewConfig(getContext().getResources());

            if (takeContentChanged() || mApps == null || configChange) {
                // If the data has changed since the last time it was loaded
                // or is not currently available, start a load.
                forceLoad();
            }
        }

        /**
         * Handles a request to stop the Loader.
         */
        @Override
        protected void onStopLoading() {
            // Attempt to cancel the current load task if possible.
            cancelLoad();
        }

        /**
         * Handles a request to cancel a load.
         */
        @Override
        public void onCanceled(List<AppOpEntry> apps) {
            super.onCanceled(apps);

            // At this point we can release the resources associated with 'apps'
            // if needed.
            onReleaseResources(apps);
        }

        /**
         * Handles a request to completely reset the Loader.
         */
        @Override
        protected void onReset() {
            super.onReset();

            // Ensure the loader is stopped
            onStopLoading();

            // At this point we can release the resources associated with 'apps'
            // if needed.
            if (mApps != null) {
                onReleaseResources(mApps);
                mApps = null;
            }

            // Stop monitoring for changes.
            if (mPackageObserver != null) {
                getContext().unregisterReceiver(mPackageObserver);
                mPackageObserver = null;
            }
        }

        /**
         * Helper function to take care of releasing resources associated with an actively loaded data set.
         */
        protected void onReleaseResources(List<AppOpEntry> apps) {
            // For a simple List<> there is nothing to do. For something
            // like a Cursor, we would close it here.
        }
    }

    public static class AppListAdapter extends BaseAdapter {
        private final Resources mResources;
        private final LayoutInflater mInflater;
        private final AppOpsState mState;

        List<AppOpEntry> mList = new ArrayList<AppOpsState.AppOpEntry>();

        public AppListAdapter(Context context, AppOpsState state) {
            mResources = context.getResources();
            mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            mState = state;
        }

        public void setData(List<AppOpEntry> data, int flag) {
            mList.clear();
            if (data != null) {
                for (int i = 0; i < data.size(); i++) {
                    if ((data.get(i).getAppEntry().getApplicationInfo().flags
                            & ApplicationInfo.FLAG_SYSTEM) == flag) {
                        mList.add(data.get(i));
                    }
                }
                removeDuplicate(mList);//filter app
            } else {
                mList = null;
            }

            //mList = data;
            notifyDataSetChanged();
        }

        @Override
        public int getCount() {
            return mList != null ? mList.size() : 0;
        }

        @Override
        public AppOpEntry getItem(int position) {
            return mList.get(position);
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        /**
         * 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.app_ops_item, parent, false);
            } else {
                view = convertView;
            }

            AppOpEntry item = getItem(position);
            ((ImageView) view.findViewById(R.id.app_icon)).setImageDrawable(item.getAppEntry().getIcon());
            ((TextView) view.findViewById(R.id.app_name)).setText(item.getAppEntry().getLabel());
            ((TextView) view.findViewById(R.id.op_name)).setText(item.getSummaryText(mState));
            ((TextView) view.findViewById(R.id.op_time)).setText(item.getTimeText(mResources, false));
            return view;
        }
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mState = new AppOpsState(getActivity());
        localBroadcastManager = LocalBroadcastManager.getInstance(getActivity());
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(MainActivity.BR_UPDATE);
        localBroadcastManager.registerReceiver(broadcastReceiver, intentFilter);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        // Give some text to display if there is no data. In a real
        // application this would come from a resource.
        setEmptyText("No applications");

        // We have a menu item to show in action bar.
        setHasOptionsMenu(true);

        // Create an empty adapter we will use to display the loaded data.
        mAdapter = new AppListAdapter(getActivity(), mState);
        setListAdapter(mAdapter);

        // Start out with a progress indicator.
        setListShown(false);

        // Prepare the loader.
        //getLoaderManager().initLoader(0, null, this);
    }

    // utility method used to start sub activity
    private void startApplicationDetailsActivity() {
        // start new fragment to display extended information
        Bundle args = new Bundle();
        args.putString(AppOpsDetails.ARG_PACKAGE_NAME, mCurrentPkgName);

        //            PreferenceActivity pa = (PreferenceActivity) getActivity();
        //            pa.startPreferencePanel(AppOpsDetails.class.getName(), args, R.string.app_ops_settings, null, this,
        //                  RESULT_APP_DETAILS);
        Intent intent = new Intent(getActivity(), AppOpsDetails.class);
        intent.putExtra("args", args);
        getActivity().startActivity(intent);
    }

    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
        AppOpEntry entry = mAdapter.getItem(position);
        if (entry != null) {
            mCurrentPkgName = entry.getAppEntry().getApplicationInfo().packageName;
            startApplicationDetailsActivity();
        }
    }

    @Override
    public Loader<List<AppOpEntry>> onCreateLoader(int id, Bundle args) {
        //            Bundle fargs = getArguments();
        //            AppOpsState.OpsTemplate template = null;
        //            if (fargs != null)
        //               {
        //                  template = (AppOpsState.OpsTemplate) fargs.getParcelable("template");
        //               }
        return new AppListLoader(getActivity(), mState, template);
    }

    @Override
    public void onLoadFinished(Loader<List<AppOpEntry>> loader, List<AppOpEntry> data) {
        // Set the new data in the adapter.
        mAdapter.setData(data, flag);

        // The list should now be shown.
        if (isResumed()) {
            setListShown(true);
        } else {
            setListShownNoAnimation(true);
        }
    }

    @Override
    public void onLoaderReset(Loader<List<AppOpEntry>> loader) {
        // Clear the data in the adapter.
        mAdapter.setData(null, flag);
    }

    private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if ("update".equals(intent.getAction())) {
                template = intent.getParcelableExtra(MainActivity.BR_UPDATE);
                getLoaderManager().restartLoader(0, null, AppOpsCategory.this);
            }

        }
    };

    @Override
    public void onDestroy() {
        localBroadcastManager.unregisterReceiver(broadcastReceiver);
        getLoaderManager().destroyLoader(0);
        super.onDestroy();
    }

    /**
     * app filter
     * @param list
     */
    public static void removeDuplicate(List<AppOpEntry> list) {
        for (int i = 0; i < list.size() - 1; i++) {
            for (int j = list.size() - 1; j > i; j--) {
                if (list.get(j).getAppEntry().equals(list.get(i).getAppEntry())) {
                    list.remove(j);
                }
            }
        }
    }
}