-2

I am trying to end the call the user dialed. Basically I would allow some number that user would be able to dial and call, else all other call would be end up and User would not be able to call other then those numbers.

Now the problem is I have tried several ways to do so , but its not working

What I am Doing:

I have a broadcast receiver Which got fired when User call the Number

Under It I gets the dialed number , if it is not my desired number I try to end it.

Here is what I am doing in my on Receive method.

     public void onReceive(Context context, Intent intent) {
        Log.d(OutgoingCallReceiver.class.getSimpleName(), intent.toString());

        //TODO: Handle outgoing call event here
        String phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
            disconnectCall();
            Toast.makeText(context, "DisConnecting! = "+phoneNumber, Toast.LENGTH_LONG).show();
            killCall(context);
            TelephonyManager tm=(TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);

            Method m1 = null;
            try {
                m1 = tm.getClass().getDeclaredMethod("getITelephony");
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }
            m1.setAccessible(true);
            Object iTelephony = null;
            try {
                iTelephony = m1.invoke(tm);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }

            Method m2 = null;
            try {
                m2 = iTelephony.getClass().getDeclaredMethod("silenceRinger");
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }
            Method m3 = null;
            try {
                m3 = iTelephony.getClass().getDeclaredMethod("endCall");
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }

//            try {
//               // m2.invoke(iTelephony);
//            } catch (IllegalAccessException e) {
//                e.printStackTrace();
//            } catch (InvocationTargetException e) {
//                e.printStackTrace();
//            }
            try {
                m3.invoke(iTelephony);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }



            TelephonyManager telephony = (TelephonyManager)
                    context.getSystemService(Context.TELEPHONY_SERVICE);
            try {
                Class c = Class.forName(telephony.getClass().getName());
                Method m = c.getDeclaredMethod("getITelephony");
                m.setAccessible(true);
                telephonyService = (ITelephony) m.invoke(telephony);
                //telephonyService.silenceRinger();
                telephonyService.endCall();
            } catch (Exception e) {
                e.printStackTrace();
            }

      //  }

    }

and Endig Call method as well

public void disconnectCall(){
    try {

        String serviceManagerName = "android.os.ServiceManager";
        String serviceManagerNativeName = "android.os.ServiceManagerNative";
        String telephonyName = "com.android.internal.telephony.ITelephony";
        Class<?> telephonyClass;
        Class<?> telephonyStubClass;
        Class<?> serviceManagerClass;
        Class<?> serviceManagerNativeClass;
        Method telephonyEndCall;
        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);
        telephonyEndCall = telephonyClass.getMethod("endCall");
        telephonyEndCall.invoke(telephonyObject);

    } catch (Exception e) {
        e.printStackTrace();
        Log.d("Receiver",
                "FATAL ERROR: could not connect to telephony subsystem");
        Log.d("Receiver", "Exception object: " + e);
    }
}



public boolean killCall(Context context) {
    try {
        // Get the boring old TelephonyManager
        TelephonyManager telephonyManager =
                (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);

        // Get the getITelephony() method
        Class classTelephony = Class.forName(telephonyManager.getClass().getName());
        Method methodGetITelephony = classTelephony.getDeclaredMethod("getITelephony");

        // Ignore that the method is supposed to be private
        methodGetITelephony.setAccessible(true);

        // Invoke getITelephony() to get the ITelephony interface
        Object telephonyInterface = methodGetITelephony.invoke(telephonyManager);

        // Get the endCall method from ITelephony
        Class telephonyInterfaceClass =
                Class.forName(telephonyInterface.getClass().getName());
        Method methodEndCall = telephonyInterfaceClass.getDeclaredMethod("endCall");

        // Invoke endCall()
        methodEndCall.invoke(telephonyInterface);

    } catch (Exception ex) { // Many things can go wrong with reflection calls
        Log.d("Receiver","PhoneStateReceiver **" + ex.toString());
        return false;
    }
    return true;
}

As We can see I am using 4 different types of ways I found on internet to end the call , but its not working. At the moment I am trying this code on jelly beans. But its not working. Please help me if any one has I dea how to end the call and what is a proper way please help.

Allay Khalil
  • 674
  • 3
  • 11
  • 31

1 Answers1

2

Code to kill call

 public boolean killCall(Context context) {
        try {
            // Get the boring old TelephonyManager
            TelephonyManager telephonyManager =
                    (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);

            // Get the getITelephony() method
            Class classTelephony = Class.forName(telephonyManager.getClass().getName());
            Method methodGetITelephony = classTelephony.getDeclaredMethod("getITelephony");

            // Ignore that the method is supposed to be private
            methodGetITelephony.setAccessible(true);

            // Invoke getITelephony() to get the ITelephony interface
            Object telephonyInterface = methodGetITelephony.invoke(telephonyManager);

            // Get the endCall method from ITelephony
            Class telephonyInterfaceClass =
                    Class.forName(telephonyInterface.getClass().getName());
            Method methodEndCall = telephonyInterfaceClass.getDeclaredMethod("endCall");

            // Invoke endCall()
            methodEndCall.invoke(telephonyInterface);

        } catch (Exception ex) { // Many things can go wrong with reflection calls
            LogUtil.warn(TAG, "PhoneStateReceiver **" + ex.toString());
            return false;
        }
        return true;

    }

Code for different states

public abstract class PhoneCallReceiver extends BroadcastReceiver {

    private static final String TAG = "PhoneCallReceiver";

    //The receiver will be recreated whenever android feels like it.  We need a static variable to remember data between instantiations

    private static int lastState = TelephonyManager.CALL_STATE_IDLE;
    private static Date callStartTime;
    private static boolean isIncoming;
    private static String savedNumber;  //because the passed incoming is only valid in ringing


    @Override
    public void onReceive(Context context, Intent intent) {

        //We listen to two intents.  The new outgoing call only tells us of an outgoing call.  We use it to get the number.
        if (intent.getAction().equals("android.intent.action.NEW_OUTGOING_CALL")) {
            savedNumber = intent.getExtras().getString("android.intent.extra.PHONE_NUMBER");
        } else {
            String stateStr = intent.getExtras().getString(TelephonyManager.EXTRA_STATE);
            String number = intent.getExtras().getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
            int state = 0;
            if (stateStr.equals(TelephonyManager.EXTRA_STATE_IDLE)) {
                state = TelephonyManager.CALL_STATE_IDLE;
            } else if (stateStr.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) {
                state = TelephonyManager.CALL_STATE_OFFHOOK;
            } else if (stateStr.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
                state = TelephonyManager.CALL_STATE_RINGING;
            }


            onCallStateChanged(context, state, number);
            // Added this line to remove broadcast from caller application
//            abortBroadcast();
            TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
            telephonyManager.listen(new PhoneStateListener(context), PhoneStateListener.LISTEN_CALL_STATE);

        }
    }

    //Derived classes should override these to respond to specific events of interest
    protected void onIncomingCallStarted(Context ctx, String number, Date start) {
    }

    protected void onOutgoingCallStarted(Context ctx, String number, Date start) {
    }

    protected void onIncomingCallEnded(Context ctx, String number, Date start, Date end) {
    }

    protected void onOutgoingCallEnded(Context ctx, String number, Date start, Date end) {
    }

    protected void onMissedCall(Context ctx, String number, Date start) {
    }

    //Deals with actual events

    //Incoming call-  goes from IDLE to RINGING when it rings, to OFFHOOK when it's answered, to IDLE when its hung up
    //Outgoing call-  goes from IDLE to OFFHOOK when it dials out, to IDLE when hung up
    public void onCallStateChanged(Context context, int state, String number) {
        if (lastState == state) {
            //No change, debounce extras
            return;
        }
        switch (state) {
            case TelephonyManager.CALL_STATE_RINGING:
                isIncoming = true;
                callStartTime = new Date();
                savedNumber = number;
                onIncomingCallStarted(context, number, callStartTime);
                break;
            case TelephonyManager.CALL_STATE_OFFHOOK:
                //Transition of ringing->offhook are pickups of incoming calls.  Nothing done on them
                if (lastState != TelephonyManager.CALL_STATE_RINGING) {
                    isIncoming = false;
                    callStartTime = new Date();
                    onOutgoingCallStarted(context, savedNumber, callStartTime);
                }
                break;
            case TelephonyManager.CALL_STATE_IDLE:
                //Went to idle-  this is the end of a call.  What type depends on previous state(s)
                if (lastState == TelephonyManager.CALL_STATE_RINGING) {
                    //Ring but no pickup-  a miss
                    onMissedCall(context, savedNumber, callStartTime);
                } else if (isIncoming) {
                    onIncomingCallEnded(context, savedNumber, callStartTime, new Date());
                } else {
                    onOutgoingCallEnded(context, savedNumber, callStartTime, new Date());
                }
                break;
        }
        lastState = state;
    }

    class PhoneStateListener extends PhoneStateListener {

        //private static final String TAG = "PhoneStateChanged";
        Context context; //Context to make Toast if required

        public PhoneStateListener(Context context) {
            super();
            this.context = context;
        }

        @Override
        public void onCallStateChanged(int state, String incomingNumber) {
            super.onCallStateChanged(state, incomingNumber);

            switch (state) {
                case TelephonyManager.DATA_CONNECTED:
                    LogUtil.debug(TAG, "Data connected send broadcast");
                    Intent dataConnectedIntent = new Intent(PhoneCallTimerService.DATA_CONNECTED);
                    context.sendBroadcast(dataConnectedIntent);
                    break;
                case TelephonyManager.DATA_DISCONNECTED:
                    LogUtil.debug(TAG, "Data disconnected send broadcast");
                    Intent dataDisConnectedIntent = new Intent(PhoneCallOutgoingService.DATA_DISCONNECTED);
                    context.sendBroadcast(dataDisConnectedIntent);
                    break;
                default:
                    break;
            }
        }
    }
}

public class CallReceiver extends PhoneCallReceiver {

    private static final String TAG = "CallReceiver";


    @Override
    protected void onIncomingCallStarted(Context ctx, String number, Date start) {
    }

    @Override
    protected void onOutgoingCallStarted(final Context ctx, final String number, Date start) {
        LogUtil.debug(TAG, "Outgoing call  started from  :: " + number);
        final String name = Utils.getContactName(ctx, number);
        Handler outgoingCallHandler = new Handler();
        outgoingCallHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                if (!Utils.isMyServiceRunning(PhoneCallOutgoingService.class, ctx) && !Utils.isMyServiceRunning(PhoneCallTimerService.class, ctx)) {
                    Intent outGoingCallService = new Intent(ctx, PhoneCallOutgoingService.class);
                    if (name != null && name.length() > 0) {
                        outGoingCallService.putExtra(CallReceiver.CALLER_NUMBER, name);
                    } else {
                        outGoingCallService.putExtra(CallReceiver.CALLER_NUMBER, number);
                    }
                    ctx.startService(outGoingCallService);
                } else {
                    LogUtil.error(TAG, "Outgoing call service already started");
                }
            }
        }, 2000);

    }

    @Override
    protected void onIncomingCallEnded(Context ctx, String number, Date start, Date end) {
        LogUtil.debug(TAG, "Incoming call  end from  :: " + number);
        Intent callTerminatedIntent = new Intent(ACTION_CALL_TERMINATED);
        ctx.sendBroadcast(callTerminatedIntent);

    }

    @Override
    protected void onOutgoingCallEnded(Context ctx, String number, Date start, Date end) {
        LogUtil.debug(TAG, "Outgoing call ended from  :: " + number);
        Intent dataDisConnectedIntent = new Intent(PhoneCallOutgoingService.DATA_DISCONNECTED);
        ctx.sendBroadcast(dataDisConnectedIntent);
    }

    @Override
    protected void onMissedCall(Context ctx, String number, Date start) {
        LogUtil.debug(TAG, "Missed call  from  :: " + number);
        Intent missedCallIntent = new Intent(ACTION_CALL_MISSED);
        ctx.sendBroadcast(missedCallIntent);
    }

Of-course there is some code which is not important for your app so please comment or delete just delete that line.

silentsudo
  • 6,730
  • 6
  • 39
  • 81