Java tutorial
package biz.bokhorst.xprivacy; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; import android.annotation.SuppressLint; import android.content.Context; import android.content.Intent; import android.graphics.Color; import android.graphics.drawable.Drawable; import android.os.AsyncTask; import android.os.Bundle; import android.support.v4.app.NavUtils; import android.support.v4.app.TaskStackBuilder; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.Filter; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.TextView; public class ActivityUsage extends ActivityBase { private boolean mAll = true; private int mUid; private String mRestrictionName; private UsageAdapter mUsageAdapter; public static final String cUid = "Uid"; public static final String cRestriction = "Restriction"; private static ExecutorService mExecutor = Executors .newFixedThreadPool(Runtime.getRuntime().availableProcessors(), new PriorityThreadFactory()); private static class PriorityThreadFactory implements ThreadFactory { @Override public Thread newThread(Runnable r) { Thread t = new Thread(r); t.setPriority(Thread.NORM_PRIORITY); return t; } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Check privacy service client if (!PrivacyService.checkClient()) return; // Set layout setContentView(R.layout.usagelist); // Get uid Bundle extras = getIntent().getExtras(); mUid = (extras == null ? 0 : extras.getInt(cUid, 0)); mRestrictionName = (extras == null ? null : extras.getString(cRestriction)); // Show title updateTitle(); // Start task to get usage data UsageTask usageTask = new UsageTask(); usageTask.executeOnExecutor(mExecutor, (Object) null); // Up navigation getActionBar().setDisplayHomeAsUpEnabled(true); } @Override protected void onResume() { super.onResume(); if (mUsageAdapter != null) mUsageAdapter.notifyDataSetChanged(); } @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); if (inflater != null && PrivacyService.checkClient()) { inflater.inflate(R.menu.usage, menu); return true; } else return false; } @Override public boolean onOptionsItemSelected(MenuItem item) { UsageTask usageTask; switch (item.getItemId()) { case android.R.id.home: Intent upIntent = NavUtils.getParentActivityIntent(this); if (upIntent != null) if (NavUtils.shouldUpRecreateTask(this, upIntent)) TaskStackBuilder.create(this).addNextIntentWithParentStack(upIntent).startActivities(); else NavUtils.navigateUpTo(this, upIntent); return true; case R.id.menu_usage_all: mAll = !mAll; if (mUsageAdapter != null) mUsageAdapter.getFilter().filter(Boolean.toString(mAll)); return true; case R.id.menu_refresh: updateTitle(); usageTask = new UsageTask(); usageTask.executeOnExecutor(mExecutor, (Object) null); return true; case R.id.menu_clear: PrivacyManager.deleteUsage(mUid); usageTask = new UsageTask(); usageTask.executeOnExecutor(mExecutor, (Object) null); return true; default: return super.onOptionsItemSelected(item); } } // Tasks private class UsageTask extends AsyncTask<Object, Object, List<PRestriction>> { @Override protected List<PRestriction> doInBackground(Object... arg0) { List<PRestriction> listUsageData = new ArrayList<PRestriction>(); for (PRestriction usageData : PrivacyManager.getUsageList(ActivityUsage.this, mUid, mRestrictionName)) listUsageData.add(usageData); return listUsageData; } @Override protected void onPostExecute(List<PRestriction> listUsageData) { if (!ActivityUsage.this.isFinishing()) { mUsageAdapter = new UsageAdapter(ActivityUsage.this, R.layout.usageentry, listUsageData); ListView lvUsage = (ListView) findViewById(R.id.lvUsage); lvUsage.setAdapter(mUsageAdapter); mUsageAdapter.getFilter().filter(Boolean.toString(mAll)); } super.onPostExecute(listUsageData); } } // Adapters private class UsageAdapter extends ArrayAdapter<PRestriction> { private boolean mHasProLicense = false; private List<PRestriction> mListUsageData; private LayoutInflater mInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); public UsageAdapter(Context context, int textViewResourceId, List<PRestriction> objects) { super(context, textViewResourceId, objects); mHasProLicense = (Util.hasProLicense(ActivityUsage.this) != null); mListUsageData = new ArrayList<PRestriction>(); mListUsageData.addAll(objects); } @Override public Filter getFilter() { return new UsageFilter(); } private class UsageFilter extends Filter { public UsageFilter() { } @Override protected FilterResults performFiltering(CharSequence constraint) { FilterResults results = new FilterResults(); // Get argument boolean all = Boolean.parseBoolean((String) constraint); // Match applications List<PRestriction> lstResult = new ArrayList<PRestriction>(); for (PRestriction usageData : UsageAdapter.this.mListUsageData) { if (all ? true : usageData.restricted) lstResult.add(usageData); } synchronized (this) { results.values = lstResult; results.count = lstResult.size(); } return results; } @Override @SuppressWarnings("unchecked") protected void publishResults(CharSequence constraint, FilterResults results) { clear(); if (results.values == null) notifyDataSetInvalidated(); else { addAll((ArrayList<PRestriction>) results.values); notifyDataSetChanged(); } } } private class ViewHolder { private View row; private int position; public LinearLayout llUsage; public TextView tvTime; public ImageView imgIcon; public ImageView imgRestricted; public TextView tvApp; public TextView tvRestriction; public TextView tvParameter; public ViewHolder(View theRow, int thePosition) { row = theRow; position = thePosition; llUsage = (LinearLayout) row.findViewById(R.id.llUsage); tvTime = (TextView) row.findViewById(R.id.tvTime); imgIcon = (ImageView) row.findViewById(R.id.imgIcon); imgRestricted = (ImageView) row.findViewById(R.id.imgRestricted); tvApp = (TextView) row.findViewById(R.id.tvApp); tvRestriction = (TextView) row.findViewById(R.id.tvRestriction); tvParameter = (TextView) row.findViewById(R.id.tvParameter); } } private class HolderTask extends AsyncTask<Object, Object, Object> { private int position; private ViewHolder holder; private PRestriction usageData; private Drawable icon = null; private boolean system; private Hook hook; public HolderTask(int thePosition, ViewHolder theHolder, PRestriction theUsageData) { position = thePosition; holder = theHolder; usageData = theUsageData; } @Override protected Object doInBackground(Object... params) { if (usageData != null) { ApplicationInfoEx appInfo = new ApplicationInfoEx(ActivityUsage.this, usageData.uid); icon = appInfo.getIcon(ActivityUsage.this); system = appInfo.isSystem(); hook = PrivacyManager.getHook(usageData.restrictionName, usageData.methodName); return holder; } return null; } @Override protected void onPostExecute(Object result) { if (holder.position == position && result != null) { if (system || (hook != null && hook.isDangerous())) holder.row.setBackgroundColor(getResources().getColor(getThemed(R.attr.color_dangerous))); else holder.row.setBackgroundColor(Color.TRANSPARENT); holder.imgIcon.setImageDrawable(icon); holder.imgIcon.setVisibility(View.VISIBLE); View.OnClickListener listener = new View.OnClickListener() { @Override public void onClick(View view) { PRestriction usageData = mUsageAdapter.getItem(position); Intent intent = new Intent(ActivityUsage.this, ActivityApp.class); intent.putExtra(ActivityApp.cUid, usageData.uid); intent.putExtra(ActivityApp.cRestrictionName, usageData.restrictionName); intent.putExtra(ActivityApp.cMethodName, usageData.methodName); startActivity(intent); } }; holder.llUsage.setOnClickListener(listener); holder.tvRestriction.setOnClickListener(listener); } } } @Override @SuppressLint("InflateParams") public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; if (convertView == null) { convertView = mInflater.inflate(R.layout.usageentry, null); holder = new ViewHolder(convertView, position); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); holder.position = position; } // Get data PRestriction usageData = getItem(position); // Build entry holder.row.setBackgroundColor(Color.TRANSPARENT); Date date = new Date(usageData.time); SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss", Locale.ROOT); holder.tvTime.setText(format.format(date)); holder.imgIcon.setVisibility(View.INVISIBLE); holder.imgRestricted.setVisibility(usageData.restricted ? View.VISIBLE : View.INVISIBLE); holder.tvApp.setText(Integer.toString(usageData.uid)); holder.tvRestriction.setText(String.format("%s/%s", usageData.restrictionName, usageData.methodName)); if (!TextUtils.isEmpty(usageData.extra) && mHasProLicense) { holder.tvParameter.setText(usageData.extra); holder.tvParameter.setVisibility(View.VISIBLE); } else holder.tvParameter.setVisibility(View.GONE); // Async update new HolderTask(position, holder, usageData).executeOnExecutor(mExecutor, (Object) null); return convertView; } } // Helpers private void updateTitle() { // Get statistics long count = 0; long restricted = 0; double persec = 0; try { @SuppressWarnings("rawtypes") Map statistics = PrivacyService.getClient().getStatistics(); count = (Long) statistics.get("restriction_count"); restricted = (Long) statistics.get("restriction_restricted"); long uptime = (Long) statistics.get("uptime_milliseconds"); persec = (double) count / (uptime / 1000); } catch (Throwable ex) { Util.bug(null, ex); } // Set title setTitle(String.format("%s %d/%d %.2f/s", getString(R.string.app_name), restricted, count, persec)); } }