How to hang up outgoing call in Android?
Asked Answered
P

8

48

I am developing an application where one of the things we need is to control the outgoing call, at least to be able to stop it from our application.

I've tried using Intent.ACTION_CALL from an existing activity:

Intent callIntent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + phoneNumber)); 
startActivity(callIntent); 

But stopping the call seems to be disallowed through the API.

Can you suggest some workaround?

For example: enabling airplane mode during the call? Just an example; this hack didn't work for me.

Poster answered 1/3, 2009 at 7:37 Comment(2)
Terminating the call is possible. TextMe4Callback on the Android market does this.Marche
Did using BroadcastReceiver work for you? Could you revise this question and/or accept an answer?Silassilastic
S
31

Capturing the outgoing call in a BroadcastReceiver has been mentioned and is definitely the best way to do it if you want to end the call before dialing.

Once dialing or in-call, however, that technique no longer works. The only way to hang up that I've encountered so far, is to do so through Java Reflection. As it is not part of the public API, you should be careful to use it, and not rely upon it. Any change to the internal composition of Android will effectively break your application.

Prasanta Paul's blog demonstrates how it can be accomplished, which I have summarized below.

Obtaining the ITelephony object:

TelephonyManager tm = (TelephonyManager) context
        .getSystemService(Context.TELEPHONY_SERVICE);
try {
    // Java reflection to gain access to TelephonyManager's
    // ITelephony getter
    Log.v(TAG, "Get getTeleService...");
    Class c = Class.forName(tm.getClass().getName());
    Method m = c.getDeclaredMethod("getITelephony");
    m.setAccessible(true);
    com.android.internal.telephony.ITelephony telephonyService =
            (ITelephony) m.invoke(tm);
} catch (Exception e) {
    e.printStackTrace();
    Log.e(TAG,
            "FATAL ERROR: could not connect to telephony subsystem");
    Log.e(TAG, "Exception object: " + e);
}

Ending the call:

telephonyService.endCall();
Silassilastic answered 15/3, 2011 at 15:54 Comment(10)
+1 Not good practice to do, but the OP asks specifically for a workaround for something that is not allowed by the API, thus this is a good answer.Misogyny
If this is the only solution, then I think this is a great answer!Xylina
hey i am not able to block particlar call by this code i checkedDougald
@Rstar What kind of exception are you getting? Which line or method is failing? Which device are you running? Which version of Android?Silassilastic
i am not getting any exception see this code and i have also written some notes in pastebin.com/3TW0ieVZDougald
This is a much better answer than Ash's. The OP obviously states that he wants to end a call rather than stop it from being answered.Masorete
@Rstar I would suggest adding some debug statements to check that your BroadcastReceiver is correctly registered from the manifest.Silassilastic
worked on 4.2 within emulator (with modified .jar's to avoid hiding APIs by Eclipse-ADT)Survival
How do you import com.android.internal.telephony.ITelephony? It generates 'Cannot resolve symbol error'.Palsgrave
@EnesBattal You need to include ITelephony.aidl in your project to provide an interface to the class.Silassilastic
S
28

EDIT: To Android P or newer, please see: https://mcmap.net/q/58042/-how-to-hang-up-outgoing-call-in-android

Try this:

(I used Reflection to access advanced telephony features and modify somethings)

// required permission <uses-permission android:name="android.permission.CALL_PHONE"/>

try {
    //String serviceManagerName = "android.os.IServiceManager";
    String serviceManagerName = "android.os.ServiceManager";
    String serviceManagerNativeName = "android.os.ServiceManagerNative";
    String telephonyName = "com.android.internal.telephony.ITelephony";

    Class telephonyClass;
    Class telephonyStubClass;
    Class serviceManagerClass;
    Class serviceManagerStubClass;
    Class serviceManagerNativeClass;
    Class serviceManagerNativeStubClass;

    Method telephonyCall;
    Method telephonyEndCall;
    Method telephonyAnswerCall;
    Method getDefault;

    Method[] temps;
    Constructor[] serviceManagerConstructor;

    // Method getService;
    Object telephonyObject;
    Object serviceManagerObject;

    telephonyClass = Class.forName(telephonyName);
    telephonyStubClass = telephonyClass.getClasses()[0];
    serviceManagerClass = Class.forName(serviceManagerName);
    serviceManagerNativeClass = Class.forName(serviceManagerNativeName);

    Method getService = // getDefaults[29];
    serviceManagerClass.getMethod("getService", String.class);

    Method tempInterfaceMethod = serviceManagerNativeClass.getMethod(
                "asInterface", IBinder.class);

    Binder tmpBinder = new Binder();
    tmpBinder.attachInterface(null, "fake");

    serviceManagerObject = tempInterfaceMethod.invoke(null, tmpBinder);
    IBinder retbinder = (IBinder) getService.invoke(serviceManagerObject, "phone");
    Method serviceMethod = telephonyStubClass.getMethod("asInterface", IBinder.class);

    telephonyObject = serviceMethod.invoke(null, retbinder);
    //telephonyCall = telephonyClass.getMethod("call", String.class);
    telephonyEndCall = telephonyClass.getMethod("endCall");
    //telephonyAnswerCall = telephonyClass.getMethod("answerRingingCall");

    telephonyEndCall.invoke(telephonyObject);

} catch (Exception e) {
    e.printStackTrace();
    Log.error(DialerActivity.this,
                "FATAL ERROR: could not connect to telephony subsystem");
    Log.error(DialerActivity.this, "Exception object: " + e);
}
Scrub answered 5/12, 2011 at 2:33 Comment(6)
thanks it works just fine to hangup a telephone call throw an applicationPusey
works excellent. [ required permission "<uses-permission android:name="android.permission.CALL_PHONE"/>" ]Isaac
works really well. do you know of other useful call actions, like enable speaker, answer, ... ?Catchword
Sorry @androiddeveloper I don't know. Actually, I make this code based on a lot of other tips found on StackOverflow. After a lot of tries, I built it.Scrub
@FelipeMicaroniLalli thank you. wonder why it's sometimes so hard to find out how to do things on android.Catchword
@Scrub This doesn't work anymore on Android P. Here's an updated code: https://mcmap.net/q/58042/-how-to-hang-up-outgoing-call-in-androidCatchword
R
21
  1. Create a BroadcastReceiver with a priority of 0.
  2. In the BC intercept the ACTION_NEW_OUTGOING_CALL intent in its onReceive method
  3. call setResultData(null) in the same method

This will prevent the call from initiating (as long as your receiver is the last to process the intent I think)

Responsiveness answered 12/3, 2009 at 3:44 Comment(1)
Any thoughts on why this works on Android 2.3.3 and earlier, but not Android 4.0 and later? I can't seem to pick up on the ACTION_NEW_OUTGOING_CALL with my BroadcastReceiver. I'm not interested in the cancelling call part though, just even knowing about a call I can't get working. Any thoughts would be appreciated, thanks!Xe
C
9

Here's the most updated code, which will work for Android P too, because it has an official API for it (here) :

in manifest, add this:

<uses-permission android:name="android.permission.ANSWER_PHONE_CALLS"/>

In code, use this:

Java:

@SuppressLint("PrivateApi")
public static boolean endCall(Context context) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
        final TelecomManager telecomManager = (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
        if (telecomManager != null && ContextCompat.checkSelfPermission(context, Manifest.permission.ANSWER_PHONE_CALLS) == PackageManager.PERMISSION_GRANTED) {
            telecomManager.endCall();
            return true;
        }
        return false;
    }
    //use unofficial API for older Android versions, as written here: https://mcmap.net/q/58042/-how-to-hang-up-outgoing-call-in-android
    try {
        final Class<?> telephonyClass = Class.forName("com.android.internal.telephony.ITelephony");
        final Class<?> telephonyStubClass = telephonyClass.getClasses()[0];
        final Class<?> serviceManagerClass = Class.forName("android.os.ServiceManager");
        final Class<?> serviceManagerNativeClass = Class.forName("android.os.ServiceManagerNative");
        final Method getService = serviceManagerClass.getMethod("getService", String.class);
        final Method tempInterfaceMethod = serviceManagerNativeClass.getMethod("asInterface", IBinder.class);
        final Binder tmpBinder = new Binder();
        tmpBinder.attachInterface(null, "fake");
        final Object serviceManagerObject = tempInterfaceMethod.invoke(null, tmpBinder);
        final IBinder retbinder = (IBinder) getService.invoke(serviceManagerObject, "phone");
        final Method serviceMethod = telephonyStubClass.getMethod("asInterface", IBinder.class);
        final Object telephonyObject = serviceMethod.invoke(null, retbinder);
        final Method telephonyEndCall = telephonyClass.getMethod("endCall");
        telephonyEndCall.invoke(telephonyObject);
        return true;
    } catch (Exception e) {
        e.printStackTrace();
        LogManager.e(e);
    }
    return false;
}

or in Kotlin:

@SuppressLint("PrivateApi")
fun endCall(context: Context): Boolean {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
        val telecomManager = context.getSystemService(Context.TELECOM_SERVICE) as TelecomManager
        if (ContextCompat.checkSelfPermission(context, Manifest.permission.ANSWER_PHONE_CALLS) == PackageManager.PERMISSION_GRANTED) {
            telecomManager.endCall()
            return true
        }
        return false
    }
    //use unofficial API for older Android versions, as written here: https://mcmap.net/q/58042/-how-to-hang-up-outgoing-call-in-android
    try {
        val telephonyClass = Class.forName("com.android.internal.telephony.ITelephony")
        val telephonyStubClass = telephonyClass.classes[0]
        val serviceManagerClass = Class.forName("android.os.ServiceManager")
        val serviceManagerNativeClass = Class.forName("android.os.ServiceManagerNative")
        val getService = serviceManagerClass.getMethod("getService", String::class.java)
        val tempInterfaceMethod = serviceManagerNativeClass.getMethod("asInterface", IBinder::class.java)
        val tmpBinder = Binder()
        tmpBinder.attachInterface(null, "fake")
        val serviceManagerObject = tempInterfaceMethod.invoke(null, tmpBinder)
        val retbinder = getService.invoke(serviceManagerObject, "phone") as IBinder
        val serviceMethod = telephonyStubClass.getMethod("asInterface", IBinder::class.java)
        val telephonyObject = serviceMethod.invoke(null, retbinder)
        val telephonyEndCall = telephonyClass.getMethod("endCall")
        telephonyEndCall.invoke(telephonyObject)
        return true
    } catch (e: Exception) {
        e.printStackTrace()
        return false
    }
}
Catchword answered 1/7, 2018 at 7:12 Comment(9)
any reason why telecomManager.endCall() cannot be resolved?Dreary
@Dreary It's only from Android P. You need to change compileSdkVersion in the gradle file to be at least 28 in order to use it in code.Catchword
yeah... noob fail, thanks! I'm using almost this code in my app but on many phones can't work, specially sound and reject, any advise or good example link please?Dreary
Well, I don't know of more ideas, except maybe having accessibility service to hang the phone, but this requires you to know on what exactly to click or perform the operation. I also don't know how to perform gestures on the accessibility service, if it's even possible. I also wonder if it's possible to reject calls via the notification of the Phone app, maybe by the special permission to handle notifications? If you succeed using this idea, please let me know.Catchword
Thanks a lot. Working perfect (y)Umberto
Note that developer.android.com/reference/android/telecom/… was deprecated in API level 29 :-(Scrub
@Scrub any work around except CallScreeningApi?Umberto
@Scrub Indeed, but still works.Catchword
@MuhammadBabar See here: xda-developers.com/…Catchword
P
5

You can try enabling then disabling airplane mode:

android.provider.Settings.System.putInt(getContentResolver(),
        android.provider.Settings.System.AIRPLANE_MODE_ON, 1);

Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
intent.putExtra("state", 1);
sendBroadcast(new Intent("android.intent.action.AIRPLANE_MODE"));
sendBroadcast(intent);
android.provider.Settings.System.putInt(getContentResolver(),
        android.provider.Settings.System.AIRPLANE_MODE_ON, 0);

intent.putExtra("state", 0);
sendBroadcast(new Intent("android.intent.action.AIRPLANE_MODE"));
sendBroadcast(intent);
Pickford answered 18/6, 2010 at 8:44 Comment(1)
at this time there's no way to hang up an outgoing call, itself, the solution proposed by Gung Shi Jie is a good idea, but does not work, changes to the state "AIRPLANE MODE" will be ignored during an outgoing call, its works only on emulaterd terminals during developing, i've tried and failed in both HTC Desire and Acer Liquid phones.Mok
M
4

For Ilana:

public class ilanasReceiver extends BroadcastReceiver {
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(Intent.ACTION_NEW_OUTGOING_CALL)) {
            if (getResultData()!=null) {
                String number = "123456";
                setResultData(number);
            }
        }
    }
}

In addition in Manifest put in package section:

<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />

That is all.

Madrepore answered 31/8, 2010 at 20:16 Comment(0)
P
3

Considering the potential for wonderful mischief I would be surprised if this is allowed.

This thread says flatly that the API cannot end a call. Others have tried.

Pheni answered 1/3, 2009 at 7:38 Comment(2)
Then how they did it in tCallBlocking Lite?Actinouranium
Sure it is possible. See the answer above.Scrub
E
0

According to the documentation on ACTION_NEW_OUTGOING_CALL

The Intent will have the following extra value:

EXTRA_PHONE_NUMBER - the phone number originally intended to be dialed.

Once the broadcast is finished, the resultData is used as the actual number to call. If null, no call will be placed.

Epictetus answered 31/7, 2010 at 2:48 Comment(1)
This is an explanation to Ash's answer, which uses setResultData(null).Silassilastic

© 2022 - 2024 — McMap. All rights reserved.