11

Up to Android 2.2 I know I can use reflection and terminate the call through getITelephony.

However, as of 2.3 this no longer works because even if you grant the MODIFY_PHONE_STATE permission to your app, it's now a system app only permission: https://stackoverflow.com/a/5095956/821423

That said, it's possible still because a myriad of applications on the google play market are doing it just fine on ICS, for example, this one:

https://play.google.com/store/apps/details?id=com.androminigsm.fscifree&hl=en

So the question is, how do they do it? I know I can pick up the call using simulating a headset hook, but I can't figure out how to end the call.

Thank you.

Community
  • 1
  • 1
Stephan Tual
  • 2,617
  • 3
  • 27
  • 49

3 Answers3

16

Well after much soul-searching I realize something really, really, really dumb. On the plus side no one on StackOverflow seems to have noticed it either. MODIFY_PHONE_STATE is no longer working on silenceRinger() since 2.3+, but endCall is just fine.

So the solution is to comment out the call to silenceRinger().

Can't believe I've just spent a week on this! I'll try to update the other questions as there seem to be tons of dupe on SO along the lines of 'it's not possible to use reflection to terminate the calls anymore'.

Stephan Tual
  • 2,617
  • 3
  • 27
  • 49
  • You mean, we can stil use the ITelephony.aidl technique to accept and reject calls programatically but it only doesn't work for silenceRinger ? Then the only solution remains is to comment the silenceRinger in the aidl file ? Pls suggest, as your discovery on this would allow me to utilise this technique in designing a new app. – omkar.ghaisas Apr 17 '12 at 12:54
  • On 2.3.6, endCall() through iTelephony does just that. It's indeed silenceRinger() that triggers the permission issue. You can just comment silenceRinger() in your actual code, leave the AIDL as such. I haven't tested this on 1.5 to 2.2, am about to do so soon though. Will let you know on this page. – Stephan Tual Apr 17 '12 at 13:32
  • Wow... I was actually had endCall() in my code, but it wasn't getting hit because of some if-statements. I just assumed it wasn't working because the API was disabled. I'm tempted to flag your answer for deletion so Google doesn't fix this issue! :) +1 – you786 Jul 26 '12 at 16:08
  • Will endCall() cause the ringer to become silent? I would think it would as well... – hsanders Oct 25 '12 at 17:36
  • @ stephan Tual Can you upload your whole code or post a link of you downloadable project – Pro_Zeck May 26 '13 at 01:30
  • Hi @Pro_Zeck, unfortunately I'm not in a position to do this as I've moved on to pastures new. If one day I get back to android programming I'll push something on Git as-is. Sorry! – Stephan Tual Jun 01 '13 at 13:47
3

The call() , endcall() functions work fine for me as well. But there is also another way tha works without using iTelephony.aidl. Its published in this post. BTW I think google already knows but for some reason they havent done anything with the rest of functions, wich is good!!!

http://androidbridge.blogspot.com/2011/05/how-to-answer-incoming-call-in-android.html

Byron
  • 31
  • 2
1

private void endCall(final String cutofftime) {

TelephonyManager telephony = (TelephonyManager) srvs
            .getSystemService(Context.TELEPHONY_SERVICE);
    Class c;
    final com.android.internal.telephony.ITelephony telephonyService;
    try {
        c = Class.forName("android.telephony.TelephonyManager");//telephony.getClass().getName());
        Log.i("TelephonyClass Name", telephony.getClass().getName());
        Method m = c.getDeclaredMethod("getITelephony");
        m.setAccessible(true);
        telephonyService = (ITelephony) m.invoke(telephony);
        TimerTask task = new TimerTask() {

            @Override
            public void run() {
                try {
                    if (telephonyService.isIdle()
                            || telephonyService.isOffhook()
                            || telephonyService.isRinging())
                        telephonyService.endCall();
                } catch (RemoteException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        };
        long delay = Integer.parseInt(cutofftime) * 1000;
        new Timer().schedule(task, delay);
    } catch (ClassNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (SecurityException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (NoSuchMethodException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IllegalArgumentException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

}
dastan
  • 892
  • 10
  • 17