I am using broadcastreceiver to detect the outgoing call and start a service once it started dialing.Service is started. Now i want to stop the service once call ends or dialing ends.
#Override
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_NEW_OUTGOING_CALL.equals(intent.getAction())) {
intent = new Intent(context, serv.class);
context.startService(intent);
}
if(intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(
TelephonyManager.EXTRA_STATE_IDLE)) {
intent = new Intent(context, serv.class);
context.stopService(intent);
}
}
try {
//to Fix Lolipop broadcast issue.
long subId = intent.getLongExtra("subscription", Long.MIN_VALUE);
if (subId < Integer.MAX_VALUE) {
if (intent.getAction().equals("android.intent.action.NEW_OUTGOING_CALL")) {
savedNumber = intent.getExtras().getString("android.intent.extra.PHONE_NUMBER");
} else {
String stateStr = intent.getExtras().getString(TelephonyManager.EXTRA_STATE);
String number = intent.getExtras().getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
int state = 0;
if (stateStr.equals(TelephonyManager.EXTRA_STATE_IDLE)) {
state = TelephonyManager.CALL_STATE_IDLE;
} else if (stateStr.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) {
state = TelephonyManager.CALL_STATE_OFFHOOK;
} else if (stateStr.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
state = TelephonyManager.CALL_STATE_RINGING;
}
onCallStateChanged(context, state, number);
}
}
} catch (Exception e) {
e.printStackTrace();
}
public void onCallStateChanged(final Context context, int state, String number) {
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
isIncoming = true;
callStartTime = new Date();
savedNumber = number;
TimerTask tt = new TimerTask() {
#Override
public void run() {
onIncomingCallStarted(context, savedNumber, callStartTime);
}
};
Timer t = new Timer();
t.schedule(tt, 1000);
// TimerTask tt = new TimerTask() {
// #Override
// public void run() {
// }
// };
// onIncomingCallStarted(context, savedNumber, callStartTime);
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
if (lastState == TelephonyManager.CALL_STATE_RINGING) {
isIncoming = true;
callStartTime = new Date();
onReceiveCall(context, savedNumber, callStartTime, "received");
} else {
isIncoming = false;
}
break;
case TelephonyManager.CALL_STATE_IDLE:
if (lastState == TelephonyManager.CALL_STATE_RINGING) {
onMissedCall(context, savedNumber, callStartTime, "Missed");
} else if (isIncoming) {
onIncomingCallEnded(context, savedNumber, callStartTime, new Date());
} else {
onOutgoingCallEnded(context, savedNumber, callStartTime, new Date(), "outgoing");
}
break;
}
lastState = state;
}
Related
This is my Receiver Class where i'm getting phone state of both incoming and outgoing calls
public class MyBroadcastReceiver extends BroadcastReceiver {
private static final String TAG = "MyBroadcastReceiver";
//The receiver will be recreated whenever android feels like it. We need a static variable to remember data between instantiations
private String phoneIncomingNumber = "";
private String PhoneState = "";
private String Message = "";
private MediaRecorder recorder;
Context context;
//Call Recording varibales
private static final String AUDIO_RECORDER_FILE_EXT_3GP = ".3gp";
private static final String AUDIO_RECORDER_FILE_EXT_MP4 = ".mp3";
private static final String AUDIO_RECORDER_FOLDER = "Recordings";
Uri audiouri;
ParcelFileDescriptor file;
AudioManager audioManager;
private int currentFormat = 0;
private int output_formats[] = { MediaRecorder.OutputFormat.MPEG_4,
MediaRecorder.OutputFormat.THREE_GPP };
private String file_exts[] = { AUDIO_RECORDER_FILE_EXT_MP4,
AUDIO_RECORDER_FILE_EXT_3GP };
//The receiver will be recreated whenever android feels like it. We need a static variable to remember data between instantiations
private static int lastState = TelephonyManager.CALL_STATE_IDLE;
private static Date callStartTime;
private static boolean isIncoming;
private static String savedNumber; //because the passed incoming is only valid in ringing
#Override
public void onReceive(Context context, Intent intent) {
// TODO: This method is called when the BroadcastReceiver is receiving
// Registering service
context.startService(new Intent(context, MyService.class));
// Getting Call Details
String stateStr = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
phoneIncomingNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
Log.d("Call Status1", "Number1: " + phoneIncomingNumber + ":STATE : " + stateStr);
if (intent.getAction().equals("android.intent.action.NEW_OUTGOING_CALL")) {
savedNumber = intent.getStringExtra("android.intent.extra.PHONE_NUMBER");
} else {
phoneIncomingNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
int state = 0;
if (stateStr.equals(TelephonyManager.EXTRA_STATE_IDLE)) {
state = TelephonyManager.CALL_STATE_IDLE;
} else if (stateStr.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) {
state = TelephonyManager.CALL_STATE_OFFHOOK;
startRecording(getRecordFileName(phoneIncomingNumber), context);
} else if (stateStr.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
state = TelephonyManager.CALL_STATE_RINGING;
}
onCallStateChanged(context, state, phoneIncomingNumber);
}
}
//Derived classes should override these to respond to specific events of interest
protected void onIncomingCallStarted(Context ctx, String number, Date start) {
Message = "Call from : \"+number+\" on DATE \"+start+\" started";
Log.d("Call Status", "INCOMING CALL STARTED");
}
protected void onOutgoingCallStarted(Context ctx, String number, Date start) {
Message = "Call to : \"+number+\" on DATE \"+start+\" started";
Log.d("Call Status", "OUTGOING CALL STARTED to :" + number);
PhoneState = "OFFHOOK";
}
protected void onIncomingCallEnded(Context ctx, String number, Date start, Date end) {
Log.d("Call Status", "INCOMING CALL ENDED");
Message = "Call from : \"+number+\" on DATE \"+start+\" ended";
stopRecording();
}
protected void onOutgoingCallEnded(Context ctx, String number, Date start, Date end) {
Message = "Call to : \"+number+\" on DATE \"+start+\" ended";
Log.d("Call Status", "OUTGOING CALL ENDED");
stopRecording();
}
protected void onMissedCall(Context ctx, String number, Date start) {
Message = "Missed call : \"+number+\" on DATE \"+start+\"";
Log.d("Call Status", "MISSED CALL");
}
//Deals with actual events
//Incoming call- goes from IDLE to RINGING when it rings, to OFFHOOK when it's answered, to IDLE when its hung up
//Outgoing call- goes from IDLE to OFFHOOK when it dials out, to IDLE when hung up
public void onCallStateChanged(Context context, int state, String number) {
Log.d("Call", "Number: " + number);
if (lastState == state) {
//No change, debounce extras
return;
}
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
isIncoming = true;
callStartTime = new Date();
savedNumber = number;
PhoneState = "RINGING";
onIncomingCallStarted(context, number, callStartTime);
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
//Transition of ringing->offhook are pickups of incoming calls. Nothing done on them
if (lastState != TelephonyManager.CALL_STATE_RINGING) {
isIncoming = false;
callStartTime = new Date();
PhoneState = "OFFHOOK";
onOutgoingCallStarted(context, phoneIncomingNumber, callStartTime);
}
break;
case TelephonyManager.CALL_STATE_IDLE:
//Went to idle- this is the end of a call. What type depends on previous state(s)
if (lastState == TelephonyManager.CALL_STATE_RINGING) {
//Ring but no pickup- a miss
PhoneState = "IDLE";
onMissedCall(context, phoneIncomingNumber, callStartTime);
} else if (isIncoming) {
PhoneState = "INCOMING CALL ENDED";
onIncomingCallEnded(context, phoneIncomingNumber, callStartTime, new Date());
} else {
PhoneState = "OUTGOING CALL ENDED";
onOutgoingCallEnded(context, phoneIncomingNumber, callStartTime, new Date());
}
break;
}
lastState = state;
}
private MediaRecorder.OnErrorListener errorListener = new MediaRecorder.OnErrorListener() {
#Override
public void onError(MediaRecorder mr, int what, int extra) {
Toast.makeText(context,
"Error: " + what + ", " + extra, Toast.LENGTH_SHORT).show();
}
};
private MediaRecorder.OnInfoListener infoListener = new MediaRecorder.OnInfoListener() {
#Override
public void onInfo(MediaRecorder mr, int what, int extra) {
Toast.makeText(context,
"Warning: " + what + ", " + extra, Toast.LENGTH_SHORT)
.show();
}
};
// Recording Audio
private void startRecording(String fileName, Context ctx) {
Log.d("Call Status", "Inside");
ContentValues values = new ContentValues(4);
values.put(MediaStore.Audio.Media.TITLE, fileName);
values.put(MediaStore.Audio.Media.DATE_ADDED, (int) (System.currentTimeMillis() / 1000));
values.put(MediaStore.Audio.Media.MIME_TYPE, "audio/mpeg");
values.put(MediaStore.Audio.Media.RELATIVE_PATH, "Music/Recordings/");
audiouri = ctx.getContentResolver().insert(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, values);
Log.d("Call Status", "Call Status: "+audiouri);
try {
file = ctx.getContentResolver().openFileDescriptor(audiouri, "w");
} catch (Exception e) {
Log.d("Call Status", "File Error"+e);
}
audioManager = (AudioManager) ctx.getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
audioManager.setMode(AudioManager.MODE_IN_CALL);
// audioManager.setSpeakerphoneOn(true);
recorder = new MediaRecorder();
recorder.setAudioSource(MediaRecorder.AudioSource.VOICE_COMMUNICATION);
recorder.setOutputFormat(output_formats[currentFormat]);
//recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
recorder.setOutputFile(file.getFileDescriptor());
recorder.setOnErrorListener(errorListener);
recorder.setOnInfoListener(infoListener);
try {
recorder.prepare();
recorder.start();
} catch (IllegalStateException e) {
Log.e("REDORDING :: ",e.getMessage());
e.printStackTrace();
} catch (IOException e) {
Log.e("REDORDING :: ",e.getMessage());
e.printStackTrace();
}
}
private void stopRecording() {
// audioManager.setSpeakerphoneOn(false);
try{
if (null != recorder) {
recorder.stop();
recorder.reset();
recorder.release();
recorder = null;
}
}catch(Exception stopException){
Log.d("Exce",stopException+"");
}
}
private String getRecordFileName(String phoneNumber) {
// Generate a unique file name based on the phone number and the current time
String timeStamp = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
return phoneNumber + "_" + timeStamp + ".wav";
}
}
My Service Class to run receiver as a forground service
public class MyService extends Service {
private static final int SERVICE_NOTIFICATION_ID =2 ;
private static final String CHANNEL_ID = "PhoneStateModule";
public MyService() {
}
private Handler handler = new Handler();
private Runnable runnableCode = new Runnable() {
#Override
public void run() {
try{
handler.postDelayed(this, 2000);
}catch (Exception ex){
Log.d("Error",ex+"");
}
}
};
private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
int importance = NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, "PhoneStateModule", importance);
channel.setDescription("CHANEL DESCRIPTION");
NotificationManager notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
this.handler.post(this.runnableCode); // Starting the interval
// Turning into a foreground service
createNotificationChannel(); // Creating channel for API 26+
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_CANCEL_CURRENT|PendingIntent.FLAG_MUTABLE);
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("Phone Recording Service")
.setContentText("Running…")
.setSmallIcon(R.mipmap.ic_launcher)
.setContentIntent(contentIntent)
.setOngoing(true)
.build();
startForeground(SERVICE_NOTIFICATION_ID, notification);
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
return null;
}
}
Can anyone help me with the issue facing, I am using device with android 10 and am not getting the recordings, even if the recording is saved inside folder I'm not getting any audio.
I have a function to initiate an outbound phone call. I need to set up the listener to know the state of the call (ringing, hang-up, etc). I am having trouble figuring out how to do that and haven't found a tutorial that shows how. Here is the setup to place the call:
PhoneCall.kt
class PhoneCall : AppCompatActivity() {
private fun placeCall() {
if(ActivityCompat.checkSelfPermission(this, android.Manifest.permission.CALL_PHONE) == PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permision.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) {
val telephonyManager = getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
telephonyManager.listen(CallListener, PhoneStateListener.LISTEN_CALL_STATE) //Not sure how to set up CallListener here?
val callIntent = Intent(Intent.ACTION_CALL, Uri.parse(phoneNumber))
startActivity(callIntent)
}
}
}
I believe from CallListener I can create a when() to find the current state. But I'm not sure how to create CallListener and this doesn't appear to be a true listener? Does CallListener need to be a new class, object, or something else? I think I may need a Broadcast Receiver? I don't know the correct way to handle this.
I have a project where I do something similar I created two classes one PhoneCallListener and PhoneCallReceiver. I have removed some code that is used for my needs but if you implement these two classes you should be ok. I am no expert but I hope it helps you.
The jsonObject is just used as an example to show "doing something". I should also mention that I do not know Kotlin but I am told that Android Studio can convert the Java to Kotlin so it might help, hopefully someone more experienced will know how in Kotlin.
PhoneCallListener.java
public class PhoneCallListener extends PhoneCallReceiver {
#Override
protected void onIncomingCallStarted(Context c, String number, Date start) {
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("Timestamp", App.getUTCTimestamp());
jsonObject.put("Direction", "incoming");
jsonObject.put("Number", number);
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
protected void onOutgoingCallStarted(Context c, String number, Date start) {
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("Timestamp", App.getUTCTimestamp());
jsonObject.put("Direction", "outgoing");
jsonObject.put("Number", number);
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
protected void onIncomingCallEnded(Context c, String number, Date start, Date end)
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("Timestamp", App.getUTCTimestamp());
jsonObject.put("Direction", "incoming call ended");
jsonObject.put("Number", number);
} catch (JSONException e) {
e.printStackTrace();
});
}
#Override
protected void onOutgoingCallEnded(Context c, String number, Date start, Date end) {
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("Timestamp", App.getUTCTimestamp());
jsonObject.put("Direction", "outgoing call ended");
jsonObject.put("Number", number);
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
protected void onMissedCall(Context c, String number, Date start) {
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("Timestamp", App.getUTCTimestamp());
jsonObject.put("Direction", "missed");
jsonObject.put("Number", number);
} catch (JSONException e) {
e.printStackTrace();
}
}
}
PhoneCallReceiver.java
abstract class PhoneCallReceiver extends BroadcastReceiver {
//The receiver will be recreated whenever android feels like it. We need a static variable to remember data between instantiations
private static int lastState = TelephonyManager.CALL_STATE_IDLE;
private static Date callStartTime;
private static boolean isIncoming;
private static String savedNumber; //because the passed incoming is only valid in ringing
#Override
public void onReceive(Context context, Intent intent) {
//We listen to two intents. The new outgoing call only tells us of an outgoing call. We use it to get the number.
try {
if (Objects.equals(intent.getAction(), "android.intent.action.NEW_OUTGOING_CALL")) {
savedNumber = Objects.requireNonNull(intent.getExtras()).getString("android.intent.extra.PHONE_NUMBER");
} else {
String stateStr = Objects.requireNonNull(intent.getExtras()).getString(TelephonyManager.EXTRA_STATE);
String number = intent.getExtras().getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
if (number == null) {
number = "00000000000"; // Caller Withheld.
}
int state = 0;
assert stateStr != null;
if (!stateStr.equals(TelephonyManager.EXTRA_STATE_IDLE)) {
if (stateStr.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) {
state = TelephonyManager.CALL_STATE_OFFHOOK;
} else if (stateStr.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
state = TelephonyManager.CALL_STATE_RINGING;
}
}
onCallStateChanged(context, state, number);
}
} catch (Exception e) {
e.printStackTrace();
}
}
//Derived classes should override these to respond to specific events of interest
protected void onIncomingCallStarted(Context ctx, String number, Date start) {
}
protected void onOutgoingCallStarted(Context ctx, String number, Date start) {
}
protected void onIncomingCallEnded(Context ctx, String number, Date start, Date end) {
}
protected void onOutgoingCallEnded(Context ctx, String number, Date start, Date end) {
}
protected void onMissedCall(Context ctx, String number, Date start) {
}
//Deals with actual events
//Incoming call- goes from IDLE to RINGING when it rings, to OFFHOOK when it's answered, to IDLE when its hung up
//Outgoing call- goes from IDLE to OFFHOOK when it dials out, to IDLE when hung up
public void onCallStateChanged(Context context, int state, String number) {
if (lastState == state) {
//No change, debounce extras
return;
}
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
isIncoming = true;
callStartTime = new Date();
savedNumber = number;
onIncomingCallStarted(context, number, callStartTime);
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
//Transition of ringing->offhook are pickups of incoming calls. Nothing done on them
if (lastState != TelephonyManager.CALL_STATE_RINGING) {
isIncoming = false;
callStartTime = new Date();
onOutgoingCallStarted(context, savedNumber, callStartTime);
}
break;
case TelephonyManager.CALL_STATE_IDLE:
//Went to idle- this is the end of a call. What type depends on previous state(s)
if (lastState == TelephonyManager.CALL_STATE_RINGING) {
//Ring but no pickup- a miss
onMissedCall(context, savedNumber, callStartTime);
} else if (isIncoming) {
onIncomingCallEnded(context, savedNumber, callStartTime, new Date());
} else {
onOutgoingCallEnded(context, savedNumber, callStartTime, new Date());
}
break;
}
lastState = state;
}
}
Can anyone provide me sample code for detecting outgoing call state on Android Oreo and Above ?
My code is working fine up to android 6 but not working on Android 8.1 and Android 9. Almost all answers on stack overflow are consisting deprecated code.
Manifest is having necessary permissions and doesn't have any registered receiver as per guidelines by Google
BroadcastReceiver
public class CallReceiver extends BroadcastReceiver{
private static int lastState = TelephonyManager.CALL_STATE_IDLE;
private static Date callStartTime;
private static boolean isIncoming;
private static String savedNumber;
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("android.intent.action.NEW_OUTGOING_CALL")) {
savedNumber = intent.getExtras().getString("android.intent.extra.PHONE_NUMBER");
} else {
String stateStr = intent.getExtras().getString(TelephonyManager.EXTRA_STATE);
String number = intent.getExtras().getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
int state = 0;
if (stateStr.equals(TelephonyManager.EXTRA_STATE_IDLE)) {
state = TelephonyManager.CALL_STATE_IDLE;
} else if (stateStr.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) {
state = TelephonyManager.CALL_STATE_OFFHOOK;
} else if (stateStr.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
state = TelephonyManager.CALL_STATE_RINGING;
}
onCallStateChanged(context, state, number);
}
}
public void onCallStateChanged(Context context, int state, String number) {
if(lastState == state){
//No change, debounce extras
return;
}
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
isIncoming = true;
callStartTime = new Date();
savedNumber = number;
Toast.makeText(context, "Incoming Call Ringing" , Toast.LENGTH_SHORT).show();
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
//Transition of ringing->offhook are pickups of incoming calls. Nothing done on them
if(lastState != TelephonyManager.CALL_STATE_RINGING){
isIncoming = false;
callStartTime = new Date();
Toast.makeText(context, "Outgoing Call Started" , Toast.LENGTH_SHORT).show();
}
break;
case TelephonyManager.CALL_STATE_IDLE:
//Went to idle- this is the end of a call. What type depends on previous state(s)
if(lastState == TelephonyManager.CALL_STATE_RINGING){
//Ring but no pickup- a miss
Toast.makeText(context, "Ringing but no pickup" + savedNumber + " Call time " + callStartTime +" Date " + new Date() , Toast.LENGTH_SHORT).show();
}
else if(isIncoming){
Toast.makeText(context, "Incoming " + savedNumber + " Call time " + callStartTime , Toast.LENGTH_SHORT).show();
}
else{
Toast.makeText(context, "Outgoing "+ savedNumber + " Call time " + callStartTime +" Date " + new Date() , Toast.LENGTH_SHORT).show();
}
break;
}
lastState = state;
}
}
MainActivity
public class MainActivity extends AppCompatActivity {
private CallReceiver callReceiver;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
callReceiver = new CallReceiver();
}
#Override
protected void onResume() {
super.onResume();
IntentFilter filter = new IntentFilter();
filter.addAction("android.intent.action.PHONE_STATE");
filter.addAction("android.intent.action.NEW_OUTGOING_CALL");
registerReceiver(callReceiver, filter);
}
#Override
protected void onPause() {
try {
unregisterReceiver(callReceiver);
} catch (Exception e) {
e.getMessage();
}
super.onPause();
}
#Override
protected void onDestroy() {
super.onDestroy();
}
}
I want to know the outgoing call is answered or not in android program.I just want to know the outgoing call has answered or not.I am new in android.Please help me to solve this problem.For getting the call answered time i use this.
I want to know the outgoing call is answered or not in android program. I just want to know the outgoing call has answered or not. I am new in android. Please help me to solve this problem. For getting the call answered time I use this.
BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("android.intent.action.NEW_OUTGOING_CALL")) {
savedNumber = intent.getExtras().getString("android.intent.extra.PHONE_NUMBER");
} else {
String stateStr = intent.getExtras().getString(TelephonyManager.EXTRA_STATE);
String number = intent.getExtras().getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
int state = 0;
if (stateStr.equals(TelephonyManager.EXTRA_STATE_IDLE)) {
state = TelephonyManager.CALL_STATE_IDLE;
} else if (stateStr.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) {
state = TelephonyManager.CALL_STATE_OFFHOOK;
} else if (stateStr.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
state = TelephonyManager.CALL_STATE_RINGING;
}
onCallStateChanged(context, state, number);
}
}
};
protected void onIncomingCallStarted(Context ctx, String number, Date start) {
}
protected void onOutgoingCallStarted(Context ctx, String number, Date start) {
}
protected void onIncomingCallEnded(Context ctx, String number, Date start, Date end) {
}
protected void onOutgoingCallEnded(Context ctx, String number, Date start, Date end) {
SimpleDateFormat localDateFormat = new SimpleDateFormat("HH:mm:ss");
startime = localDateFormat.format(start);
endtime = localDateFormat.format(end);
long aa = start.getTime();
long bb = end.getTime();
long cc = bb - aa;
long diffMinutes = cc / 1000 % 60;
duration = Long.toString(diffMinutes);
Bundle bundle = new Bundle();
bundle.putString("start", startime);
bundle.putString("end", endtime);
bundle.putString("duration", duration);
Call_End dFragment = new Call_End();
dFragment.setArguments(bundle);
dFragment.show(fragmentManager, "Dialog Fragment");
}
protected void onMissedCall(Context ctx, String number, Date start) {
}
public void onCallStateChanged(Context context, int state, String number) {
if (lastState == state) {
//No change, debounce extras
return;
}
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
isIncoming = true;
callStartTime = new Date();
savedNumber = number;
onIncomingCallStarted(context, number, callStartTime);
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
callStartTime = new Date();
onOutgoingCallStarted(context, savedNumber, callStartTime);
//Transition of ringing->offhook are pickups of incoming calls. Nothing done on them
if (lastState != TelephonyManager.CALL_STATE_RINGING) {
isIncoming = false;
callStartTime = new Date();
onOutgoingCallStarted(context, savedNumber, callStartTime);
}
break;
case TelephonyManager.CALL_STATE_IDLE:
//Went to idle- this is the end of a call. What type depends on previous state(s)
if (lastState == TelephonyManager.CALL_STATE_RINGING) {
//Ring but no pickup- a miss
onMissedCall(context, savedNumber, callStartTime);
} else if (isIncoming) {
onIncomingCallEnded(context, savedNumber, callStartTime, new Date());
} else {
onOutgoingCallEnded(context, savedNumber, callStartTime, new Date());
}
break;
}
lastState = state;
}
#Override
public void onReceive(Context context, Intent intent) {
Log.d("Intent", intent.toString());
if(intent.getAction().equals("android.intent.action.NEW_OUTGOING_CALL"))
{
Log.e("Call_state","outgoing call detected");
}
// Checking for the call status
try {
// TELEPHONY MANAGER class object to register one listner
TelephonyManager tmgr = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
//Create Listner
MyPhoneStateListener PhoneListener = new MyPhoneStateListener();
// Register listener for LISTEN_CALL_STATE
tmgr.listen(PhoneListener, PhoneStateListener.LISTEN_CALL_STATE);
} catch (Exception e) {
e.printStackTrace();
}
}
private class MyPhoneStateListener extends PhoneStateListener {
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
Log.e("Call_state","call ringing");
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
Log.e("Call_state","call offhook");
break;
case TelephonyManager.CALL_STATE_IDLE:
Log.e("Call_state","call idle");
break;
}
}
}
You can do like this but this will not work on all phone.
Create notification listener service which tell you another person has pick up the call.public class CallNotification extends NotificationListenerService {
public void onNotificationPosted(StatusBarNotification sbn)
{
//your code here after you getting notification another person has pick up the call
}
}
Ask for the allow notification from the system.
Intent intent = new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS");
startActivity(intent);
Hi I searched a lot on this forum for correct result but unable to find. I need details of last outgoing call once call is ended. For this I am using BroadcasteReceiver here is code for my receiver
public class CallStateBroadcaster extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
((TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE)).listen(new CustomPhoneStateListener(context), PhoneStateListener.LISTEN_CALL_STATE);
}}
Here is code for PhoneStateListener
public class CustomPhoneStateListener extends PhoneStateListener{
private Context context;
public CustomPhoneStateListener(Context paramContext)
{
this.context = paramContext;
}
#Override
public void onCallStateChanged(int state, String incomingNumber) {
// TODO Auto-generated method stub
super.onCallStateChanged(state, incomingNumber);
((TelephonyManager)this.context.getSystemService("phone")).listen(this, PhoneStateListener.LISTEN_NONE);
if(TelephonyManager.CALL_STATE_IDLE == state)
{
try {
Thread.sleep(1500L);
Intent intent = new Intent(this.context,LastCallInfoActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
this.context.startActivity(intent);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Here is code for my activity which fetch call details for call log
public class LastCallInfoActivity extends Activity{
String addtolist;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
Cursor callDetailCursor = getContentResolver().query(CallLog.Calls.CONTENT_URI, null,null,null,android.provider.CallLog.Calls.DATE + " DESC limit 1");
int phoneNumber= callDetailCursor.getColumnIndex(CallLog.Calls.NUMBER);
int callType=callDetailCursor.getColumnIndex(CallLog.Calls.TYPE);
int callDate=callDetailCursor.getColumnIndex(CallLog.Calls.DATE);
int callDuration=callDetailCursor.getColumnIndex(CallLog.Calls.DURATION);
Log.i(">>CAllDetails", "getsCallLogs" );
if(callDetailCursor.getCount()>0)
{
while(callDetailCursor.moveToNext())
{
String phoneNumberString=callDetailCursor.getString(phoneNumber);
String contactName= getContactName(this, phoneNumberString);
String callTypeString =callDetailCursor.getString(callType);
String callDateString=callDetailCursor.getString(callDate);
String callDurationString=callDetailCursor.getString(callDuration);
Date callDayTime=new Date(Long.valueOf(callDateString));
int callCode = Integer.parseInt(callTypeString);
int calldur=Integer.parseInt(callDurationString);
if (callCode==2 && calldur>=1)
{
Double callCost=Double.parseDouble(callDurationString);
String callCostString= String.valueOf( callCost);
Log.i(">>CAllDetails", "getsLocation" );
addtolist= "Name :"+contactName+"\n"+
"Phone Number: "+phoneNumberString+"\n"+"Call Duration :"+
callDurationString+" Seconds\n"+"Call Date: "+callDayTime+"\n"+
callCostString;
}
}
}callDetailCursor.close();
Toast.makeText(this, addtolist, Toast.LENGTH_LONG).show();
}
public String getContactName(Context context, String phoneNumber) {
ContentResolver cr = context.getContentResolver();
Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber));
Cursor cursor = cr.query(uri, new String[]{PhoneLookup.DISPLAY_NAME}, null, null, null);
if (cursor == null) {
return null;
}
String contactName = null;
if(cursor.moveToFirst()) {
contactName = cursor.getString(cursor.getColumnIndex(PhoneLookup.DISPLAY_NAME));
}
if(cursor != null && !cursor.isClosed()) {
cursor.close();
}
return contactName;
}
}
My this program show toast even before my call got disconnected and start my activity. Please help me and correct my code so that it will get executed after call ends
thanks
just try this add an additional if statement for checking previous sate was off hook.
boolean wasoffhook=false;
if(TelephonyManager.CALL_STATE_OFFHOOK == state)
{
wasoffhook=true;
}
if(TelephonyManager.CALL_STATE_IDLE == state&&wasoffhook)
{
try {
Thread.sleep(1500L);
Intent intent = new Intent(this.context,LastCallInfoActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
this.context.startActivity(intent);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
In your onreceive method of Callstatebroadcaster add this code and it would work fine.I just solved it.
#Override
public void onReceive(Context context, Intent intent)
{
try
{
if (intent.getAction().equals("android.intent.action.NEW_OUTGOING_CALL"))
{
savedNumber = intent.getExtras().getString("android.intent.extra.PHONE_NUMBER");
Toast.makeText(context,"the no. is"+savedNumber,Toast.LENGTH_LONG).show();
// onOutgoingCallStarted(context,"",callStartTime);
}
else
{
String stateStr = intent.getExtras().getString(TelephonyManager.EXTRA_STATE);
String number = intent.getExtras().getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
int state = 0;
if(stateStr.equals(TelephonyManager.EXTRA_STATE_IDLE)) {
switch (state) {
case TelephonyManager.CALL_STATE_IDLE:
Log.d("Testing", "Outgoing call has been disconnect");
intent = new Intent(context, MyCustomDialog.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
context.startActivity(intent);
System.out.println("CAll has been disconnect...............");
// Toast.makeText(this, "CAll has been disconnect", Toast.LENGTH_LONG).show();
break;
}
}
else if(stateStr.equals(TelephonyManager.EXTRA_STATE_OFFHOOK))
{
state = TelephonyManager.CALL_STATE_OFFHOOK;
}
else if(stateStr.equals(TelephonyManager.EXTRA_STATE_RINGING))
{
state = TelephonyManager.CALL_STATE_RINGING;
}
onCallStateChanged(context, state, number);
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
And in Callstatechanged method add this code.
public void onCallStateChanged(Context context, int state, String number)
{
if(lastState == state)
{
//No change, debounce extras
return;
}
switch (state)
{
case TelephonyManager.CALL_STATE_RINGING:
isIncoming = true;
callStartTime = new Date();
savedNumber = number;
// onIncomingCallStarted(context, number, callStartTime);
// onIncomingCallEnded(context, savedNumber, callStartTime, new Date());
// onOutgoingCallEnded(context, savedNumber, callStartTime, new Date());
// wasRinging = true;
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
if (!wasRinging) {
// Start your new activity
onIncomingCallEnded(context,savedNumber,callStartTime,new Date());
onOutgoingCallEnded(context,savedNumber,callStartTime,new Date());
} else {
onIncomingCallStarted(context,savedNumber,callStartTime);
// Cancel your old activity
}
// this should be the last piece of code before the break
break;
case TelephonyManager.CALL_STATE_IDLE:
if(isIncoming)
{
onIncomingCallEnded(context, savedNumber, callStartTime, new Date());
}
}
lastState = state;
}
This would work.