3

Using this simple example to create a PhoneCall application that dials out a hard coded # and monitors phone state.

http://www.mkyong.com/android/how-to-make-a-phone-call-in-android/

Unfortunately, on making the phone call, we always switch to the actual built -in phone application.

I want to avoid this, or at the very least hide the dialer pad button. The user SHOULD NOT have the option to enter a phone#.

Does anyone know of a way to achieve this? i.e. keep the actual built-in phone application in the background (I would need to add buttons for speaker, and end call in the primary application)

OR

alternatively, hide just the dial pad button in the native, built-in phone application?

Bachalo
  • 6,965
  • 27
  • 95
  • 189

2 Answers2

1

Here is a solution I came up with to hide the caller app shortly after the call is placed. I don't believe there is a way to make it totally transparent without re-writing the Android system. I believe this could be improved by detecting when the caller app is set up and dialing instead of the postDelayed() I'm using which could be unreliable.

EDIT: I tried making a receiver to listen for NEW_OUTGOING_CALL to restart the original Activity, but it doesn't really improve anything, the dialer app must be running for an arbitrary amount of time before it can start it's background service.

EDIT: I tried making a PhoneStateListener that listens for CALL_STATE_OFFHOOK and re starts the Activity there. This doesn't work either as it happens before the dialing app is fully ready to go into the background.

EDIT: You can look at this thread: Reflection to access advanced telephony features, but I believe Google has since locked down all methods of placing a call outside the standard app.

This solution will start the dialing, and then switch back to the original Activity after a couple of seconds.

In my manifest I have:

android:launchMode="singleInstance"

on my Activity so I don't get a new instance.

public class MainActivity extends Activity
{
  ....
    public void clickMe(View view)
    {
        startService(new Intent(this, PhoneService.class));
    }
}


public class PhoneService extends Service
{
    @Override
    public int onStartCommand(Intent intent, int flags, int startId)
    {
        Intent call = new Intent(Intent.ACTION_CALL);
        call.setData(Uri.parse("tel:XXXXXXXXX"));
        call.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(call);

        Handler h = new Handler();
        h.postDelayed(new Runnable() {

            @Override
            public void run()
            {
                Intent act = new Intent(PhoneService.this, MainActivity.class);
                act.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                startActivity(act);
            }

        }, 4000);

        return super.onStartCommand(intent, flags, startId);


    }

    @Override
    public IBinder onBind(Intent arg0)
    {
        // TODO Auto-generated method stub
        return null;
    }

}

I believe it impossible to provide a cleaner solution, given the constraints of the SDK.

Community
  • 1
  • 1
Steve M
  • 9,296
  • 11
  • 49
  • 98
  • thanks. What about incoming calls? is there a way for a custom app NOT to lose focus? – user2005121 Jan 08 '14 at 22:48
  • You can probably rig up a PhoneStateListener to listen for TelephonyManager.CALL_STATE_RINGING (with your number), and then launch your app on TelephoneManager.CALL_STATE_OFFHOOK if it occurs within a certain amount of time of the first. The user will have to pick it up from the normal phone app. – Steve M Jan 09 '14 at 02:19
1

The functionality you are wanting isn't possible without some type of hack-ish work around. The Android system only allows the Phone app to control the underlying RIL and telephony stack and the Phone app UI responds to the dial URI by presenting this user with the dial screen where they must confirm (or alter) the number. This is a security provision to prevent unwanted apps from using the telephone device without the user knowing about it. Also, due to the way the Intent system works in Android, it is possible for other apps to handle calls using SIP or other VoIP functionality (i.e. Skype). In this case the user may have set a global preference to always use the other app and you have no control over how that app behaves with the dial Intent.

Larry Schiefer
  • 15,687
  • 2
  • 27
  • 33
  • At least on my phone, using Intent.ACTION_CALL will immediately place the call, without giving the user opportunity to change or confirm. It does however bring the phone app to the foreground with the options to hang up, etc. – Steve M Jan 03 '14 at 22:19
  • The ACTION_CALL action does immediately call; however, it is restricted by the platform implementation to be allowed by only certain apps. Your app must hold the CALL_PHONE permission. Even then, it is still possible for the user to be prompted if there is more than one application whose manifest declares that it handles this Intent. – Larry Schiefer Jan 07 '14 at 11:28
  • Good point, Skype could be presented as an option to handle the intent, eg. – Steve M Jan 07 '14 at 12:21