Skip to content

Commit

Permalink
1.13 Add input validation to ContentProvider insert() method
Browse files Browse the repository at this point in the history
  • Loading branch information
Beginning Android committed Aug 23, 2016
1 parent c64812e commit 6861be5
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 0 deletions.
11 changes: 11 additions & 0 deletions app/src/main/java/com/example/android/pets/data/PetContract.java
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,17 @@ public static final class PetEntry implements BaseColumns {
public static final int GENDER_UNKNOWN = 0;
public static final int GENDER_MALE = 1;
public static final int GENDER_FEMALE = 2;

/**
* Returns whether or not the given gender is {@link #GENDER_UNKNOWN}, {@link #GENDER_MALE},
* or {@link #GENDER_FEMALE}.
*/
public static boolean isValidGender(int gender) {
if (gender == GENDER_UNKNOWN || gender == GENDER_MALE || gender == GENDER_FEMALE) {
return true;
}
return false;
}

This comment has been minimized.

Copy link
@PackHg

PackHg Apr 25, 2017

Could be simply:
return gender == GENDER_UNKNOWN || gender == GENDER_MALE || gender == GENDER_FEMALE;

This comment has been minimized.

Copy link
@ayush251196

ayush251196 Jun 1, 2018

What is the need to validate the gender attribute as we are bound to enter only one of 3 through the spinner?

This comment has been minimized.

Copy link
@mostafazaghlol

mostafazaghlol Jun 18, 2018

The Question Here How will the user choose Something not GENDER_UNKNOWN || gender == GENDER_MALE || gender == GENDER_FEMALE it is not necessary to make this validation

This comment has been minimized.

Copy link
@doilio

doilio Jun 25, 2018

True, there is no need to validate the campSpinner only has 3 fields

This comment has been minimized.

Copy link
@ID2GO

ID2GO Jul 11, 2018

Indeed, just adding extra code that will not be of use on the gender method due to the spinner.
It might have been of use for the breed method. But then all of a sudden all input is fine, even null.

This comment has been minimized.

Copy link
@Boccialex

Boccialex Jul 23, 2018

@ayush251196
Without the isValid () method I got an error, because I stored gender as a string but then I recall it as an integer (for the validation purpose)

This comment has been minimized.

Copy link
@enachescurobert

enachescurobert Apr 22, 2019

If you want to display a Toast if no name is passed in instead of crashing the app, you can just change a few lines of code in the EditorActivity.java when the Save button(✓) is pressed.
You need to make changes only to onOptionsItemSelected:

@Override
    public boolean onOptionsItemSelected(MenuItem item) {
        EditText petName = (EditText)findViewById(R.id.edit_pet_name);
        String name  =  petName.getText().toString();
        // 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 database
                if(TextUtils.isEmpty(name)){
                    Toast.makeText(getApplicationContext(), "You need to add name", LENGTH_LONG).show();
                } else {
                    savePet();
                    // Exit activity
                    finish();
                }
                return true;
            // Respond to a click on the "Delete" menu option
            case R.id.action_delete:

The rest of the code stays the same. :)

This comment has been minimized.

Copy link
@SabalNiroula

SabalNiroula Oct 23, 2020

just check there if the gender is greater than 2 in insertPet() method like
if(gender == null || gender>2) as we know that the gender can be only 0, 1, 2 and it cannot be greater than 2.

This comment has been minimized.

Copy link
@AdanGabrielBalbuenaLuna

AdanGabrielBalbuenaLuna Apr 18, 2021

This is my first comment, thank you bro!

}

}
Expand Down
20 changes: 20 additions & 0 deletions app/src/main/java/com/example/android/pets/data/PetProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,26 @@ public Uri insert(Uri uri, ContentValues contentValues) {
* 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(PetEntry.COLUMN_PET_NAME);
if (name == null) {

This comment has been minimized.

Copy link
@pooriant

pooriant Dec 22, 2017

it doesn't work because if we leave name box empty , EditText automatically save input data as empty string ("")and this is different from null string ! so i think its better to change if statement to this
(name==null || name.isEmpty() ){}

This comment has been minimized.

Copy link
@vferreirati

vferreirati Apr 11, 2018

Indeed, but instead of using:
(name==null || name.isEmpty() ){}
You should use Androids native:
(TextUtils.isEmpty(name))
It's faster and will return true if the String is empty or null.

This comment has been minimized.

Copy link
@eddyabraham

eddyabraham May 21, 2018

Isn't it better to show a toast to signal the problem to the user and return null? That way we don't crash the app, and the new pet isn't stored

This comment has been minimized.

Copy link
@Ghumndroid

Ghumndroid Sep 7, 2018

I have tried all the above methods regarding the name field. However, the issue still persists. Blank name pets are getting stored. Is there any other thing we can try?

This comment has been minimized.

Copy link
@zzulueta

zzulueta Sep 7, 2018

use this (TextUtils.isEmpty(name))

This comment has been minimized.

Copy link
@AbdallahShaqrah

AbdallahShaqrah Sep 23, 2018

After adding this code , I tried to insert some stupid data and its accepted and didn't through any exception

screen shot 2018-09-23 at 3 12 36 pm

This comment has been minimized.

Copy link
@rpop67

rpop67 Nov 11, 2018

You can change the input type in xml file .So user can enter only numeric or characters as per requirement

This comment has been minimized.

Copy link
@darkkshadow

darkkshadow Mar 10, 2019

try : if(name.equals("")) instead of (name==null)

This comment has been minimized.

Copy link
@enachescurobert

enachescurobert Apr 22, 2019

Isn't it better to show a toast to signal the problem to the user and return null? That way we don't crash the app, and the new pet isn't stored

Here is the code for adding the Toast instead of crashing the app:
6861be5#commitcomment-33260481

This comment has been minimized.

Copy link
@enachescurobert

enachescurobert Apr 22, 2019

@eddyabraham if we make only toast , the pet will be accepted with no name and the app will show a brief toast about it.

This is the fix that you wanted:
6861be5#commitcomment-33260481

This comment has been minimized.

Copy link
@Hasanabbas

Hasanabbas Jun 20, 2020

I don't think the purpose of this check is to ensure that the user doesn't enter in an empty name. The purpose is to make sure that another developer doesn't accidentally write some code which enters a null value (remember that null is different to empty). Obviously this is an unlikely scenario for us because only one person will be writing all the code. But if you're working within a team of developers in the future then it's good to write defensive programs.

throw new IllegalArgumentException("Pet requires a name");
}

// Check that the gender is valid
Integer gender = values.getAsInteger(PetEntry.COLUMN_PET_GENDER);
if (gender == null || !PetEntry.isValidGender(gender)) {

This comment has been minimized.

Copy link
@trobbierob

trobbierob Mar 6, 2017

Is there a need for this? It's not like you have the choice to add anything other than unknown, male or female. Or is it just a best practice if the user did have a choice?

This comment has been minimized.

Copy link
@kowa1ski

kowa1ski May 27, 2017

I think like you

This comment has been minimized.

Copy link
@ankurg22

ankurg22 Aug 12, 2017

I was wondering the same.

This comment has been minimized.

Copy link
@xlucn

xlucn Sep 9, 2017

I had the same thought, but I guess this is to prevent a programmer use insert method (other than from the app UI, ContentProvider let us access the database from other apps, right?) to insert a row with wrong gender.

This comment has been minimized.

Copy link
@AlexandraDamaschin

AlexandraDamaschin Apr 28, 2018

I will call this good practice!

This comment has been minimized.

Copy link
@Nikoloutsos

Nikoloutsos Jun 19, 2018

@trobbierob I believe that in this case you are right but if you think it again we are building a content provider.
A content provider can be called with other apps which may allow the user to enter the gender(manually).
Therefore, I believe that this check is necessary.

This comment has been minimized.

Copy link
@satyampatil

satyampatil Sep 6, 2018

// Check that the gender is valid
Integer gender = values.getAsInteger(PetEntry.COLUMN_PET_GENDER);
if (gender == 0 || !PetEntry.isValidGender(gender)) {
throw new IllegalArgumentException("Pet requires valid gender");
}
using "null" isn't showing anything , so i changed it to "0".
It's now running fine.
Is my process is right?

This comment has been minimized.

Copy link
@zzulueta

zzulueta Sep 6, 2018

it has to be null. if gender == 0 then its a valid gender type which is "unknown". null is to check if the gender field is not populated at all. However in this code exercise it will never happen because the user interface explicitly states a default value of 0. but in the future, if some other app uses the content provider and the user interface doesn't explicitly state a 0 default value then gender will be null and the system will crash

This comment has been minimized.

Copy link
@EnduranceCode

EnduranceCode Dec 15, 2018

Android Studio shows an error when I write `gender == null, it says "Operator '==' cannot be applied to 'int', 'null'"

This comment has been minimized.

Copy link
@RMdMehar

RMdMehar Jan 11, 2019

Android Studio shows an error when I write `gender == null, it says "Operator '==' cannot be applied to 'int', 'null'"

@EnduranceCode , the reason for that is probably because you might have declared gender variable as int. The thing is, int and other primitive datatypes cannot be null. So, if you want to check if any variable of primitive datatype is null, use a wrapper class instead.

In this case, instead of int gender, it should be Integer gender. Here, Integer is the wrapper class for the primitive datatype int.

This comment has been minimized.

Copy link
@gitam2869

gitam2869 Aug 2, 2019

yes i agree with you @trobbierob.

throw new IllegalArgumentException("Pet requires valid gender");
}

// If the weight is provided, check that it's greater than or equal to 0 kg
Integer weight = values.getAsInteger(PetEntry.COLUMN_PET_WEIGHT);
if (weight != null && weight < 0) {

This comment has been minimized.

Copy link
@Cnikhil7

Cnikhil7 Mar 6, 2017

It should be OR [||] instead of AND [&&].

This comment has been minimized.

Copy link
@trobbierob

trobbierob Mar 6, 2017

Thanks

This comment has been minimized.

Copy link
@oluwasegunmaths

oluwasegunmaths Jun 4, 2017

It is correct as it is. If its "OR", the program will always throw an exception with non-null weight which is what we want to store in the db. With " OR", if the first part of the condition is true, the code skips the second part and executes the body of the "if" statement

This comment has been minimized.

Copy link
@nishchay-suteri

nishchay-suteri Jun 26, 2017

Shouldn't the if condition be:-
if(weight==null || weight<0){ //Since we'll throw an exception when EITHER weight is null OR weight in less than 0

This comment has been minimized.

Copy link
@xlucn

xlucn Sep 9, 2017

"&&" is correct. Weight can be "null", because the database will automatically set it to zero.
The exercise in "add data validation to pet provider" lesson also proves the same.

This comment has been minimized.

Copy link
@Arthzil

Arthzil Sep 23, 2017

It is pointless to even check if user enters weight < 0 simply because in activity_editor.xml we have :
<EditText android:id="@+id/edit_pet_weight" android:hint="@string/hint_pet_weight" android:inputType="number" style="@style/EditorFieldStyle" />

inputType "number" doesn't allow negative values. It is basically impossible for user to enter negative value as it is.

If you want to test if the exception is thrown when you enter negative weight, you need to change this to "numberSigned".

This comment has been minimized.

Copy link
@shalahuddinn

shalahuddinn Jan 24, 2018

I got a problem when I save without entering any value at weight section, I got an exception. I think we should check the string before using parseInteger at editoractivity.

This comment has been minimized.

Copy link
@bakhbk

bakhbk Jun 24, 2018

I suppose that if, in the future, another programmer wants to change the input method to "numberSigned", then our code will still work. :)

This comment has been minimized.

Copy link
@zzulueta

zzulueta Aug 17, 2018

@shalahuddinn - yes you are right. the system doesn't even go further after this statement
int weightField = Integer.parseInt(mWeightEditText.getText().toString().trim());
parseInt will give out a NumberFormatException as the null string can't be parsed to integer..
https://developer.android.com/reference/java/lang/Integer.html#parseInt(java.lang.String)

This comment has been minimized.

Copy link
@satyampatil

satyampatil Sep 6, 2018

// If the weight is provided, check that it's greater than or equal to 0 kg and less than 50.
Integer weight = values.getAsInteger(PetEntry.COLUMN_PET_WEIGHT);
if (weight == null || weight < 0 || weight > 50) {
throw new IllegalArgumentException("Pet requires valid weight");
}

I think this is the right way. As we are using if statement and OR statement we have to use == instead of !=.
I added an extra code of weight > 50.

This comment has been minimized.

Copy link
@zzulueta

zzulueta Sep 6, 2018

why do you need to add 50kg?!

This comment has been minimized.

Copy link
@oasissan

oasissan Mar 23, 2020

you should remove this statement
int weightField = Integer.parseInt(mWeightEditText.getText().toString().trim());
and it will work as expected

This comment has been minimized.

Copy link
@hamada-developer

hamada-developer Jun 30, 2020

why is weight != null ? be should weight == null, because if weight is content value ex weight 7kg != null --is true !!! and throw exception ?!

throw new IllegalArgumentException("Pet requires valid weight");
}

This comment has been minimized.

Copy link
@rydarg

rydarg Dec 15, 2016

Since null value cases are being handled, and with a negative weight being a non-null value, why can't we skip the AND op and code it as if(weight<0)?

This comment has been minimized.

Copy link
@benong777

benong777 Sep 13, 2018

@rydarg I have the same question as you. Not sure why we need to check that the weight is NOT null if the weight of less than 0 already imply it's NOT null.

This comment has been minimized.

Copy link
@Mosamiryb7

Mosamiryb7 May 23, 2020

me too

// No need to check the breed, any value is valid (including null).

// Get writeable database
SQLiteDatabase database = mDbHelper.getWritableDatabase();

Expand Down

26 comments on commit 6861be5

@MarekFish93
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesnt work for me. I still can add a pet without name, and breed. Leaving weight empty i crashing my app with "java.lang.NumberFormatException: For input string: "" " communicate. I just dont get it

@brewsfab
Copy link

@brewsfab brewsfab commented on 6861be5 Mar 28, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MarekFish93 I had the same issue where it works without name but I realized that the Editext has initially an empty String "" (length = 0) so it is always different from null, I modified the condition like this if (name == null || name.length()==0) {...} and it works now.

Also, for the exception you get when the weight is empty, I think it is because somewhere you are parsing the weight from String to int like this
int weight =Integer.parseInt(mWeightEditText.getText().toString().trim()); which excepts a valid String representing a number but finds "" .

@cl5rt
Copy link

@cl5rt cl5rt commented on 6861be5 Mar 29, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The app crashes on this line of code:
throw new IllegalArgumentException("Pet requires a name");

Error:
E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.android.pets, PID: 8539
java.lang.IllegalArgumentException: Pet requires a name

Please help! Thanks!

@brewsfab
Copy link

@brewsfab brewsfab commented on 6861be5 Mar 29, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cl5rt Did you input a name?
If no, this is the expected behavior as you are throwing a IllegalArgumentException when the name is empty so the app crashes.
I think for new learners, Udacity should use visual feedback like Toast to know if the input validation is correct instead of exceptions.

@cl5rt
Copy link

@cl5rt cl5rt commented on 6861be5 Mar 30, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@brewsfab
Ooohhh I got it!!!! Thank you!
I must have not been listening too hard on the lesson.

@juandgaines
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MarekFish93 On the EditorsActivity. java you can find this lines of code:
String weightString = mWeightEditText.getText().toString().trim();
int weight = Integer.parseInt(weightString);

This is okay on a ideal world where the user doesn't make mistakes, but what if you try to parse to an integer value when the weightString value is empty, which means "" (No user input). This throws an NumberFormatException because we are trying to convert a empty string to an integer.

my solution:

    String weightString = mWeightEditText.getText().toString().trim();
    int weight ;

   try {
    weight = Integer.parseInt(weightString);
    }catch (NumberFormatException e){
        weight=0; // I set the weight to 0 because this is the default value in the database so..
    }

Regards.

@karkinissan
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My app doesnt crash even if I put in a black pet name.
I had to check for the "" and " " conditions as well to make it crash.
if (petName == null||petName.equals("")||petName.equals(" ")) {

@benji0988
Copy link

@benji0988 benji0988 commented on 6861be5 Aug 17, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@karkinissan
try to edit the if statement for petName into:
if(petName.isEmpty)

i think this is better to check if a String is null or not.

@ahmadjawidmuhammadi
Copy link

@ahmadjawidmuhammadi ahmadjawidmuhammadi commented on 6861be5 Dec 24, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is not working for me. my app crashes and error is:

Process: com.example.android.pets, PID: 30835
                  java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.android.pets
/com.example.android.pets.CatalogActivity}: java.lang.NumberFormatException: Invalid long: "pets"

@awake659
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ahmadjawidmuhammadi Go to PetProvider.java and double check your sUriMatcher.addUri() method. I forgot to put in "/#" after using the PetContract.PATH_PETS.

This was my original way:
sUriMatcher.addURI(PetContract.CONTENT_AUTHORITY, PetContract.PATH_PETS, PetProvider.PET_ID);

So if you look at what i had originally the output would look like: content://com.example.android.pets/pets(then Pet_ID).
If you look below to the correct method call, it would look like this when output: content://com.example.android.pets/pets/5. As you can see i was missing the extra slash and the wildcard that would be replaced by an Integer of pet id. Thus causing the number format exception as it can't find the location to insert the id.

This is the correct way:
sUriMatcher.addURI(PetContract.CONTENT_AUTHORITY, PetContract.PATH_PETS + "/#", PetProvider.PET_ID);

@MadeleineKatherine
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My app has just crashed before I could insert anything. It was beacuse of
"CatalogActivity}: java.lang.IllegalArgumentException: Cannot query unknown URI content://com.example.android.pets/pets"
It is stupid because most of time I was copying everything and i have no idea, where I could do mistake 😢

@MadeleineKatherine
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now when I've opened master version of this app I see that when I don't insert name, or breed, or weight, nothing happens. I thought that we want to see some messages. at least.

@fisal77
Copy link

@fisal77 fisal77 commented on 6861be5 Feb 2, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Katherine, make sure the URI is correct by check the PetProvider.java file

@khash021
Copy link

@khash021 khash021 commented on 6861be5 Feb 20, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am getting errors with both " weight == null" and "gender ==null" sections. Android Studio says "Operator == cannot be applied to 'int' 'null'"

However, I do feel like that by just checking for negative numbers in weight, we are covering it all; since the default is 0 if there is nothing entered, and if the input is negative then it throws an exception.
Also for the Gender, this is un-necessary check since our input is a spinner which has the only three acceptable options, and the user cannot enter anything else.

@SalomeNB
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was getting NullPointer errors when I set the weight to 0 and I couldn't figure out how to solve it other than adding code in the EditorActivity to convert an empty user input to int 0:
String WeightString = WeightField.getText().toString();
int petWeight;
if (WeightString.isEmpty()) {
petWeight = 0;
} else {
petWeight = Integer.parseInt(WeightString);
}

@Apurba000Biswas
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@khash021 - Did you receive weight as "Integer weight = values.getAsInteger(...); or int weight = values.getAsInteger(...); ??"

@khash021
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Apurba000Biswas It was a while ago, I can't remember what I had. Since it was giving me errors, I changed it and got it to work. But now that you mentioned it, I probably used int that's why I was getting an error. == would work with Integer only I assume.
Thanks

@KaidenCoder
Copy link

@KaidenCoder KaidenCoder commented on 6861be5 Apr 19, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can anyone help me here? isValidGender is never used in my code so the program is not working?

Code here:
/**
* Returns whether or not the given gender is {@link #GENDER_UNKNOWN}, {@link #GENDER_MALE},
* or {@link #GENDER_FEMALE}.
*/
public static boolean isValidGender(int gender) {
if (gender == GENDER_UNKNOWN || gender == GENDER_MALE || gender == GENDER_FEMALE) {
return true;
}
return false;
}

/**
* Insert a pet into the database with the given content values. Return the new 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(PetEntry.COLUMN_PET_NAME);
    if (name == null) {
        throw new IllegalArgumentException("Pet requires a name");
    }

    // Check that the gender is valid
    Integer gender = values.getAsInteger(PetEntry.COLUMN_PET_GENDER);
    if (gender == null || !PetEntry.isValidGender(gender)) {
        throw new IllegalArgumentException("Pet requires valid gender");
    }

    // If the weight is provided, check that it's greater than or equal to 0 kg
    Integer weight = values.getAsInteger(PetEntry.COLUMN_PET_WEIGHT);
    if (weight != null && weight < 0) {
        throw new IllegalArgumentException("Pet requires valid weight");
    }

    // No need to check the breed, any value is valid (including null).

    // Get writeable database
    SQLiteDatabase database = mDbHelper.getWritableDatabase();

    // Insert the new pet with the given values
    long id = database.insert(PetEntry.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 at the end
    return ContentUris.withAppendedId(uri, id);
}

Error: error: cannot find symbol method isValidGender(Integer)

gitHub Link: https://github.com/Kurosakicoder/Udacity-done-Pets-starting-point/blob/master/app/src/main/java/com/example/android/pets/data/PetProvider.java

@sherifhisham
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a lot of information and but it is beautiful work

@joaosouzadev
Copy link

@joaosouzadev joaosouzadev commented on 6861be5 May 11, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Kurosakicoder you need to implement the method isValidGender in PetContract.java inside PetEntry class

public static boolean isValidGender(int gender) { if (gender == GENDER_UNKNOWN || gender == GENDER_MALE || gender == GENDER_FEMALE) { return true; } return false; }

@Babadzhanov
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should validate on insertion and not allow the user to proceed if its wrong input. 😃
Keep Calm and Carry On

@Nikoloutsos
Copy link

@Nikoloutsos Nikoloutsos commented on 6861be5 Jun 15, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At first I made weight and gender as int but then I realized that by doing it I cannot check if they are null.
Good work!!
@joaosouzadev Why making an entire method for a simple if statement ??

@Tarek-Bohdima
Copy link

@Tarek-Bohdima Tarek-Bohdima commented on 6861be5 Jul 17, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

     * Prompt the user to confirm that they want to delete all pets.
     */
    private void showDeleteConfirmationDialog() {
        // Create an AlertDialog.Builder and set the message, and click listeners
        // for the positive and negative buttons on the dialog.
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setMessage(R.string.delete_all_pets);
        builder.setPositiveButton(R.string.delete, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
                // User clicked the "Delete" button, so delete the pet.
                deleteAllPets();
                Toast.makeText(getApplicationContext(), R.string.del_pets_success,
                        Toast.LENGTH_SHORT).show();
            }
        });
        builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
                // User clicked the "Cancel" button, so dismiss the dialog
                // and continue editing the pet.
                if (dialog != null) {
                    dialog.dismiss();
                }
            }
        });

        // Create and show the AlertDialog
        AlertDialog alertDialog = builder.create();
        alertDialog.show();
    }

    /**
     * Helper method to delete all pets in the database.
     */
    private void deleteAllPets() {
        int rowsDeleted = getContentResolver().delete(PetEntry.CONTENT_URI, null, null);
        Log.v("CatalogActivity", rowsDeleted + "rows deleted from pets database");
    }

@abdullah-shamali
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

guy I'm struggling with CatalogActivity. app is stopping. and Logcat says its NPE but as a beginner i dont understand which part to change. here is the code.
`package com.example.android.pets;

import android.content.ContentValues;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;

import com.example.android.pets.data.PetContract.PetEntry;

/**

  • Displays list of pets that were entered and stored in the app.
    */
    public class CatalogActivity extends AppCompatActivity {

    @OverRide
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_catalog);

     // Setup FAB to open EditorActivity
     FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
     fab.setOnClickListener(new View.OnClickListener() {
         @Override
         public void onClick(View view) {
             Intent intent = new Intent(CatalogActivity.this, EditorActivity.class);
             startActivity(intent);
         }
     });
    

    }

    @OverRide
    protected void onStart() {
    super.onStart();
    displayDatabaseInfo();
    }

    /**

    • Temporary helper method to display information in the onscreen TextView about the state of

    • the pets database.
      */
      private void displayDatabaseInfo() {
      // Define a projection that specifies which columns from the database
      // you will actually use after this query.
      String[] projection = {
      PetEntry._ID,
      PetEntry.COLUMN_PET_NAME,
      PetEntry.COLUMN_PET_BREED,
      PetEntry.COLUMN_PET_GENDER,
      PetEntry.COLUMN_PET_WEIGHT };

      // Perform a query on the provider using the ContentResolver.
      // Use the {@link PetEntry#CONTENT_URI} to access the pet data.
      Cursor cursor = getContentResolver().query(
      PetEntry.CONTENT_URI, // The content URI of the words table
      projection, // The columns to return for each row
      null, // Selection criteria
      null, // Selection criteria
      null); // The sort order for the returned rows

      TextView displayView = (TextView) findViewById(R.id.text_view_pet);

      try {
      // Create a header in the Text View that looks like this:
      //
      // The pets table contains pets.
      // _id - name - breed - gender - weight
      //
      // In the while loop below, iterate through the rows of the cursor and display
      // the information from each column in this order.
      displayView.setText("The pets table contains " + cursor.getCount() + " pets.\n\n");
      displayView.append(PetEntry._ID + " - " +
      PetEntry.COLUMN_PET_NAME + " - " +
      PetEntry.COLUMN_PET_BREED + " - " +
      PetEntry.COLUMN_PET_GENDER + " - " +
      PetEntry.COLUMN_PET_WEIGHT + "\n");

       // Figure out the index of each column
       int idColumnIndex = cursor.getColumnIndex(PetEntry._ID);
       int nameColumnIndex = cursor.getColumnIndex(PetEntry.COLUMN_PET_NAME);
       int breedColumnIndex = cursor.getColumnIndex(PetEntry.COLUMN_PET_BREED);
       int genderColumnIndex = cursor.getColumnIndex(PetEntry.COLUMN_PET_GENDER);
       int weightColumnIndex = cursor.getColumnIndex(PetEntry.COLUMN_PET_WEIGHT);
      
       // Iterate through all the returned rows in the cursor
       while (cursor.moveToNext()) {
           // Use that index to extract the String or Int value of the word
           // at the current row the cursor is on.
           int currentID = cursor.getInt(idColumnIndex);
           String currentName = cursor.getString(nameColumnIndex);
           String currentBreed = cursor.getString(breedColumnIndex);
           int currentGender = cursor.getInt(genderColumnIndex);
           int currentWeight = cursor.getInt(weightColumnIndex);
           // Display the values from each column of the current row in the cursor in the TextView
           displayView.append("\n" + currentID + " - " +
                   currentName + " - " +
                   currentBreed + " - " +
                   currentGender + " - " +
                   currentWeight);
       }
      

      } finally {
      // Always close the cursor when you're done reading from it. This releases all its
      // resources and makes it invalid.
      if (cursor != null) {
      cursor.close();
      }
      }
      }

    /**

    • Helper method to insert hardcoded pet data into the database. For debugging purposes only.
      */
      private void insertPet() {
      // Create a ContentValues object where column names are the keys,
      // and Toto's pet attributes are the values.
      ContentValues values = new ContentValues();
      values.put(PetEntry.COLUMN_PET_NAME, "Toto");
      values.put(PetEntry.COLUMN_PET_BREED, "Terrier");
      values.put(PetEntry.COLUMN_PET_GENDER, PetEntry.GENDER_MALE);
      values.put(PetEntry.COLUMN_PET_WEIGHT, 7);

      // Insert a new row for Toto into the provider using the ContentResolver.
      // Use the {@link PetEntry#CONTENT_URI} to indicate that we want to insert
      // into the pets database table.
      // Receive the new content URI that will allow us to access Toto's data in the future.
      Uri newUri = getContentResolver().insert(PetEntry.CONTENT_URI, values);
      }

    @OverRide
    public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu options from the res/menu/menu_catalog.xml file.
    // This adds menu items to the app bar.
    getMenuInflater().inflate(R.menu.menu_catalog, 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 "Insert dummy data" menu option
    case R.id.action_insert_dummy_data:
    insertPet();
    displayDatabaseInfo();
    return true;
    // Respond to a click on the "Delete all entries" menu option
    case R.id.action_delete_all_entries:
    // Do nothing for now
    return true;
    }
    return super.onOptionsItemSelected(item);
    }
    }`
    here is the Logcat
    npe

@kretherford0983
Copy link

@kretherford0983 kretherford0983 commented on 6861be5 Nov 4, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@abdullah-shamali I tried using your code but I am not getting any NullPointerExceptions. Not sure what to tell you. Looking at the lines Logcat is pointing at (if I counted correctly) those are comment lines.

@enachescurobert
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cl5rt Did you input a name?
If no, this is the expected behavior as you are throwing a IllegalArgumentException when the name is empty so the app crashes.
I think for new learners, Udacity should use visual feedback like Toast to know if the input validation is correct instead of exceptions.

Here is my fix:
6861be5#commitcomment-33260481

Please sign in to comment.