Creating an app for seeing pets in the store, where I've created a database and a table called shelter.db and pets respectively. I've created a contract class to store all the constants related to the database, a class called PetDbHelper that extends SQLiteOpenHelper. I have two activities CatalogActivity and EditorActivity. In CatalogActivity, I'm trying to read the table and here I tried to get the column indices of each column but the last column named 'weight' returns -1 which means as you may know 'no column exists' and in EditorActivity, I'm trying to insert pets in the table. I've checked everything but have no clue what's wrong with my code.
Here's the PetContract class:
package com.example.android.pets.data;
import android.provider.BaseColumns;
public final class PetsContract {
public static final class PetEntry implements BaseColumns {
// CONSTANTS FOR TABLE AND COLUMN NAMES
public static final String TABLE_NAME = "pets";
public static final String _ID = BaseColumns._ID;
public static final String COLUMN_PET_NAME = "name";
public static final String COLUMN_PET_BREED = "breed";
public static final String COLUMN_PET_GENDER = "gender";
public static final String COLUMN_PET_WEIGHT = " weight";
// CONSTANTS FOR GENDER
public static final int GENDER_UNKNOWN = 0;
public static final int GENDER_MALE = 1;
public static final int GENDER_FEMALE = 2;
}
}
Here's the PetDbHelper that extends SQLiteOpenHelper class:
package com.example.android.pets.data;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class PetDbHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "shelter.db";
private static final int DATABASE_VERSION = 1;
public PetDbHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
String CREATE_TABLE = "CREATE TABLE " + PetsContract.PetEntry.TABLE_NAME
+ " (" + PetsContract.PetEntry._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ PetsContract.PetEntry.COLUMN_PET_NAME + " TEXT NOT NULL, "
+ PetsContract.PetEntry.COLUMN_PET_BREED + " TEXT, "
+ PetsContract.PetEntry.COLUMN_PET_GENDER + " INTEGER NOT NULL, "
+ PetsContract.PetEntry.COLUMN_PET_WEIGHT + " INTEGER NOT NULL DEFAULT 0);";
db.execSQL(CREATE_TABLE);
}
#Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
}
}
Here's the code of CatalogActivity.java that is related to database:
/**
* Displays list of pets that were entered and stored in the app.
*/
public class CatalogActivity extends AppCompatActivity {
private PetDbHelper mDbHelper;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_catalog);
mDbHelper = new PetDbHelper(this);
private void displayDatabaseInfo() {
// To access our database, we instantiate our subclass of
SQLiteOpenHelper
// and pass the context, which is the current activity.
// CREATE AND/OR OPEN A DATABASE TO READ FROM IT
SQLiteDatabase db = mDbHelper.getReadableDatabase();
// String[] projection = {PetEntry._ID, PetEntry.COLUMN_PET_NAME, PetEntry.COLUMN_PET_BREED, PetEntry.COLUMN_PET_GENDER, PetEntry.COLUMN_PET_WEIGHT};
Cursor cursor = db.query(PetEntry.TABLE_NAME, null, null, null, null, null, null);
//Cursor cursor = db.rawQuery("SELECT * FROM pets", null);
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 <number of rows in Cursor> 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.getColumnCount() + " pets.\n\n");
displayView.append(PetEntry._ID + " - " +
PetEntry.COLUMN_PET_NAME + " - " +
PetEntry.COLUMN_PET_BREED + " - " +
PetEntry.COLUMN_PET_GENDER + " - " +
PetEntry.COLUMN_PET_WEIGHT );
// 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);
Toast.makeText(this,
"weight_index ?" + weightColumnIndex + "\n"
+ "id_index" + idColumnIndex + "\n"
+ "name_index" + nameColumnIndex + "\n"
+ "breed_index" + breedColumnIndex + "\n"
+ "gender_index" + genderColumnIndex , Toast.LENGTH_LONG).show();
} finally {
// Always close the cursor when you're done reading from it. This releases all its
// resources and makes it invalid.
cursor.close();
}
}
#Override
protected void onStart() {
super.onStart();
displayDatabaseInfo();
}
I know that's a lot of code, and here's the last piece of code of EditorActivity.java class: (excluded the code related to spinner object)
**
* 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;
#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);
}
private void addPet() {
String name = mNameEditText.getText().toString().trim();
String breed = mBreedEditText.getText().toString().trim();
int weight = Integer.parseInt(mWeightEditText.getText().toString().trim());
ContentValues values = new ContentValues();
values.put(COLUMN_PET_NAME, name);
values.put(COLUMN_PET_BREED, breed);
values.put(COLUMN_PET_GENDER, mGender);
values.put(COLUMN_PET_WEIGHT, weight);
PetDbHelper mDbHelper = new PetDbHelper(this);
SQLiteDatabase db = mDbHelper.getWritableDatabase();
long result = db.insert(TABLE_NAME, null, values);
if (result != -1) {
Toast.makeText(this, "Pet saved with id: " + result, Toast.LENGTH_SHORT).show();
} else {Toast.makeText(this, "Error with saving pet", Toast.LENGTH_SHORT).show();}
}
#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 into the database
addPet();
// Exit the 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);
}
}
Leading whitespace is ignored in SQL but it matters in map keys - column names and their indices are essentially stored in a map you can access with getColumnIndex().
public static final String COLUMN_PET_WEIGHT = " weight";
Remove the leading whitespace here.
Related
I'm working on an assignment for a college course. I'm really new to coding so I apologize if this is an obvious fix.
The assignment is:
Create an activity app with two forms. The main form should have a list view, an add button, an edit button, a view button, and a delete button. On the click of any button you should navigate the user to the second form that will be populated properly for the button action using data passed using an intent object. Your second form should be a layout to input a name and address. The form needs to contain First Name, Last Name, Street Address, Town, State, and Zip code. All your entry fields should be correctly labeled / Hinted so the user will know what to enter. In addition to the fields you will need an “OK”, "Cancel", and a “Clear” button. If the user clicks the “Clear” button you need to clear all the entries. If the user clicks the “OK” or “Cancel” buttons, you should return the button selection and form data to the main form using an intent object. The main activity should process the response and add, update, or delete the record. All records should be added, updated, or delete within a SQLite database that is automatically created by your application. Your program should generate an alert message that confirms the action completed.
I'm getting an error in the cursorToAddressAttributeGroup method saying that the value cursor.getColumnIndexshould be greater than 0. How do I set it to be greater than 0?
This is the class that is having the issue:
package com.example.program5;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.*;
import com.example.program5.AddressCollection.AddressCollectionDB;
public class AddressDatabaseHelper extends SQLiteOpenHelper
{
public static final String TABLE_ADDRESS = "address";
public static final String COLUMN_ID = "id";
public static final String COLUMN_FIRSTNAME = "firstName";
public static final String COLUMN_LASTNAME ="lastName";
public static final String COLUMN_STREET_ADDRESS = "streetAddress";
public static final String COLUMN_TOWN = "town";
public static final String COLUMN_STATE = "state";
public static final String COLUMN_ZIP ="zip";
private static final String DATABASE_NAME = "address.db";
private static final int DATABASE_VERSION = 1;
// Database creation SQL statement
private static final String DATABASE_CREATE_SQL = "create table "
+ TABLE_ADDRESS + "("
+ COLUMN_ID + " integer primary key autoincrement, "
+COLUMN_FIRSTNAME + " text not null, "
+COLUMN_LASTNAME + "text not null, "
+COLUMN_STREET_ADDRESS + "text not null, "
+COLUMN_TOWN + "text not null, "
+COLUMN_STATE + "text not null, "
+COLUMN_ZIP + "text not null);";
public AddressDatabaseHelper(Context context)
{
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
//onCreate method creates table
#Override
public void onCreate(SQLiteDatabase database)
{
//directly executes SQl statement create table
database.execSQL(DATABASE_CREATE_SQL);
}
//onUpgrade method upgrades the table
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
{
//drops table if it exists
db.execSQL("DROP TABLE IF EXISTS " + TABLE_ADDRESS);
//calls onCreate method and passes db as an argument
onCreate(db);
}
}
class AddressDataSource
{
private SQLiteDatabase database;
private final AddressDatabaseHelper dbHelper;
private String[] allColumns = { AddressDatabaseHelper.COLUMN_ID,
AddressDatabaseHelper.COLUMN_FIRSTNAME, AddressDatabaseHelper.COLUMN_LASTNAME,
AddressDatabaseHelper.COLUMN_STREET_ADDRESS, AddressDatabaseHelper.COLUMN_TOWN,
AddressDatabaseHelper.COLUMN_STATE, AddressDatabaseHelper.COLUMN_ZIP };
//AddressDataSource passes c as argument
public AddressDataSource(Context c)
{
super();
// dbHelper equals AddressDatabaseHelper passing c as parameter
dbHelper = new AddressDatabaseHelper(c);
}
//open method
public void open() throws SQLException {
//sets database equal to dbHelper.getWritableDatabase
database = dbHelper.getWritableDatabase();
}
//close method
public void close()
{
//closes dbHelper
dbHelper.close();
}
//createAddress method passes address as argument
public long createAddress(AddressAttributeGroup address)
{
//creates new ContentValues object called values
ContentValues values = new ContentValues();
//puts values of firstname and lastname into COLUMN_NAME
values.put(AddressDatabaseHelper.COLUMN_ID,address.id);
values.put(AddressDatabaseHelper.COLUMN_FIRSTNAME, address.firstName );
values.put(AddressDatabaseHelper.COLUMN_LASTNAME, address.lastName );
values.put(AddressDatabaseHelper.COLUMN_STREET_ADDRESS, address.streetAddress);
values.put(AddressDatabaseHelper.COLUMN_TOWN,
address.town);
values.put(AddressDatabaseHelper.COLUMN_STATE,address.state);
values.put(AddressDatabaseHelper.COLUMN_ZIP,address.zip);
/* returns insertId */
long insertId = database.insert(AddressDatabaseHelper.TABLE_ADDRESS,
null,
values);
return insertId;
// return database.insert(AddressDatabaseHelper.TABLE_ADDRESS,null,values);
}
//deleteAddress method passes address as argument
public void deleteAddress(AddressAttributeGroup address)
{ //sets id equal to address.id
long id = address.id;
//deletes the entry stored at address.id in the TABLE_ADDRESS table
database.delete(AddressDatabaseHelper.TABLE_ADDRESS,
AddressDatabaseHelper.COLUMN_ID + " = " + id, null);
}
//getAllAddresses method
public AddressCollectionDB getAllAddresses() throws Exception
{ AddressCollectionDB addresses = new AddressCollectionDB();
Cursor cursor = database.query(AddressDatabaseHelper.TABLE_ADDRESS,
allColumns, null, null, null, null, null);
cursor.moveToFirst();
while (!cursor.isAfterLast())
{
//adds address to addresses
addresses.addAddress(cursorToAddressAttributeGroup(cursor));
//and moves cursor to next entry
cursor.moveToNext();
}
//closes the cursor
cursor.close();
//returns addresses
return addresses;
}
private AddressAttributeGroup cursorToAddressAttributeGroup(Cursor cursor)
{
//error must be greater than 0. Figure out what is causing the error?
(cursor.getInt(cursor.getColumnIndex(AddressDatabaseHelper.COLUMN_ID)),
cursor.getString(cursor.getColumnIndex(AddressDatabaseHelper.COLUMN_FIRSTNAME)),
cursor.getString(cursor.getColumnIndex(AddressDatabaseHelper.COLUMN_LASTNAME)),
cursor.getString(cursor.getColumnIndex(AddressDatabaseHelper.COLUMN_STREET_ADDRESS)),
cursor.getString(cursor.getColumnIndex(AddressDatabaseHelper.COLUMN_TOWN)),
cursor.getString(cursor.getColumnIndex(AddressDatabaseHelper.COLUMN_STATE)),
cursor.getString(cursor.getColumnIndex(AddressDatabaseHelper.COLUMN_ZIP)));
}
}
Here are theother classes in the program for context:
AddressAttributeGroup Class:
package com.example.program5;
public class AddressAttributeGroup {
//declare Strings for name and address and a long for the id number
public long id;
public String firstName;
public String lastName;
public String streetAddress;
public String town;
public String state;
public String zip;
//constructor
public AddressAttributeGroup(long id, String firstName, String lastName, String streetAddress,
String town, String state, String zip) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
this.streetAddress = streetAddress;
this.town = town;
this.state = state;
this.zip = zip;
}
AddressCollection Class:
package com.example.program5;
import android.content.Context;
import java.util.ArrayList;
public class AddressCollection {
ArrayList<AddressAttributeGroup> addressList = new ArrayList<>();
final int MAXIMUM_ADDRESS_COUNT = 10;
//boolean that checks if amount of records in arrayList equal to or greater than limit
public boolean isAddressLimitReached()
{
return (addressList.size() >= MAXIMUM_ADDRESS_COUNT);
}
public int addAddress(AddressAttributeGroup address) throws Exception {
//if arrayList is full
if (isAddressLimitReached())
{
throw (new Exception("Maximum Address Reached."));
}
//adds new address to the arraylist addressList
addressList.add(address);
//returns the index of address
return addressList.indexOf(address);
}
public void setAddress(int addressIndex, AddressAttributeGroup address) {
addressList.set(addressIndex, address);
}
public void removeAddress(int addressIndex) {
//removes address at the index addressIndex
addressList.remove(addressIndex);
}
//
public AddressAttributeGroup getAddress(int addressIndex) {
return addressList.get(addressIndex);
}
static class AddressCollectionDB extends AddressCollection
{static public AddressDataSource addressData;
public static AddressCollectionDB AddressCollectionFactory(Context context)
{
AddressCollectionDB resultCode = new AddressCollectionDB();
addressData = new AddressDataSource(context);
try {
addressData.open();
resultCode = addressData.getAllAddresses();
addressData.close();
} catch (Exception e) {
e.printStackTrace();
}
return resultCode;
}
public int addAddress (AddressAttributeGroup address) throws Exception
{
if (isAddressLimitReached())
throw (new Exception("Maximum Address Reached."));
addressData.open();
address.id = addressData.createAddress(address);
addressData.close();
return super.addAddress(address);
}
public void setAddress ( int addressIndex, AddressAttributeGroup address)
{
addressData.open();
addressData.deleteAddress(getAddress(addressIndex));
address.id = addressData.createAddress(address);
addressData.close();
super.setAddress(addressIndex, address);
}
public void removeAddress ( int addressIndex)
{
addressData.open();
addressData.deleteAddress(getAddress(addressIndex));
addressData.close();
super.removeAddress(addressIndex);
}
}
}
AddressConsole class:
package com.example.program5;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import com.example.program5.StrongIntent.TypeOfAction;
import com.example.program5.AddressCollection.AddressCollectionDB;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
public class AddressConsole extends AppCompatActivity implements View.OnClickListener,
AdapterView.OnItemClickListener, AdapterView.OnItemSelectedListener {
Button cmdAdd;
Button cmdDelete;
Button cmdView;
Button cmdEdit;
TextView textAddressMessage;
EditText editRecordNumber;
ListView listOfAddresses;
final int ADDRESS_ENTRY = 1001;
AddressCollectionDB addresses;
//AddressCollection addresses = new AddressCollection();
AddressArrayAdapter addressAdapter;
int recordNumber = +1;
#Override
protected void onCreate(Bundle saveInstanceState)
{
super.onCreate(saveInstanceState);
setContentView(R.layout.address_console);
textAddressMessage = findViewById(R.id.textAddressMessage);
editRecordNumber = findViewById(R.id.editRecordNumber);
cmdAdd = findViewById(R.id.cmdAdd);
cmdAdd.setOnClickListener(this);
cmdEdit = findViewById(R.id.cmdEdit);
cmdEdit.setOnClickListener(this);
cmdDelete = findViewById(R.id.cmdDelete);
cmdDelete.setOnClickListener(this);
cmdView = findViewById(R.id.cmdView);
cmdView.setOnClickListener(this);
listOfAddresses = findViewById(R.id.listOfAddresses);
listOfAddresses.setOnItemClickListener (this);
listOfAddresses.setOnItemSelectedListener( this);
addresses = AddressCollectionDB.AddressCollectionFactory(this);
addressAdapter = new AddressArrayAdapter(this, R.layout.row_layout, addresses);
listOfAddresses.setAdapter(addressAdapter);
}
void displayError(Exception message) {
Toast.makeText(this,message.getMessage(),Toast.LENGTH_LONG).show();
}
void displayError(){
Toast.makeText(this, "Maximum Number Of Addresses Reached!",Toast.LENGTH_LONG).show();
}
void displayInfo(String message)
{
Toast.makeText(this, message,Toast.LENGTH_SHORT).show();
}
//hmm why is this never used?
void displayAddressMessage(AddressAttributeGroup address)
{//issue
textAddressMessage.setText("Address:" + address.firstName + " " + address.lastName + " " +
address.streetAddress + " "
+ address.town + "" + address.state + " " + address.zip);
}
void clearAddressMessage()
{
textAddressMessage.setText("");
}
#Override
public void onClick(View view) {
StrongIntent intent;
//if user clicks add button
if(cmdAdd.getId() == view.getId())
{
//if address limit has not been reached
if(!addresses.isAddressLimitReached())
{
//intent equals new Strong Intent
intent = new StrongIntent();
//intent action is equal to ADD
intent.action = TypeOfAction.ADD;
startActivityForResult(intent.getIntent(this, AddressEntry.class),ADDRESS_ENTRY);
}
//else
else
//calls display error message
displayError();
}
else
{
try {
{
AddressAttributeGroup address = addresses.getAddress(recordNumber);
//if user clicks edit
if(cmdEdit.getId() == view.getId())
{
//intent equals new StrongIntent passing address, typeOfAction and record number as arguments
intent = new StrongIntent(address,TypeOfAction.EDIT,recordNumber);
startActivityForResult(intent.getIntent(this,AddressEntry.class),ADDRESS_ENTRY);
}
//if user clicks delete button
if(cmdDelete.getId()==view.getId())
{
//intent equals StrongIntent passing address DELETE and record number as arguments
intent = new StrongIntent(address, TypeOfAction.DELETE,recordNumber);
startActivityForResult(intent.getIntent(this,AddressEntry.class),ADDRESS_ENTRY);
}
//if user clicks view
if(cmdView.getId() == view.getId())
{
//calls displayAddressMessage and passes address as an argument
displayAddressMessage(address);
}
}
//catch block
} catch (Exception ex) {
displayError(ex);
}
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
StrongIntent addressIntent = new StrongIntent(data);
if (requestCode == ADDRESS_ENTRY) {
try {
//switch statement passes resultCode as argument
switch (resultCode) {
case RESULT_OK:
AddressAttributeGroup address = new AddressAttributeGroup(addressIntent.addressIndex,addressIntent.firstName, addressIntent.lastName,
addressIntent.streetAddress, addressIntent.town, addressIntent.state, addressIntent.zip);
switch (addressIntent.action) {
case ADD:
addresses.addAddress(address);
displayAddressMessage(address);
displayInfo("Added + Address:" + address.firstName + " " + address.lastName + " " + address.streetAddress + " "
+ address.town + "" + address.state + " " + address.zip);
break;
case DELETE:
addresses.removeAddress(addressIntent.addressIndex);
displayInfo("Address Deleted");
clearAddressMessage();
editRecordNumber.setText("");
recordNumber =-1;
break;
case EDIT:
addresses.setAddress(addressIntent.addressIndex,address);
displayAddressMessage(address);
displayInfo("Address Updated");
break;
}
addressAdapter.notifyDataSetChanged();
break;
case RESULT_CANCELED:
displayInfo("Cancelled");
break;
}
}
//catch block
catch(Exception ex)
{
displayError(ex);
}
}
super.onActivityResult(requestCode,resultCode,data);
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
onItemSelected(parent, view, position,id);
AddressAttributeGroup address = addresses.getAddress(recordNumber);
displayAddressMessage(address);
}
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
recordNumber = position;
editRecordNumber.setText(String.valueOf(recordNumber));
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
class AddressArrayAdapter extends ArrayAdapter<AddressAttributeGroup> {
private final Context context;
private final AddressCollection addresses;
public AddressArrayAdapter(Context context, int resource, AddressCollection addresses) {
super(context, resource, addresses.addressList);
this.context = context;
this.addresses = addresses;
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
AddressAttributeGroup address = addresses.getAddress(position);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView;
rowView = inflater.inflate(R.layout.row_layout, parent, false);
TextView firstNameTextView = rowView.findViewById(R.id.editFirstName);
TextView lastNameTextView = rowView.findViewById(R.id.editLastName);
TextView addressTextView = rowView.findViewById(R.id.editStreetAddress);
TextView townTextView;
townTextView = rowView.findViewById(R.id.editTown);
TextView stateTextView = rowView.findViewById(R.id.editState);
TextView zipTextView = rowView.findViewById(R.id.editZip);
firstNameTextView.setText(address.firstName);
lastNameTextView.setText(address.lastName);
addressTextView.setText(address.streetAddress);
townTextView.setText(address.town);
stateTextView.setText(address.state);
zipTextView.setText(address.zip);
return rowView;
}
}
}
Strong Intent Class:
package com.example.program5;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
public class StrongIntent
{
public String firstName;
public String lastName;
public String streetAddress;
public String town;
public String state;
public String zip;
public enum TypeOfAction
{
ADD,
EDIT,
DELETE
}
TypeOfAction action;
int addressIndex = +1;
Intent intent;
public StrongIntent(Intent intent)
{
Bundle bundle = intent.getExtras();
//try/catch block for retrieving key value pairs for intent bundle
try
{
firstName = bundle.getString("firstName");
lastName = bundle.getString("lastName");
streetAddress = bundle.getString("streetAddress");
town = bundle.getString("town");
state = bundle.getString("state");
zip = bundle.getString("zip");
//retrieves the action type chosen
action = TypeOfAction.values()[bundle.getInt("action",0)];
//gets address index
addressIndex = bundle.getInt("addressIndex");
}
//catch block
catch (Exception ex) {
ex.printStackTrace();
}
}
//constructor
public StrongIntent()
{ firstName = "";
lastName = "";
streetAddress = "";
town = "";
state= "";
zip = "";
}
//constructor which passes addressAttributes, action and addressIndex as arguments
public StrongIntent(AddressAttributeGroup addressAttributes, TypeOfAction action, int addressIndex)
{
firstName = addressAttributes.firstName;
lastName = addressAttributes.lastName;
streetAddress = addressAttributes.streetAddress;
town = addressAttributes.town;
state= addressAttributes.state;
zip = addressAttributes.zip;
this.action = action;
this.addressIndex = addressIndex;
}
//sets intent equal to null
public void clearIntent()
{
intent = null;
}
//adds data to intent bundle
void putExtras()
{
intent.putExtra("firstName",firstName);
intent.putExtra("lastName",lastName);
intent.putExtra("streetAddress",streetAddress);
intent.putExtra("town",town);
intent.putExtra("state",state);
intent.putExtra("zip",zip);
intent.putExtra("action",action.ordinal());
intent.putExtra("addressIndex",addressIndex);
}
public Intent getIntent()
{ //if intent is equal to null
if (intent == null)
//sets intent equal to new Intent
{ intent = new Intent();
//calls putExtras method
putExtras();
}
//returns intent
return intent;
}
public Intent getIntent(Activity addressEntry,
Class<AddressEntry> class1)
{
//if intent is equal to null
if (intent == null)
{
intent = new Intent(addressEntry,class1);
//calls putExtras method
putExtras();
}
//returns intent
return intent;
}
}
AddressEntry Class:
package com.example.program5;
import android.os.Bundle;
import android.app.Activity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
public class AddressEntry extends Activity implements View.OnClickListener{
Button cmdSave;
Button cmdClear;
Button cmdCancel;
EditText editFirstName;
EditText editLastName;
EditText editStreetAddress;
EditText editTown;
EditText editState;
EditText editZip;
int result;
StrongIntent stIntent;
#Override
public void onCreate(Bundle savedInstanceState)
{ super.onCreate(savedInstanceState);
setContentView(R.layout.address_entry);
editFirstName = findViewById(R.id.editFirstName);
editLastName = findViewById(R.id.editLastName);
editStreetAddress = findViewById(R.id.editStreetAddress) ;
editTown = findViewById(R.id.editTown);
editState = findViewById(R.id.editState);
editZip = findViewById(R.id.editZip);
cmdSave = findViewById(R.id.cmdSave);
cmdSave.setOnClickListener(this);
cmdClear = findViewById(R.id.cmdClear);
cmdClear.setOnClickListener(this);
cmdCancel = findViewById(R.id.cmdCancel);
cmdCancel.setOnClickListener(this);
stIntent = new StrongIntent(getIntent());
editFirstName.setText(stIntent.firstName);
editLastName.setText(stIntent.lastName);
editStreetAddress.setText(stIntent.streetAddress);
editTown.setText(stIntent.town);
editState.setText(stIntent.state);
editZip.setText(stIntent.zip);
//if the type of action is equal to DELETE
if (stIntent.action ==StrongIntent.TypeOfAction.DELETE)
//if user clicks Save sets text to Delete
cmdSave.setText(R.string.deleteString);
//enables action when delete is not selected
editFirstName.setEnabled(stIntent.action!=StrongIntent.TypeOfAction.DELETE);
editLastName.setEnabled(stIntent.action!=StrongIntent.TypeOfAction.DELETE);
editStreetAddress.setEnabled(stIntent.action != StrongIntent.TypeOfAction.DELETE);
editTown.setEnabled(stIntent.action != StrongIntent.TypeOfAction.DELETE);
editState.setEnabled(stIntent.action != StrongIntent.TypeOfAction.DELETE);
editZip.setEnabled(stIntent.action != StrongIntent.TypeOfAction.DELETE);
cmdClear.setEnabled(stIntent.action!=StrongIntent.TypeOfAction.DELETE);
}
#Override
public void onClick(View view)
{
//if Save is clicked
if(cmdSave.getId() == view.getId())
{
//result equals RESULT_OK
result = RESULT_OK;
//calls the finish method
finish();
}
//if Clear is clicked
if(cmdClear.getId() == view.getId())
//clears all values entered
{ editFirstName.setText("");
editLastName.setText("");
editStreetAddress.setText("");
editTown.setText("");
editState.setText("");
editZip.setText("");
}//if Cancel is clicked
if(cmdCancel.getId() == view.getId())
{ //result is equal to RESULT_CANCELED
result = RESULT_CANCELED;
//calls finish method
finish();
}
}
#Override
public void finish()
{ //clears intent
stIntent.clearIntent();
//sets firstName equal to editFirstName
stIntent.firstName= editFirstName.getText().toString();
//sets lastName equal to editLastName
stIntent.lastName = editLastName.getText().toString();
//sets streetAddress equal to editStreetAddress
stIntent.streetAddress =editStreetAddress.getText().toString();
//sets town equal to editTown
stIntent.town = editTown.getText().toString();
//sets state equal to editState
stIntent.state = editState.getText().toString();
//sets zip equal to editZip
stIntent.zip = editZip.getText().toString();
//sets result passing result and the intent as arguments
setResult(result, stIntent.getIntent());
//calls super.finish method
super.finish();
}
}
I believe that the cause is an issue with SDK 31.
The options to circumvent this is to do one of the following:-
Change to use SDK 30 in the build gradle.
Use #SuppressLint("Range") on the line before private AddressAttributeGroup cursorToAddressAttributeGroup(Cursor cursor)
Use getColumnIndexOrThrow instead of getColumnIndex
get the index prior to the get????
e.g.
int idx = cursor.getColumnIndex(AddressDatabaseHelper.COLUMN_ID);
cursor.getInt(idx);
You should also change :
// Database creation SQL statement
private static final String DATABASE_CREATE_SQL = "create table "
+ TABLE_ADDRESS + "("
+ COLUMN_ID + " integer primary key autoincrement, "
+COLUMN_FIRSTNAME + " text not null, "
+COLUMN_LASTNAME + "text not null, "
+COLUMN_STREET_ADDRESS + "text not null, "
+COLUMN_TOWN + "text not null, "
+COLUMN_STATE + "text not null, "
+COLUMN_ZIP + "text not null);";
to :-
// Database creation SQL statement
private static final String DATABASE_CREATE_SQL = "create table "
+ TABLE_ADDRESS + "("
+ COLUMN_ID + " integer primary key autoincrement, "
+COLUMN_FIRSTNAME + " text not null, "
+COLUMN_LASTNAME + " text not null, "
+COLUMN_STREET_ADDRESS + "text not null, " //<<<<< ADDED SPACE
+COLUMN_TOWN + " text not null, " //<<<<< ADDED SPACE
+COLUMN_STATE + " text not null, " //<<<<< ADDED SPACE
+COLUMN_ZIP + " text not null);"; //<<<<< ADDED SPACE
As otherwise the column names (those commented with //<<<<< ADDED SPACE) will be the expected column name suffixed with text and would then result in -1 being returned and a resultant column index error when run. e.g. Instead of lastname the column name would be lastnametext
I've got two Fragments
AddActivityFragment - This Fragment is responsible for adding data into my SQLite database.
and
ActivityListFragment - This Fragment is responsible for displaying the data in a ListView
The problem is that whenever data is added to the SQLite table, the table is not updated until the application is restarted. Because of this, if I try to add some data into the table, it is not updated in the ListView until I restart the application.
I've come across adapter.notifyDataSetChanged() on multiple threads regarding similar problems but I can not for the life of me figure out how I'm supposed to implement this into my own code.
AddActivityFragment.java:
public class AddActivityFragment extends Fragment implements View.OnClickListener {
private static final String TAG = "AddActivityFragment";
private TextInputLayout activityNameTextField, activityDateTextField;
private TextInputEditText activityNameInput, activityDateInput;
public DatabaseHelper mDatabaseHelper;
private LocationRequest mLocationRequest;
private FusedLocationProviderClient mFusedLocationProviderClient;
private Location mLastLocation;
private ActivityListFragment mActivityListFragment;
private DatePicker mDatePicker;
Context mContext;
private double activityLocationLat;
private double activityLocationLong;
public AddActivityFragment() {
// Required empty public constructor
}
#Override
public android.view.View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View activityViewFragment = inflater.inflate(R.layout.fragment_add_activity, container, false);
// Get context from fragment.
this.mContext = activityViewFragment.getContext();
mDatabaseHelper = new DatabaseHelper(mContext);
// Find the layout components.
activityNameTextField = activityViewFragment.findViewById(R.id.activityNameTextField);
activityNameInput = activityViewFragment.findViewById(R.id.activityNameInput);
mDatePicker = activityViewFragment.findViewById(R.id.datePicker);
Button addActivityButton = activityViewFragment.findViewById(R.id.addActivityButton);
// Set listener to addActivityButton in this view.
addActivityButton.setOnClickListener(this);
// Set hints for text fields.
activityNameTextField.setHint("Activity Name");
return activityViewFragment;
}
#Override
public void onClick(View v) {
switch(v.getId()) {
case R.id.addActivityButton:
StringBuilder sb = new StringBuilder();
int day = mDatePicker.getDayOfMonth();
int month = mDatePicker.getMonth() + 1;
int year = mDatePicker.getYear();
sb.append(day);
sb.append("-");
sb.append(month);
sb.append("-");
sb.append(year);
String activityName = activityNameInput.getText().toString();
String activityDate = sb.toString();
activityNameInput.setText("");
//Add the activity data to the SQL database
mDatabaseHelper.addData(activityName,activityDate,activityLocationLat,activityLocationLong);
break;
default:
break;
}
#Override
public void onResume(){
super.onResume();
Log.d(TAG,"Log when activity is swiped to.");
}
#Override
public void onPause() {
super.onPause();
Log.d(TAG, "List paused.");
}
}
ActivityListFragment.java:
public class ActivityListFragment extends Fragment {
//Class tag
private static final String TAG = "ActivityListFragment";
private static final String ACTIVITY_LIST_FRAGMENT_TAG = "ACTIVITY_LIST_FRAGMENT";
DatabaseHelper mDatabaseHelper;
Context mContext;
private ListView mListView;
public ArrayAdapter adapter;
private ArrayList<ArrayList> listData;
public ActivityListFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View listViewFragment = inflater.inflate(R.layout.fragment_activity_list, container, false);
this.mContext = listViewFragment.getContext();
mListView = listViewFragment.findViewById(R.id.activity_list_view);
mDatabaseHelper = new DatabaseHelper(mContext);
listData = new ArrayList<>();
for(int i = 0; i < mDatabaseHelper.getRowCount(); i++) {
listData.add(mDatabaseHelper.getDataFromIndex(i));
}
adapter = new ArrayAdapter<>(mContext, android.R.layout.simple_list_item_1, listData);
mListView.setAdapter(adapter);
handleOnItemClick();
return listViewFragment;
}
#Override
public void onResume(){
super.onResume();
Log.d(TAG,"Log when activity is swiped to.");
}
#Override
public void onPause() {
super.onPause();
Log.d(TAG, "List paused.");
}
ViewPagerAdapter.java:
public class ViewPagerAdapter extends FragmentStateAdapter {
public ViewPagerAdapter(#NonNull FragmentManager fragmentManager, #NonNull Lifecycle lifecycle) {
super(fragmentManager, lifecycle);
}
#NonNull
#Override
public Fragment createFragment(int position) {
switch (position) {
case 0:
return new MapViewFragment();
case 1:
return new AddActivityFragment();
case 2:
return new ActivityListFragment();
}
return null;
}
#Override
public int getItemCount() {
return 3;
}
}
DataBaseHelper.java:
public class DatabaseHelper extends SQLiteOpenHelper {
private static final String TAG = "DatabaseHelper";
//Table name, column names.
private static final String TABLE_NAME = "activity_table";
private static final String COL_ID = "ID";
private static final String COL_NAME = "name";
private static final String COL_DATE = "date";
private static final String COL_LOCATION_LAT = "location_lat";
private static final String COL_LOCATION = "location_long";
private Cursor mCursor;
ArrayList latLongList;
public DatabaseHelper(Context context) {
super(context, TABLE_NAME, null, 1);
}
/**
* Method: onCreate
* #param db - The database that we are creating the table in.
*/
#Override
public void onCreate(SQLiteDatabase db) {
String CREATE_ACTIVITES_TABLE = "CREATE TABLE " + TABLE_NAME + "("
+ COL_ID + " INTEGER PRIMARY KEY," + COL_NAME + " VARCHAR,"
+ COL_DATE + " VARCHAR," + COL_LOCATION_LAT + " DOUBLE," + COL_LOCATION + " DOUBLE" + ");";
db.execSQL(CREATE_ACTIVITES_TABLE);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
onCreate(db);
}
/**
* Method: addData
* #param name - The "name"-value which is added to the table column COL_NAME.
* #param date - The "date"-value which is added to the table column COL_DATE.
* #param locationLat - The "locationLat"-value which is added to the table column COL_LOCATION_LAT.
* #param locationLong - The "locationLong"-value which is added to the table column COL_LOCATION_LONG.
* #return true or false, depending if the addition to the table was successful or not.
*/
public boolean addData(String name, String date, Double locationLat, Double locationLong) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(COL_NAME, name);
contentValues.put(COL_DATE, date);
contentValues.put(COL_LOCATION_LAT, locationLat);
contentValues.put(COL_LOCATION, locationLong);
Log.d(TAG, "addData: Adding " + name + " to " + TABLE_NAME);
Log.d(TAG, "addData: Adding " + date + " to " + TABLE_NAME);
Log.d(TAG, "addData: Adding " + locationLat + " to " + TABLE_NAME);
Log.d(TAG, "addData: Adding " + locationLong + " to " + TABLE_NAME);
long result = db.insert(TABLE_NAME, null, contentValues);
if(result == -1) {
Log.d(TAG, "Something went wrong when adding data to database.");
return false;
} else {
Log.d(TAG, "Data correctly added to database");
return true;
}
}
/**
* Method: getData
* #return mCursor - Returns entire table from database.
*/
public Cursor getData() {
SQLiteDatabase db = this.getWritableDatabase();
String query = "SELECT * FROM " + TABLE_NAME;
mCursor = db.rawQuery(query, null);
return mCursor;
}
/**
* Method: getDataFromIndex
* #param index - Row index in activity_table table.
* #return list - ArrayList of data at row index.
*/
public ArrayList getDataFromIndex (int index) {
ArrayList list = new ArrayList();
if(mCursor == null) {
getData();
}
mCursor.moveToPosition(index);
list.add(mCursor.getString(1));
list.add(mCursor.getString(2));
list.add(mCursor.getDouble(3));
list.add(mCursor.getDouble(4));
return list;
}
/**
* Method: getRowCount
* #return mCursor.getCount - Total amount of rows in table.
*/
public int getRowCount() {
if(mCursor == null) {
getData();
}
return mCursor.getCount();
}
/** TODO: This might be useless as we will need to fetch the names associated to the activity anyway, to be decided.
* Method: latLongArrayListFromIndex
* #param index - Row index in activity_table table.
* #return latLongList - ArrayList of data at row index.
*/
public ArrayList latLongArrayListFromIndex(int index) {
latLongList = new ArrayList();
if(mCursor == null) {
getData();
}
mCursor.moveToPosition(index);
latLongList.add(mCursor.getDouble(mCursor.getColumnIndex("location_lat")));
latLongList.add(mCursor.getDouble(mCursor.getColumnIndex("location_long")));
return latLongList;
}
/**
* Method getItemId
*/
public Cursor getItemId(String name) {
SQLiteDatabase db = this.getWritableDatabase();
String query = "SELECT " + COL_ID + " FROM " + TABLE_NAME + " WHERE " + COL_NAME + " = '" + name + "'";
Cursor data = db.rawQuery(query, null);
return data;
}
/**
* Method: updateName
* #param newName
* #param id
* #param oldName
*/
public void updateName(String newName, int id, String oldName) {
SQLiteDatabase db = this.getWritableDatabase();
String query = "UPDATE " + TABLE_NAME + " SET " + COL_NAME + " = '" + newName + "' WHERE " + COL_ID + " = '" + id + "'" + " AND " + COL_NAME + " = '" + oldName + "'";
Log.d(TAG, "updateName: query: " + query);
Log.d(TAG, "updateName: Setting new name of activity to: " + newName);
db.execSQL(query);
}
public void deleteActivity(int id, String name) {
SQLiteDatabase db = this.getWritableDatabase();
String query = "DELETE FROM " + TABLE_NAME + " WHERE " + COL_ID + " = '" + id + "'" + " AND " + COL_NAME + " = '" + name + "'";
Log.d(TAG, "deleteActivity: query: " + query);
Log.d(TAG, "deleteActivity: Deleting " + name + " from table");
db.execSQL(query);
}
}
You can achieve the desired behaviour just by observing the SQLite data using content observer. I have a Github project here, that might help you to understand how this works.
The first step would be defining a content URI that is unique. The URI might look something as follows.
public static final Uri DB_TABLE_USER_URI = Uri
.parse("sqlite://" + com.package.your.app + "/" + "user_table");
Then use the LoaderManager.LoaderCallbacks<Cursor> in your ActivityListFragment to load the users in that fragment using CursorLoader callback functions (i.e. onCreateLoader, onLoadFinished, etc.). Also register for content observer in your onCreateLoader.
this.registerContentObserver(cursor, DBConstants.DB_TABLE_USER_URI);
And after you add/update a user in your DataBaseHelper class, you might also want to notify the observer that the data is changed in your database, so that it refreshes the data automatically in the RecyclerView.
context.getContentResolver().notifyChange(DBConstants.DB_TABLE_USER_URI, null);
I would recommend forking the Github project and run the code to see how it works.
I saw this tutorial: https://www.youtube.com/watch?v=gaOsl2TtMHs
but it seem that when i see the activity there isn't any item listview :\
What can be the problem? I put my code under below
The Main Activity.java
public class Prova2 extends Activity {
int[] imageIDs = {
R.drawable.spaghettiscoglio,
R.drawable.abbacchioascottadito,
R.drawable.agnellocacioeova,
R.drawable.agnolotti,
R.drawable.alettedipollo,
R.drawable.amaretti,
R.drawable.anatraarancia,
R.drawable.alberinatale
};
int nextImageIndex = 0;
DBAdapter myDb;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.prova2);
openDB();
populateListViewFromDB();
registerListClickCallback();
}
#Override
protected void onDestroy() {
super.onDestroy();
closeDB();
}
private void openDB() {
myDb = new DBAdapter(this);
myDb.open();
}
private void closeDB() {
myDb.close();
}
/*
* UI Button Callbacks
*/
public void onClick_AddRecord(View v) {
int imageId = imageIDs[nextImageIndex];
nextImageIndex = (nextImageIndex + 1) % imageIDs.length;
// Add it to the DB and re-draw the ListView
myDb.insertRow("Jenny" + nextImageIndex, imageId, "Green");
populateListViewFromDB();
}
public void onClick_ClearAll(View v) {
myDb.deleteAll();
populateListViewFromDB();
}
private void populateListViewFromDB() {
Cursor cursor = myDb.getAllRows();
// Allow activity to manage lifetime of the cursor.
// DEPRECATED! Runs on the UI thread, OK for small/short queries.
startManagingCursor(cursor);
// Setup mapping from cursor to view fields:
String[] fromFieldNames = new String[]
{DBAdapter.KEY_NAME, DBAdapter.KEY_STUDENTNUM, DBAdapter.KEY_FAVCOLOUR, DBAdapter.KEY_STUDENTNUM};
int[] toViewIDs = new int[]
{R.id.tvFruitPrice, R.id.ivFruit, R.id.tvFruitPrice, R.id.smalltext};
// Create adapter to may columns of the DB onto elemesnt in the UI.
SimpleCursorAdapter myCursorAdapter =
new SimpleCursorAdapter(
this, // Context
R.layout.sis, // Row layout template
cursor, // cursor (set of DB records to map)
fromFieldNames, // DB Column names
toViewIDs // View IDs to put information in
);
// Set the adapter for the list view
ListView myList = (ListView) findViewById(R.id.listViewFromDB);
myList.setAdapter(myCursorAdapter);
}
private void registerListClickCallback() {
ListView myList = (ListView) findViewById(R.id.listViewFromDB);
myList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View viewClicked,
int position, long idInDB) {
updateItemForId(idInDB);
displayToastForId(idInDB);
}
});
}
private void updateItemForId(long idInDB) {
Cursor cursor = myDb.getRow(idInDB);
if (cursor.moveToFirst()) {
long idDB = cursor.getLong(DBAdapter.COL_ROWID);
String name = cursor.getString(DBAdapter.COL_NAME);
int studentNum = cursor.getInt(DBAdapter.COL_STUDENTNUM);
String favColour = cursor.getString(DBAdapter.COL_FAVCOLOUR);
favColour += "!";
myDb.updateRow(idInDB, name, studentNum, favColour);
}
cursor.close();
populateListViewFromDB();
}
private void displayToastForId(long idInDB) {
Cursor cursor = myDb.getRow(idInDB);
if (cursor.moveToFirst()) {
long idDB = cursor.getLong(DBAdapter.COL_ROWID);
String name = cursor.getString(DBAdapter.COL_NAME);
int studentNum = cursor.getInt(DBAdapter.COL_STUDENTNUM);
String favColour = cursor.getString(DBAdapter.COL_FAVCOLOUR);
String message = "ID: " + idDB + "\n"
+ "Name: " + name + "\n"
+ "Std#: " + studentNum + "\n"
+ "FavColour: " + favColour;
Toast.makeText(Prova2.this, message, Toast.LENGTH_LONG).show();
}
cursor.close();
}
The DBAdaptor.java
public class DBAdapter {
/////////////////////////////////////////////////////////////////////
// Constants & Data
/////////////////////////////////////////////////////////////////////
// For logging:
private static final String TAG = "DBAdapter";
// DB Fields
public static final String KEY_ROWID = "_id";
public static final int COL_ROWID = 0;
/*
* CHANGE 1:
*/
// TODO: Setup your fields here:
public static final String KEY_NAME = "name";
public static final String KEY_STUDENTNUM = "studentnum";
public static final String KEY_FAVCOLOUR = "favcolour";
// TODO: Setup your field numbers here (0 = KEY_ROWID, 1=...)
public static final int COL_NAME = 1;
public static final int COL_STUDENTNUM = 2;
public static final int COL_FAVCOLOUR = 3;
public static final String[] ALL_KEYS = new String[] {KEY_ROWID, KEY_NAME, KEY_STUDENTNUM, KEY_FAVCOLOUR};
// DB info: it's name, and the table we are using (just one).
public static final String DATABASE_NAME = "MyDb";
public static final String DATABASE_TABLE = "mainTable";
// Track DB version if a new version of your app changes the format.
public static final int DATABASE_VERSION = 2;
private static final String DATABASE_CREATE_SQL =
"create table " + DATABASE_TABLE
+ " (" + KEY_ROWID + " integer primary key autoincrement, "
/*
* CHANGE 2:
*/
// TODO: Place your fields here!
// + KEY_{...} + " {type} not null"
// - Key is the column name you created above.
// - {type} is one of: text, integer, real, blob
// (http://www.sqlite.org/datatype3.html)
// - "not null" means it is a required field (must be given a value).
// NOTE: All must be comma separated (end of line!) Last one must have NO comma!!
+ KEY_NAME + " text not null, "
+ KEY_STUDENTNUM + " integer not null, "
+ KEY_FAVCOLOUR + " string not null"
// Rest of creation:
+ ");";
// Context of application who uses us.
private final Context context;
private DatabaseHelper myDBHelper;
private SQLiteDatabase db;
/////////////////////////////////////////////////////////////////////
// Public methods:
/////////////////////////////////////////////////////////////////////
public DBAdapter(Context ctx) {
this.context = ctx;
myDBHelper = new DatabaseHelper(context);
}
// Open the database connection.
public DBAdapter open() {
db = myDBHelper.getWritableDatabase();
return this;
}
// Close the database connection.
public void close() {
myDBHelper.close();
}
// Add a new set of values to the database.
public long insertRow(String name, int studentNum, String favColour) {
/*
* CHANGE 3:
*/
// TODO: Update data in the row with new fields.
// TODO: Also change the function's arguments to be what you need!
// Create row's data:
ContentValues initialValues = new ContentValues();
initialValues.put(KEY_NAME, name);
initialValues.put(KEY_STUDENTNUM, studentNum);
initialValues.put(KEY_FAVCOLOUR, favColour);
// Insert it into the database.
return db.insert(DATABASE_TABLE, null, initialValues);
}
// Delete a row from the database, by rowId (primary key)
public boolean deleteRow(long rowId) {
String where = KEY_ROWID + "=" + rowId;
return db.delete(DATABASE_TABLE, where, null) != 0;
}
public void deleteAll() {
Cursor c = getAllRows();
long rowId = c.getColumnIndexOrThrow(KEY_ROWID);
if (c.moveToFirst()) {
do {
deleteRow(c.getLong((int) rowId));
} while (c.moveToNext());
}
c.close();
}
// Return all data in the database.
public Cursor getAllRows() {
String where = null;
Cursor c = db.query(true, DATABASE_TABLE, ALL_KEYS,
where, null, null, null, null, null);
if (c != null) {
c.moveToFirst();
}
return c;
}
// Get a specific row (by rowId)
public Cursor getRow(long rowId) {
String where = KEY_ROWID + "=" + rowId;
Cursor c = db.query(true, DATABASE_TABLE, ALL_KEYS,
where, null, null, null, null, null);
if (c != null) {
c.moveToFirst();
}
return c;
}
// Change an existing row to be equal to new data.
public boolean updateRow(long rowId, String name, int studentNum, String favColour) {
String where = KEY_ROWID + "=" + rowId;
/*
* CHANGE 4:
*/
// TODO: Update data in the row with new fields.
// TODO: Also change the function's arguments to be what you need!
// Create row's data:
ContentValues newValues = new ContentValues();
newValues.put(KEY_NAME, name);
newValues.put(KEY_STUDENTNUM, studentNum);
newValues.put(KEY_FAVCOLOUR, favColour);
// Insert it into the database.
return db.update(DATABASE_TABLE, newValues, where, null) != 0;
}
/////////////////////////////////////////////////////////////////////
// Private Helper Classes:
/////////////////////////////////////////////////////////////////////
/**
* Private class which handles database creation and upgrading.
* Used to handle low-level database access.
*/
private static class DatabaseHelper extends SQLiteOpenHelper
{
DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase _db) {
_db.execSQL(DATABASE_CREATE_SQL);
}
#Override
public void onUpgrade(SQLiteDatabase _db, int oldVersion, int newVersion) {
Log.w(TAG, "Upgrading application's database from version " + oldVersion
+ " to " + newVersion + ", which will destroy all old data!");
// Destroy old database:
_db.execSQL("DROP TABLE IF EXISTS " + DATABASE_TABLE);
// Recreate new database:
onCreate(_db);
}
}
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I've been trying to get the price value from the database and try to make a grand total. I used the rawQuery but always crashed.I think theres a problem in my rawQuery..i still cant get the total after many times i've tried..
this is the code:
DBAdapter
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
// ------------------------------------ DBAdapter.java ---------------------------------------------
// TO USE:
// Change the package (at top) to match your project.
// Search for "TODO", and make the appropriate changes.
public class DBAdapter {
/////////////////////////////////////////////////////////////////////
// Constants & Data
/////////////////////////////////////////////////////////////////////
// For logging:
private static final String TAG = "DBAdapter";
// DB Fields
public static final String KEY_ROWID = "_id";
public static final int COL_ROWID = 0;
/*
* CHANGE 1:
*/
// TODO: Setup your fields here:
public static final String KEY_NAME = "name";
public static final String KEY_QUANTITY = "studentnum";
public static final String KEY_PRICE = "favcolour";
// TODO: Setup your field numbers here (0 = KEY_ROWID, 1=...)
public static final int COL_NAME = 1;
public static final int COL_QUANTITY = 2;
public static final int COL_PRICE = 3;
public static final String[] ALL_KEYS = new String[] {KEY_ROWID, KEY_NAME, KEY_QUANTITY, KEY_PRICE};
// DB info: it's name, and the table we are using (just one).
public static final String DATABASE_NAME = "MyDb";
public static final String DATABASE_TABLE = "mainTable";
// Track DB version if a new version of your app changes the format.
public static final int DATABASE_VERSION = 2;
private static final String DATABASE_CREATE_SQL =
"create table " + DATABASE_TABLE
+ " (" + KEY_ROWID + " integer primary key autoincrement, "
/*
* CHANGE 2:
*/
// TODO: Place your fields here!
// + KEY_{...} + " {type} not null"
// - Key is the column name you created above.
// - {type} is one of: text, integer, real, blob
// (http://www.sqlite.org/datatype3.html)
// - "not null" means it is a required field (must be given a value).
// NOTE: All must be comma separated (end of line!) Last one must have NO comma!!
+ KEY_NAME + " text not null, "
+ KEY_QUANTITY + " integer not null, "
+ KEY_PRICE + " string not null"
// Rest of creation:
+ ");";
// Context of application who uses us.
private final Context context;
private DatabaseHelper myDBHelper;
private SQLiteDatabase db;
/////////////////////////////////////////////////////////////////////
// Public methods:
/////////////////////////////////////////////////////////////////////
public DBAdapter(Context ctx) {
this.context = ctx;
myDBHelper = new DatabaseHelper(context);
}
// Open the database connection.
public DBAdapter open() {
db = myDBHelper.getWritableDatabase();
return this;
}
// Close the database connection.
public void close() {
myDBHelper.close();
}
// Add a new set of values to the database.
public long insertRow(String name, String studentNum, String favColour) {
/*
* CHANGE 3:
*/
// TODO: Update data in the row with new fields.
// TODO: Also change the function's arguments to be what you need!
// Create row's data:
ContentValues initialValues = new ContentValues();
initialValues.put(KEY_NAME, name);
initialValues.put(KEY_QUANTITY, studentNum);
initialValues.put(KEY_PRICE, favColour);
// Insert it into the database.
return db.insert(DATABASE_TABLE, null, initialValues);
}
// Delete a row from the database, by rowId (primary key)
public boolean deleteRow(long rowId) {
String where = KEY_ROWID + "=" + rowId;
return db.delete(DATABASE_TABLE, where, null) != 0;
}
public Cursor getTotalPrice() {
Cursor c = db.rawQuery("SELECT SUM("+ KEY_PRICE +")from " + DATABASE_TABLE, null);
return c;
}
public void deleteAll() {
Cursor c = getAllRows();
long rowId = c.getColumnIndexOrThrow(KEY_ROWID);
if (c.moveToFirst()) {
do {
deleteRow(c.getLong((int) rowId));
} while (c.moveToNext());
}
c.close();
}
// Return all data in the database.
public Cursor getAllRows() {
String where = null;
Cursor c = db.query(true, DATABASE_TABLE, ALL_KEYS,
where, null, null, null, null, null);
if (c != null) {
c.moveToFirst();
}
return c;
}
// Get a specific row (by rowId)
public Cursor getRow(long rowId) {
String where = KEY_ROWID + "=" + rowId;
Cursor c = db.query(true, DATABASE_TABLE, ALL_KEYS,
where, null, null, null, null, null);
if (c != null) {
c.moveToFirst();
}
return c;
}
// Change an existing row to be equal to new data.
public boolean updateRow(long rowId, String name, int studentNum, String favColour) {
String where = KEY_ROWID + "=" + rowId;
/*
* CHANGE 4:
*/
// TODO: Update data in the row with new fields.
// TODO: Also change the function's arguments to be what you need!
// Create row's data:
ContentValues newValues = new ContentValues();
newValues.put(KEY_NAME, name);
newValues.put(KEY_QUANTITY, studentNum);
newValues.put(KEY_PRICE, favColour);
// Insert it into the database.
return db.update(DATABASE_TABLE, newValues, where, null) != 0;
}
/////////////////////////////////////////////////////////////////////
// Private Helper Classes:
/////////////////////////////////////////////////////////////////////
/**
* Private class which handles database creation and upgrading.
* Used to handle low-level database access.
*/
private static class DatabaseHelper extends SQLiteOpenHelper
{
DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase _db) {
_db.execSQL(DATABASE_CREATE_SQL);
}
#Override
public void onUpgrade(SQLiteDatabase _db, int oldVersion, int newVersion) {
Log.w(TAG, "Upgrading application's database from version " + oldVersion
+ " to " + newVersion + ", which will destroy all old data!");
// Destroy old database:
_db.execSQL("DROP TABLE IF EXISTS " + DATABASE_TABLE);
// Recreate new database:
onCreate(_db);
}
}
}
Listprice:
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.*;
/**
* Created by User on 6/2/2015.
*/
public class Listprice extends ActionBarActivity {
DBAdapter myDb;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.listprice);
openDB();
TextView textView = (TextView) findViewById(R.id.order90);
TextView textView1 = (TextView) findViewById(R.id.quan90);
TextView textView2 = (TextView) findViewById(R.id.price90);
TextView textView3 = (TextView) findViewById(R.id.totalprice);
Bundle extras = getIntent().getExtras();
if (extras != null) {
String newText = extras.getString("firstmessage");
String newText1 = extras.getString("secondmessage");
String newText2 = extras.getString("thirdmessage");
if (newText != null) {
textView.setText(newText);
}
if (newText1 != null) {
textView1.setText(newText1);
}
if (newText2 != null) {
textView2.setText(newText2);
}
}
String num1 = textView.getText().toString().trim();
int num2 = Integer.parseInt(textView1.getText().toString());
int num3 = Integer.parseInt(textView2.getText().toString());
int num4 = num2 * num3;
registerListClickCallBack();
myDb.insertRow(num1, "Quantity = " + num2, ""+num4);
populateListViewFromDB();
Cursor sum=myDb.getTotalPrice();
textView3.setText(""+sum);
}
private void populateListViewFromDB() {
Cursor cursor = myDb.getAllRows();
//Query for the record we just added.
//Use the ID:
startManagingCursor(cursor);
String[] fromFieldNames = new String[]
{DBAdapter.KEY_NAME, DBAdapter.KEY_QUANTITY, DBAdapter.KEY_PRICE};
int[] toViewIDs = new int[]
{R.id.item_name, R.id.quantities, R.id.pricest};
SimpleCursorAdapter myCursorAdapter =
new SimpleCursorAdapter(
this,
R.layout.item_layout,
cursor,
fromFieldNames,
toViewIDs
);
// Set the adapter for the list view
ListView myList = (ListView) findViewById(R.id.listViewFromDB);
myList.setAdapter(myCursorAdapter);
}
private void openDB(){
myDb = new DBAdapter(this);
myDb.open();
}
#Override
protected void onDestroy() {
super.onDestroy();
closeDB();
}
private void closeDB() {
myDb.close();
}
private void registerListClickCallBack() {
ListView myList = (ListView) findViewById(R.id.listViewFromDB);
myList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View viewClicked,
int position, long idInDB) {
updateItemForId(idInDB);
}
});
}
private void updateItemForId(final long idInDB) {
final Cursor cursor = myDb.getRow(idInDB);
if (cursor.moveToFirst()) {
AlertDialog.Builder alertDialog = new AlertDialog.Builder(Listprice.this);
// Setting Dialog Title
alertDialog.setTitle("Confirm Delete...");
// Setting Dialog Message
alertDialog.setMessage("Are you sure you want delete this?");
// Setting Positive "Yes" Button
alertDialog.setPositiveButton("YES", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int which) {
// Write your code here to invoke YES event
Toast.makeText(getApplicationContext(), "You clicked on YES", Toast.LENGTH_SHORT).show();
myDb.deleteRow(idInDB);
populateListViewFromDB();
}
});
// Setting Negative "NO" Button
alertDialog.setNegativeButton("NO", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// Write your code here to invoke NO event
Toast.makeText(getApplicationContext(), "You clicked on NO", Toast.LENGTH_SHORT).show();
dialog.cancel();
}
});
// Showing Alert Message
alertDialog.show();
}
cursor.close();
populateListViewFromDB();
}
public void clear(View view) {
myDb.deleteAll();
populateListViewFromDB();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
public void addFood(View view) {
Intent gotofood = new Intent(this, food.class);
startActivity(gotofood);
}
public void addDrinks(View view) {
Intent gotodrinks = new Intent(this, drink.class);
startActivity(gotodrinks);
}
public void gotomainmaenu(View view) {
Intent gotomain = new Intent(this, MainActivity.class);
startActivity(gotomain);
}
}
It sounds like you want the sum of each item's price multiplied by that item's quantity. If so, this should work:
public double getTotalPrice() {
String sql = "select sum(" + KEY_QUANTITY + " * " + KEY_PRICE + ") from "
+ DATABASE_TABLE;
Cursor cursor = db.rawQuery(sql, null);
if (cursor.moveToFirst()) {
return cursor.getDouble(0);
}
return 0;
}
So this is my code:
public void onItemClick(AdapterView<?> listView, View view, int position, long id)
{
Cursor cursor = (Cursor) listView.getItemAtPosition(position);
int _id = cursor.getInt(0);
String _recipe = cursor.getString(1);
Intent intent = new Intent(Luzon1Activity.this,RecipeInstruction.class);
intent.putExtra("id", _id);
intent.putExtra("recipe", _recipe);
startActivity(intent);
}
This is my code for the next activity:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.recipeinstruction);
dbHelper = new Dbadapter(this);
dbHelper.open();
bg = (RelativeLayout) findViewById(R.id.relativeLayout1);
Bundle extras = getIntent().getExtras();
if (extras != null) {
id = extras.getInt("id");
recipe = extras.getString("recipe");
}
Toast.makeText(this, id+"\n"+recipe, Toast.LENGTH_SHORT).show();
bg.setBackgroundResource(getImageId(this, recipe));
}
My problem is on this part: String _recipe = cursor.getString(1).
It always gives me the wrong data. I tried to change the number but still it gives me the wrong data.
This is my database:
package com.pinoycookbook;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
public class Dbadapter
{
public static final String ROWID = "_id";
public static final String NAME = "foodname";
public static final String ORIGIN = "origin";
public static final String RECIPE = "recipe";
public static final String CATEGORY = "category";
private static final String TAG = "Dbadapter";
private DatabaseHelper mDbHelper;
private SQLiteDatabase mDb;
private static final String DATABASE_NAME = "PinoyCookbook.sqlite";
public static final String SQLITE_TABLE = "Food";
private static final int DATABASE_VERSION = 1;
private final Context mCtx;
private static final String DATABASE_CREATE =
"CREATE TABLE if not exists " + SQLITE_TABLE + " (" +
ROWID + " integer PRIMARY KEY autoincrement," +
NAME + " TEXT," +
RECIPE + " TEXT," +
ORIGIN + " TEXT," +
CATEGORY+ " TEXT,"+
" UNIQUE (" + ROWID +"));";
private static class DatabaseHelper extends SQLiteOpenHelper
{
DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
Log.w(TAG, DATABASE_CREATE);
db.execSQL(DATABASE_CREATE);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
+ newVersion + ", which will destroy all old data");
db.execSQL("DROP TABLE IF EXISTS " + SQLITE_TABLE);
onCreate(db);
}
}
public Dbadapter(Context ctx) {
this.mCtx = ctx;
}
public Dbadapter open() throws SQLException {
mDbHelper = new DatabaseHelper(mCtx);
mDb = mDbHelper.getWritableDatabase();
return this;
}
public void close() {
if (mDbHelper != null) {
mDbHelper.close();
}
}
public long createData(String foodname, String recipe, String origin, int i) {
ContentValues initialValues = new ContentValues();
initialValues.put(NAME, foodname);
initialValues.put(RECIPE, recipe);
initialValues.put(ORIGIN, origin);
initialValues.put(CATEGORY, i);
return mDb.insert(SQLITE_TABLE, null, initialValues);
}
public boolean deleteAllData() {
int doneDelete = 0;
doneDelete = mDb.delete(SQLITE_TABLE, null , null);
Log.w(TAG, Integer.toString(doneDelete));
return doneDelete > 0;
}
public void insertData() {
createData("Adobong Manok","adobongmanok","Manila",1);
createData("Lechon","lechon","Cebu",2);
createData("Crispy Pata","crispypata","Cebu",2);
createData("Bulalo","bulalo","Batangas",1);
createData("Taba ng Talangka Rice","talangkarice","Roxas",2);
createData("Arroz Caldo","arrozcaldo","Roxas",2);
createData("Sinigang","sinigang","Manila",1);
}
}
So i recommend you to use getColumnIndex() method rather than hardcode it.
String _recipe = cursor.getString(cursor.getColumnIndex(Dbadapter.RECIPE));
It will ensure that you will get always right field. And if it still get wrong data problem is in query not in Cursor
Note: An usage of static fields that hold column names is always the best practise.
Update:
I've tried it before and it gives me this error:
java.lang.IllegalArgumentException: column 'recipe' does not exist
You need to find out your actual table structure. Try to perform this statement:
PRAGMA table_info(Dbadapter.SQLITE_TABLE);
What says docs(source):
This pragma returns one row for each column in the named table.
Columns in the result set include the column name, data type, whether
or not the column can be NULL, and the default value for the column.
The "pk" column in the result set is zero for columns that are not
part of the primary key, and is the index of the column in the primary
key for columns that are part of the primary key.
Example:
Here i created for you method for getting tableinfo via PRAGMA:
public String getTableInfo() {
StringBuilder b = new StringBuilder("");
Cursor c = null;
try {
db = helper.getReadableDatabase();
String query = "pragma table_info(" + Dbadapter.SQLITE_TABLE + ")";
c = db.rawQuery(query, null);
if (c.moveToFirst()) {
do {
b.append("Col:" + c.getString(c.getColumnIndex("name")) + " ");
b.append(c.getString(c.getColumnIndex("type")));
b.append("\n");
} while (c.moveToNext());
}
return b.toString();
}
finally {
if (c != null) {
c.close();
}
if (db != null) {
db.close();
}
}
}
Output will be something like this:
Column: type text
Column: date text
Only for imagination i will give you screen:
you can try it this way:
cursor.getString(cursor.getColumnIndex("recipe"));
it returns you the correct index and as result the correct value.