Saturday, November 9, 2013

Really Simple Basic Custom Planner Project: Android

How about a really simple project for Android beginners?... This time, let's make it a very basic custom personal planner. We'll incorporate custom adapters, SQLite, intents, and Date/TimePickers.

Without further ado, let's get started.

  • Call the application Basic Custom Planner, the main activity HomePage.java, and its associated layout activity_home_page_xml. 
  • Call the next activity CalendarDisplay.java, and its associated layout activity_calendar_display.xml.
  • Call the activity after that PlansList.java, and its associated layout activity_plans_list.xml.
  • Call the final activity CreatePlan.java, and its associated layout activity_create_plan.xml.
As for the code, first up, the home page. We'll go with a very simple design that uses two buttons and a DatePicker. One button will bring up a DatePicker Dialog that allows us to set the calendar month we're interested in viewing. The other button just sends us to the CalendarDisplay activity.

activity_home_page.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    android:gravity="center"
    tools:context=".HomePage" >
   
    <Button
        android:id="@+id/setMonth"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Select Calendar Month"
        android:onClick="onClick"/>
    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="  "/>
    <DatePicker
        android:id="@+id/monthSelector"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:calendarViewShown="false"/>
    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="  "/>
    <Button
        android:id="@+id/getMonth"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Go!"
        android:onClick="onClick2"/>
   
</LinearLayout>

HomePage.java
public class HomePage extends Activity {
                public final static String EXTRA_DATE = "com.stirfriedcode.basiccustomplanner.DATE";
                public final static String EXTRA_MONTH = "com.stirfriedcode.basiccustomplanner.MONTH";
                public final static String EXTRA_YEAR = "com.stirfriedcode.basiccustomplanner.YEAR";
               
                static final int DATE_DIALOG_ID = 999;
                private int month, day, year;
                DatePicker datePicker;
                Button setMonth;

                @Override
                protected void onCreate(Bundle savedInstanceState) {
                            super.onCreate(savedInstanceState);
                            setContentView(R.layout.activity_home_page);
                               
                            datePicker = (DatePicker) findViewById(R.id.monthSelector);
                            Calendar c = Calendar.getInstance();
                            month = c.get(Calendar.MONTH);
                            day = c.get(Calendar.DATE);
                            year = c.get(Calendar.YEAR);
                               
                            datePicker.init(year, month, day, null);
                               
                }
               
                public void onClick(View v) {
                                showDialog(DATE_DIALOG_ID);
                }
               
                @Override
                protected Dialog onCreateDialog(int id) {
                          switch (id) {
                          case DATE_DIALOG_ID:
                                return new DatePickerDialog(this, datePickerListener, year, month, day);

                          }
                                return null;
                }
               
                private DatePickerDialog.OnDateSetListener datePickerListener = new
                 DatePickerDialog.OnDateSetListener() {
                 public void onDateSet(DatePicker view, int selectedYear, int selectedMonth, int selectedDay) {
                                         year = selectedYear;
                                        month = selectedMonth;
                                        day = selectedDay;
                                        datePicker.init(year, month, day, null);
                         }
                };
               
               
                public void onClick2(View v) {
                                int yr = datePicker.getYear();
                                int mo = datePicker.getMonth();
                               
                                Intent intent = new Intent(this, CalendarDisplay.class);
                                intent.putExtra(EXTRA_YEAR, yr);
                                intent.putExtra(EXTRA_MONTH, mo);
                                startActivity(intent);
                }

                @Override
                public boolean onCreateOptionsMenu(Menu menu) {
                                // Inflate the menu; this adds items to the action bar if it is present.
                                getMenuInflater().inflate(R.menu.home_page, menu);
                                return true;
                }

}
If we run our application at this point, we see...


If we click "Select Calendar Month", we see the DatePicker Dialog pop up...


Roll the month to January, which will automatically roll the year forward to 2014. You don't need to select the date since we'll do that when we bring up our calendar display. Unfortunately, there isn't a MonthPicker available in the Android API at this point; you have to make a custom one yourself, which is beyond the scope of this project. Click "Done", but not "Go" yet.

Our next activity, CalendarDisplay.java, will display our custom calendar. If you don't have a colors.xml file in your resources folder, make and add one now. Then, the code...

activity_calendar_display.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    android:gravity="center_horizontal"
    tools:context=".CalendarDisplay" >

    <TextView
        android:id="@+id/displayInfo"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <GridView
        android:id="@+id/daysView"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:numColumns="7"/>
    <GridView
        android:id="@+id/calendarView"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:numColumns="7"/>"

</LinearLayout>

CalendarDisplay.java
public class CalendarDisplay extends Activity {
                public final static String EXTRA_DATE = "com.stirfriedcode.basiccustomplanner.DATE";
                public final static String EXTRA_MONTH = "com.stirfriedcode.basiccustomplanner.MONTH";
                public final static String EXTRA_YEAR = "com.stirfriedcode.basiccustomplanner.YEAR";
               
                TextView thisMonth;
                GridView daysView;
                GridView calendarView;
                static int a, b;
               
                String[] months = new String[]{"January", "February", "March", "April", "May", "June",   "July", "August", "September", "October", "November", "December"};
                String[] days = new String[]{"Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"};

                @Override
                protected void onCreate(Bundle savedInstanceState) {
                         super.onCreate(savedInstanceState);
                         setContentView(R.layout.activity_calendar_display);
                         // Show the Up button in the action bar.
                         setupActionBar();
                               
                         Intent intent = getIntent();
                         int a = intent.getIntExtra(HomePage.EXTRA_YEAR, 0);
                         int b = intent.getIntExtra(HomePage.EXTRA_MONTH, 0);
                               
                        String month = months[b];
                        String year = Integer.toString(a);
                         thisMonth = (TextView) findViewById(R.id.displayInfo);
                         thisMonth.setText(month + "  " + year);
                               
                         daysView = (GridView) findViewById(R.id.daysView);
                         ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
                                                                R.layout.dow_view, days);
                         daysView.setAdapter(adapter);
                               
                         MonthDisplayHelper mdh = new MonthDisplayHelper(a, b);
                         int y = mdh.getFirstDayOfMonth();
                               
                         calendarView = (GridView) findViewById(R.id.calendarView);
                         List dates = new ArrayList();
                         for (int i = y+1; i < 42; i++) {
                                         String k = Integer.toString(i);
                                         Button butt = new Button(this);
                                         butt.setText(k);
                                         dates.add(butt);
                         }
                               
                        calendarView.setAdapter(new CalendarAdapter(this, R.layout.button_view, dates, a, b));
                               
                }
               
                public void onClick(View v) {
                     String sDate = v.getTag().toString();
                     Intent intent = getIntent();
                     String sMonth = months[intent.getIntExtra(HomePage.EXTRA_MONTH, 0)];
                     String sYear = Integer.toString(intent.getIntExtra(HomePage.EXTRA_YEAR, 0));
                               
                                Intent intent1 = new Intent(this, PlansList.class);
                                intent1.putExtra(EXTRA_DATE, sDate);
                                intent1.putExtra(EXTRA_MONTH, sMonth);
                                intent1.putExtra(EXTRA_YEAR, sYear);
                                startActivity(intent1);
                               
                }

                /**
                 * Set up the {@link android.app.ActionBar}, if the API is available.
                 */
              @TargetApi(Build.VERSION_CODES.HONEYCOMB)
              private void setupActionBar() {
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
                                                getActionBar().setDisplayHomeAsUpEnabled(true);
                        }
              }

                @Override
                public boolean onCreateOptionsMenu(Menu menu) {
                                // Inflate the menu; this adds items to the action bar if it is present.
                                getMenuInflater().inflate(R.menu.calendar_display, menu);
                                return true;
                }

                @Override
                public boolean onOptionsItemSelected(MenuItem item) {
                                switch (item.getItemId()) {
                                case android.R.id.home:
                               // This ID represents the Home or Up button. In the case of this
                               // activity, the Up button is shown. Use NavUtils to allow users
                               // to navigate up one level in the application structure. For
                               // more details, see the Navigation pattern on Android Design:
                               //
                               // http://developer.android.com/design/patterns/navigation.html#up-vs-back
                                                //
                                                NavUtils.navigateUpFromSameTask(this);
                                                return true;
                                }
                                return super.onOptionsItemSelected(item);
                }

}

Notice that there's a bit of unnecessary code; I just leave it as is after creating the activity and inserting the necessary code. I'll leave it as a minor exercise for you to remove what's not needed. Also, notice that we use a custom adapter called CalendarAdapter. The code for it is as follows...

CalendarAdapter.java
public class CalendarAdapter extends ArrayAdapter<Button> {
         private int  resource;
         private LayoutInflater inflater;
         private Context context;
         private int year;
         private int month;
               
         public CalendarAdapter(Context ctx, int resourceId, List<Button> objects, int calendarYear, int calendarMonth) {
             super( ctx, resourceId, objects);
             resource = resourceId;
             inflater = LayoutInflater.from( ctx );
             context = ctx;
             year = calendarYear;
             month = calendarMonth;
         }
               
                 @Override
                    public View getView ( int position, View convertView, ViewGroup parent ) {
                                            
                            /* create a new layout view and inflate it in the row */
                            convertView = ( LinearLayout ) inflater.inflate( resource, null );

                            
                            Button button = getItem(position);
                                            
                           
                            Calendar c = Calendar.getInstance();
                            MonthDisplayHelper mdh = new MonthDisplayHelper(year, month);
                            int y = mdh.getFirstDayOfMonth();
                            int n = mdh.getNumberOfDaysInMonth();
                            button = (Button) convertView.findViewById(R.id.dateButton);
                            if ((position+1)<y || (position+1)> (y+n-1)) {
                                button.setText("");
                                button.setBackgroundResource(R.color.white);
                            } else {
                            button.setText(Integer.toString(position-y+2));
                            button.setTag(position-y+2);
                            }               
                          
                                            
                           return convertView;
                   }


}
Note above that the individual views are buttons. R.id.dateButton comes from the following layout...

button_view.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
   
    <Button
        android:id="@+id/dateButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="12sp"
        android:onClick="onClick"/>
   

</LinearLayout>
Also, note that for the days of the week in CalendarDisplay.java, we use GridView again to display a row above the date buttons. We use a basic ArrayAdapter and a layout called dow_view.xml...

dow_view.xml
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:textSize="12sp"
    android:gravity="center">"
   

</TextView>
If we run our application now, we see...


In order to view existing plans or add a new one on a specific date, we click the date's button on the calendar display. But, not until we add the code for an activity called PlansList.java...

activity_plans_list.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    android:gravity="center_horizontal"
    tools:context=".PlansList" >

    <TextView
        android:id="@+id/listTitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <ListView
        android:id="@+id/theList"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content">
    </ListView>
    <TextView
        android:id="@+id/empty"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="No Plans Yet"/>"
    <Button
        android:id="@+id/makePlan"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Make New Plan"
        android:onClick="newPlan"/>

</LinearLayout>
PlansList.Java
public class PlansList extends Activity {
                public final static String EXTRA_DATE = "com.stirfriedcode.basiccustomplanner.DATE";
                public final static String EXTRA_MONTH = "com.stirfriedcode.basiccustomplanner.MONTH";
                public final static String EXTRA_YEAR = "com.stirfriedcode.basiccustomplanner.YEAR";
               
                PlansDataSource datasource;
                TextView listTitle;
                ListView theList;
                Button newPlan;
                EditText planName, planDetails, planTime;

                @Override
                protected void onCreate(Bundle savedInstanceState) {
                                super.onCreate(savedInstanceState);
                                setContentView(R.layout.activity_plans_list);
                                // Show the Up button in the action bar.
                                setupActionBar();
                               
                                datasource = new PlansDataSource(this);
                                datasource.open();
                               
                                Intent intent = getIntent();
                                String yr = intent.getStringExtra(CalendarDisplay.EXTRA_YEAR);
                                String mo = intent.getStringExtra(CalendarDisplay.EXTRA_MONTH);
                                String day = intent.getStringExtra(CalendarDisplay.EXTRA_DATE);
                                String date = mo+day+yr;
                               
                                listTitle = (TextView) findViewById(R.id.listTitle);
                                listTitle.setText("Plans for " + mo + " " + day + ", " + yr);
                               

                                theList = (ListView) findViewById(R.id.theList);
                                List<Plan> myPlans = datasource.getAllPlansOnDate(date);
                                theList.setAdapter(new PlanListAdapter(this, R.layout.list_row, myPlans));
                                theList.setEmptyView(findViewById(R.id.empty));
                                               
                }
               
                public void newPlan(View v) {
                                Intent intent = getIntent();
                                String yr = intent.getStringExtra(CalendarDisplay.EXTRA_YEAR);
                                String mo = intent.getStringExtra(CalendarDisplay.EXTRA_MONTH);
                                String day = intent.getStringExtra(CalendarDisplay.EXTRA_DATE);
                               
                                Intent intent1 = new Intent(this, CreatePlan.class);
                                intent1.putExtra(EXTRA_YEAR, yr);
                                intent1.putExtra(EXTRA_MONTH, mo);
                                intent1.putExtra(EXTRA_DATE, day);
                                startActivity(intent1);
                }
               

                /**
                 * Set up the {@link android.app.ActionBar}, if the API is available.
                 */
                @TargetApi(Build.VERSION_CODES.HONEYCOMB)
                private void setupActionBar() {
                                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
                                                getActionBar().setDisplayHomeAsUpEnabled(true);
                                }
                }

                @Override
                public boolean onCreateOptionsMenu(Menu menu) {
                                // Inflate the menu; this adds items to the action bar if it is present.
                                getMenuInflater().inflate(R.menu.plans_list, menu);
                                return true;
                }

                @Override
                public boolean onOptionsItemSelected(MenuItem item) {
                    switch (item.getItemId()) {
                    case android.R.id.home:
                    // This ID represents the Home or Up button. In the case of this
                    // activity, the Up button is shown. Use NavUtils to allow users
                    // to navigate up one level in the application structure. For
                    // more details, see the Navigation pattern on Android Design:
                    //
                    // http://developer.android.com/design/patterns/navigation.html#up-vs-back
                                                //
                                                NavUtils.navigateUpFromSameTask(this);
                                                return true;
                                }
                                return super.onOptionsItemSelected(item);
                }

}

This activity (PlansList.java) displays a list of scheduled plans for the date chosen in CalendarDisplay.java (if there are any) and allows the user to add a new plan to the list. To display the list of scheduled plans (if it exists already), we need a custom adapter. And, since our most basic objects used in this application are the plans themselves, we should create a Plan class now.

Plan.java
public class Plan {
                private long id;
                private String name, date, time, details;
               
                public Plan(String name, String date, String time, String details) {
                                this.name = name;
                                this.date = date;
                                this.time = time;
                                this.details = details;
                }
               
                public long getId(){
                                return id;
                }
               
                public void setId(long planId){
                                this.id = planId;
                }
               
                public String getName(){
                                return name;
                }
               
                public void setName(String planName){
                                name = planName;
                }
               
                public String getDate(){
                                return date;
                }
               
                public void setDate(String planDate){
                                date = planDate;
                }
               
                public String getTime(){
                                return time;
                }
               
                public void setTime(String planTime){
                                time = planTime;
                }
               
                public String getDetails(){
                                return details;
                }
               
                public void setDetails(String planDetails){
                                details = planDetails;
                }
               
                @Override
                  public String toString() {
                                  return "Plan [id=" + id + ", name=" + name + ", date=" + date
                                + ", time=" + time + ", details=" + details +"]";
                  }

}
Also, to display plans in PlansList (and add new ones) we need a plan-list adapter...

PlanListAdapter.java
public class PlanListAdapter extends ArrayAdapter<Plan> {
                private int  resource;
    private LayoutInflater inflater;
    private Context context;
   
    public PlanListAdapter(Context ctx, int resourceId, List<Plan> objects) {
        super( ctx, resourceId, objects );
        resource = resourceId;
        inflater = LayoutInflater.from( ctx );
        context = ctx;
    }
   
    @Override
    public View getView ( int position, View convertView, ViewGroup parent ) {
                             
            /* create a new layout view and inflate it in the row */
            convertView = ( LinearLayout ) inflater.inflate( resource, null );

            
            Plan plan = getItem(position);
           
            TextView ptime = (TextView) convertView.findViewById(R.id.pt);
            ptime.setText(plan.getTime() + " ");
                             
            
            TextView pname = (TextView) convertView.findViewById(R.id.pn);
            pname.setText(plan.getName());
                             
           
           TextView pdetails = (TextView) convertView.findViewById(R.id.pd);
           pdetails.setText(plan.getDetails());
                             
           return convertView;
   }


}
We need a custom list-row layout for our adapter...

list_row.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
   
    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <TextView
            android:id="@+id/pt"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
       <TextView
            android:id="@+id/pn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/> "
    </LinearLayout>
   
    <TextView
            android:id="@+id/pd"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"/>
   

</LinearLayout>

We can display our list if we have plans saved to a database for retrieval. So, we create an SQLite database and a Data Access Object to help us store and get data from it...

PlanDBHelper.java
public class PlanDBHelper extends SQLiteOpenHelper {
                public static final String TABLE_PLANS = "plans";
                public static final String COLUMN_ID = "_id";
                public static final String COLUMN_NAME = "name";
                public static final String COLUMN_DATE = "date";
                public static final String COLUMN_TIME = "time";
                public static final String COLUMN_DETAILS = "details";
               
                private static final String DATABASE_NAME = "plans.db";
                private static final int DATABASE_VERSION = 1;
               
                private static final String DATABASE_CREATE = "create table " +    TABLE_PLANS + " (" + COLUMN_ID
                              + " integer primary key autoincrement, " + COLUMN_NAME + " text, " + COLUMN_DATE + " text, " + COLUMN_TIME + " text, " + COLUMN_DETAILS + " text);";
               
                public PlanDBHelper(Context context) {
                                super(context, DATABASE_NAME, null, DATABASE_VERSION);
                }

                @Override
                public void onCreate(SQLiteDatabase database) {
                                database.execSQL(DATABASE_CREATE);

                }

                @Override
                public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
                                Log.w(PlanDBHelper.class.getName(),
                                                                "Upgrading database from version " + oldVersion + " to "
                                                                + newVersion + ", which will destroy all old data");
                                db.execSQL("DROP TABLE IF EXISTS " + TABLE_PLANS);
                                onCreate(db);

                }

}


PlansDataSource.java
public class PlansDataSource {
                private SQLiteDatabase database;
                private PlanDBHelper dbHelper;
                private String[] allColumns = {PlanDBHelper.COLUMN_ID, PlanDBHelper.COLUMN_NAME,
                                                PlanDBHelper.COLUMN_DATE, PlanDBHelper.COLUMN_TIME,
                                                PlanDBHelper.COLUMN_DETAILS };
               
                public PlansDataSource(Context context){
                                dbHelper = new PlanDBHelper(context);
                }
               
                public void open() throws SQLException {
                                database = dbHelper.getWritableDatabase();
                }
               
                public void close() {
                                dbHelper.close();
                }
               
                public Plan createPlan(Plan plan) {
                         ContentValues values = new ContentValues();
                          values.put(PlanDBHelper.COLUMN_NAME, plan.getName());
                          values.put(PlanDBHelper.COLUMN_DATE, plan.getDate());
                          values.put(PlanDBHelper.COLUMN_TIME, plan.getTime());
                          values.put(PlanDBHelper.COLUMN_DETAILS, plan.getDetails());
                          long insertId = database.insert(PlanDBHelper.TABLE_PLANS, null, values);
                         Cursor cursor = database.query(PlanDBHelper.TABLE_PLANS, allColumns,
                                                                PlanDBHelper.COLUMN_ID + " = " + insertId, null,
                                                                null, null, null);
                                cursor.moveToFirst();
                                Plan newPlan = cursorToPlan(cursor);
                                cursor.close();
                                return newPlan;
                               
                }
               
                public void deletePlan(Plan plan) {
                       long id = plan.getId();
                       System.out.println("Plan deleted with id: " + id);
                       database.delete(PlanDBHelper.TABLE_PLANS, PlanDBHelper.COLUMN_ID
                                                                + " = " + id, null);
                }
               
            public List<Plan> getAllPlansOnDate(String planDate) {
                  List<Plan> plans = new ArrayList<Plan>();
                 Cursor cursor = database.query(true, PlanDBHelper.TABLE_PLANS, allColumns,
                                       PlanDBHelper.COLUMN_DATE + " =?" , new String[]{planDate}, null,
                                                                null, null, null);
                               
            cursor.moveToFirst();
                    while (!cursor.isAfterLast()) {
                      Plan plan = cursorToPlan(cursor);
                      plans.add(plan);
                      cursor.moveToNext();
                    }
                    // make sure to close the cursor
                    cursor.close();
                    return plans;
                }
               
                private Plan cursorToPlan(Cursor cursor) {
                    Plan plan = new Plan(cursor.getString(1), cursor.getString(2), cursor.getString(3), cursor.getString(4));
                    plan.setId(cursor.getLong(0));
                    plan.setName(cursor.getString(1));
                    plan.setDate(cursor.getString(2));
                    plan.setTime(cursor.getString(3));
                    plan.setDetails(cursor.getString(4));
                    return plan;
                  }
               

}

So now, if we click the "14" button on our CalendarDisplay, we see our plans list...



You can see that a couple of plans (previously stored in our database) have been retrieved and displayed. To make a new plan, we need to add an activity we'll call CreatePlan.java...

activity_create_plan.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    android:gravity="center_horizontal"
    tools:context=".CreatePlan" >

   
    <TextView
        android:id="@+id/dateYear"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    <EditText
        android:id="@+id/nameField"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:hint="Give Your Plan a Name"/>
    <EditText
        android:id="@+id/detailsField"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:hint="Enter Plan Details"/>
    <Button
        android:id="@+id/getPicker"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Set Time"
        android:onClick="setTime"/>
    <TimePicker
        android:id="@+id/setTime"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>"
    <Button
        android:id="@+id/storePlan"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Save Plan"
        android:onClick="onClick"/>"

</LinearLayout>

CreatePlan.java
public class CreatePlan extends Activity {
                PlansDataSource datasource;
                private TimePicker timePicker;
                private int hour, minute;
                static final int TIME_DIALOG_ID = 999;
               
                TextView showDate;
                EditText name, details;

                @Override
                protected void onCreate(Bundle savedInstanceState) {
                                super.onCreate(savedInstanceState);
                                setContentView(R.layout.activity_create_plan);
                                // Show the Up button in the action bar.
                                setupActionBar();
                                timePicker = (TimePicker) findViewById(R.id.setTime);
                                name = (EditText) findViewById(R.id.nameField);
                                details = (EditText) findViewById(R.id.detailsField);
                               
                                Intent intent = getIntent();
                                String a = intent.getStringExtra(PlansList.EXTRA_MONTH);
                                String b = intent.getStringExtra(PlansList.EXTRA_DATE);
                                String d = intent.getStringExtra(PlansList.EXTRA_YEAR);
                               
                                showDate = (TextView) findViewById(R.id.dateYear);
                                showDate.setText("New Plan For " + a + " " + b + ", " + d);
                }
               
                public void setTime(View v) {
                                showDialog(TIME_DIALOG_ID);
                }
               
                @Override
                protected Dialog onCreateDialog(int id) {
                       switch (id) {
                       case TIME_DIALOG_ID:
                               return new TimePickerDialog(this, timePickerListener, hour, minute,false);

                      }
                               return null;
                }
               
                private TimePickerDialog.OnTimeSetListener timePickerListener = new
                                                TimePickerDialog.OnTimeSetListener() {
                        public void onTimeSet(TimePicker view, int selectedHour, int selectedMinute) {
                                                hour = selectedHour;
                                                minute = selectedMinute;
                                                timePicker.setCurrentHour(hour);
                                                timePicker.setCurrentMinute(minute);
                       }
                };
               
                public void onClick(View v) {
                                name = (EditText) findViewById(R.id.nameField);
                                details = (EditText) findViewById(R.id.detailsField);
                                String planName = name.getText().toString();
                                String planDetails = details.getText().toString();
                                timePicker = (TimePicker) findViewById(R.id.setTime);
                                String hr = timePicker.getCurrentHour().toString();
                                int minute = timePicker.getCurrentMinute();
                                String min = String.format("%02d", minute);

                                String planTime = hr + ":" + min;
                               
                                Intent intent = getIntent();
                                String month = intent.getStringExtra(PlansList.EXTRA_MONTH);
                                String date = intent.getStringExtra(PlansList.EXTRA_DATE);
                                String year = intent.getStringExtra(PlansList.EXTRA_YEAR);
                                String planDate = month+date+year;
                               
                                datasource = new PlansDataSource(this);
                                datasource.open();
                   
                               Plan newPlan = null;
                               Plan plan = new Plan(planName, planDate, planTime, planDetails);
                               newPlan = datasource.createPlan(plan);
                               finish();
                                               
                }

                /**
                 * Set up the {@link android.app.ActionBar}, if the API is available.
                 */
                @TargetApi(Build.VERSION_CODES.HONEYCOMB)
                private void setupActionBar() {
                             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
                                                getActionBar().setDisplayHomeAsUpEnabled(true);
                                }
                }

                @Override
                public boolean onCreateOptionsMenu(Menu menu) {
                                // Inflate the menu; this adds items to the action bar if it is present.
                                getMenuInflater().inflate(R.menu.create_plan, menu);
                                return true;
                }

                @Override
                public boolean onOptionsItemSelected(MenuItem item) {
                                switch (item.getItemId()) {
                                case android.R.id.home:
                                                // This ID represents the Home or Up button. In the case of this
                                                // activity, the Up button is shown. Use NavUtils to allow users
                                                // to navigate up one level in the application structure. For
                                                // more details, see the Navigation pattern on Android Design:
                                                //
                                                // http://developer.android.com/design/patterns/navigation.html#up-vs-back
                                                //
                                                NavUtils.navigateUpFromSameTask(this);
                                                return true;
                                }
                                return super.onOptionsItemSelected(item);
                }

}
So, now if we click "Make New Plan", we're taken to the CreatePlan activity...



We enter the plan name and details, as well as set the time using the TimePicker. 3:00 is as good a time as any for eating a pineapple, in my opinion...

After we click "Save Plan", we hit the back button and start from the beginning... Go to the PlansList page for January 14, 2014, and you should see...


As usual, if you have any questions or concerns about this exercise, please let me know via the comments section. And, as always, thanks for following.