1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14.

Wednesday, December 8, 2010

Detecting incoming and outgoing calls in Android

In one of my project, I wanted to detect incoming and outgoing calls. I used BroadcastReceiver with action android.intent.action.NEW_OUTGOING_CALL and android.intent.action.PHONE_STATE.

The android.intent.action.NEW_OUTGOING_CALL will be broadcasted when an outgoing call is initiated. The receiving intent will have an extra string variable Intent.EXTRA_PHONE_NUMBER which contains the outgoing number. This requires the permission android.permission.PROCESS_OUTGOING_CALLS.

To detect the incoming call, we register a BroadcastReceiver for the action android.intent.action.PHONE_STATE. This will be broadcasted when there is a change in phone state. The receiving intent will have an extra string variable TelephonyManager.EXTRA_STATE which describes the phone state. If this state is TelephonyManager.EXTRA_STATE_RINGING then there will be another extra string variable TelephonyManager.EXTRA_INCOMING_NUMBER. This variable contains the incoming phone number. Note that this variable will not be present when the state is not TelephonyManager.EXTRA_STATE_RINGING.

The sample application is a simple one just for demonstration. The application registers for these actions and when the calls are detected it just displays a toast.

For receiver I implemented two IncomingCallReceiver.java and OutgoingCallReceiver.java.For ui I created MainActivity.java.
Below is the source code for this application.

IncomingCallReceiver.java :-

package com.raghu.samples.detectcalls.receivers;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.widget.Toast;
public class IncomingCallReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
if(null == bundle)
return;
Log.i("IncomingCallReceiver",bundle.toString());
String state = bundle.getString(TelephonyManager.EXTRA_STATE);
Log.i("IncomingCallReceiver","State: "+ state);
if(state.equalsIgnoreCase(TelephonyManager.EXTRA_STATE_RINGING))
{
String phonenumber = bundle.getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
Log.i("IncomingCallReceiver","Incomng Number: " + phonenumber);
String info = "Detect Calls sample application\nIncoming number: " + phonenumber;
Toast.makeText(context, info, Toast.LENGTH_LONG).show();
}
}
}

OutgoingCallReceiver.java :-

package com.raghu.samples.detectcalls.receivers;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
public class OutgoingCallReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
if(null == bundle)
return;
String phonenumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
Log.i("OutgoingCallReceiver",phonenumber);
Log.i("OutgoingCallReceiver",bundle.toString());
String info = "Detect Calls sample application\nOutgoing number: " + phonenumber;
Toast.makeText(context, info, Toast.LENGTH_LONG).show();
}
}

MainActivity.java
package com.raghu.samples.detectcalls.ui;
import com.raghu.samples.detectcalls.R;
import android.app.Activity;
import android.os.Bundle;
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}

Simple logcat viewer -- Android Sample Application

Here is a sample application to view logcat messages on device. The application runs the command “logcat” using Runtime class, reads each log string and adds the string to a list view. Whenever you click on an item, an alert box is displayed with the corresponding log message.

Below is Source code for Log Viewer :

LogViewerActivity.java :-

package com.raghu.samples.logviewer.ui;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import android.app.AlertDialog;
import android.app.ListActivity;
import android.content.Context;
import android.graphics.Color;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;

import com.raghu.samples.logviewer.R;

public class LogViewerActivity extends ListActivity{
private LogStringAdaptor adaptor = null;
private ArrayList logarray = null;
private LogReaderTask logReaderTask = null;

public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

logarray = new ArrayList();
adaptor = new LogStringAdaptor(this, R.id.txtLogString, logarray);

setListAdapter(adaptor);

logReaderTask = new LogReaderTask();

logReaderTask.execute();
}

@Override
protected void onDestroy() {
logReaderTask.stopTask();

super.onDestroy();
}

@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);

final AlertDialog.Builder builder = new AlertDialog.Builder(LogViewerActivity.this);
String text = ((String) ((TextView)v).getText());

builder.setMessage(text);

builder.show();
}

private int getLogColor(String type) {
int color = Color.BLUE;

if(type.equals("D"))
{
color = Color.rgb(0, 0, 200);
}
else if(type.equals("W"))
{
color = Color.rgb(128, 0, 0);
}
else if(type.equals("E"))
{
color = Color.rgb(255, 0, 0);;
}
else if(type.equals("I"))
{
color = Color.rgb(0, 128, 0);;
}

return color;
}

private class LogStringAdaptor extends ArrayAdapter{
private List objects = null;

public LogStringAdaptor(Context context, int textviewid, List objects) {
super(context, textviewid, objects);

this.objects = objects;
}

@Override
public int getCount() {
return ((null != objects) ? objects.size() : 0);
}

@Override
public long getItemId(int position) {
return position;
}

@Override
public String getItem(int position) {
return ((null != objects) ? objects.get(position) : null);
}

public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;

if(null == view)
{
LayoutInflater vi = (LayoutInflater)LogViewerActivity.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = vi.inflate(R.layout.logitem, null);
}

String data = objects.get(position);

if(null != data)
{
TextView textview = (TextView)view.findViewById(R.id.txtLogString);
String type = data.substring(0, 1);
String line = data.substring(2);

textview.setText(line);
textview.setTextColor(getLogColor(type));
}

return view;
}
}

private class LogReaderTask extends AsyncTask
{
private final String[] LOGCAT_CMD = new String[] { "logcat" };
private final int BUFFER_SIZE = 1024;

private boolean isRunning = true;
private Process logprocess = null;
private BufferedReader reader = null;
private String[] line = null;

@Override
protected Void doInBackground(Void... params) {
try {
logprocess = Runtime.getRuntime().exec(LOGCAT_CMD);
} catch (IOException e) {
e.printStackTrace();

isRunning = false;
}

try {
reader = new BufferedReader(new InputStreamReader(
logprocess.getInputStream()),BUFFER_SIZE);
}
catch(IllegalArgumentException e){
e.printStackTrace();

isRunning = false;
}

line = new String[1];

try {
while(isRunning)
{
line[0] = reader.readLine();

publishProgress(line);
}
}
catch (IOException e) {
e.printStackTrace();

isRunning = false;
}

return null;
}

@Override
protected void onCancelled() {
super.onCancelled();
}

@Override
protected void onPreExecute() {
super.onPreExecute();
}

@Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
}

@Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);

adaptor.add(values[0]);
}

public void stopTask(){
isRunning = false;
logprocess.destroy();
}
}
}

 
# #