Android Call Recorder Source Code

Hi Guys, today it’s time to take a look at how to record phone call in Android programmatically.

This tutorial or page has Android call recorder app source code.

Let’s jump into coding.

 Android Call Recorder Source Code

MainActivity.java


package com.thul.CallRecorder;

import java.util.ArrayList;
import android.app.NotificationManager;
import android.app.Service;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.ActivityManager.RunningServiceInfo;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivity extends Activity {
private static final String TAG = MainActivity.class.getName();

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button b = (Button) findViewById(R.id.btnStartStop);
b.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Log.d(TAG, "start or stop service");
Intent i = new Intent(MainService.ACTION);
if (isServiceRunning()) {
stopService(i);
((NotificationManager) getSystemService(NOTIFICATION_SERVICE))
.cancelAll();

} else {
startService(i);

runAsForeground();

}
updateButtonState((Button)v);
}
});
updateButtonState(b);
}

private void updateButtonState(Button b) {
if (isServiceRunning()) {
b.setText(R.string.stop_record);
} else {
b.setText(R.string.start_record);

}
}

private boolean isServiceRunning() {
ActivityManager myManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
ArrayList<RunningServiceInfo> runningService = (ArrayList<RunningServiceInfo>) myManager
.getRunningServices(30);
for (int i = 0; i < runningService.size(); i++) {
if (runningService.get(i).service.getClassName().equals(
MainService.class.getName())) {
return true;
}
}
return false;
}

private void runAsForeground(){
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent=PendingIntent.getActivity(this, 0,
notificationIntent, Intent.FLAG_ACTIVITY_NEW_TASK);

Notification notification=new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle(getString(R.string.app_name))
.setContentText("Call Record")
.setContentIntent(pendingIntent).build();
NotificationManager notificationManager =
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
notification.flags = notification.flags
| Notification.FLAG_ONGOING_EVENT;
notification.flags |= Notification.FLAG_AUTO_CANCEL;

notificationManager.notify(0, notification);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.settings, menu);
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.item1:
openFolder();
// Toast.makeText(getApplicationContext(),"Item 1 Selected",Toast.LENGTH_LONG).show();
return true;
default:
return super.onOptionsItemSelected(item);
}
}

public void openFolder()
{
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
Uri uri = Uri.parse(Environment.getExternalStorageDirectory().getPath()
+ "/callrec/");
intent.setDataAndType(uri, "audio/amr");

startActivity(Intent.createChooser(intent, "Open folder"));
}
}

 

MainService.java

package com.thul.CallRecorder;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

import android.app.Service;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.media.MediaRecorder;
import android.net.Uri;
import android.os.Environment;
import android.os.IBinder;
import android.os.PowerManager;
import android.provider.ContactsContract.PhoneLookup;
import android.util.Log;

public class MainService extends Service {
 public static final String ACTION = "com.thul.CallRecorder.CALL_RECORD";
 public static final String STATE = "STATE";
 public static final String START = "START";
 public static final String STORAGE = "STORAGE";
 public static final String INCOMING = "INCOMING";
 public static final String OUTGOING = "OUTGOING";
 public static final String BEGIN = "BEGIN";
 public static final String END = "END";

 protected static final String TAG = MainService.class.getName();
 protected static final boolean DEBUG = false;

 private static final String AMR_DIR = "/callrec/";
 private static final String IDLE = "";
 private static final String INCOMING_CALL_SUFFIX = "_i";
 private static final String OUTGOING_CALL_SUFFIX = "_o";

 private Context cntx;
 private volatile String fileNamePrefix = IDLE;
 private volatile MediaRecorder recorder;
 private volatile PowerManager.WakeLock wakeLock;
 private volatile boolean isMounted = false;
 private volatile boolean isInRecording = false;

 @Override
 public IBinder onBind(Intent i) {
 return null;
 }

 @Override
 public void onCreate() {
 // TODO Auto-generated method stub
 super.onCreate();
 this.cntx = getApplicationContext();
 this.prepareAmrDir();
 log("service create");
 }

 @Override
 public void onDestroy() {
 log("service destory");
 this.stopRecording();
 this.cntx = null;
 super.onDestroy();
 }

 @Override
 public int onStartCommand(Intent intent, int flags, int startId) {
 if (null == intent || !ACTION.equals(intent.getAction())) {
 return super.onStartCommand(intent, flags, startId);
 }
 String state = intent.getStringExtra(STATE);
 String phoneNo = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
 log("state: " + state + " phoneNo: " + phoneNo);
 if (OUTGOING.equals(state)) {
 fileNamePrefix = getContactName(this.getContext(), phoneNo)
 + OUTGOING_CALL_SUFFIX;
 } else if (INCOMING.equals(state)) {
 fileNamePrefix = getContactName(this.getContext(), phoneNo)
 + INCOMING_CALL_SUFFIX;
 } else if (BEGIN.equals(state)) {
 startRecording();
 } else if (END.equals(state)) {
 stopRecording();
 } else if (STORAGE.equals(state)) {
 String mountState = Environment.getExternalStorageState();
 if (Environment.MEDIA_MOUNTED.equals(mountState)) {
 prepareAmrDir();
 } else {
 isMounted = false;
 }
 if (!isInRecording) {
 stopSelf();
 }
 }
 return START_STICKY;
 }

 public Context getContext() {
 return cntx;
 }

 private void stopRecording() {
 if (isInRecording) {
 isInRecording = false;
 recorder.stop();
 recorder.release();
 recorder = null;
 releaseWakeLock();
 stopSelf();
 log("call recording stopped");
 }
 }

 private String getDateTimeString() {
 SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd'_'HHmmss");
 Date now = new Date();
 return sdf.format(now);
 }

 private String getMonthString() {
 SimpleDateFormat sdf = new SimpleDateFormat("yyyyMM");
 Date now = new Date();
 return sdf.format(now);
 }

 private String getDateString() {
 SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
 Date now = new Date();
 return sdf.format(now);
 }

 private String getTimeString() {
 SimpleDateFormat sdf = new SimpleDateFormat("HHmmss");
 Date now = new Date();
 return sdf.format(now);
 }

 private void startRecording() {
 if (!isMounted)
 return;
 stopRecording();
 try {
 File amr = new File(Environment.getExternalStorageDirectory()
 .getAbsolutePath()
 + AMR_DIR
 + getDateTimeString()
 + "_"
 + fileNamePrefix + ".amr");
 log("Prepare recording in " + amr.getAbsolutePath());
 recorder = new MediaRecorder();
 recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
 recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
 recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
 recorder.setOutputFile(amr.getAbsolutePath());
 recorder.prepare();
 recorder.start();
 isInRecording = true;
 acquireWakeLock();
 log("Recording in " + amr.getAbsolutePath());
 } catch (Exception e) {
 Log.w(TAG, e);
 }
 }

 private void prepareAmrDir() {
 isMounted = Environment.getExternalStorageState().equals(
 Environment.MEDIA_MOUNTED);
 if (!isMounted)
 return;
 File amrRoot = new File(Environment.getExternalStorageDirectory()
 .getAbsolutePath() + AMR_DIR);
 if (!amrRoot.isDirectory())
 amrRoot.mkdir();
 }

 private String getContactName(Context cntx, String phoneNo) {
 if (null == phoneNo)
 return "";
 Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI,
 Uri.encode(phoneNo));
 ContentResolver cr = cntx.getContentResolver();
 Cursor c = cr.query(uri, new String[] { PhoneLookup.DISPLAY_NAME },
 null, null, null);
 if (null == c) {
 log("getContactName: The cursor was null when query phoneNo = "
 + phoneNo);
 return phoneNo;
 }
 try {
 if (c.moveToFirst()) {
 String name = c.getString(0);
 name = name.replaceAll("(\\||\\\\|\\?|\\*|<|:|\"|>)", "");
 log("getContactName: phoneNo: " + phoneNo + " name: " + name);
 return name;
 } else {
 log("getContactName: Contact name of phoneNo = " + phoneNo
 + " was not found.");
 return phoneNo;
 }
 } finally {
 c.close();
 }
 }

 private void log(String info) {
 if (DEBUG && isMounted) {
 File log = new File(Environment.getExternalStorageDirectory()
 .getAbsolutePath()
 + AMR_DIR
 + "log_"
 + getMonthString()
 + ".txt");
 try {
 BufferedWriter out = new BufferedWriter(new FileWriter(log,
 true));
 try {
 synchronized (out) {
 out.write(getDateString()+getTimeString());
 out.write(" ");
 out.write(info);
 out.newLine();
 }
 } finally {
 out.close();
 }
 } catch (IOException e) {
 Log.w(TAG, e);
 }
 }
 }

 private void acquireWakeLock() {
 if (wakeLock == null) {
 log("Acquiring wake lock");
 PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
 wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, this
 .getClass().getCanonicalName());
 wakeLock.acquire();
 }

 }

 private void releaseWakeLock() {
 if (wakeLock != null && wakeLock.isHeld()) {
 wakeLock.release();
 wakeLock = null;
 log("Wake lock released");
 }

 }
}

 

Receiver.java


package com.thul.CallRecorder;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.TelephonyManager;
import android.util.Log;

public class Receiver extends BroadcastReceiver {
 @Override
 public void onReceive(Context context, Intent intent) {
 if (null == intent)
 return;
 Intent i = new Intent(MainService.ACTION);
 if (Intent.ACTION_NEW_OUTGOING_CALL.equals(intent.getAction())) {
 i.putExtra(MainService.STATE, MainService.OUTGOING);
 i.putExtra(Intent.EXTRA_PHONE_NUMBER,
 intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER));
 } else if (TelephonyManager.ACTION_PHONE_STATE_CHANGED.equals(intent
 .getAction())) {
 String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
 if (TelephonyManager.EXTRA_STATE_RINGING.equals(state)) {
 i.putExtra(MainService.STATE,
 MainService.INCOMING);
 i.putExtra(Intent.EXTRA_PHONE_NUMBER, intent
 .getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER));
 } else if (TelephonyManager.EXTRA_STATE_OFFHOOK.equals(state)) {
 i.putExtra(MainService.STATE, MainService.BEGIN);
 } else if (TelephonyManager.EXTRA_STATE_IDLE.equals(state)) {
 i.putExtra(MainService.STATE, MainService.END);
 }
 } else if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
 i.putExtra(MainService.STATE, MainService.START);
 } else if (intent.getAction().equals(Intent.ACTION_MEDIA_MOUNTED)
 || intent.getAction().equals(Intent.ACTION_MEDIA_REMOVED)) {
 i.putExtra(MainService.STATE, MainService.STORAGE);
 } else {
 return;
 }
 context.startService(i);
 Log.d(MainService.TAG,
 "AutoRunReceiver startService "
 + i.getStringExtra(MainService.STATE) + ":"
 + i.getStringExtra(Intent.EXTRA_PHONE_NUMBER));
 }
}

 

Layout: Main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent"
 android:orientation="vertical" >

 <Button
 android:id="@+id/btnStartStop"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:text="@string/start_record" />

</LinearLayout>

 

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
 package="com.thul.CallRecorder"
 android:versionCode="1"
 android:versionName="1.0" >

 <uses-sdk android:minSdkVersion="8" />

 <uses-permission android:name="android.permission.READ_PHONE_STATE" />
 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
 <uses-permission android:name="android.permission.RECORD_AUDIO" />
 <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
 <uses-permission android:name="android.permission.READ_CONTACTS" />
 <uses-permission android:name="android.permission.WAKE_LOCK"/>
 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

 <application
 android:icon="@drawable/ic_launcher"
 android:label="@string/app_name" >
 <activity
 android:name="com.thul.CallRecorder.MainActivity"
 android:label="@string/app_name" >
 <intent-filter>
 <action android:name="android.intent.action.MAIN" />

 <category android:name="android.intent.category.LAUNCHER" />
 </intent-filter>
 </activity>

 <service android:name="com.thul.CallRecorder.MainService" >
 <intent-filter>
 <action android:name="com.thul.CallRecorder.CALL_RECORD" />
 </intent-filter>
 </service>

 <receiver
 android:name="com.thul.CallRecorder.Receiver"
 android:enabled="true"
 android:exported="true" >
 <intent-filter>
 <action android:name="android.intent.action.NEW_OUTGOING_CALL" />
 <action android:name="android.intent.action.PHONE_STATE" />
 <action android:name="android.intent.action.BOOT_COMPLETED" />
 <action android:name="android.intent.action.MEDIA_MOUNTED" />
 <action android:name="android.intent.action.MEDIA_REMOVED" />
 </intent-filter>
 </receiver>
 </application>

</manifest>

Leave a Reply

Your email address will not be published. Required fields are marked *