Java tutorial
/** * 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); } } } } }