在Android中,我可以通过编程的方式挂断电话吗?

33

我希望能够阻止一些 crank call,因此我需要在 Android 上编程挂断一些电话。

以下片段来自如何在 Android 上挂断呼出电话?
这是不是意味着在以后的Android版本中,挂断电话的技术将随时被屏蔽?
这是不是意味着我无法编写一个应用程序来挂断电话?

迄今为止,我遇到的唯一挂断电话的方法是通过 Java 反射来完成。由于它不是公共 API 的一部分,您应该小心使用它,并且不要依赖它。对 Android 内部组成的任何更改都将有效地破坏您的应用程序。

5个回答

76

首先,您需要在AndroidManifest.xml中声明此权限。

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

然后,您可以通过将以下内容添加到AndroidManifest.xml来为android.intent.action.PHONE_STATE(呼入电话)和android.intent.action.NEW_OUTGOING_CALL(呼出电话)设置一个BroadcastReceiver服务。

AndroidManifest.xml

<receiver android:name=".PhoneStateReceiver">
    <intent-filter android:priority="0">
        <action android:name="android.intent.action.PHONE_STATE" />
        <action android:name="android.intent.action.NEW_OUTGOING_CALL" />
    </intent-filter>
</receiver>

PhoneStateReceiver.JAVA

import java.lang.reflect.Method;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.TelephonyManager;
import android.util.Log;

public class PhoneStateReceiver extends BroadcastReceiver {

    public static String TAG="PhoneStateReceiver";
    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals("android.intent.action.PHONE_STATE")) { 
            String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
            Log.d(TAG,"PhoneStateReceiver**Call State=" + state);

            if (state.equals(TelephonyManager.EXTRA_STATE_IDLE)) {
                Log.d(TAG,"PhoneStateReceiver**Idle");
            } else if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) { 
                // Incoming call
                String incomingNumber = 
                        intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
                Log.d(TAG,"PhoneStateReceiver**Incoming call " + incomingNumber);

                if (!killCall(context)) { // Using the method defined earlier
                    Log.d(TAG,"PhoneStateReceiver **Unable to kill incoming call");
                }

            } else if (state.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) {
                Log.d(TAG,"PhoneStateReceiver **Offhook");
            }
        } else if (intent.getAction().equals("android.intent.action.NEW_OUTGOING_CALL")) { 
            // Outgoing call
            String outgoingNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
            Log.d(TAG,"PhoneStateReceiver **Outgoing call " + outgoingNumber);

            setResultData(null); // Kills the outgoing call

        } else {
            Log.d(TAG,"PhoneStateReceiver **unexpected intent.action=" + intent.getAction());
        }
    }

    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(TAG,"PhoneStateReceiver **" + ex.toString());
            return false;
        }
        return true;
    }

}

你也可以使用来自https://android.googlesource.com/platform/frameworks/base/+blame/71c2c37554ae53dffdf8e210f484d92af30620fa/docs/html/preview/features/runtime-permissions.jd?pli=1#548的以下代码 —

MainActivity.JAVA

import android.Manifest; import android.content.pm.PackageManager;
import android.support.v4.app.ActivityCompat; import
android.support.v4.content.ContextCompat; import
android.support.v7.app.AppCompatActivity; import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

public static final int MY_PERMISSIONS_REQUEST_READ_PHONE_STATE = 101;
@Override protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    if (ContextCompat.checkSelfPermission(this,
            Manifest.permission.READ_PHONE_STATE)
            != PackageManager.PERMISSION_GRANTED) {

        // Should we show an explanation?
        if (ActivityCompat.shouldShowRequestPermissionRationale(this,
                Manifest.permission.READ_PHONE_STATE)) {

            // Show an explanation to the user *asynchronously* -- don't block
            // this thread waiting for the user's response! After the user
            // sees the explanation, try again to request the permission.

        } else {

            // No explanation needed, we can request the permission.

            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.READ_PHONE_STATE},
                    MY_PERMISSIONS_REQUEST_READ_PHONE_STATE);

            // MY_PERMISSIONS_REQUEST_READ_PHONE_STATE is an
            // app-defined int constant. The callback method gets the
            // result of the request.
        }
    } }

@Override public void onRequestPermissionsResult(int requestCode,
                                       String permissions[], int[] grantResults) {
    switch (requestCode) {
        case MY_PERMISSIONS_REQUEST_READ_PHONE_STATE: {
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                // permission was granted, yay!

            } else {

                // permission denied, boo! Disable the
                // functionality that depends on this permission.
            }
            return;
        }

        // other 'case' lines to check for other
        // permissions this app might request
    } } }

这个能解决你的问题吗?你试过将手机设置为阻止模式了吗? 链接http://www.techrepublic.com/article/get-the-most-out-of-samsungs-blocking-mode/#。或者直接通过编程设置。 - izbrannick
1
已在运行6.0.1的Nexus 6P上进行测试,killCall方法正常工作。 - pelotasplus
1
PhoneStateReceiver ** java.lang.reflect.InvocationTargetException - Zax
这个在Android 8上能用吗?java.lang.reflect.InvocationTargetException也出现了! - Karl-John Chow
TelecomManager tm = null; if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { tm = (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE); if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ANSWER_PHONE_CALLS) != PackageManager.PERMISSION_GRANTED) { Log.d(TAG, "权限被拒绝"); return false; } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { tm.endCall(); } } - Ankit Kumar
显示剩余12条评论

4

在Android API >= 26(ANDROID_O)更改后,其他答案不起作用。

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

那么。
requestPermissions(new String[] {
   Manifest.permission.ANSWER_PHONE_CALLS
 }, PERMISSION_RQUEST);

接着

TelecomManager mgr = (TelecomManager) getSystemService(TELECOM_SERVICE);
mgr.endCall();

3

这是否意味着在未来的Android版本中,挂断电话技术将被阻止?

有可能Android团队会为这项具体服务彻底改变一切。但我认为这种可能性非常小。

这是否意味着我不能编写一个挂断电话的应用程序?

如果提出的方法可行,为什么不呢?只要记住(在你的脑海中某个地方,是的 :)) 在遥远的未来,有些事情可能会变得复杂,你将不得不寻找另一种通过无锈API突破的肮脏技巧,以允许你挂断电话。


2

1
@dave 提供的链接完全正常。我自己已经试过了。那个例子可以阻止所有来电。 - Gautami

0

如果你正在进行JUnit测试,那么这就是方法;

mInstrumentation = InstrumentationRegistry.getInstrumentation();
mInstrumentation.getUiAutomation().executeShellCommand( "input keyevent " + KeyEvent.KEYCODE_ENDCALL );

它可能也可以在测试之外工作,但我还没有尝试过。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接