quarta-feira, 30 de janeiro de 2013

Using Intents

Hello people,

After a long time I am writing a new post to you. In this post we will talk about the use of Intents.
According the book Professional Android 4 - Application Development "Intents are used as a message-passing mechanism that works both within your application and between applications", it means that you can create a application that uses actions from others applications. Actions will be a word mentioned many times here.

Using Intents you can start a Activity or a Service, to perform a action with (or on) a particular piece of data and broadcast that a event has occurred. Furthermore, you can take a lot of advantages from Intents to create a powerful application using even Android actions. I searched on the web good samples from use of Intents but I didn't success, so I created one exclusively to this post.

We will to use two applications during this post. At first we will to see like the intents works executing basics operations like start a new Activity and get results from it, after we will to see like these applications can interact between them.

I could use only one application to demonstrate like the interaction works, but I think is very interesting the experience of use two applications to talking between them.


ContactCentral

ContactCentral is the main application which we will work. Before we follow in this post, it is very important know that is necessary configure the permissions for the device resources that our application will be use. For this application we will send SMS, read the contacts and make calls. See the permissions declared in the AndroidManifest.xml:



 <!-- These permissions are used for this application -->
    <uses-permission android:name="android.permission.CALL_PHONE" />
    <uses-permission android:name="android.permission.SEND_SMS" />
    <uses-permission android:name="android.permission.READ_CONTACTS" />


When we try use anyone of this resources without declare the permissions a exception will occur.

Our application has a simple layout, the user can type a phone number and call this number or send a SMS, if the user do not remember the phone number, it can select one on the default Android contact list. To become easier to user clear the number, it can use the button clean.




Call

Make a call using the Android API is very easy. You need create a URI for the protocol "tel" and pass the phone number. After you will create a new Intent using the Android default action ACTION_CALL.  See the code below:


// creates a URI from phoneNumber...
String uri = "tel:" + editPhone.getText().toString();

// creates a Intent that will call phone number...
// This is a implicit intent...
Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse(uri));
startActivity(intent);

When the method startActivity is called, the default call screen is started. It is a implicit call to a Activity.


SMS

For start the actitivy that displays the SMS dialog, I had to create a new Activity called DialogSMS.


In this case we are calling this Activity explicitly.


// creates a URI from phoneNumber...
String phoneNumber = "tel:" + editPhone.getText().toString();
Bundle bundle = new Bundle();
bundle.putString(DialogSMS.KEY_PHONENUMBER, phoneNumber);

// creates a Intent that will call phone number...
// This is a explicit intent...
Intent intent = new Intent(getBaseContext(), DialogSMS.class);
intent.putExtra(DialogSMS.KEY_EXTRA, bundle);
startActivity(intent);


See that a Bundle is passed to Intent, this Bundle has the phone number that will be used within this Activity.
Build this example was very important and interesting because I could use a PendingIntent. A PendingIntent is a Intent that wait for a application or service to be used. In this case we will see that a PendingIntent is needed for receive the SMS send status. See the code below:


buttonSend = (Button) findViewById(R.id.dialogsms_send);
buttonSend.setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View v) {

Bundle bundle = getIntent().getBundleExtra(KEY_EXTRA);
String phoneNumber = bundle.getString(KEY_PHONENUMBER);

PendingIntent sentPI = PendingIntent.getBroadcast(
getBaseContext(), 0, new Intent(ACTION_SENT), 0);


if(editMessage.getText().toString().length()==0)
{
Toast.makeText(
getApplicationContext(),
getResources()
.getString(
R.string.string_message_invalid_text),
Toast.LENGTH_SHORT).show();
return;
}

editMessage.setVisibility(View.GONE);
buttonCancel.setVisibility(View.GONE);
buttonSend.setVisibility(View.GONE);
setVisible(false);

SmsManager sms = SmsManager.getDefault();
sms.sendTextMessage(phoneNumber, null, editMessage.getText()
.toString(), sentPI, null);


}
});

// when the SMS has been sent...
sendBroadcastReceiver = new BroadcastReceiver() {

public void onReceive(Context context, Intent intent) {
switch (getResultCode()) {
case Activity.RESULT_OK:
Toast.makeText(
getApplicationContext(),
getResources()
.getString(
R.string.string_message_has_been_sent),
Toast.LENGTH_SHORT).show();

break;
default:
Toast.makeText(
getApplicationContext(),
getResources()
.getString(
R.string.string_message_could_not_be_sent),
Toast.LENGTH_SHORT).show();

break;
}

finish();
}
};

registerReceiver(sendBroadcastReceiver,new IntentFilter(ACTION_SENT) );


In this code, the bundle passed for this Activity is used to retrieve the phone number. The PendingIntent is being declared and your Receiver is being built to receive the SMS send status and process this action.


Contact List

We will use the Android default contact list to select a contact to use. See that we are using a startActivityForResult for call this Intent. 

// this intent uses a action from the system to select
// contacts...
Intent intent = new Intent(Intent.ACTION_PICK, Contacts.CONTENT_URI);
intent.setType(ContactsContract.Contacts.CONTENT_TYPE);
startActivityForResult(intent, PICK_CONTACT_CODE);

At this moment we will use the method onActivityResult from root Actitvity, for process the result from the contact selection. I could paste the code here, but I think it is very interesting you see the complete code in the source available for download. It is important to you seeing that the result of a contact pick is a URI that is used to search the contact on the list and display all phone numbers from each contact.


Calling the DialogSMS from other application

I built a application called CallDialogMessage that uses the popup dialog from ContactCentral. I used the startActivity to call the popup dialog, but we can the same using a broadcast, however, we should have created a receiver on ContactList.

Intent intent = new Intent();
intent.setComponent(new ComponentName("com.example.contactcentral", "com.example.contactcentral.DialogSMS"));
String phoneNumber = "tel:123456789";
Bundle bundle = new Bundle();
bundle.putString("PHONENUMBER", phoneNumber);
intent.putExtra("EXTRA", bundle);
startActivity(intent);

It is not necessary worry us with the permissions on this application, because the permissions were declared on the main application.

I hope that you like of this post.

The code is avaliable here.

Thanks!