I'm working on a project for a college course using Java in Android Studio.
Here is the assignment:
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. 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.
When I try to save an address I get the following error:
Attempt to invoke virtual method android.database.sqlite.SQLiteDatabase
Com.example.program5.AddressDatabaseHelper.getWritableDatabse() on an null object reference
I'm new to programming and right-brained so I'm probably missing something obvious but would appreciate any help. Thank you. Here is my code: Address Collection Class
package com.example.program4;
import android.content.Context;
import java.util.ArrayList;
public class AddressCollection {
ArrayList<AddressAttributeGroup> addressList = new ArrayList<AddressAttributeGroup>();
final int MAXIMUM_ADDRESS_COUNT = 10;
public AddressAttributeGroup address;
//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 {
this.address = address;
//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
{public static AddressDataSource addressData;
public static AddressCollection AddressCollectionFactory(Context context)
{
AddressCollection rCode = new AddressCollection();
addressData = new AddressDataSource(context);
try {
addressData.open();
rCode = addressData.getAllAddresses();
addressData.close();
}
catch (Exception e) {
e.printStackTrace();
}
return rCode;
}
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);
}
}
Address Console Class
package com.example.program4;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
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.program4.StrongIntent.TypeOfAction;
import com.example.program4.AddressCollection.AddressCollectionDB;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
public class AddressConsole extends Activity implements View.OnClickListener,
ListView.OnItemClickListener, ListView.OnItemSelectedListener {
Button cmdAdd;
Button cmdDelete;
Button cmdView;
Button cmdEdit;
TextView textAddressMessage;
EditText editRecordNumber;
ListView listOfAddresses;
final int ADDRESS_ENTRY = 1001;
AddressCollectionDB addresses;
AddressDataSource addressData;
//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) AddressCollectionDB.AddressCollectionFactory(this);
addressAdapter = new AddressArrayAdapter(this, android.R.layout.simple_list_item_1,
android.R.id.text1,
addresses);
listOfAddresses.setAdapter(addressAdapter);
}
void displayError(Exception message) {
Toast.makeText(this,message.getMessage(),Toast.LENGTH_LONG).show();
}
void displayError(String message){
Toast.makeText(this,message,Toast.LENGTH_LONG).show();
}
void displayInfo(String message)
{
Toast.makeText(this, message,Toast.LENGTH_SHORT).show();
}
void displayAddressMessage(AddressAttributeGroup address)
{
textAddressMessage.setText("Address: " + address.firstName + " " + address.lastName + " " + address.streetAddress +
" "+ address.town + " " + address.state + " " + address.zip);
}
void clearAddressMessage()
{
textAddressMessage.setText("");
}
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
getMenuInflater().inflate(R.menu.activity_address_message,menu);
return true;
}
@Override
protected void onStart()
{
super.onStart();
}
@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("Maximum Number Of Addresses Reached!");
}
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.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,int textViewResourceId, AddressCollection addresses) {
super(context, resource, textViewResourceId, 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 = 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 = 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;
}
}
}
Address Database helper Class
package com.example.program4;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.*;
import com.example.program4.AddressCollection.AddressCollectionDB;
public class AddressDatabaseHelper extends SQLiteOpenHelper
{
//declares table, columns, and database
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;
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 c)
{
//pass database name, null and the database version
super(c, 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
{ // declares SQLDatabase
private SQLiteDatabase database;
//declares AddressDatabaseHelper dbHelper
private AddressDatabaseHelper dbHelper;
//declares String array allColumns
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)
{
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_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);
long insertId = database.insert(AddressDatabaseHelper.TABLE_ADDRESS,null,values);
//returns insertId
return insertId;
}
//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);
//move cursor to first column in database
cursor.moveToFirst();
//while the cursor is not after the last entry
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) {
/* int idCOLUMN_ID = cursor.getColumnIndex(AddressDatabaseHelper.COLUMN_ID);
int idCOLUMN_FIRSTNAME = cursor.getColumnIndex(AddressDatabaseHelper.COLUMN_FIRSTNAME);
int idCOLUMN_LASTNAME = cursor.getColumnIndex(AddressDatabaseHelper.COLUMN_LASTNAME);
int idCOLUMN_STREET_ADDRESS = cursor.getColumnIndex(AddressDatabaseHelper.COLUMN_STREET_ADDRESS);
int idCOLUMN_TOWN = cursor.getColumnIndex(AddressDatabaseHelper.COLUMN_TOWN);
int idCOLUMN_STATE = cursor.getColumnIndex(AddressDatabaseHelper.COLUMN_STATE);
int idCOLUMN_ZIP = cursor.getColumnIndex(AddressDatabaseHelper.COLUMN_ZIP);
if (idCOLUMN_ID >= 0 && idCOLUMN_FIRSTNAME >= 0 && idCOLUMN_LASTNAME >= 0 &&
idCOLUMN_STREET_ADDRESS >= 0 && idCOLUMN_TOWN >= 0 && idCOLUMN_STATE >= 0 && idCOLUMN_ZIP >= 0) {*/
//creates new AddressAttributeGroup called address
//returns address
// return new AddressAttributeGroup
AddressAttributeGroup address = new AddressAttributeGroup
(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)));
return address;
}
}
AddressEntry Class
package com.example.program4;
import android.app.Activity;
import android.os.Bundle;
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 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();
}
@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();
}
}
}