Java tutorial
/* * 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.providerlab; import android.app.Activity; import android.content.ContentValues; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.support.v4.app.ActivityCompat; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.*; import com.github.michalbednarski.intentslab.R; import com.github.michalbednarski.intentslab.Utils; import java.util.ArrayList; public class AdvancedQueryActivity extends Activity { public static final int METHOD_QUERY = 0; public static final int METHOD_INSERT = 1; public static final int METHOD_UPDATE = 2; public static final int METHOD_DELETE = 3; public static final int METHOD_GET_TYPE = 4; public static final int METHOD_OPEN_FILE = 5; public static final int METHOD_OPEN_ASSET_FILE = 6; private static final String[] METHOD_NAMES = new String[] { "query", "insert", "update", "delete" }; public static final String EXTRA_METHOD = "[method]__"; public static final String EXTRA_PROJECTION = "[pr]"; public static final String EXTRA_PROJECTION_AVAILABLE_COLUMNS = "[pr-a]"; public static final String EXTRA_SELECTION = "[sel]"; public static final String EXTRA_SELECTION_ARGS = "[sel-a]"; public static final String EXTRA_CONTENT_VALUES = "[cv]"; public static final String EXTRA_SORT_ORDER = "_order[_]"; private AutoCompleteTextView mUriTextView; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.advanced_query); Intent intent = getIntent(); Bundle instanceStateOrExtras = savedInstanceState != null ? savedInstanceState : intent.getExtras(); if (instanceStateOrExtras == null) { instanceStateOrExtras = Bundle.EMPTY; } // Uri mUriTextView = (AutoCompleteTextView) findViewById(R.id.uri); if (intent.getData() != null) { mUriTextView.setText(intent.getDataString()); } mUriTextView.setAdapter(new UriAutocompleteAdapter(this)); // Projection { mSpecifyProjectionCheckBox = (CheckBox) findViewById(R.id.specify_projection); mProjectionLayout = (LinearLayout) findViewById(R.id.projection_columns); // Bind events for master CheckBox and add new button findViewById(R.id.new_projection_column).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new UserProjectionColumn(""); } }); mSpecifyProjectionCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { mProjectionLayout.setVisibility(isChecked ? View.VISIBLE : View.GONE); } }); // Get values to fill String[] availableProjectionColumns = intent.getStringArrayExtra(EXTRA_PROJECTION_AVAILABLE_COLUMNS); String[] specifiedProjectionColumns = instanceStateOrExtras.getStringArray(EXTRA_PROJECTION); if (specifiedProjectionColumns == null) { mSpecifyProjectionCheckBox.setChecked(false); } if (availableProjectionColumns != null && availableProjectionColumns.length == 0) { availableProjectionColumns = null; } if (availableProjectionColumns != null && specifiedProjectionColumns == null) { specifiedProjectionColumns = availableProjectionColumns; } // Create available column checkboxes int i = 0; if (availableProjectionColumns != null) { for (String availableProjectionColumn : availableProjectionColumns) { boolean isChecked = i < specifiedProjectionColumns.length && availableProjectionColumn.equals(specifiedProjectionColumns[i]); new DefaultProjectionColumn(availableProjectionColumn, isChecked); if (isChecked) { i++; } } } // Create user column text fields if (specifiedProjectionColumns != null && i < specifiedProjectionColumns.length) { for (int il = specifiedProjectionColumns.length; i < il; i++) { new UserProjectionColumn(specifiedProjectionColumns[i]); } } } // Selection { // Find views mSelectionCheckBox = (CheckBox) findViewById(R.id.selection_header); mSelectionText = (TextView) findViewById(R.id.selection); mSelectionLayout = findViewById(R.id.selection_layout); mSelectionArgsTable = (TableLayout) findViewById(R.id.selection_args); // Bind events for add button and master CheckBox findViewById(R.id.selection_add_arg).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new SelectionArg("", true); } }); mSelectionCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { mSelectionLayout.setVisibility(isChecked ? View.VISIBLE : View.GONE); } }); // Fill selection text view and CheckBox String selection = intent.getStringExtra(EXTRA_SELECTION); String[] selectionArgs = instanceStateOrExtras.getStringArray(EXTRA_SELECTION_ARGS); mSelectionCheckBox.setChecked(selection != null); if (selection != null) { mSelectionText.setText(selection); } // Fill selection arguments if ((selection != null || savedInstanceState != null) && selectionArgs != null && selectionArgs.length != 0) { for (String selectionArg : selectionArgs) { new SelectionArg(selectionArg); } } } // Content values { // Find views mContentValuesHeader = (TextView) findViewById(R.id.content_values_header); mContentValuesTable = (TableLayout) findViewById(R.id.content_values); mContentValuesTableHeader = (TableRow) findViewById(R.id.content_values_table_header); // Bind add new button event findViewById(R.id.new_content_value).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new ContentValue("", "", true); } }); // Create table ContentValues contentValues = instanceStateOrExtras.getParcelable(EXTRA_CONTENT_VALUES); if (contentValues != null) { contentValues.valueSet(); for (String key : Utils.getKeySet(contentValues)) { new ContentValue(key, contentValues.getAsString(key)); } } } // Order { // Find views mSpecifyOrderCheckBox = (CheckBox) findViewById(R.id.specify_order); mOrderTextView = (TextView) findViewById(R.id.order); // Bind events mSpecifyOrderCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { mOrderTextView.setVisibility(isChecked ? View.VISIBLE : View.GONE); } }); // Fill fields String order = intent.getStringExtra(EXTRA_SORT_ORDER); if (order == null) { mSpecifyOrderCheckBox.setChecked(false); } else { mOrderTextView.setText(order); } } // Method (affects previous views so they must be initialized first) mMethodSpinner = (Spinner) findViewById(R.id.method); mMethodSpinner .setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, METHOD_NAMES)); mMethodSpinner.setOnItemSelectedListener(onMethodSpinnerItemSelectedListener); mMethodSpinner.setSelection(intent.getIntExtra(EXTRA_METHOD, METHOD_QUERY)); } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putStringArray(EXTRA_PROJECTION, getProjection()); outState.putStringArray(EXTRA_SELECTION_ARGS, getSelectionArgs()); outState.putParcelable(EXTRA_CONTENT_VALUES, getContentValues()); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.query, menu); return true; } @Override public boolean onPrepareOptionsMenu(Menu menu) { menu.findItem(R.id.execute).setTitle(METHOD_NAMES[mMethodSpinner.getSelectedItemPosition()] + "()"); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.execute: executeQuery(); } return false; } // Method private Spinner mMethodSpinner; private final AdapterView.OnItemSelectedListener onMethodSpinnerItemSelectedListener = new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { boolean showProjectionAndOrder, showSelection, showContentValues; // determine if views should be shown or hidden switch (position) { case METHOD_QUERY: showProjectionAndOrder = true; showSelection = true; showContentValues = false; break; case METHOD_INSERT: showProjectionAndOrder = false; showSelection = false; showContentValues = true; break; case METHOD_UPDATE: showProjectionAndOrder = false; showSelection = true; showContentValues = true; break; case METHOD_DELETE: showProjectionAndOrder = false; showSelection = true; showContentValues = false; break; default: throw new RuntimeException("Unexpected method spinner position"); } // Show/hide projection mSpecifyProjectionCheckBox.setVisibility(showProjectionAndOrder ? View.VISIBLE : View.GONE); mProjectionLayout.setVisibility( (showProjectionAndOrder && mSpecifyProjectionCheckBox.isChecked()) ? View.VISIBLE : View.GONE); // Show/hide selection (WHERE) mSelectionCheckBox.setVisibility(showSelection ? View.VISIBLE : View.GONE); mSelectionLayout .setVisibility((showSelection && mSelectionCheckBox.isChecked()) ? View.VISIBLE : View.GONE); // Show/hide ContentValues mContentValuesHeader.setVisibility(showContentValues ? View.VISIBLE : View.GONE); mContentValuesTable.setVisibility(showContentValues ? View.VISIBLE : View.GONE); // Show/hide order mSpecifyOrderCheckBox.setVisibility(showProjectionAndOrder ? View.VISIBLE : View.GONE); mOrderTextView.setVisibility( (showProjectionAndOrder && mSpecifyOrderCheckBox.isChecked()) ? View.VISIBLE : View.GONE); // Update execute `method()` menu item title ActivityCompat.invalidateOptionsMenu(AdvancedQueryActivity.this); } @Override public void onNothingSelected(AdapterView<?> parent) { // Spinner won't have nothing selected } }; // Projection private CheckBox mSpecifyProjectionCheckBox; private LinearLayout mProjectionLayout; private final ArrayList<ProjectionColumn> mProjectionColumns = new ArrayList<ProjectionColumn>(); private String[] getProjection() { if (!mSpecifyProjectionCheckBox.isChecked()) { return null; } ArrayList<String> projection = new ArrayList<String>(); for (ProjectionColumn projectionColumn : mProjectionColumns) { String name = projectionColumn.getName(); if (name != null) { projection.add(name); } } return projection.toArray(new String[projection.size()]); } private interface ProjectionColumn { String getName(); } private class DefaultProjectionColumn implements ProjectionColumn { private final String mName; private final CheckBox mCheckBox; DefaultProjectionColumn(String name, boolean isDefaultSelected) { mName = name; mCheckBox = new CheckBox(AdvancedQueryActivity.this); mCheckBox.setText(name); mCheckBox.setChecked(isDefaultSelected); mProjectionLayout.addView(mCheckBox, mProjectionLayout.getChildCount() - 1); mProjectionColumns.add(this); } @Override public String getName() { return mCheckBox.isChecked() ? mName : null; } } private class UserProjectionColumn implements ProjectionColumn, View.OnClickListener { private final View mView; private final TextView mTextView; UserProjectionColumn(String name) { mView = getLayoutInflater().inflate(R.layout.category_row, null); mTextView = (TextView) mView.findViewById(R.id.categoryText); mTextView.setText(name); mView.findViewById(R.id.row_remove).setOnClickListener(this); mProjectionLayout.addView(mView, mProjectionLayout.getChildCount() - 1); mProjectionColumns.add(this); } // For remove button @Override public void onClick(View v) { mProjectionLayout.removeView(mView); mProjectionColumns.remove(this); } @Override public String getName() { return mTextView.getText().toString(); } } // /Projection // Selection private CheckBox mSelectionCheckBox; private TextView mSelectionText; private View mSelectionLayout; private TableLayout mSelectionArgsTable; private final ArrayList<SelectionArg> mSelectionArgs = new ArrayList<SelectionArg>(); private class SelectionArg implements View.OnClickListener { private final TextView mArgNumber; private final TextView mArgValue; private final View mView; SelectionArg(String value) { this(value, false); } SelectionArg(String value, boolean shouldRequestFocus) { // Inflate mView = getLayoutInflater().inflate(R.layout.selection_arg, mSelectionArgsTable, false); // Find text views mArgNumber = (TextView) mView.findViewById(R.id.arg_number); mArgValue = (TextView) mView.findViewById(R.id.arg); // Bind remove button mView.findViewById(R.id.row_remove).setOnClickListener(this); // Fill texts setArgNumber(mSelectionArgs.size()); mArgValue.setText(value); // Register and attach mSelectionArgsTable.addView(mView); mSelectionArgs.add(this); // Request focus if (shouldRequestFocus) { mArgValue.requestFocus(); } } @Override public void onClick(View v) { // For remove button mSelectionArgsTable.removeView(mView); // detach from view mSelectionArgs.remove(this); // un-register reorderSelectionArgs(); } void setArgNumber(int number) { mArgNumber.setText(number + ":"); } String getValue() { return mArgValue.getText().toString(); } } private void reorderSelectionArgs() { for (int i = 0; i < mSelectionArgs.size(); i++) { SelectionArg selectionArg = mSelectionArgs.get(i); selectionArg.setArgNumber(i); } } private String getSelection() { return mSelectionCheckBox.isChecked() ? mSelectionText.getText().toString() : null; } private String[] getSelectionArgs() { int selectionArgsCount = mSelectionArgs.size(); String[] arr = new String[selectionArgsCount]; for (int i = 0; i < selectionArgsCount; i++) { SelectionArg selectionArg = mSelectionArgs.get(i); arr[i] = selectionArg.getValue(); } return arr; } // /Selection // Content values private final ArrayList<ContentValue> mContentValues = new ArrayList<ContentValue>(); private TextView mContentValuesHeader; private TableLayout mContentValuesTable; private TableRow mContentValuesTableHeader; private class ContentValue implements View.OnClickListener { private final TextView mName; private final TextView mValue; private final View mView; ContentValue(String name, String value) { this(name, value, false); } ContentValue(String name, String value, boolean shouldRequestFocus) { // Inflate mView = getLayoutInflater().inflate(R.layout.content_value, mContentValuesTable, false); // Find text views mName = (TextView) mView.findViewById(R.id.name); mValue = (TextView) mView.findViewById(R.id.value); // Fill text views mName.setText(name); if (value != null) { mValue.setText(value); } // Register and show table header if needed mContentValues.add(this); if (mContentValues.size() == 1) { mContentValuesTableHeader.setVisibility(View.VISIBLE); } // Bind remove button mView.findViewById(R.id.row_remove).setOnClickListener(this); // Attach to table before add new button mContentValuesTable.addView(mView, mContentValuesTable.getChildCount() - 1); if (shouldRequestFocus) { mName.requestFocus(); } } void putContentValue(ContentValues values) { values.put(mName.getText().toString(), mValue.getText().toString()); } void remove() { // remove from table mContentValuesTable.removeView(mView); // Un-register and hide table header if no longer needed mContentValues.remove(this); if (mContentValues.size() == 0) { mContentValuesTableHeader.setVisibility(View.GONE); } } @Override public void onClick(View v) { // For remove button remove(); } } private ContentValues getContentValues() { ContentValues values = new ContentValues(); for (ContentValue contentValue : mContentValues) { contentValue.putContentValue(values); } return values; } // /Content values // Order private CheckBox mSpecifyOrderCheckBox; private TextView mOrderTextView; private String getSortOrder() { return mSpecifyOrderCheckBox.isChecked() ? mOrderTextView.getText().toString() : null; } // /Order private void executeQuery() { Uri uri = Uri.parse(mUriTextView.getText().toString()); try { switch (mMethodSpinner.getSelectedItemPosition()) { case METHOD_QUERY: startActivity(new Intent(this, QueryResultActivity.class).setData(uri) .putExtra(EXTRA_PROJECTION, getProjection()) .putExtra(EXTRA_PROJECTION_AVAILABLE_COLUMNS, getIntent().getStringArrayExtra(EXTRA_PROJECTION_AVAILABLE_COLUMNS)) .putExtra(EXTRA_SELECTION, getSelection()) .putExtra(EXTRA_SELECTION_ARGS, getSelectionArgs()) .putExtra(EXTRA_SORT_ORDER, getSortOrder())); break; case METHOD_INSERT: getContentResolver().insert(uri, getContentValues()); break; case METHOD_UPDATE: getContentResolver().update(uri, getContentValues(), getSelection(), getSelectionArgs()); break; case METHOD_DELETE: getContentResolver().delete(uri, getSelection(), getSelectionArgs()); break; } } catch (Exception e) { Utils.toastException(this, e); } } }