Calling system applications in Android


In my previous posts I have used reading contacts through API calls, however there is an easy method for doing standard tasks by calling system’s pre installed apps. In this post I am going to cover the details of how we can call the system apps through intents.

We are going to create a spinner control for providing the user some options and hit a submit button.

Here’s main.xml which defines the UI.

 <?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"  
     >  
   <Spinner  
       android:id="@+id/spinner1"  
       android:layout_width="match_parent"  
       android:layout_height="wrap_content"  
       android:entries="@array/application_array"  
       android:prompt="@string/app_prompt" />  
   <Button  
       android:id="@+id/btnSubmit"  
       android:layout_width="wrap_content"  
       android:layout_height="wrap_content"  
       android:text="Submit"  
       android:onClick="btnSubmitOnClick"/>  
 </LinearLayout>  

Spinner control requires a string array (application_array) for it’s entries which is defined in strings.xml.

 <?xml version="1.0" encoding="utf-8"?>  
 <resources>  
   <string name="app_name">callingsystemapps</string>  
   <string name="app_prompt">Choose a application</string>  
   <string-array name="application_array">  
     <item>Browser</item>  
     <item>Dialler</item>  
     <item>Map</item>  
     <item>Contacts</item>  
   </string-array>  
 </resources>  

In main.xml we have also have defined onClick method btnSubmitOnClick which is defined in MyActivity.java

   public void btnSubmitOnClick (View v)  
   {  
     Spinner spinner1 = (Spinner) findViewById(R.id.spinner1);  
     if (spinner1.getSelectedItem().toString().equals("Browser")){  
       Intent i = new  
           Intent(android.content.Intent.ACTION_VIEW,  
           Uri.parse("http://www.google.com"));  
       startActivity(i);  
     }  
     else if (spinner1.getSelectedItem().toString().equals("Dialler")){  
       Intent i = new  
           Intent(android.content.Intent.ACTION_DIAL);  
       startActivity(i);  
     }  
     else if (spinner1.getSelectedItem().toString().equals("Map")) {  
         Intent i = new  
             Intent(android.content.Intent.ACTION_VIEW,  
             Uri.parse("geo:37.827500,-122.481670"));  
         startActivity(i);  
     }  
     else if (spinner1.getSelectedItem().toString().equals("Contacts")) {  
       Intent i = new  
           Intent(android.content.Intent.ACTION_PICK);  
       i.setType(ContactsContract.CommonDataKinds.Phone.CONTENT_TYPE);  
       startActivity(i);  
     }  

Only difference between the four is the passing intent which is as below:

ACTION_VIEW
ACTION_DIAL
ACTION_PICK

Along with that we are passing parameters depending upon intent type. After that it’s just calling startActivity on the intent.

Try running the example and you shall get like this.

getActionBar and targetSdkVersion in Android development


Hi All,Recently I was trying to reiterate Android docs training just to fill in anything I missed previously. There I came across this piece of code:

// Initialize member TextView so we can manipulate it later  
     mTextView = (TextView) findViewById(R.id.edit_message);  
     // Make sure we're running on Honeycomb or higher to use ActionBar APIs  
     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {  
       // For the main activity, make sure the app icon in the action bar  
       // does not behave as a button  
       ActionBar actionBar = getActionBar();  
       actionBar.setHomeButtonEnabled(false);  
     }

I tried to put that in a simple hello world example and it worked on an 2.2 emulator, however it failed to run on 4.0 emulator. On debugging it turned out that getActionBar was returning null value. Though there was on-line help available for some other directions it just came to my mind to check AndroidManifest.xml file. There I saw only “android:minSdkVersion=”8″” I remembered that there was a target SDK  as well which can be defined. So I checked a project created by eclipse and found the “android:targetSdkVersion=”15″” line and added it to “uses-sdk ” tag in AndroidManifest.xml and the app started working on 4.0 emulator.

This clears two things, first is that Idea IDE adds only minSDKVersion while eclipse adds targetSDKVersion as well. Which is reflected in new project also but could effect like this.

Second, if you search for getActionBar returning null you get loads of advice but maybe not this. So check if you are having this issue.

Thanks for reading. Thanks for Android guys for creating such a good documentation, which by and large so much better than Facebook developer docs. Only wish Facebook docs were also as clear as the Android docs.

Nexus 4 unboxing and first impressions


Google’s newest flagship handset, the LG Nexus, 4 is finally upon us. The highly anticipated stock Android smartphone features some of the highest-end specs of any phone currently on the market, but does it manage to satisfy? Stay tuned for a complete review. However, in the meantime, be sure to catch our unboxing and first impressions below.

http://supertechblog.com/2012/11/17/nexus-4-unboxing-and-first-impressions/

via Blogger http://ashish-yadav.blogspot.com/2012/11/nexus-4-unboxing-and-first-impressions.html

An outrageously simple note taking android app made further better (part 5)


In this post we will cover sending SMS through Android App and also how to read contacts.

I apologize for the gap in coming up with this post. I can only work as much as my health permits, which sometimes not very long. :)

The very first thing an Android app needs is to register for permission to send SMS and read contacts. This can be done by putting these lines into AndroidManifest.xml.

<uses-permission android:name=”android.permission.SEND_SMS”></uses-permission>
<uses-permission android:name=”android.permission.READ_CONTACTS”/>

We will add a new menu item in context menu like below.

    public void onCreateContextMenu(ContextMenu menu, View v,ContextMenu.ContextMenuInfo menuInfo) {
        super.onCreateContextMenu(menu, v, menuInfo);
        currentNote = ((TextView)v).getText().toString();
        // Create your context menu here
        menu.setHeaderTitle(“Context Menu”);
        menu.add(0, v.getId(), 0, “Edit n Replace”);
        menu.add(0, v.getId(), 1, “Delete”);
        menu.add(0, v.getId(), 2, “Send as SMS”);
    }

And we will see somethinglike below.

For handling this menu item we will add a new else section.

    public boolean onContextItemSelected(MenuItem item) {
        // Call your function to preform for buttons pressed in a context menu
        // can use item.getTitle() or similar to find out button pressed
        // item.getItemID() will return the v.getID() that we passed before
        super.onContextItemSelected(item);

        if ( item.getTitle().toString().equals(“Delete”)){
            NotesDatabase db =new NotesDatabase(this);

            db.searchAndDelete(currentNote);
            onResume();
        }
        else if ( item.getTitle().toString().equals(“Edit n Replace”)) {
            Intent intent = new Intent(this, EditNoteActivity.class);
            intent.putExtra(“ACTION”,”oldnote”);
            intent.putExtra(“ACTION2″,”replace”);
            intent.putExtra(EXTRA_MESSAGE,currentNote);
            startActivity(intent);
        }
        else if (item.getTitle().toString().equals(“Send as SMS”)){
            Intent intent = new Intent(this, SendAsSmsActivity.class);
            intent.putExtra(“SMS”, currentNote);
            startActivity(intent);
        }

        return true;
    }

In the newly added code we are creating a new Activity SendAsSmsActivity and passing the note as SMS in intent.

Here is SendAsSmsActivity.xml which is defined as below.

<?xml version=”1.0″ encoding=”utf-8″?>

<LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android&#8221;
              android:layout_width=”fill_parent”
              android:layout_height=”fill_parent”
              android:orientation=”vertical”>
    <EditText
        android:id=”@+id/editText1″
        android:layout_width=”match_parent”
        android:layout_height=”wrap_content”
        android:ems=”10″
        android:inputType=”number”
        android:hint=”Enter number here…”
        android:gravity=”top|left”>
        <requestFocus />
    </EditText>
    <EditText
            android:id=”@+id/editText2″
            android:layout_width=”match_parent”
            android:layout_height=”1dp”
            android:layout_weight=”1″
            android:ems=”10″
            android:inputType=”text”
            android:hint=”Enter note here…”
            android:gravity=”top|left” >

    </EditText>

    <LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android&#8221;
                  android:layout_width=”match_parent”
                  android:layout_height=”wrap_content”
                  android:orientation=”horizontal”
                  android:weightSum=”2″>
        <Button
                android:id=”@+id/buttonSendSMS”
                android:layout_weight=”1″
                android:layout_width=”0dp”
                android:layout_height=”wrap_content”
                android:onClick=”onClickSend”

                android:text=”Send” />
        <Button
                android:id=”@+id/button2″
                android:layout_weight=”1″
                android:layout_width=”0dp”
                android:layout_height=”wrap_content”
                android:onClick=”onClickCancel”

                android:text=”Cancel” />
    </LinearLayout>
</LinearLayout>

It will come up like this

Here we are using nested LinearLayout with nested wights assigned to buttons as well as second edit text, which though is not a good practise; but for our small app workes fine.

Below is SendAsSmsActivity.java

public class SendAsSmsActivity extends Activity {
    String sms = new String();

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.sendassmsactivity);
        Intent intent = getIntent();
        EditText text = (EditText) findViewById(R.id.editText2);
        Bundle extras = intent.getExtras();
        sms = extras.getString(“SMS”);
        text.setText(sms);
        EditText text1 = (EditText) findViewById(R.id.editText1);
        registerForContextMenu (text1);
    }
    public void onClickSend ( View button){
        String SENT = “SMS_SENT”;
        String DELIVERED = “SMS_DELIVERED”;

        PendingIntent sentPI = PendingIntent.getBroadcast(this,0,new Intent(SENT),0);
        PendingIntent deliveredPI = PendingIntent.getBroadcast(this,0,new Intent(DELIVERED),0);

        //—when the SMS has been sent—
        registerReceiver(new BroadcastReceiver(){
            @Override
            public void onReceive(Context arg0, Intent arg1) {
                switch (getResultCode())
                {
                    case Activity.RESULT_OK:
                        Toast.makeText(getBaseContext(), “SMS sent”,
                                Toast.LENGTH_SHORT).show();
                        break;
                    case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
                        Toast.makeText(getBaseContext(), “Generic failure”,
                                Toast.LENGTH_SHORT).show();
                        break;
                    case SmsManager.RESULT_ERROR_NO_SERVICE:
                        Toast.makeText(getBaseContext(), “No service”,
                                Toast.LENGTH_SHORT).show();
                        break;
                    case SmsManager.RESULT_ERROR_NULL_PDU:
                        Toast.makeText(getBaseContext(), “Null PDU”,
                                Toast.LENGTH_SHORT).show();
                        break;
                    case SmsManager.RESULT_ERROR_RADIO_OFF:
                        Toast.makeText(getBaseContext(), “Radio off”,
                                Toast.LENGTH_SHORT).show();
                        break;
                }
            }
        }, new IntentFilter(SENT));

        //—when the SMS has been delivered—
        registerReceiver(new BroadcastReceiver(){
            @Override
            public void onReceive(Context arg0, Intent arg1) {
                switch (getResultCode())
                {
                    case Activity.RESULT_OK:
                        Toast.makeText(getBaseContext(), “SMS delivered”,
                                Toast.LENGTH_SHORT).show();
                        break;
                    case Activity.RESULT_CANCELED:
                        Toast.makeText(getBaseContext(), “SMS not delivered”,
                                Toast.LENGTH_SHORT).show();
                        break;
                }
            }
        }, new IntentFilter(DELIVERED));

        SmsManager smsManager = SmsManager.getDefault();

        EditText text1 = (EditText) findViewById(R.id.editText1);
        Log.v(“phoneNumber”, text1.getText().toString());
        Log.v(“MEssage”,sms);
        smsManager.sendTextMessage(text1.getText().toString(), null, sms, sentPI, deliveredPI);
        finish();
    }
    public void onClickCancel( View button){
        finish();
    }
    public void onCreateContextMenu(ContextMenu menu, View v,ContextMenu.ContextMenuInfo menuInfo) {
        super.onCreateContextMenu(menu, v, menuInfo);
        //currentNote = ((TextView)v).getText().toString();
        // Create your context menu here
        // Clear current contents
        menu.clearHeader();
        menu.clear();

        menu.setHeaderTitle(“Context Menu”);
        menu.add(0, v.getId(), 0, “Contacts”);
    }
    public boolean onContextItemSelected(MenuItem item) {
        // Call your function to preform for buttons pressed in a context menu
        // can use item.getTitle() or similar to find out button pressed
        // item.getItemID() will return the v.getID() that we passed before
        super.onContextItemSelected(item);

        if ( item.getTitle().toString().equals(“Contacts”)){
            Intent intent = new Intent(this,readAllActivity.class);
            startActivityForResult( intent, 0);
        }
        return true;
    }

}

Kindly go through my previous post if you are not familier with above code.

We are here in onCreate method; setting the view by setContentView, getting the intent by getIntent, getting the note by getExtras and getString and assigning to second edit text. We are also registering the first edit text for a context menu.

onClickSend is the method registered for “Send” button. Here is the actual code for sending SMS  Here we are creating PendingIntent which are a kind of callback mechanism in which we specifies the action need to be performed at a certain event later in lifecycle of application.

registerReceiver defines the method which needs to be performed in the case of event (SMS sent). It has two parameters one is BroadcastReceiver which actually holds the methods needs to be performed. When the onReceive overridden method is called it raises a Toast ( small info window) based on  the return value of getResultCode which tells whether the action was prformed well.

Second parameter is a IntentFilter object.

Here’s the toast :)

After that SmsManager.getDefault returns a sms manager object, which actually send the sms and also registers the PendingIntents.

Overriding onCreateContextMenu definesthe context menu which we have registered for text1 in onCreate. “Contacts” is the only menu item here.

In onContextItemSelected when we find this selected we start a new activity readAllActivity.

Here is readAllActivity.java

public class readAllActivity extends Activity {

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        readContacts();
    }
    public void readContacts (){
        LinearLayout lLayout = (LinearLayout)findViewById(R.id.layout1);
        final LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        Cursor cursor = getContentResolver().query(ContactsContract.Contacts.CONTENT_URI,null, null, null, null);
        while (cursor.moveToNext()) {
            String contactId = cursor.getString(cursor.getColumnIndex(
                    ContactsContract.Contacts._ID));
                Cursor phones = getContentResolver().query( ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID +” = “+ contactId, null, null);
                while (phones.moveToNext()) {
                    String name = phones.getString(phones.getColumnIndex( ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
                    TextView b2 = (TextView) inflater.inflate(R.layout.textviews,null);
                    b2.setTextColor(Color.BLACK) ;
                    b2.setText(name);
                    registerForContextMenu(b2);
                    lLayout.addView(b2);

                    String phoneNumber = phones.getString(phones.getColumnIndex( ContactsContract.CommonDataKinds.Phone.NUMBER));
                    TextView b = (TextView) inflater.inflate(R.layout.textviews,null);
                    b.setTextColor(Color.BLACK) ;
                    b.setText(phoneNumber);
                    registerForContextMenu(b);
                    lLayout.addView(b);

                }
                phones.close();
        }
        cursor.close();
    }
}

getContentResolve returns all the contacts in a cursor “phones”, which we scrolls through and populates edit texts.

Till now all is fine except how do we return the selected phone number.

We have used startActivityForResult instead of startActivity in onContextItemSelected of SendAsSmsActivity.java file.

In readAllActivity.java we will add this method to set returning data

     public void onClickTextView1(View v) {
        Intent resultData = new Intent();
        String s =((TextView)v).getText().toString();
        resultData.putExtra(“number”, s);
        setResult(Activity.RESULT_OK, resultData);
        finish();
    }
Aaaaand we shall have our number in first EditText.

Thanks to Wei-Meng Lee for his “Beginning Android Application Development” for sms code and stackoverflow.com for rest of help.

An outrageously simple note taking android app made even more better (part 4)


In this post we will add code to display context menu to “edit and replace”, and “delete” note.

Adding a context menu is easy ( well, most of the things are easy once you know how :) ). Just call  registerForContextMenu(b); in for loop in onResume of MyActivity.java.

Further override onCreateContextMenu to add items in context menu.

    public void onCreateContextMenu(ContextMenu menu, View v,ContextMenu.ContextMenuInfo menuInfo) {
        super.onCreateContextMenu(menu, v, menuInfo);
        currentNote = ((TextView)v).getText().toString();
        // Create your context menu here
        menu.setHeaderTitle("Context Menu");
        menu.add(0, v.getId(), 0, "Edit n Replace");
        menu.add(0, v.getId(), 1, "Delete");
    }

And you shall see a context menu as below

we are also saving the current note here in currentNote.

We also need to override onContextItemSelected method as below.

    public boolean onContextItemSelected(MenuItem item) {
        // Call your function to perform for buttons pressed in a context menu
        // can use item.getTitle() or similar to find out button pressed
        // item.getItemID() will return the v.getID() that we passed before
        super.onContextItemSelected(item);

        if ( item.getTitle().toString().equals("Delete")){
            NotesDatabase db =new NotesDatabase(this);

            db.searchAndDelete(currentNote);
            onResume();
        }
        else if ( item.getTitle().toString().equals("Edit n Replace")) {
            Intent intent = new Intent(this, EditNoteActivity.class);
            intent.putExtra("ACTION","oldnote");
            intent.putExtra("ACTION2","replace");
            intent.putExtra(EXTRA_MESSAGE,currentNote);
            startActivity(intent);
        }

        return true;
    }

If the item selected in menu is “Delete” then a new function searchAndDelete in NotesDatabase.java deletes the note.

If it’s “Edit n Replace” then the EditNoteActivity is started with intent carrying extra messages to describe the action needs to be performed in aptly named ACTION1 and ACTION2.

Below is searchAndDelete function in NotesDatabase.java

    public void searchAndDelete ( String note) {
        String selectQuery = "SELECT  " +  KEY_ID + " FROM " + TABLE_NOTES + " WHERE " + KEY_NOTE + " = " + "'" + note + "';";
        Notes notes= new Notes();

        SQLiteDatabase db = this.getWritableDatabase();
        Cursor cursor = db.rawQuery(selectQuery, null);

        cursor.moveToFirst();
        notes.setID(Integer.parseInt(cursor.getString(0)));

        deleteNote(notes);
    }

Very simply note is searched in database for its id, and when found complete notes objet is passed to deleteNote for actual deletion.

Below is EditNoteActivity.java

public class EditNoteActivity extends Activity {
    public final static String EXTRA_MESSAGE = "com.example.NoteTaking.MESSAGE";
    String action = new String(),action2 = new String(),oldnote = new String();

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.editnote);
        Intent intent = getIntent();
        EditText text = (EditText) findViewById(R.id.editText1);

        Bundle extras = intent.getExtras();
        if ( extras.getString("ACTION").equals("oldnote")) {
            action = "oldnote";
            if ( extras.getString("ACTION2").equals("replace")) {
                action2 = "replace";
            }
            oldnote = extras.getString(EXTRA_MESSAGE);
            text.setText(extras.getString(EXTRA_MESSAGE));
        }
    }

    public void onClickSave(View theButton) {
        EditText text = (EditText) findViewById(R.id.editText1);
        NotesDatabase db =new NotesDatabase(this);

        if ( action.equals("oldnote") && action2.equals("replace")) {
            db.searchAndDelete(oldnote);
        }
        db.addNote(new Notes(text.getText().toString()));
        finish();
    }
    public void onClickBack(View theButton) {
        finish();
    }
}

Here action, action2 and oldnote store the messages passed in intent either onClickTextView1 or onContextItemSelected. Based on action messages sent onClickSave will either delete the note and save the new, or just save the new note leaving old one intact.

Again lot of people helped from stackoverflow.com, many thanks to them.

Here is the complete source code, licensed under GPLv2.

http://www.mediafire.com/download.php?prbz0i39iaxc09i

I hope these post give a lot of learning to readers as they had been to mine. Of Course it’s still not perfect and we will keep improving it in future.

Thanks for reading. :)

Update

Adding this functionality broke the old code. In EditNoteActivity.java we need to count number of messages passed in intent before trying to access the third message. As we send 2 message for normal editing and three for replace. Here is the code which will be in EditNoteActivity.java.

public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.editnote);
        Intent intent = getIntent();
        EditText text = (EditText) findViewById(R.id.editText1);

        Bundle extras = intent.getExtras();
        Set<String> keypair = extras.keySet();

        if ( extras.getString("ACTION").equals("oldnote")) {
            action = "oldnote";
            if ( keypair.size() == 3 ) {
            if ( extras.getString("ACTION2").equals("replace")) {
                action2 = "replace";
            }
            }
            oldnote = extras.getString(EXTRA_MESSAGE);
            text.setText(extras.getString(EXTRA_MESSAGE));
        }
    }

We are taking the key value pair using extras.keySet and checking it’s size equals to 3 before accessing the third message.

An outrageously simple note taking android app made even better (part 3)


As promised we will improve further the NoteTaking app in this tutorial.

We will change the look of the app to have EditText instead of TextView to display notes on main screen. Also clicking on note will open the note for editing and save it as a new note.

Here is the main.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"
              android:id="@+id/layout1">
 </LinearLayout>

Notice that it’s just a plain layout file I have seperated the add button in addnotebutton.xml.

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

<Button  xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/AddNote"
        android:id="@+id/addnote"
        android:onClick="addNote"/>

This will make it easy to dynamically create the view to show all notes. There would be more effiecient ways to do this but for sake of simplicity I will recreate the view each time.

Below is the textvies.xml

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

<EditText xmlns:android="http://schemas.android.com/apk/res/android"
          android:id="@+id/textview1"
          android:onClick="onClickTextView1"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"/>

Notice that the file has a new onClick line which is defining the function onClickTextView1 method to be executed each time a user clicks on any note.

Update1:

It seems that TextView can be made clickable as well using

android:clickable="true"

Here is changed textviews.xml

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

<TextView xmlns:android="http://schemas.android.com/apk/res/android"
          android:id="@+id/textview1"
          android:onClick="onClickTextView1"
          android:clickable="true"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"/>

For loop in MyActivity.java will be like this.

for ( Notes nt: notes) {

            TextView b = (TextView) inflater.inflate(R.layout.textviews,null);
            b.setText(nt.getNote());
            lLayout.addView(b);
        }

Thanks to stackoverflow(http://stackoverflow.com/questions/3328757/how-to-click-or-tap-on-a-textview-text)

End Update2:

Now here is MyActivity.java

public class MyActivity extends Activity {
    public final static String EXTRA_MESSAGE = "com.example.NoteTaking.MESSAGE";
    /**
     * Called when the activity is first created.
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
    public void addNote ( View theButton) {
        Intent intent = new Intent(this, EditNoteActivity.class);
        intent.putExtra("ACTION","addnote");
        startActivity(intent);
    }
    public void onClickTextView1 ( View textview) {
        Intent intent = new Intent(this, EditNoteActivity.class);
        intent.putExtra("ACTION","oldnote");
        intent.putExtra(EXTRA_MESSAGE,((TextView)textview).getText().toString());
        startActivity(intent);
    }
    public void onResume () {
        super.onResume();
        setContentView(R.layout.main);

        LinearLayout lLayout = (LinearLayout)findViewById(R.id.layout1);
        final LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        Button add = (Button) inflater.inflate(R.layout.addnotebutton, null);
        lLayout.addView(add);
        NotesDatabase db =new NotesDatabase(this);

        List<Notes> notes = db.getAllNotes();
         for ( Notes nt: notes) {
             EditText b = (EditText) inflater.inflate(R.layout.textviews,null);
            b.setKeyListener(null);
            b.setText(nt.getNote());
            lLayout.addView(b);
        }
    }
}

We have moved most of the functionality into onResume as this will be called when the Activity starts as well as each time Activity resumes. It’s mostly like old code except that it adds the button also dynamically through inflator. Also we are setting the setKeyListner to null as we don’t want it to be editable.

In onClickTextView1 we are creating a new intent and passing it along with key value pair of “ACTION” and “oldnote” to specify that a old note needs to be set in. We are also passing the note with EXTRA_MESSAGE. Similarly in addNote we are passing the “ACTION” AS “addnote”.

Now following is EditNoteActivity.java

public class EditNoteActivity extends Activity {
    public final static String EXTRA_MESSAGE = "com.example.NoteTaking.MESSAGE";
    String action;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.editnote);
        Intent intent = getIntent();
        EditText text = (EditText) findViewById(R.id.editText1);

        Bundle extras = intent.getExtras();
        if ( extras.getString("ACTION").equals("oldnote")) {
            action = "oldnote";
            text.setText(extras.getString(EXTRA_MESSAGE));
        }
    }

    public void onClickSave(View theButton) {
        EditText text = (EditText) findViewById(R.id.editText1);
        NotesDatabase db =new NotesDatabase(this);

        db.addNote(new Notes(text.getText().toString()));
        finish();
    }
    public void onClickBack(View theButton) {
        finish();
    }
}

Here we getting the intent in onCreate which we passed from Myactivity.java in addNote or onClickTextView1 methods, by getIntent method. intent.getExtras returns the key value pairs we put inside the intent. Only if the “oldnote” is passed we retreive the note using EXTRA_MESSAGE  identifier string.  Rest is similar to what we did earlier.

Now run the app and we you will something similar.

No doubt there is still a lot of room for improvement, and we shall keep doing that.

Thanks for reading, thanks to all those who helped specially Lars Vogel (http://www.vogella.com/articles/AndroidIntent/article.html).

Update2:

These updates could have been a new post , but anyways.

You could set the style of TextView from update1 as described below in textviews.xml and back.xml.

textviews.xml

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

<TextView xmlns:android="http://schemas.android.com/apk/res/android"
          android:id="@+id/textview1"
          android:background="@layout/back"
          android:onClick="onClickTextView1"
          android:clickable="true"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"/>

Here android:background=”@layout/back” specify the style as defined in back.xml.

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

<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
    <solid android:color="#ffffff" />
    <stroke android:width="1dip" android:color="#4fa5d5"/>
    <padding
            android:left="7dp"
            android:top="7dp"
            android:right="7dp"
            android:bottom="7dp" />
</shape>

Also in for loop in oNResume of MyActivity set font color to black.

b.setTextColor(Color.BLACK) ;

Here is the final app till now.

Once again thanks to stackoverflow (http://stackoverflow.com/questions/3496269/how-to-put-a-border-around-an-android-textview)

End Update2

An outrageously simple note taking android app made better (part 2)


Hi all, in this post we will make the note taking app made in previous post better .

We will make the app to store multiple notes and shall display them in our main screen.

At the very first we will change the app icon. For this put an icon file inres/drawable-* folders ( one for each size)  and change the string in AndroidManifest.xml as below.

android:icon=”@drawable/note256″

Here the notes256 is file name of icon I put in drawable-* folders.

Notice the new icon above.

Now to store multiple notes  we will need database. We will follow the pattern championed by masters and create the notes class to store well, notes :) and NotesDatabase to create, store and retrieve notes.

Here is the notes class

public class Notes {

    int _id;
    String _note;

    public Notes(){
    }
    public Notes(int id, String note){
        this._id = id;
        this._note = note;
    }
    public Notes(String note){
        this._note = note;
    }
    public int getID(){
        return this._id;
    }
    public void setID(int id){
        this._id = id;
    }
    public String getNote(){
        return this._note;
    }
    public void setNote(String note){
        this._note = note;
    }
}

Code is self explanatory it just store notes and id for database operations and onscreen UI.

Now here is the NotesDatabase.java

http://snipt.org/vWhc3

We will understand the code by step by step

    private static final int DATABASE_VERSION = 1;
    private static final String DATABASE_NAME = "notesDatabase";
    private static final String TABLE_NOTES = "notes";
    private static final String KEY_ID = "id";
    private static final String KEY_NOTE = "note";

These fields define the database name, table name and table key name.

        String CREATE_NOTES_TABLE= "CREATE TABLE " + TABLE_NOTES+ "("
                + KEY_ID + " INTEGER PRIMARY KEY," + KEY_NOTE + " TEXT" + ")";
        db.execSQL(CREATE_NOTES_TABLE);

Above statements in onCreate method prepares the create query and when executed by db.execSQL creates the table.

        SQLiteDatabase db = this.getWritableDatabase();

        ContentValues values = new ContentValues();
        values.put(KEY_NOTE, notes.getNote());

        db.insert(TABLE_NOTES, null, values);
        db.close();

Above ones in addNote takes a Notes object and store its values in database.

        SQLiteDatabase db = this.getReadableDatabase();

        Cursor cursor = db.query(TABLE_NOTES, new String[] { KEY_ID,
                KEY_NOTE }, KEY_ID + "=?",
                new String[] { String.valueOf(id) }, null, null, null, null);
        if (cursor != null)
            cursor.moveToFirst();

        Notes notes = new Notes(Integer.parseInt(cursor.getString(0)),
                cursor.getString(1));
        return notes;
Similarly the above ones reads the database and create a notes object and returns it.
        List<Notes> notesList = new ArrayList<Notes>();
        String selectQuery = "SELECT  * FROM " + TABLE_NOTES;

        SQLiteDatabase db = this.getWritableDatabase();
        Cursor cursor = db.rawQuery(selectQuery, null);

        if (cursor.moveToFirst()) {
            do {
                Notes notes = new Notes();
                notes.setID(Integer.parseInt(cursor.getString(0)));
                notes.setNote(cursor.getString(1));

                notesList.add(notes);
            } while (cursor.moveToNext());
        }

        return notesList;

Above listed ones get all notes from database.

There are more methods but we use only the above listed code.

In EditNoteActivity.java change the onClickSave method to be like this

    public void onClickSave(View theButton) {
        EditText text = (EditText) findViewById(R.id.editText1);
        NotesDatabase db =new NotesDatabase(this);

        db.addNote(new Notes(text.getText().toString()));
        finish();
    }

This will save the note to database.

Now change the onCreate method of MyActivity to be like this.

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        NotesDatabase db =new NotesDatabase(this);

        List<Notes> notes = db.getAllNotes();

        for ( Notes nt: notes) {
            final LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);

            TextView b = (TextView) inflater.inflate(R.layout.textviews,null);
            b.setText(nt.getNote());
            LinearLayout lLayout = (LinearLayout)findViewById(R.id.layout1);
            lLayout.addView(b);
        }
    }

This requires some explanation as this dynamically adds the TextView defined in textviews.xml file and adds them to main activity.

final LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER

Above code creates a inflater object whose inflate method gets the text view.

TextView b = (TextView) inflater.inflate(R.layout.textviews,null);

This gets the TextView from below textview.xml

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

<TextView xmlns:android="http://schemas.android.com/apk/res/android"

android:id="@+id/textview1"

android:text="Press to close"

android:layout_width="wrap_content"

android:layout_height="wrap_content"/>
Below line gets the layout object for layout of main activity whose id has been set to layout1 in main.xml.

addView adds the TextView to the layout dynamically.

LinearLayout lLayout = (LinearLayout)findViewById(R.id.layout1);

Now build and run the app

Even at this stage there is lot to be desired. We will keep improving in next post.

Thanks to Sai Geetha for inflator trick, and Ravi Tamada, Lars Vogel for database pattern.