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));
}
}
Related
Currently when I run my application and if phone rings , phone get preference and my application is killed. Is there any way either my application takes a preference i.e. let phone call to hit voice mail or shift my app to background for short period of time , till user take a call , and bring back to foreground once he complete. thanks
you can do one thing. You can pause your application during the incoming call and after that, resume the application from the same place. I know this is not the exact solution of your issue but somehow, it will reduce your work load. hope this will help.
private class PhoneCallListener extends PhoneStateListener {
private boolean isPhoneCalling = false;
// needed for logging
String TAG = "PhoneCallListener";
#Override
public void onCallStateChanged(int state, String incomingNumber) {
if (TelephonyManager.CALL_STATE_RINGING == state) {
// phone ringing
Log.i(TAG, "RINGING, number: " + incomingNumber);
}
if (TelephonyManager.CALL_STATE_OFFHOOK == state) {
// active
Log.i(TAG, "OFFHOOK");
isPhoneCalling = true;
}
if (TelephonyManager.CALL_STATE_IDLE == state) {
// run when class initial and phone call ended,
// need detect flag from CALL_STATE_OFFHOOK
Log.i(TAG, "IDLE");
if (isPhoneCalling) {
Log.i(TAG, "restart app");
// restart call application
Intent i = getBaseContext().getPackageManager()
.getLaunchIntentForPackage(
getBaseContext().getPackageName());
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(i);
isPhoneCalling = false;
}
}
}
}
and also add this permission to manifest.xml file
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
I had come across a similar issue, resolved this by overriding onPause() and onResume() methods, save all the required variables in onPause() and restore these in onResume().
#Override
protected void onResume(){
super.onResume();
load();
}
#Override
protected void onPause(){
super.onPause();
save();
}
private void save() {
SharedPreferences sharedPreferences = getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("DeviceName", deviceName);
editor.putString("ConnectOption", connectOption.toString());
editor.commit();
}
private void load() {
SharedPreferences sharedPreferences = getPreferences(Context.MODE_PRIVATE);
deviceName = sharedPreferences.getString("DeviceName","");
String connectop = sharedPreferences.getString("ConnectOption","USB"); //You could provide a default value here
}
I think this is the default feature of android that any application
go inactive if incoming call is in active. We cannot change this.
While the user is in the phone call, though, they can change to another
app simply by pressing the home button and starting another app from
the home screen, or by double-pressing the home button and switching to another app, including yours.
I have registered my activity to handle the ACTION_DIAL intent but in certain cases I want to basically ignore the intent. In onCreate, I'm checking SharedPreferences for a bool that means user has access to dial, if not then I call finish() and then return; But this still shows a window flashing open and then closed, how can I avoid that?
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
boolean hasDialer = prefs.getBoolean(Preferences.HAS_DIALER, false);
// Check if ACTION_DIAL intent was launched to bring user into the app
String number = getIntent().getDataString();
if (!TextUtils.isEmpty(number))
{
if (hasDialer)
{
launchDialer = true;
}
else
{
finish();
return;
}
}
}
You could register the ACTION_DIAL in a broadcast receiver (directly in the manifest) or in a service (now this depends on what else are you planning to do) and have the same logic in there. You can start activities from there if you need to.
We create a html code to make a phone call from inside a WL App using this
document.location.href = 'tel:'+ phoneNumber;
It seems to be working at first, that is, it launches the dialer, make the call, and when the phone call ends, it meant to come back to the WL app where it was, however it restarted the WL app from the beginning, starting it from the splash screen, which is not the desired behavior, as it is expect that right after the dialer finishes, it returns to the WL app where it was before the dialer started.
Any idea on how to solve this ?
Not sure if all the steps is necessary.. but here it goes.
1) declare your activity singleInstance android:launchMode="singleInstance"
2) add this code to your activity
private PhoneStateListener callListener;
#Override
public void onCreate(Bundle savedInstanceState) {
callListener = new EndCallListener();
...
}
private class EndCallListener extends PhoneStateListener {
private final String LOG_TAG = "EndCallListener";
private boolean isPhoneCalling = false;
#Override
public void onCallStateChanged(int state, String incomingNumber) {
if (TelephonyManager.CALL_STATE_RINGING == state) {
Log.i(LOG_TAG, "RINGING, number: " + incomingNumber);
// finish();
}
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.
Log.i(LOG_TAG, "OFFHOOK");
isPhoneCalling = true;
}
if (TelephonyManager.CALL_STATE_IDLE == state) {
// when this state occurs, and your flag is set, restart your
// app
Log.i(LOG_TAG, "IDLE");
if (TelephonyManager.CALL_STATE_IDLE == state) {
// run when class initial and phone call ended,
// need detect flag from CALL_STATE_OFFHOOK
Log.i(LOG_TAG, "IDLE");
if (isPhoneCalling) {
Log.i(LOG_TAG, "restart app");
// restart app
Intent i = getBaseContext().getPackageManager()
.getLaunchIntentForPackage(
getBaseContext().getPackageName());
// i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
i.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(i);
isPhoneCalling = false;
}
}
}
}
}
3) in your manifest.xml
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
The way you are doing it now, you are replacing the worklight app with the tel URL. You need to launch the URL in its own window.
Use:
window.open("tel:5551212");
This will suspend the app, and launch the phone. When you exit the phone, the app will resume.
We have a page that has a links to a tel number (a href="tel:5551234567"), when the user touches the link, it opens up the dialer. After the user end the call, and hit back, instead of just returning the browser, you can see that the browser is being restarted, thus the page is reloading. Why this happens ?
You can easy load this URL (http://goo.gl/QKbrC9) in your device and touch the Call (555) link.
Thanks,
It is default behaviour for Android.
When the call is taking place you have moved outside the browser app and into a new one. The dialer app has no idea about the browser, so when back is pressed the Android OS takes over and starts the browser app. This starts a new browser, whereas, if the dialer knew about the browser, it could flag it to reorder to front.
That being said, it is possible to make an app counter this with somthing like:
private class EndCallListener extends PhoneStateListener {
private final String LOG_TAG = "EndCallListener";
private boolean isPhoneCalling = false;
#Override
public void onCallStateChanged(int state, String incomingNumber) {
if (TelephonyManager.CALL_STATE_RINGING == state) {
Log.i(LOG_TAG, "RINGING, number: " + incomingNumber);
// finish();
}
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.
Log.i(LOG_TAG, "OFFHOOK");
isPhoneCalling = true;
}
if (TelephonyManager.CALL_STATE_IDLE == state) {
// run when class initial and phone call ended,
// need detect flag from CALL_STATE_OFFHOOK
Log.i(LOG_TAG, "IDLE");
if (isPhoneCalling) {
Log.i(LOG_TAG, "restart app");
// restart app
Intent i = getBaseContext().getPackageManager()
.getLaunchIntentForPackage(
getBaseContext().getPackageName());
// i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
i.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(i);
isPhoneCalling = false;
}
}
}
But evidently the browser has no obvious reason to handle this specifically.
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);
}
}
}
}