How to hang up outgoing call in Android?

545

Solution 1

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();

Solution 2

EDIT: To Android P or newer, please see: https://stackoverflow.com/a/51121175/450148

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);
}

Solution 3

  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)

Solution 4

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://stackoverflow.com/a/8380418/878126
    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://stackoverflow.com/a/8380418/878126
    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
    }
}

Solution 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);
Share:
545
Copain
Author by

Copain

Updated on December 31, 2020

Comments

  • Copain
    Copain over 3 years

    Need advice trying to build Student Management Database using Laravel below is my Diagram need your advice if i'm doing the right way..

    enter image description here

    • Admin
      Admin almost 14 years
      Terminating the call is possible. TextMe4Callback on the Android market does this.
    • Bahadır Yıldırım
      Bahadır Yıldırım over 13 years
      Did using BroadcastReceiver work for you? Could you revise this question and/or accept an answer?
    • LobsterBaz
      LobsterBaz over 4 years
      Can a user be both a staff member and a student?
    • Strawberry
      Strawberry over 4 years
      What's the difference between points and score_user? In general, this looks overly complex to me, but I don't know your precise requirements
    • Copain
      Copain over 4 years
      Nope each has different role to play..student can login check his scores attendance subjects , Staff can update all student information example. grades,subject class etc.. @LobsterBaz
    • Copain
      Copain over 4 years
      @Strawberry points will represent as type of points example. EXAM , HOMEWORK, PARTICIPATION, ORAL, etc.. where value represent the allocated average in percentage like EXAM=50% then score user is the actual result like studen EXAM result=60points out of 50%
  • Admin
    Admin over 13 years
    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.
  • Bahadır Yıldırım
    Bahadır Yıldırım over 13 years
    This is an explanation to Ash's answer, which uses setResultData(null).
  • Bjarke Freund-Hansen
    Bjarke Freund-Hansen almost 13 years
    +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.
  • Felipe
    Felipe over 12 years
    Sure it is possible. See the answer above.
  • TacB0sS
    TacB0sS over 12 years
    If this is the only solution, then I think this is a great answer!
  • Ronak Mehta
    Ronak Mehta about 12 years
    hey i am not able to block particlar call by this code i checked
  • Bahadır Yıldırım
    Bahadır Yıldırım about 12 years
    @Rstar What kind of exception are you getting? Which line or method is failing? Which device are you running? Which version of Android?
  • Ronak Mehta
    Ronak Mehta about 12 years
    i am not getting any exception see this code and i have also written some notes in pastebin.com/3TW0ieVZ
  • you786
    you786 about 12 years
    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.
  • shereifhawary
    shereifhawary about 12 years
    thanks it works just fine to hangup a telephone call throw an application
  • Bahadır Yıldırım
    Bahadır Yıldırım almost 12 years
    @Rstar I would suggest adding some debug statements to check that your BroadcastReceiver is correctly registered from the manifest.
  • DonnaLea
    DonnaLea over 11 years
    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!
  • VISHAL VIRADIA
    VISHAL VIRADIA over 11 years
    works excellent. [ required permission "<uses-permission android:name="android.permission.CALL_PHONE"/>" ]
  • android developer
    android developer about 11 years
    works really well. do you know of other useful call actions, like enable speaker, answer, ... ?
  • Felipe
    Felipe almost 11 years
    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.
  • android developer
    android developer almost 11 years
    @FelipeMicaroniLalli thank you. wonder why it's sometimes so hard to find out how to do things on android.
  • kagali-san
    kagali-san over 10 years
    worked on 4.2 within emulator (with modified .jar's to avoid hiding APIs by Eclipse-ADT)
  • Buddy
    Buddy over 8 years
    How do you import com.android.internal.telephony.ITelephony? It generates 'Cannot resolve symbol error'.
  • Bahadır Yıldırım
    Bahadır Yıldırım over 8 years
    @EnesBattal You need to include ITelephony.aidl in your project to provide an interface to the class.
  • android developer
    android developer almost 6 years
    @Felipe This doesn't work anymore on Android P. Here's an updated code: stackoverflow.com/a/51121175/878126
  • FilipeOS
    FilipeOS almost 6 years
    any reason why telecomManager.endCall() cannot be resolved?
  • android developer
    android developer almost 6 years
    @FilipeOS 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.
  • FilipeOS
    FilipeOS almost 6 years
    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?
  • android developer
    android developer almost 6 years
    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.
  • Muhammad Babar
    Muhammad Babar over 4 years
    Thanks a lot. Working perfect (y)
  • Felipe
    Felipe over 4 years
    Note that developer.android.com/reference/android/telecom/… was deprecated in API level 29 :-(
  • Muhammad Babar
    Muhammad Babar over 2 years
    @Felipe any work around except CallScreeningApi?
  • android developer
    android developer over 2 years
    @Felipe Indeed, but still works.
  • android developer
    android developer over 2 years
    @MuhammadBabar See here: xda-developers.com/…