Skip to content

Instantly share code, notes, and snippets.

@Josephaguele
Created June 4, 2017 12:56
Show Gist options
  • Save Josephaguele/74816fec5839096706aa387adc1482ec to your computer and use it in GitHub Desktop.
Save Josephaguele/74816fec5839096706aa387adc1482ec to your computer and use it in GitHub Desktop.
PetProvider and EditorActivity with the updatePet method
/*
* Copyright (C) 2016 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.example.android.pets;
import android.content.ContentUris;
import android.content.ContentValues;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.NavUtils;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.Toast;
import com.example.android.pets.data.PetContract.*;
import com.example.android.pets.data.PetDbHelper;
import static com.example.android.pets.data.PetContract.PetEntry.COLUMN_PET_BREED;
import static com.example.android.pets.data.PetContract.PetEntry.COLUMN_PET_GENDER;
import static com.example.android.pets.data.PetContract.PetEntry.COLUMN_PET_NAME;
import static com.example.android.pets.data.PetContract.PetEntry.COLUMN_PET_WEIGHT;
import static com.example.android.pets.data.PetContract.PetEntry.CONTENT_URI;
import static com.example.android.pets.data.PetContract.PetEntry.GENDER_FEMALE;
import static com.example.android.pets.data.PetContract.PetEntry.GENDER_MALE;
import static com.example.android.pets.data.PetContract.PetEntry.GENDER_UNKNOWN;
/**
* Allows user to create a new pet or edit an existing one.
*/
public class EditorActivity extends AppCompatActivity {
/** EditText field to enter the pet's name */
private EditText mNameEditText;
/** EditText field to enter the pet's breed */
private EditText mBreedEditText;
/** EditText field to enter the pet's weight */
private EditText mWeightEditText;
/** EditText field to enter the pet's gender */
private Spinner mGenderSpinner;
/**
* Gender of the pet. The possible values are:
* 0 for unknown gender, 1 for male, 2 for female.
*/
private int mGender = 0;
private Uri uri;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_editor);
// Find all relevant views that we will need to read user input from
mNameEditText = (EditText) findViewById(R.id.edit_pet_name);
mBreedEditText = (EditText) findViewById(R.id.edit_pet_breed);
mWeightEditText = (EditText) findViewById(R.id.edit_pet_weight);
mGenderSpinner = (Spinner) findViewById(R.id.spinner_gender);
setupSpinner();
}
/**
* Setup the dropdown spinner that allows the user to select the gender of the pet.
*/
private void setupSpinner() {
// Create adapter for spinner. The list options are from the String array it will use
// the spinner will use the default layout
ArrayAdapter genderSpinnerAdapter = ArrayAdapter.createFromResource(this,
R.array.array_gender_options, android.R.layout.simple_spinner_item);
// Specify dropdown layout style - simple list view with 1 item per line
genderSpinnerAdapter.setDropDownViewResource(android.R.layout.simple_dropdown_item_1line);
// Apply the adapter to the spinner
mGenderSpinner.setAdapter(genderSpinnerAdapter);
// Set the integer mSelected to the constant values
mGenderSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
String selection = (String) parent.getItemAtPosition(position);
if (!TextUtils.isEmpty(selection)) {
if (selection.equals(getString(R.string.gender_male))) {
mGender = GENDER_MALE; // Male
} else if (selection.equals(getString(R.string.gender_female))) {
mGender = GENDER_FEMALE; // Female
} else {
mGender = GENDER_UNKNOWN; // Unknown
}
}
}
// Because AdapterView is an abstract class, onNothingSelected must be defined
@Override
public void onNothingSelected(AdapterView<?> parent) {
mGender = 0; // Unknown
}
});
}
private void insertPet(){
String nameString = mNameEditText.getText().toString().trim();
String breedString = mBreedEditText.getText().toString().trim();
String weightString = mWeightEditText.getText().toString().trim();
int weight = Integer.parseInt(weightString);
PetDbHelper mDbHelper = new PetDbHelper(this);
//Create a ContentValues object where column names are the keys,
// and pet attributes from the editor are the values.
ContentValues values = new ContentValues();
values.put(COLUMN_PET_NAME, nameString);
values.put(COLUMN_PET_BREED, breedString);
values.put(COLUMN_PET_GENDER, mGender);
values.put(COLUMN_PET_WEIGHT, weight);
//Insert a new pet into the provider, returning the content URI for the new pet
Uri newUri = getContentResolver().insert(PetEntry.CONTENT_URI, values);
//Show a toast message depending on whether or not the insertion was successful
if (newUri == null){
Toast.makeText(this, R.string.editor_insert_pet_failed, Toast.LENGTH_SHORT).show();
}
else{
Toast.makeText(this, getString(R.string.editor_insert_pet_successful) + newUri, Toast.LENGTH_SHORT).show();
}
}
private void updatePet(){
String nameString = mNameEditText.getText().toString().trim();
String breedString = mBreedEditText.getText().toString().trim();
String weightString = mWeightEditText.getText().toString().trim();
int weight = Integer.parseInt(weightString);
PetDbHelper mDbHelper = new PetDbHelper(this);
//Create a ContentValues object where column names are the keys,
// and pet attributes from the editor are the values.
ContentValues values = new ContentValues();
values.put(COLUMN_PET_NAME, nameString);
values.put(COLUMN_PET_BREED, breedString);
values.put(COLUMN_PET_GENDER, mGender);
values.put(COLUMN_PET_WEIGHT, weight);
String selection = PetEntry._ID + "=?";
String []selectionArgs = new String[]{String.valueOf(ContentUris.parseId(uri))};
getContentResolver().update(PetEntry.CONTENT_URI,values,selection,selectionArgs);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu options from the res/menu/menu_editor.xml file.
// This adds menu items to the app bar.
getMenuInflater().inflate(R.menu.menu_editor, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// User clicked on a menu option in the app bar overflow menu
switch (item.getItemId()) {
// Respond to a click on the "Save" menu option
case R.id.action_save:
//Save pet to the database
insertPet();
//Exit activity
finish();
return true;
// Respond to a click on the "Delete" menu option
case R.id.action_delete:
// Do nothing for now
return true;
// Respond to a click on the "Up" arrow button in the app bar
case android.R.id.home:
// Navigate back to parent activity (CatalogActivity)
NavUtils.navigateUpFromSameTask(this);
return true;
}
return super.onOptionsItemSelected(item);
}
}
package com.example.android.pets.data;
import com.example.android.pets.data.PetContract.PetEntry;
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.support.annotation.Nullable;
import android.util.Log;
import static android.R.attr.id;
import static com.example.android.pets.data.PetContract.CONTENT_AUTHORITY;
import static com.example.android.pets.data.PetContract.PATH_PETS;
import static com.example.android.pets.data.PetContract.PetEntry.COLUMN_PET_BREED;
import static com.example.android.pets.data.PetContract.PetEntry.COLUMN_PET_GENDER;
import static com.example.android.pets.data.PetContract.PetEntry.COLUMN_PET_NAME;
import static com.example.android.pets.data.PetContract.PetEntry.COLUMN_PET_WEIGHT;
import static com.example.android.pets.data.PetContract.PetEntry.CONTENT_URI;
import static com.example.android.pets.data.PetContract.PetEntry.GENDER_MALE;
import static com.example.android.pets.data.PetContract.PetEntry.GENDER_UNKNOWN;
import static com.example.android.pets.data.PetContract.PetEntry.TABLE_NAME;
import static com.example.android.pets.data.PetContract.PetEntry._ID;
/**
* Created by AGUELE OSEKUEMEN JOE on 5/29/2017.
* ContentProvider for Pets app.
*/
public class PetProvider extends ContentProvider {
private static final String LOG_TAG = PetProvider.class.getSimpleName();
/**Database helper object*/
private PetDbHelper mDbHelper;
// URI matcher code for the content URI for teh pets table
private static final int PETS = 100;
// URI matcher code for the content URI for a single pet in the pets table
private static final int PETS_ID = 101;
/**
* UriMatcher object to match a content URI to a corresponding code.
* The input passed into the constructor represents the code to return for the root URI
* It's common to use NO_MATCH as the input for this case
*/
private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
// Static initializer. This is run the first time anything is called from this class.
static{
// The calls to addURI() go here, for all of the content URI patterns that the provider
// should recognize. All paths added to the UriMatcher have a corresponding code to return
// when a match is found.
sUriMatcher.addURI(CONTENT_AUTHORITY, PATH_PETS, PETS);
sUriMatcher.addURI(CONTENT_AUTHORITY, PATH_PETS +"/#", PETS_ID);
}
// Initialize the provider and the database helper object.
@Override
public boolean onCreate() {
mDbHelper = new PetDbHelper(getContext());
return true;
}
// Perform the query for the given URI. Use the given projection, selection, selection arguments, and sort order.
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
// Get readable database
SQLiteDatabase database = mDbHelper.getReadableDatabase();
// This cursor will hold the result of the query
Cursor cursor;
// Figure out if the URI matcher can match the URI to a specific code
int match = sUriMatcher.match(uri);
switch(match){
case PETS:
// For the PETS code, query the pets table directly wit the given
// projection, selection, selection arguments and sort order. The cursor
// could contain multiple rows of the pets table.
// TODO: Perform database query on pets table.
cursor = database.query(TABLE_NAME, projection, selection, selectionArgs,null, null, sortOrder);
break;
case PETS_ID:
//For the PET_ID code, extract out the ID from the URI.
// For an example URI such as "com.example.android.pets/pets/3",
// the selection will be "_id=?" and the selection argument will be a
// String array containing the actual ID of 3 in this case.
// For every "?" in the selection, we need to have an element in the selection
// arguments that will fill in the "?". Since we have 1 question mark in the
// selection, we have 1 String in the selection arguments String array.
selection = PetEntry._ID + "=?";
selectionArgs = new String[]{String.valueOf(ContentUris.parseId(uri))};
// This will perform a query on the pets able where the _id equals 3 to return a
// Cursor containing that row of the table.
cursor = database.query(TABLE_NAME, projection, selection, selectionArgs,
null, null, sortOrder);
break;
default:
throw new IllegalArgumentException("Cannot query unknown URI" + uri);
}
return cursor;
}
// Returns the MIME type of data for the content URI.
@Override
public String getType(Uri uri) {
return null;
}
// Insert new data into the provider with the given ContentValues.
@Override
public Uri insert(Uri uri, ContentValues contentValues) {
final int match = sUriMatcher.match(uri); // URI matcher is used to check if there is a match
switch(match){
case PETS:
return insertPet(uri, contentValues);
default:
throw new IllegalArgumentException("Insertion is not supported for " +uri);
}
}
//Insert a pet into the database with thegiven content values. Return the ne content URI
// for that specific row in the database
private Uri insertPet(Uri uri, ContentValues values){
//check that the name is not null
String name = values.getAsString(COLUMN_PET_NAME);
if (name == null){
throw new IllegalArgumentException("Pet requires a name");
}
// Check that the gender is not null
Integer gender = values.getAsInteger(COLUMN_PET_GENDER);
if (gender == null || !PetEntry.isValidGender(gender)){
throw new IllegalArgumentException("Pet requires a valid gender");
}
// If the weight is provided, check that it is greater than or equal to 0kg
/*
* If the weight is null, that's fine and we can proceed with insertion (the database will insert
* default weight 0 automatically) if the wieght is not null AND it's a negative wieght, then we
* to throw an exception with the message "Pet requires valid weight". We use the "&&" SYMBOL
* to indicate that both "weight != null" must be true and "weight < 0" must be true, in order
* for the whole test condition to be true, and for the code within the "if" statement to
* execute
* */
Integer weight = values.getAsInteger(COLUMN_PET_WEIGHT);
if( weight != null && weight < 0 ) {
throw new IllegalArgumentException("Pet weight can't be less than zero");
}
//Get writeable database
SQLiteDatabase database = mDbHelper.getWritableDatabase();
// insert the new pet with the given values
long id = database.insert(TABLE_NAME,null,values);
//If the ID is -1, then the insertion failed. Log an error and return null.
if (id == -1){
Log.e(LOG_TAG, "Failed to insert row for " + uri);
return null;
}
// return the new URI with the ID (of the newly inserted row) appended to the end of it
return ContentUris.withAppendedId(uri, id);
}
// Delete data at the given selection and selection arguments
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
return 0;
}
@Override
public int update(Uri uri, ContentValues contentValues, String selection, String[] selectionArgs) {
final int match = sUriMatcher.match(uri);
switch(match){
case PETS:
return updatePet(uri, contentValues, selection, selectionArgs);
case PETS_ID:
// For the PETS_ code, extract out the ID from the URI,
// so we know which row to update. Selection will be "_id=?" and selection
// arguments will be a String array containing the actual I.
selection = _ID + "=?";
selectionArgs = new String[] { String.valueOf(ContentUris.parseId(uri))};
return updatePet(uri, contentValues, selection, selectionArgs);
default:
throw new IllegalArgumentException("Update is not supported for " + uri);
}
}
private int updatePet(Uri uri, ContentValues values, String selection, String[]selectionArgs){
// TODO: Update the selected pets in the pets database table with the given ContentValues
// TODO: Return the number of rows that were affected
if (values.containsKey(COLUMN_PET_WEIGHT)){
// Check that the weight is greater than or equal to 0kg and also
// check that the weight is not null
Integer weight = values.getAsInteger(COLUMN_PET_WEIGHT);
if (weight == null || weight < 0){
throw new IllegalArgumentException("Pets correct weight must be inputted");
}
}
//Get writable database
SQLiteDatabase database = mDbHelper.getWritableDatabase();
selection = PetEntry._ID + "=?";
selectionArgs = new String[]{String.valueOf(ContentUris.parseId(uri))};
// insert the new pet with the given values
int row = database.update(TABLE_NAME,values,selection,selectionArgs);
return row;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment