Question

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?

Was it helpful?

Solution

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.

OTHER TIPS

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top