37

I see a lot of questions that it's impossible to end call programmatically in Android. At the same time, I see a lot of dialer apps in googleplay market where you can activate the call and drop it also. How do they work?

Edit: I've read somewhere that my app has to be system app. Then how to make it system, and what is the difference between system and user apps?

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
Midnight Guest
  • 1,863
  • 3
  • 16
  • 26
  • 3
    As for me there is better [solutuion][1] to achive that. [1]: http://stackoverflow.com/questions/18977012/why-itelephony-aidl-works?lq=1 – bgplaya Mar 11 '14 at 11:55
  • See http://android.stackexchange.com/q/27/440 for instructions about how to make an app a system app. – Flow Aug 28 '14 at 10:06
  • 1
    check this answer https://stackoverflow.com/questions/47731725/how-to-end-an-incoming-call-programmatically-on-android-8-0-oreo/57356900#57356900 – Gaurav Agrawal Aug 05 '19 at 12:26

9 Answers9

51

You do not need to be a system app. First, create package com.android.internal.telephony in your project, and put this in a file called "ITelephony.aidl":

package com.android.internal.telephony; 

interface ITelephony {      

boolean endCall();     

void answerRingingCall();      

void silenceRinger(); 

}

Once you have that, you can use this code to end a call:

TelephonyManager telephonyManager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
Class clazz = Class.forName(telephonyManager.getClass().getName());
Method method = clazz.getDeclaredMethod("getITelephony");
method.setAccessible(true);
ITelephony telephonyService = (ITelephony) method.invoke(telephonyManager);
telephonyService.endCall();

You could use this inside a PhoneStateListener, for example. For this to work, you require permissions in manifest:

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

Edit: Apologies for horrible formatting, I still can't figure out how to properly do code blocks here :/

bgse
  • 8,237
  • 2
  • 37
  • 39
  • cannot be used and without the above permission you cannot access TelephonyManager in runtime. – VenomVendor Sep 14 '13 at 18:30
  • 1
    @VenomVendor I recall getting a warning along the lines of "not granting permission MODIFY_PHONE_STATE" in logcat while debugging, however it does not seem to be a problem, as the above code does work as expected on a variety of devices. Maybe the permission is not actually necessary? – bgse Sep 15 '13 at 11:10
  • @bgse : I am getting it as Error rather than warning.Is that because of minSdkVersion? i set it to 5.I am unable to add that permission in my application – Mahantesh M Ambi Feb 22 '14 at 05:37
  • 1
    @MAHANTESH This specific project was built with minSdkVersion="8" and targetSdkVersion="15". I just rechecked to confirm, it does compile and deploy without any issues. When the app is executed, it does produce a warning "Not granting permission MODIFY_PHONE_STATE" in logcat. That does not seem to affect functionality in any way though, so I guess that permission is not really required. Do you get the error at compile time, or at runtime? – bgse Feb 25 '14 at 22:34
  • @bgse: yeah i am getting a compile time error with minSdkVersion="8". even if it compiles then it should reject the call right?!?! if it is not granting permission then what is the use of having it?Basically i need to reject the call programatically. – Mahantesh M Ambi Mar 12 '14 at 16:47
  • 3
    This only works if minSdkVersion is 14 or less. If you set minSdkVersion to 15 or above, it stops working. – Bjarte Aune Olsen Nov 09 '15 at 18:07
  • Can someone please explain this code? I cannot understand how its working – Wijay Sharma Dec 06 '17 at 18:38
  • 3
    @WijaySharma This code used to work back in 2013, what it basically does is using [reflection](https://stackoverflow.com/questions/37628/what-is-reflection-and-why-is-it-useful) to gain access to internal functionality of android telephony, which was not exposed publicly otherwise. A lot of the internals have changed since 2013, so this almost guaranteed does not work anymore (at least most likely not in the exact way shown here), from the top of my head I think Android 4.0.3 was still working, not sure about later versions. – bgse Dec 06 '17 at 21:02
  • you say create package `com.internal.android.telephony` but then you use different package (android <> internal) `package com.android.internal.telephony;` ?? – user924 Apr 05 '18 at 19:14
  • @user924 It should be `com.android.internal.telephony`, thanks for pointing that out. Keep in mind that the approach shown in this post is mostly interesting for historical purposes and to get a rough idea, it is almost 5 years out of date and a lot of android internals changed since then. – bgse Apr 06 '18 at 07:12
  • @bgse I found other methods which works even for >= Marshmallow:) – user924 Apr 06 '18 at 07:15
  • @user924 Might not hurt to post your solution as an answer here in that case :-) – bgse Apr 06 '18 at 07:17
  • @user924 can you please share your solution that can work on oreo,Thanks – Ali Akram May 08 '18 at 06:03
  • On a Nexus 5x with Android 8.1 and Security Patch form August I am experiencing that the app freezes completely when calling telephonyService.endCall(); This still worked a few weeks august, and it stil works on other devices with Android 8.0, I suppose the security patch changed this (still investigating). – David Aug 24 '18 at 09:41
  • @David What is the update from your investigation ? – Pankaj Feb 14 '20 at 07:58
  • @Pankaj none, I moved on. – David Feb 14 '20 at 10:59
  • Perhaps this might be of help for people around ;-) : https://github.com/anggrayudi/android-hidden-api – Edw590 Sep 30 '20 at 02:04
22

For Android P (since Beta 2) and above, there is finally a formal API for endCall:

https://developer.android.com/reference/android/telecom/TelecomManager#endCall()

The ANSWER_PHONE_CALLS permission is required in manifest:

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

With the permission, for API level 28 or above:

TelecomManager tm = (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);

if (tm != null) {
    boolean success = tm.endCall();
    // success == true if call was terminated.
}

At the same time the original endCall() method under TelephonyManager is now protected by MODIFY_PHONE_STATE permission, and can no longer be invoked by non-system Apps by reflection without the permission (otherwise a Security Exception will be triggered).

headuck
  • 2,763
  • 16
  • 19
3

For Information.

May be of use in some situations. There is a potential workaround using the InCallService class. Most of the required information is here.https://developer.android.com/reference/android/telecom/InCallService.html#onCallRemoved(android.telecom.Call)

It does require setting your app as the default phone app and ensuring the following is granted.

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

If you implement your own class extending InCallService then when a call starts the call binds to your app and you get the call information through the onCallAdded() function. You can then simply call.disconnect() and the call will end.

etarhan
  • 4,138
  • 2
  • 15
  • 29
SLock
  • 31
  • 1
  • 1
    Important: To use ICallService, you need to set your App as Default Phone App from Settings. Which means, now other apps wont get control when you have incoming call and you have to handle all calling functionalities in your app – Pankaj Feb 14 '20 at 08:16
  • I was looking for different solutions but nothing worked and found this. So simple and so useful. Thanks – Saify Dec 07 '21 at 07:57
2

Cut Call for the Api 28+

private void cutCall(){
    ActivityCompat.requestPermissions(this, new String[] { Manifest.permission.READ_PHONE_STATE }, PHONE_STATE);
}

}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        if (requestCode == PHONE_STATE) {
            ActivityCompat.requestPermissions(this, new String[] { Manifest.permission.ANSWER_PHONE_CALLS }, ANSWER_CALLS);
        } else if (requestCode == ANSWER_CALLS) {
            cutTheCall;
        }
    }
}

//This code will work on Android N (Api 28 and Above)

private boolean cutTheCall() {
    TelecomManager telecomManager = (TelecomManager) getApplicationContext().getSystemService(TELECOM_SERVICE);
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED || telecomManager == null) {
        return false;
    }

    if (telecomManager.isInCall()) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            callDisconnected = telecomManager.endCall();
        }
    }
    return true;
}
1

SilenceRinger() does not work for android 2.3+ versions. Just comment it, other code will work fine. Hope this works for you!

1

Along with Adding android telephony interface and a broadcast receiver, you will also need to add android manifest receiver entry with the action android.intent.action.PHONE_STATE for the reciever you want to handle intent.

You will get compile time error if you add

uses-permission android:name="android.permission.MODIFY_PHONE_STATE`

in your manifest file. But even if we remove this, it automatically rejects the incoming calls.

Eugen Pechanec
  • 37,669
  • 7
  • 103
  • 124
0
public static boolean isCallActive(Context context){
    AudioManager manager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
    if(manager.getMode()==AudioManager.MODE_IN_CALL || manager.getMode()==AudioManager.MODE_IN_COMMUNICATION){
        return true;
    }

    return false;
}
slfan
  • 8,950
  • 115
  • 65
  • 78
0

Just to add to @headuck's answer. For API 28, you also need to add:

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

then request the permission in your activity. In total I requested these permissions to make it work (READ_PHONE_STATE, CALL_PHONE, ANSWER_PHONE_CALLS, READ_CONTACTS, READ_CALL_LOG)

dongkichan
  • 1,071
  • 6
  • 4
-1

You can end calls using Telecom manager. I tested it and it worked. You need permission ANSWER_PHONE_CALLS to do so. Even though it hints to answered calls I had it ending a call made from this phone. And this works for modern Androids.

   TelecomManager telecomManager = (TelecomManager) getSystemService(Context.TELECOM_SERVICE);

telecomManager.endCall();