Reputation: 1860
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?
Upvotes: 37
Views: 53217
Reputation: 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();
Upvotes: -1
Reputation: 659
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;
}
Upvotes: 2
Reputation: 1261
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)
Upvotes: 0
Reputation: 31
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.
Upvotes: 3
Reputation: 2793
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).
Upvotes: 23
Reputation: 8597
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 :/
Upvotes: 51
Reputation: 1
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;
}
Upvotes: 0
Reputation: 33
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.
Upvotes: 1
Reputation: 51
SilenceRinger()
does not work for android 2.3+ versions. Just comment it, other code will work fine.
Hope this works for you!
Upvotes: 1