Android how to detect if outgoing call is answered - android

I'm developing an app that will only be used in house for testing purpose. I have searched a lot and tried different suggestions as suggested in different post but none seems to be working for me.
I'm open to any suggestions like Reflections, Accessibility Service, root or any other hack. Please help.
Regards

TRY THIS
Set all required permission in manifest.xml file.
Call this class in Service
public class PhoneListener extends PhoneStateListener {
private static PhoneListener instance = null;
/**
* Must be called once on app startup
*
* #param context - application context
* #return
*/
public static PhoneListener getInstance(Context context) {
if (instance == null) {
instance = new PhoneListener(context);
}
return instance;
}
public static boolean hasInstance() {
return null != instance;
}
private final Context context;
private CallLog phoneCall;
private PhoneListener(Context context) {
this.context = context;
}
AtomicBoolean isRecording = new AtomicBoolean();
AtomicBoolean isWhitelisted = new AtomicBoolean();
/**
* Set the outgoing phone number
* <p/>
* Called by {#link MyCallReceiver} since that is where the phone number is available in a outgoing call
*
* #param phoneNumber
*/
public void setOutgoing(String phoneNumber) {
if (null == phoneCall)
phoneCall = new CallLog();
phoneCall.setPhoneNumber(phoneNumber);
phoneCall.setOutgoing();
// called here so as not to miss recording part of the conversation in TelephonyManager.CALL_STATE_OFFHOOK
isWhitelisted.set(Database.isWhitelisted(context, phoneCall.getPhoneNumber()));
}
#Override
public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber);
switch (state) {
case TelephonyManager.CALL_STATE_IDLE: // Idle... no call
if (isRecording.get()) {
RecordCallService.stopRecording(context);
phoneCall = null;
isRecording.set(false);
}
break;
case TelephonyManager.CALL_STATE_OFFHOOK: // Call answered
if (isWhitelisted.get()) {
isWhitelisted.set(false);
return;
}
if (!isRecording.get()) {
isRecording.set(true);
// start: Probably not ever usefull
if (null == phoneCall)
phoneCall = new CallLog();
if (!incomingNumber.isEmpty()) {
phoneCall.setPhoneNumber(incomingNumber);
}
// end: Probably not ever usefull
RecordCallService.sartRecording(context, phoneCall);
}
break;
case TelephonyManager.CALL_STATE_RINGING: // Phone ringing
// DO NOT try RECORDING here! Leads to VERY poor quality recordings
// I think something is not fully settled with the Incoming phone call when we get CALL_STATE_RINGING
// a "SystemClock.sleep(1000);" in the code will allow the incoming call to stabilize and produce a good recording...(as proof of above)
if (null == phoneCall)
phoneCall = new CallLog();
if (!incomingNumber.isEmpty()) {
phoneCall.setPhoneNumber(incomingNumber);
// called here so as not to miss recording part of the conversation in TelephonyManager.CALL_STATE_OFFHOOK
isWhitelisted.set(Database.isWhitelisted(context, phoneCall.getPhoneNumber()));
}
break;
}
}
}
And use Broadcast Receiver
public class MyCallReceiver extends BroadcastReceiver {
public MyCallReceiver() {
}
static TelephonyManager manager;
#Override
public void onReceive(Context context, Intent intent) {
Log.i("JLCreativeCallRecorder", "MyCallReceiver.onReceive ");
if (!AppPreferences.getInstance(context).isRecordingEnabled()) {
removeListener();
return;
}
if (Intent.ACTION_NEW_OUTGOING_CALL.equals(intent.getAction())) {
if (!AppPreferences.getInstance(context).isRecordingOutgoingEnabled()) {
removeListener();
return;
}
PhoneListener.getInstance(context).setOutgoing(intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER));
} else {
if (!AppPreferences.getInstance(context).isRecordingIncomingEnabled()) {
removeListener();
return;
}
}
// Start Listening to the call....
if (null == manager) {
manager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
}
if (null != manager)
manager.listen(PhoneListener.getInstance(context), PhoneStateListener.LISTEN_CALL_STATE);
}
private void removeListener() {
if (null != manager) {
if (PhoneListener.hasInstance())
manager.listen(PhoneListener.getInstance(null), PhoneStateListener.LISTEN_NONE);
}
}
}
I hope you get some help from this code.
Thanks

You can use accessibility events to detect the call duration and from that you can detect if the outgoing call is answered or not..
I have answered it in detail in Here` you can check that.

You need this permission in manifest
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
TelephonyManager has a listener to get phone state. implement this tho know if the phone is ringing or in a call.
TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
PhoneStateListener callStateListener = new PhoneStateListener() {
public void onCallStateChanged(int state, String incomingNumber) {
// TODO React to a incoming call.
try {
if (state == TelephonyManager.CALL_STATE_RINGING) {
Toast.makeText(getApplicationContext(), "Phone Is Ringing" + incomingNumber, Toast.LENGTH_LONG).show();
number = incomingNumber;
//g.setPhoneNo(incomingNumber);
AndroidNetCommunicationClientActivity.mMsgSendRequest("CommandMsgCallIncoming" + number);
} else if (state == TelephonyManager.CALL_STATE_OFFHOOK) {
Toast.makeText(getApplicationContext(), "Phone is Currently in A call" + incomingNumber, Toast.LENGTH_LONG).show();
//number = mIntent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
number = incomingNumber;
} else if (state == TelephonyManager.DATA_DISCONNECTED) {
number = "";
CallID = "";
}
} catch (Exception e) {
// TODO Auto-generated catch block
//conn.MessageBox(MainActivity.this, e.getMessage());
e.printStackTrace();
}
super.onCallStateChanged(state, incomingNumber);
}
};
telephonyManager.listen(callStateListener, PhoneStateListener.LISTEN_CALL_STATE);

Related

Android WiFi Direct android.net.wifi.p2p.PEERS_CHANGED received endlessly

community,
this is my first question, so please tell me if I accidentally don't match some norms or similiar.
I am trying to code an android application that communicates with WiFi direct.
Everything works smooth at this point, but my BroadcastReceiver receives the android.net.wifi.p2p.PEERS_CHANGED action again and again.
public class WifiP2PBroadcastReceiver extends BroadcastReceiver {
private final static String TAG = "WifiP2PBR";
private WifiP2pManager _manager;
private WifiP2pManager.Channel _channel;
private Activity _callbackActivity;
private static ArrayList<WifiBroadcastCallback> _arrayList_callbacks;
public WifiP2PBroadcastReceiver(WifiP2pManager manager, WifiP2pManager.Channel channel, Activity callback) {
_manager = manager;
_channel = channel;
_callbackActivity = callback;
}
/**
* add a callback to the receiver
*
* #param callback
*/
public static void addWifiCallback(WifiBroadcastCallback callback) {
if(!getCallbacksList().contains(callback))
{
getCallbacksList().add(callback);
}
}
public void registerReceiver()
{
Log.d(TAG,"registerReceiver called");
if(_callbackActivity != null) {
_callbackActivity.registerReceiver(this, getIntentFilter());
}
}
public void unregisterReceiver() {
if(_callbackActivity != null) {
_callbackActivity.unregisterReceiver(this);
}
}
#Override
public final void onReceive(Context context, Intent intent) {
Log.d(TAG, "action: "+intent.getAction());
switch(intent.getAction()) {
case WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION:
Log.d(TAG, "state changed action");
break;
case WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION:
Log.d(TAG, "peers changed action");
notifyPeerUpdate();
break;
case WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION:
Log.d(TAG, "wifi p2p connection changed action");
NetworkInfo networkInfo = intent.getParcelableExtra(WifiP2pManager.EXTRA_NETWORK_INFO);
Log.d(TAG,"network info available");
break;
case WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION:
Log.d(TAG, "wifi p2p this device changed action");
notifyDeviceUpdate();
WifiP2pDevice thisDevice = intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_DEVICE);
Log.d(TAG,"this device acquired");
break;
}
}
private void notifyPeerUpdate()
{
for(WifiBroadcastCallback c : getCallbacksList())
{
c.onPeersChanged();
}
}
private void notifyDeviceUpdate()
{
for(WifiBroadcastCallback c : getCallbacksList())
{
c.onDeviceChanged();
}
}
/**
* get array list of callbacks
*
* #return
*/
private static ArrayList<WifiBroadcastCallback> getCallbacksList() {
if(_arrayList_callbacks == null) {
_arrayList_callbacks = new ArrayList<WifiBroadcastCallback>();
}
return _arrayList_callbacks;
}
/**
* interface for callbacks
*/
public interface WifiBroadcastCallback {
void onDeviceChanged();
void onPeersChanged();
}
private IntentFilter getIntentFilter()
{
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
intentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
intentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
return intentFilter;
}
}
this is my BroadcastReceiver code. Everything else works fine and I'm out of ideas, it started out of the nowhere.
That's how it works indeed. Basically, what you should do there, is to call requestPeers with your instance of WifiP2pManager. Then you onPeersAvailable from WifiP2pManager.PeerListListener would be called with the array of peers seen, and there you could then check whether the change is something that you want to report.
reference implementation can be found from my github projects

Ending a phone call in Android

After a phone call ends, I must open another Activity.
However, it doesn't catch the "call end signal".
I've used mTelManager in BroadcastReceiver and Service, but it doesn't work.
When Activity is opened by a Service or BroadcastReceiver, it shows the MainActivity and not the targeted one instead.
Source code:
public class MainService extends Service{
TelephonyManager mTelManager;
PhoneStateRead pListener;
String TAG = "Call State catch";
boolean callOutState = false; //calling state
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
Log.i(TAG, "ServiceReceiver->onReceive();");
pListener = new PhoneStateRead();
mTelManager = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
mTelManager.listen(pListener, PhoneStateListener.LISTEN_CALL_STATE);
if(callOutState){ //if call end
Intent showRecord = new Intent(getBaseContext(), Call_Out_Record_Activity.class);
showRecord.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(showRecord);//open Call_Out_Record_Activity
}
}
public class PhoneStateRead extends PhoneStateListener {
private final String TAG = "Phone State Read";
#Override
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_IDLE:
Log.i(TAG,"MyPhoneStateListener->onCallStateChanged() -> CALL_STATE_IDLE "+incomingNumber);
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
Log.i(TAG,"MyPhoneStateListener->onCallStateChanged() -> CALL_STATE_OFFHOOK "+incomingNumber);
break;
case TelephonyManager.CALL_STATE_RINGING:
Log.i(TAG,"MyPhoneStateListener->onCallStateChanged() -> CALL_STATE_RINGING "+incomingNumber);
break;
default:
Log.i(TAG,"MyPhoneStateListener->onCallStateChanged() -> default -> "+Integer.toString(state));
break;
}
CatchCallState(state);
}
}
private void CatchCallState(int state){
if(state == TelephonyManager.CALL_STATE_OFFHOOK || state == TelephonyManager.CALL_STATE_RINGING)
callOutState = false;
else if(state == TelephonyManager.CALL_STATE_IDLE)
callOutState = true;
}
}
So it looks like you have a couple problems here. First, you are trying to start your activity when you start your Service - you should do this code:
if(callOutState){ //if call end
Intent showRecord = new Intent(getBaseContext(), Call_Out_Record_Activity.class);
showRecord.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(showRecord);//open Call_Out_Record_Activity
}
in the CallStateListener. Or just put it in your CatchCallState method.
Next, notice that there is not a "call end signal" - the phone will go from "OFF_HOOK" to "IDLE" so you need flags to track that. Also, notice that "RINGING" happens on incoming calls, but not outgoing calls. So you may want to display different messages depending on incoming or outgoing calls.

I am trying to delete a particular incoming number after hang up but these code not working properly

I am trying to delete a particular incoming number from call log when phone hang-up. I tried as i can do but that code not working the number still remain in call log.
it is working properly when broadcast invoke but this is not deleting number of incoming call.
Thanks in Advance.
public class ListenPhoneState extends BroadcastReceiver {
private boolean isPressOffHock = false;
static private String incomingNumberToDelete;
#Override
public void onReceive(Context context, Intent intent) {
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) {
Log.e("Phone Receive Error", " " + e);
}
if(incomingNumberToDelete != null)
{
String queryString="NUMBER="+incomingNumberToDelete;
context.getContentResolver().delete(CallLog.Calls.CONTENT_URI,queryString,null);
Log.d("Delete", "Delete Number " + incomingNumberToDelete );
}
}
private class MyPhoneStateListener extends PhoneStateListener {
public void onCallStateChanged(int state, String incomingNumber) {
if(state == TelephonyManager.CALL_STATE_RINGING)
{
incomingNumberToDelete = incomingNumber;
Log.d("Check", "income " + incomingNumberToDelete );
}
switch(state) {
case TelephonyManager.CALL_STATE_IDLE:
//Log.d("IDLE", state + "incoming" + incomingNumber);
isPressOffHock = true;
break;
case TelephonyManager.CALL_STATE_RINGING:
//Log.d("RINGING", state + "incoming" + incomingNumber);
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
String msg = "New Phone Call Event. Incomming Number : "+incomingNumber;
// Log.d("CALL_STATE_OFFHOOK",msg );
break;
}
}
}
}
Usually there is a delay between the broadcast of a phone state and the system data that is written or system activities (such as call logs or phone ringing). Right now, your receiver is probably trying to delete the call log before it is present.
You could delay the delete or take a look at this post for registering a ContentObserver:
Delete call from call log after call end

How to identify the ringing state of outgoing call in android

In my app i want to identify whether the outgoing call state like waiting,received or rejected by other side.
I searched a lot in these below links
Outgoing call status How to detect answered or rejected state in outgoing call,outgoing call information through android BroadcastReceiver,identify outgoing call connect event
But couldn'd find a proper answer.Plz help me.Thanx.
I know its been a while but i hope to be helpful for someone still looking for a solution!
I recently had to work on a similar project where i needed to capture the ringing state of an outgoing call and the only way i could find was using the hidden Api of native dial-up App. This would only be possible for android > 5.0 because of the api changes. This was tested on Android 5.0.1, and worked like a charm. (p.s. you would need a rooted device for it to work, because you need to install your app as a System application (google how!) which will then be able to detect the outgoing call states).
For the record, PhoneStateListener doesn't work for detecting the outgoing call states as mentioned in many posts.
First, add this permission in the manifest file,
<uses-permission android:name="android.permission.READ_PRECISE_PHONE_STATE" />
Then define you broadcastreceiver, (here is a sample code!)
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.TelephonyManager;
public class MyBroadcastReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, final Intent intent)
{
switch (intent.getIntExtra("foreground_state", -2)) {
case 0: // PreciseCallState.PRECISE_CALL_STATE_IDLE:
System.out.println("IDLE");
break;
case 3: // PreciseCallState.PRECISE_CALL_STATE_DIALING:
System.out.println("DIALING");
break;
case 4: // PreciseCallState.PRECISE_CALL_STATE_ALERTING:
System.out.println("ALERTING");
break;
case 1: // PreciseCallState.PRECISE_CALL_STATE_ACTIVE:
System.out.println("ACTIVE");
break;
}
}
}
I replace some of the constants with their values because i saw alot of confusion among the folks unfamiliar with the concept of reflection (for ease).
Alerting is basically the state when receiver is actually ringing! and that does not include the call setup time!.
I had a similar issue. I wanted to detect some states of outgoing calls. I solved the issue by using visualizer class in android. It can return you with a Fourier transform of the current audio playing on the speaker. Using the type of audio being played(small beeping on the front speaker) you can determine the state of out-going call. For example you can know whether the phone has started ringing on the receiver or not. When ever visualizer return non-zero samples it is a yes.
Background audio wont disturb you because during a phone call the caller app shuts down all other audio.
Wait for status off_hook and then start your visualizer class
Try this, Look in else part and do changes there, it will work.
public class CallBr extends BroadcastReceiver {
Bundle bundle;
String state;
String inCall, outCall;
public boolean wasRinging = false;
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(ACTION_IN)) {
if ((bundle = intent.getExtras()) != null) {
state = bundle.getString(TelephonyManager.EXTRA_STATE);
if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
inCall = bundle.getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
wasRinging = true;
Toast.makeText(context, "IN : " + inCall, Toast.LENGTH_LONG).show();
} else if (state.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) {
if (wasRinging == true) {
Toast.makeText(context, "ANSWERED", Toast.LENGTH_LONG).show();
String out = new SimpleDateFormat("dd-MM-yyyy hh-mm-ss").format(new Date());
File sampleDir = new File(Environment.getExternalStorageDirectory(), "/TestRecordingDasa1");
if (!sampleDir.exists()) {
sampleDir.mkdirs();
}
String file_name = "Record";
try {
audiofile = File.createTempFile(file_name, ".amr", sampleDir);
} catch (IOException e) {
e.printStackTrace();
}
String path = Environment.getExternalStorageDirectory().getAbsolutePath();
recorder = new MediaRecorder();
// recorder.setAudioSource(MediaRecorder.AudioSource.VOICE_CALL);
recorder.setAudioSource(MediaRecorder.AudioSource.VOICE_COMMUNICATION);
recorder.setOutputFormat(MediaRecorder.OutputFormat.AMR_NB);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
recorder.setOutputFile(audiofile.getAbsolutePath());
try {
recorder.prepare();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
recorder.start();
recordstarted = true;
}
} else if (state.equals(TelephonyManager.EXTRA_STATE_IDLE)) {
wasRinging = false;
Toast.makeText(context, "REJECT || DISCO", Toast.LENGTH_LONG).show();
if (recordstarted) {
recorder.stop();
recordstarted = false;
}
}
}
} else if (intent.getAction().equals(ACTION_OUT)) {
if ((bundle = intent.getExtras()) != null) {
outCall = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
Toast.makeText(context, "OUT : " + outCall, Toast.LENGTH_LONG).show();
}
}
}
}
Try this, You can use PhoneListener extends to PhoneStateListener.
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
public class ListenToCallState extends BroadcastReceiver {
// private LoadProfImage mProfile;
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
// mProfile = new LoadProfImage(context);
PhoneListener phoneListener = new PhoneListener(context);
TelephonyManager telephony = (TelephonyManager) context
.getSystemService(Context.TELEPHONY_SERVICE);
telephony.listen(phoneListener, PhoneStateListener.LISTEN_CALL_STATE);
}
class PhoneListener extends PhoneStateListener {
private Context context;
public PhoneListener(Context context) {
// TODO Auto-generated constructor stub
this.context = context;
}
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_IDLE:
//Do your stuff
break;
case TelephonyManager.CALL_STATE_RINGING:
//Do your stuff
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
//Do your stuff
break;
}
}
}
}

Broadcast receiver and phonestatelistener

I am trying to use BroadcastReceiver to receive incoming calls. I want to register call when the call is ended. Below code gives each state (idle,ringing n offhook) more than once with the same number (its not an issue of past call). Is it because phonestatelistner is called within the service.
public class IncomingCallReceiver extends BroadcastReceiver {
int stateString =0;
int prevStat = 0;
#Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
if(null == bundle)
return;
String state = bundle.getString(TelephonyManager.EXTRA_STATE);
if(state.equalsIgnoreCase(TelephonyManager.EXTRA_STATE_RINGING))
{
String phonenumber = bundle.getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
String info = "Detect Calls sample application\nIncoming number: " + phonenumber;
Toast.makeText(context, info, Toast.LENGTH_LONG).show();
}
TelephonyManager telephony = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
//CustomPhoneStateListener customPhoneListener = new CustomPhoneStateListener();
PhoneStateListener listener = new PhoneStateListener() {
#Override
public void onCallStateChanged(int state, String incomingNumber) {
String p = incomingNumber;
switch (state) {
case TelephonyManager.CALL_STATE_IDLE:
prevStat = stateString;
stateString = 1;
Log.i("ON CALL STATE CHANGED","IDLE");
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
Log.i("ON CALL STATE CHANGED","OFFFHOOK");
prevStat = stateString;
stateString = 2;
break;
case TelephonyManager.CALL_STATE_RINGING:
prevStat = stateString;
stateString = 3;
Log.i("ON CALL STATE CHANGED","RINGING");
break;
}
if(prevStat == 2 && stateString == 1)
{
Log.i("REGISTER A CALLL","==" +p);
}
}
};
telephony.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);
}
}
I also tried the same thing with phonestatelistener in a separate class, but it was not being called, i.e my code didn't reach there. In my manifest file I have registered receiver, but there is no declaration of phonestatelistener. Is that to be registered?
I am sorry if the solution is quite obvious but am new to android things.
Any help is appreciated :)
Yes, choose listener or received , not both of them

Categories

Resources