【问题标题】:Programmatically disconnect call in android Marshmallow version在 android Marshmallow 版本中以编程方式断开呼叫
【发布时间】:2018-05-17 20:26:28
【问题描述】:

我需要通过高版本android中的代码断开呼叫。

根据文档,我们无权这样做,因为它是私有的。

在搜索 SO 时,我发现了不同的解决方案,直到棒棒糖为止。

内联是我迄今为止尝试过的方法。

方法一:

public void disconnectCall(String type){
        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);

            // Reject call and send SMS
            if (type.equalsIgnoreCase("reject")) {
                SmsManager smsManager = SmsManager.getDefault();
                smsManager.sendTextMessage(_incomingNumber, null, "Hey! I am driving right now. Please call me back after some time", null, null);
                Toast.makeText(context, "CALL REJECTED", Toast.LENGTH_SHORT).show();
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

方法二:

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
            return false;
        }
        return true;
    }

方法三:

public void endCall(Context context) {
        TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        try {
            Class c = Class.forName(tm.getClass().getName());
            Method m = c.getDeclaredMethod("getITelephony");
            m.setAccessible(true);
            Object telephonyService = m.invoke(tm);

            c = Class.forName(telephonyService.getClass().getName());
            m = c.getDeclaredMethod("endCall");
            m.setAccessible(true);
            m.invoke(telephonyService);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

【问题讨论】:

    标签: android android-6.0-marshmallow


    【解决方案1】:

    上面提到的方法一正在工作..我只是为 M+ 版本的 android 添加了 CALL_PHONE 的运行时权限。

    关注内联提及:

    在 Android Manifest 文件中定义权限。

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

    现在获取安卓M+版本的运行时权限。

    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
            {
    
                if (ContextCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED)
                {
                    ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CALL_PHONE}, PERMISSION_ACCESS_CALL_PHONE);
                }
                else
                {
                    // Proceed as we already have permission.
                }
            }
            else
            {
                // Proceed as we need not get the permission
            }
    
    
    @Override
        public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
            switch (requestCode) {
                case PERMISSION_ACCESS_CALL_PHONE:
                    if (grantResults.length > 0 && grantResults[0] PackageManager.PERMISSION_GRANTED) {
                        // All good!
    
                        //Toast.makeText(context, "All Good", Toast.LENGTH_SHORT).show();
                    } else {
                        finish();
                        //Toast.makeText(this, "Need call phone permission", Toast.LENGTH_SHORT).show();
                    }
    
                    break;
            }
        }
    

    现在使用内联方法以编程方式断开呼叫。

    private void declinePhone(Context context) throws Exception {
    
            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("unable", "msg cant dissconect call....");
    
            }
    

    就是这样!你可以走了。

    干杯!

    【讨论】:

    • @ErichGarcía 嘿!我应该在哪里添加这个dellPhone(上下文上下文)?
    • 在您的广播接收器中使用它,执行一些自定义操作,例如将数字保存在数据库中,或其他操作,然后再调用它。
    • 谢谢!!!是我发现的唯一没有冻结整个应用程序的答案!顺便说一句,在 Lollipop 上也可以使用,但我不确定该应用程序是否需要成为系统应用程序(我的应用程序是并且也具有 root 权限)。但它的工作原理!
    猜你喜欢
    • 2013-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-05
    • 2019-02-03
    • 1970-01-01
    相关资源
    最近更新 更多