How to change the ringing state of android phone? - android

I'm trying to silent my phone when any call is ended and for that i'm using audiomanager object. When i write setRingerMode at position 1 it works but at position 2 its not working. Its inside BroadCast Recevier. Here is my code:
public void onReceive(Context context, Intent intent)
{
AudioManager am= (AudioManager)context.getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
//POSITION 1 am.setRingerMode(AudioManager.RINGER_MODE_SILENT);
Bundle myBundle = intent.getExtras();
if (myBundle != null)
{
System.out.println("--------Not null-----");
try
{
if (intent.getAction().equals("android.intent.action.PHONE_STATE"))
{
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
if (state.equals(TelephonyManager.EXTRA_STATE_RINGING))
{
//code...
}
else if (state1.equals(TelephonyManager.EXTRA_STATE_OFFHOOK))
{
//POSITION 2
am.setRingerMode(AudioManager.RINGER_MODE_SILENT);
}
}
}
catch (Exception ex)
{ // Many things can go wrong with reflection calls
ex.printStackTrace();
}
}
}

As per android documentation -
Device call state: Off-hook. At least one call exists that is
dialing, active, or on hold, and no calls are ringing or waiting.
if you want to set after the call is ended use EXTRA_STATE_IDLEand in your code you have used state1variable in if statement and you have declared and used statevariable.

Related

Starting an Activity does not put application in foreground

I make a phone call from an Activity and when call ends I want to come back to application. I tried all the solutions available on stackoverflow. One of them used to work for few minutes but not working now.
I tried using recreate() method which successfully calls onCreate method of an Activity but app is not in foreground. I tried using various flags such as FLAG_ACTIVITY_CLEAR_TOP, FLAG_ACTIVITY_CLEAR_TASK, FLAG_ACTIVITY_NO_HISTORY. But does not work.
Code to go back to application from call app :
private class PhoneCallListener extends PhoneStateListener {
private boolean isPhoneCalling = false;
#Override
public void onCallStateChanged(int state, String incomingNumber) {
// If call ringing
if (state == TelephonyManager.CALL_STATE_RINGING) {
}
// Else if call active
else if (state == TelephonyManager.CALL_STATE_OFFHOOK) {
isPhoneCalling = true;
}
// Else if call idle
else if (state == TelephonyManager.CALL_STATE_IDLE) {
if (isPhoneCalling) {
isPhoneCalling = false;
MyActivity.this.recreate();
}
}
}
}
This is my solution, it works perfectly on 4.3 - other OS versions not tested yet, but everything should be fine.
Registering the listener in MainActivity:
TelephonyManager tManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
listener = new ListenToPhoneState();
tManager.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);
The PhoneStateListener from MainActivty:
private class ListenToPhoneState extends PhoneStateListener {
private String LOG_TAG = "mainactivity";
private boolean isCallFinished = false;
public void onCallStateChanged(int state, String incomingNumber) {
if (TelephonyManager.CALL_STATE_RINGING == state) {
Log.i(LOG_TAG, "RINGING, number: " + incomingNumber);
}
if (TelephonyManager.CALL_STATE_OFFHOOK == state) {
// wait for phone to go offhook (probably set a boolean flag) so
// you know your app initiated the call.
isCallFinished = true;
Log.i(LOG_TAG, "OFFHOOK");
}
if (TelephonyManager.CALL_STATE_IDLE == state) {
// when this state occurs, and your flag is set, restart your
// app
if (isCallFinished) {
isCallFinished = false;
Intent i = new Intent(getApplicationContext(),
MainActivity.class);
// this needs if you want some special action after the phone call
//ends, that is different from your normal lauch configuration
i.setAction("SHOW_PHONE_CALL_LIST");
startActivity(i);
finish();
}
Log.i(LOG_TAG, "IDLE");
}
}
}
I start the phone call from a fragment, but that doesn't make any difference:
Uri uri = Uri.parse("tel:" + Uri.encode(callIt));
Intent intent = new Intent(Intent.ACTION_CALL, uri);
startActivity(intent);
getActivity().finish();
You have to call finish() on the activity that starts the call, otherwise after the phone call, your app will stay behing the default Phone application.
When your app is starting, you can have a look at the intent, and you can set up your after call configuration. Call this in your onCreate() method:
if (intent.getAction().equals("SHOW_PHONE_CALL_LIST")) {
//perfom after call config here
}
I hope everything is clearly explained.
I think you must use a broadcast receiver and start the activity upon uphook. Also you need to declare permissions to read phone state.
Try to modify your code, that the important stuff is not in the onCreate() method but in the onResume() method, because when you come back from the phone call, the onCreate() method will not be triggered but the onResume() method. See http://developer.android.com/reference/android/app/Activity.html for more details on the Activity live cycle.
If that still does not help, use the flag Intent.FLAG_ACTIVITY_REORDER_TO_FRONT.
Try to use a context from the listener. Either the listener directly provides a context (so you can just call startActivity(…) or call getApplicationContext().startActivity(…)
In the end your code should something like this:
Intent intent = new Intent(RS_HomeScreenActivity.this,RS_HomeScreenActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(intent);
The solution is to launch an application with an extra included in bundle that says that app is launched as part of coming back from any other app.
When call ends, I launch an app using below code :
// Launch app
Intent i = new Intent(ActivityThatMadeCall.this,
LauncherActivity.class);
i.putExtra("EXTRA_RETURNED_FROM_CALL_APP", true);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
Then in my launcher activity I check for the extra and if it exists then start the activty that placed call. :
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
if(getIntent().getExtras().getString("EXTRA_RETURNED_FROM_CALL_APP") != null) {
startActivity(new Intent(this, ActivityThatMadeCall.class));
}
}

BroadcastReceiver for call answers

I'm trying to programmatically intercept a call answer.
I've got a BroadcastReceiver with the following method:
#Override
public void onReceive(Context context, Intent intent) {
Bundle extras = intent.getExtras();
if (extras != null) {
String state = extras.getString(TelephonyManager.EXTRA_STATE);
if(state.equals("OFFHOOK")) {
// ...
}
// ANSWER ??
}
}
While the code works successfully if the phone receives a call (offhook is related to the answer, because before I've got the ringing state) I can't detect the answer relatively to a placed call: in this case offhook is relative to the ringing.
How can I intercept the answer relatively to a placed call?

Android BroadCastReceiver and android.intent.action.PHONE_STATE Event

I am catching the android.intent.action.PHONE_STATE change event by using following code snippet with android BroadCastReceiver. I could recognize the event successfully and handle the incoming calls also can be done by following code.
My requirement is identifying calls which are coming form a particular number, end that call through the code and invoke a web service for that incoming event.
In here this code runs twice for call receiving and ending events.
I want to stop calling this method for twice. How can i stop calling that code snippet for the second event (ending the call). It would be great-full if any one can help me on this.
if (intent.getAction().equals(
"android.intent.action.PHONE_STATE")) {
Log.i("INFO", "Call Received");
try {
TelephonyManager telephony = (TelephonyManager) context
.getSystemService(Context.TELEPHONY_SERVICE);
Bundle bundle = intent.getExtras();
Log.i("Calling database", "Creatinng DataHandler Object");
DatabaseHandler db = new DatabaseHandler(context);
String phoneNumber =db.getContact().getPhoneNumber();
Log.i("Retriving : ", "Retriving .."+ db.getContact().getPhoneNumber());
if ((bundle.getString("incoming_number").equals(phoneNumber))) {
Log.i("Test Call", "This is the test call");
#SuppressWarnings("rawtypes")
Class c = Class.forName(telephony.getClass().getName());
Method m = c.getDeclaredMethod("getITelephony");
m.setAccessible(true);
ITelephony telephonyService = (ITelephony) m
.invoke(telephony);
telephonyService = (ITelephony) m.invoke(telephony);
telephonyService.endCall();
// Call the web service and send log details
ServiceClient sc = new ServiceClient();
sc.serviceCall(context);
} else {
Log.i("Normal Call", "This is not the test call");
}
} catch (Exception e) {
Log.i("Exception Occured", "Exception in call code snipet");
}
}
}
I believe the issue you are having is that the phone state changes twice, once when the phone rings, then, after you end the call, when the phone goes idle.
You only want this code to run once so the best way to do that is to add an additional check of the phone state to see if it is ringing, if the phone is ringing then end the call.
This can be accomplished by adding the following the check:
if (intent.getAction().equals(
"android.intent.action.PHONE_STATE")) {
Log.i("INFO", "Call Received");
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
//your code here that starts with try block
}
Hope that helps
you can try doing something like this as soon as the receiver starts:
Bundle bundle = nIntent.getExtras();
String phoneNr= bundle.getString("incoming_number");
if(null == phoneNr)
{ // this is outgoing call so bail out
return;
}
You cannot terminate incoming call using third party application due to android security reason. Check in "android application development cookbook" page number "164 "
I know it's too late but I found a batter solution for this.
This normally happens on 5.0 and 5.1. You cannot stop it from calling twice but you can have a universal check to do all your work at one point. And this solution universally work on all OS.
Here is the code
public void onReceive(Context context, Intent intent) {
Object obj = intent.getExtras().get("subscription");
long subId;
if(obj == null) {
subId = Long.MIN_VALUE; // subscription not in extras
} else {
subId = Long.valueOf(obj.toString()); // subscription is long or int
}
if(subId < Integer.MAX_VALUE) {
// hurray, this is called only once on all operating system versions!
}}
for more info check this link.

how to get the state for outgoing calls

In the OnReceive method I have something like this:
Bundle bundle=intent.getExtras();
String phonenumber=intent.getStrngExtra(Intent.EXTRA_PHONE_NUMBER);
How to chech if the dialing call is still on or the client hanged up the call?
How to check if the call was answered?
I need to print up a toat when the client hanged up the call or when the called client answered to the call.
You will need a broadcast receiver registered for action android.intent.action.PHONE_STATEiF THE phone state has not changed to idle once it is offhook, it means the call is still going on.
the call was answered if the state in read phone state broadcast receiver changes to offhook. Put a toast as need in these states.
public class CallDurationReceiver extends BroadcastReceiver {
static boolean flag =false;
static long start_time,end_time;
#Override
public void onReceive(Context arg0, Intent intent) {
String action = intent.getAction();
if(action.equalsIgnoreCase("android.intent.action.PHONE_STATE")){
if (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(
TelephonyManager.EXTRA_STATE_RINGING)) {
//tOAST FOR INCOMING CALL, NOT YET PICKED UP
}
if (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(
TelephonyManager.EXTRA_STATE_IDLE)) {
end_time=System.currentTimeMillis();
//Total time talked =
long total_time = end_time-start_time;
//Store total_time somewhere or pass it to an Activity using intent
} if (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(
TelephonyManager.EXTRA_STATE_OFFHOOK)) {
start_time=System.currentTimeMillis();
}
}
}
Register your receiver in your manifest file like this:
<receiver android:name=".CallDurationReceiver">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
}
Also add the uses permission:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
Well all I find out a solution for this and I successfully implemented it.Its not possible to fetch the exact time when the callee has accepted an outgoing call.
Before picking up a call in the other end it has already passed through 2 stages namely on_State_idle and on_state_offhook. On_state_ringing is not working for the outgoing calls.
Let's assume a phone is ringing for 40sec (this am not sure) continuously if the person at the other side didn't pick the call.
Start a timer along with the starting stage of on_State_idle and on_state_offhook.
Two cases if the timer cross above 40sec means the person at the other hand pick my call.
If on_State_idle->on_state_offhook->on_State_idle worked within 40sec means the other hand didn't pick my call.
If the second case is true, fetch the call talk duration from the call log.
Totaltimer running time - time in call log gives you the exact time of picking of the outgoing Call!
you can use the below code for handling call state:::
private Runnable callMonitor = new Runnable() {
public void run() {
try {
EndCallListener callListener = new EndCallListener();
TelephonyManager mTM = (TelephonyManager)m_activity.getSystemService(Context.TELEPHONY_SERVICE);
mTM.listen(callListener, PhoneStateListener.LISTEN_CALL_STATE);
} catch(Exception e) {
Log.e("callMonitor", "Exception: "+e.toString());
}
}
};
private class EndCallListener extends PhoneStateListener {
private boolean active = false;
#Override
public void onCallStateChanged(int state, String incomingNumber) {
if(TelephonyManager.CALL_STATE_RINGING == state) {
Log.i("EndCallListener", "RINGING, number: " + incomingNumber);
}
if(TelephonyManager.CALL_STATE_OFFHOOK == state) {
//wait for phone to go offhook (probably set a boolean flag) so you know your app initiated the call.
active = true;
Log.i("EndCallListener", "OFFHOOK");
}
if(TelephonyManager.CALL_STATE_IDLE == state) {
//when this state occurs, and your flag is set, restart your app
Log.i("EndCallListener", "IDLE");
if (active) {
active = false;
// stop listening
TelephonyManager mTM = (TelephonyManager)m_activity.getSystemService(Context.TELEPHONY_SERVICE);
mTM.listen(this, PhoneStateListener.LISTEN_NONE);
// restart the inbox activity
// Intent intent = new Intent(m_activity, MDInboxActivity.class);
// m_activity.startActivity(intent);
}
}
}
}

How do I get state of a outgoing call in android phone?

I noticed in the class TelephonyManager there are CALL_STATE_IDLE, CALL_STATE_OFFHOOK and CALL_STATE_RINGING. They seem to be used for incoming calls.
What I actually want to do is to be notified when an outgoing call is made, is received, or timed out. How to do that?
I don't know if you can detect a timed call, but differentiate when the call started is possible.
You can do it like this, in the CALL_STATE_IDLE:
Uri allCalls = Uri.parse("content://call_log/calls");
String lastMinute = String.valueOf(new Date().getTime() - DAY_IN_MILISECONDS);
//before the call started
Cursor c = app.getContentResolver().query(allCalls, null, Calls.DATE + " > "
+ lastMinute, null, Calls.DATE + " desc");
c.moveToFirst();
if (c.getCount() > 0) {
int duration = Integer.parseInt(c.getString(c.getColumnIndex(Calls.DURATION)));
}
if duration is > 0 then then it call was answered.
Obviously there are other flags that you should use to determine that CALL_STATE_IDLE is called after a call was made.
Hope that helps and put you in the corret way for what you are trying to do.
From what I understand, you can detect that an outgoing call has been initiated because the phone state changes from idle to offhook. However, from there, knowing the state of that call- ie knowing if the call you are placing is ringing, being transferred to voice mail, actually picked up or just timed out appears to be something that we cannot detect.
Now I'm not sure if it is just undetectable in the SDK, but is communicated over the network and possibly detectable from the radio receiver itself, or if that information just plain isn't being transmitted.
The minimum that is need to do is:
public class CallCounter extends PhoneStateListener {
public void onCallStateChanged(int state, String incomingNumber) {
switch(state) {
case TelephonyManager.CALL_STATE_IDLE:
Log.d("Tony","Outgoing Call finished");
// Call Finished -> stop counter and store it.
callStop=new Date().getTime();
context.stopService(new Intent(context,ListenerContainer.class));
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
Log.d("Tony","Outgoing Call Starting");
// Call Started -> start counter.
// This is not precise, because it starts when calling,
// we can correct it later reading from call log
callStart=new Date().getTime();
break;
}
}
public class ListenerContainer extends Service {
public class LocalBinder extends Binder {
ListenerContainer getService() {
return ListenerContainer.this;
}
}
#Override
public void onStart(Intent intent, int startId) {
TelephonyManager tManager =(TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
CallCounter callCounter=new CallCounter(this);
tManager.listen(callCounter,PhoneStateListener.LISTEN_CALL_STATE);
Log.d("Tony","Call COUNTER Registered");
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
// This is the object that receives interactions from clients. See
// RemoteService for a more complete example.
private final IBinder mBinder = new LocalBinder();
}
public class myReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_NEW_OUTGOING_CALL)) {
context.startService(new Intent(context,ListenerContainer.class));
}
}
}

Categories

Resources