Java – A very open-ended, n00b question about extending this tutorial in Android

A very open-ended, n00b question about extending this tutorial in Android… here is a solution to the problem.

A very open-ended, n00b question about extending this tutorial in Android

I would like to ask for your patience first… I’m trying to learn Android programming with trial-and-error type modifications of Google sample code: “Note this tutorial” so far everything has gone very smoothly and slowly. (I’m also reading Head First Java 🙂

.)

My goal is to add an extra TextEdit field and a button to the tutorial app… I want the user to be able to enter text in that field, then press the button and append the text they just entered to the database, and then drop down to the textView in the scrollView so that viewers can see the record of the entry. Basically, my goal is to allow users to add an indefinite amount of data (depending on the number of times the button is clicked) to each database entry. I’ve done part of the work (adding new database fields, creating TextEdits, buttons, etc.) but I can’t put them all together… Especially how to make it work on the database side. I’m not sure if I explained this correctly… But I’ll attach the relevant source code to try to make it clearer.

(Note: KEY_HOUSE is the db field I added, house/mHouseText is the relevant variable).

NoteEdit.java

    package com.android.demo.notepad3;

import android. R.string;
import android.app.Activity;
import android.database.Cursor;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
import android.widget.TableRow.LayoutParams;

public class NoteEdit extends Activity{

private EditText mTitleText;
    private EditText mBodyText;
    private Long mRowId;
    private NotesDbAdapter mDbHelper;
    Button btn;
    int counter = 0;
    private EditText mHouseText;

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mDbHelper = new NotesDbAdapter(this);
        mDbHelper.open();

setContentView(R.layout.note_edit);
        setTitle(R.string.edit_note);

mTitleText = (EditText) findViewById(R.id.title);
        mBodyText = (EditText) findViewById(R.id.body);
        mHouseText = (EditText) findViewById(R.id.house);

Button confirmButton = (Button) findViewById(R.id.confirm);
        Button btn = (Button) findViewById(R.id.Button01);

mRowId = (savedInstanceState == null) ? null :
            (Long) savedInstanceState.getSerializable(NotesDbAdapter.KEY_ROWID);
        if (mRowId == null) {
            Bundle extras = getIntent().getExtras();
            mRowId = extras != null ? extras.getLong(NotesDbAdapter.KEY_ROWID)
                                    : null;
        }

populateFields();

confirmButton.setOnClickListener(new View.OnClickListener() {

public void onClick(View view) {
                setResult(RESULT_OK);
                finish();
            }

});

btn.setOnClickListener(new View.OnClickListener() {

public void onClick(View view) {
            addrow();

}

});

}

private void populateFields() {
        if (mRowId != null) {
            Cursor note = mDbHelper.fetchNote(mRowId);
            startManagingCursor(note);
            mTitleText.setText(note.getString(
                    note.getColumnIndexOrThrow(NotesDbAdapter.KEY_TITLE)));
            mBodyText.setText(note.getString(
                    note.getColumnIndexOrThrow(NotesDbAdapter.KEY_BODY)));
            mHouseText.setText(note.getString(
                    note.getColumnIndexOrThrow(NotesDbAdapter.KEY_HOUSE)));
        }
    }

@Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        saveState();
        outState.putSerializable(NotesDbAdapter.KEY_ROWID, mRowId);
    }

@Override
    protected void onPause() {
        super.onPause();
        saveState();
    }

@Override
    protected void onResume() {
        super.onResume();
        populateFields();
    }

private void saveState() {
        String title = mTitleText.getText().toString();
        String body = mBodyText.getText().toString();
        String house = mHouseText.getText().toString();

if (mRowId == null) {
            long id = mDbHelper.createNote(title, body, house);
            if (id > 0) {
                mRowId = id;
            }
        } else {
            mDbHelper.updateNote(mRowId, title, body, house);
        }
    }

private void addrow(){

mHouseText = (EditText) findViewById(R.id.house);
        String house = mHouseText.getText().toString();
         get a reference for the TableLayout
                TableLayout table = (TableLayout) findViewById(R.id.TableLayout02);

 create a new TableRow
        TableRow row = new TableRow(this);

 create a new TextView
        TextView t = new TextView(this);
         set the text to "text xx"
        t.setText(house);

 create a CheckBox
        CheckBox c = new CheckBox(this);

 add the TextView and the CheckBox to the new TableRow
        row.addView(t);
        row.addView(c);

 add the TableRow to the TableLayout
        table.addView(row,new TableLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));

}

}

NotesDbAdapter.java

package com.android.demo.notepad3;

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;

* Simple notes database access helper class. Defines the basic CRUD operations
 * for the notepad example, and gives the ability to list all notes as well as
 * retrieve or modify a specific note.
 * 
 * This has been improved from the first version of this tutorial through the
 * addition of better error handling and also using returning a Cursor instead
 * of using a collection of inner classes (which is less scalable and not
 * recommended).

public class NotesDbAdapter {

public static final String KEY_TITLE = "title";
    public static final String KEY_BODY = "body";
    public static final String KEY_HOUSE = "house";
    public static final String KEY_ROWID = "_id";

private static final String TAG = "NotesDbAdapter";
    private DatabaseHelper mDbHelper;
    private SQLiteDatabase mDb;

/**
     * Database creation sql statement
     */
    private static final String DATABASE_CREATE =
        "create table notes (_id integer primary key autoincrement, "
        + "title text not null, body text not null, house text not null);";

private static final String DATABASE_NAME = "data";
    private static final String DATABASE_TABLE = "notes";
    private static final int DATABASE_VERSION = 2;

private final Context mCtx;

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);
        }

@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 notes");
            onCreate(db);
        }
    }

/**
     * Constructor - takes the context to allow the database to be
     * opened/created
     * 
     * @param ctx the Context within which to work
     */
    public NotesDbAdapter(Context ctx) {
        this.mCtx = ctx;
    }

/**
     * Open the notes database. If it cannot be opened, try to create a new
     * instance of the database. If it cannot be created, throw an exception to
     * signal the failure
     * 
     * @return this (self reference, allowing this to be chained in an
     *         initialization call)
     * @throws SQLException if the database could be neither opened or created
     */
    public NotesDbAdapter open() throws SQLException {
        mDbHelper = new DatabaseHelper(mCtx);
        mDb = mDbHelper.getWritableDatabase();
        return this;
    }

public void close() {
        mDbHelper.close();
    }

/**
     * Create a new note using the title and body provided. If the note is
     * successfully created return the new rowId for that note, otherwise return
     * a -1 to indicate failure.
     * 
     * @param title the title of the note
     * @param body the body of the note
     * @return rowId or -1 if failed
     */
    public long createNote(String title, String body, String house) {
        ContentValues initialValues = new ContentValues();
        initialValues.put(KEY_TITLE, title);
        initialValues.put(KEY_BODY, body);
        initialValues.put(KEY_HOUSE, house);

return mDb.insert(DATABASE_TABLE, null, initialValues);
    }

/**
     * Delete the note with the given rowId
     * 
     * @param rowId id of note to delete
     * @return true if deleted, false otherwise
     */
    public boolean deleteNote(long rowId) {

return mDb.delete(DATABASE_TABLE, KEY_ROWID + "=" + rowId, null) > 0;
    }

/**
     * Return a Cursor over the list of all notes in the database
     * 
     * @return Cursor over all notes
     */
    public Cursor fetchAllNotes() {

return mDb.query(DATABASE_TABLE, new String[] {KEY_ROWID, KEY_TITLE,
                KEY_BODY, KEY_HOUSE}, null, null, null, null, null);
    }

/**
     * Return a Cursor positioned at the note that matches the given rowId
     * 
     * @param rowId id of note to retrieve
     * @return Cursor positioned to matching note, if found
     * @throws SQLException if note could not be found/retrieved
     */
    public Cursor fetchNote(long rowId) throws SQLException {

Cursor mCursor =

mDb.query(true, DATABASE_TABLE, new String[] {KEY_ROWID,
                    KEY_TITLE, KEY_BODY, KEY_HOUSE}, KEY_ROWID + "=" + rowId, null,
                    null, null, null, null);
        if (mCursor != null) {
            mCursor.moveToFirst();
        }
        return mCursor;

}

/**
     * Update the note using the details provided. The note to be updated is
     * specified using the rowId, and it is altered to use the title and body
     * values passed in
     * 
     * @param rowId id of note to update
     * @param title value to set note title to
     * @param body value to set note body to
     * @return true if the note was successfully updated, false otherwise
     */
    public boolean updateNote(long rowId, String title, String body, String house) {
        ContentValues args = new ContentValues();
        args.put(KEY_TITLE, title);
        args.put(KEY_BODY, body);
        args.put(KEY_HOUSE, house);

return mDb.update(DATABASE_TABLE, args, KEY_ROWID + "=" + rowId, null) > 0;
    }
}

NoteEdit.xml

 <?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="fill_parent"
    android:layout_height="fill_parent">

<TableLayout android:id="@+id/TableLayout01" android:layout_width="fill_parent" android:layout_height="wrap_content"  android:stretchColumns="0">

<TableRow android:id="@+id/TableRow01" android:layout_width="wrap_content" android:layout_height="wrap_content">

<TextView android:layout_width="fill_parent"
            android:layout_height="wrap_content" 
            android:text="@string/title" />
        <EditText android:id="@+id/title" 
          android:layout_height="wrap_content" 
            android:layout_width="wrap_content" android:hint="Montague St." />
  </TableRow>

<TableRow android:id="@+id/TableRow02" android:layout_width="wrap_content" android:layout_height="wrap_content">

<TextView android:layout_width="wrap_content"
            android:layout_height="wrap_content" 
            android:text="@string/body" />
        <EditText android:id="@+id/body" android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:scrollbars="vertical" android:hint="44"/>
        </TableRow>

</TableLayout>

<ScrollView android:id="@+id/ScrollView01" android:layout_width="wrap_content" android:layout_height="wrap_content">

<TableLayout android:id="@+id/TableLayout02" android:layout_width="fill_parent" android:layout_height="wrap_content" android:stretchColumns="0">

<TableRow android:id="@+id/TableRow03" android:layout_width="wrap_content" android:layout_height="wrap_content">
      <EditText android:id="@+id/house" android:layout_width="fill_parent" android:layout_height="wrap_content" android:hint="House Number"></EditText>

<CheckBox android:id="@+id/CheckBox01" android:layout_width="wrap_content" android:layout_height="wrap_content"></CheckBox>
    </TableRow>
    <Button android:id="@+id/Button01" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Add House"></Button>

</TableLayout>
</ScrollView>

<LinearLayout android:orientation="horizontal"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
    <Button android:id="@+id/confirm" 
      android:text="@string/confirm"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>
</LinearLayout>

I know my question is very open-ended and “n00b” style, but any help, or even just an insertion in the right direction, would be appreciated.

Thanks

Frank

Related Problems and Solutions