我希望能够阻止一些 crank call,因此我需要在 Android 上编程挂断一些电话。
以下片段来自如何在 Android 上挂断呼出电话?
这是不是意味着在以后的Android版本中,挂断电话的技术将随时被屏蔽?
这是不是意味着我无法编写一个应用程序来挂断电话?
迄今为止,我遇到的唯一挂断电话的方法是通过 Java 反射来完成。由于它不是公共 API 的一部分,您应该小心使用它,并且不要依赖它。对 Android 内部组成的任何更改都将有效地破坏您的应用程序。
我希望能够阻止一些 crank call,因此我需要在 Android 上编程挂断一些电话。
以下片段来自如何在 Android 上挂断呼出电话?
这是不是意味着在以后的Android版本中,挂断电话的技术将随时被屏蔽?
这是不是意味着我无法编写一个应用程序来挂断电话?
迄今为止,我遇到的唯一挂断电话的方法是通过 Java 反射来完成。由于它不是公共 API 的一部分,您应该小心使用它,并且不要依赖它。对 Android 内部组成的任何更改都将有效地破坏您的应用程序。
首先,您需要在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;
}
}
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
} } }
在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();
这是否意味着在未来的Android版本中,挂断电话技术将被阻止?
有可能Android团队会为这项具体服务彻底改变一切。但我认为这种可能性非常小。
这是否意味着我不能编写一个挂断电话的应用程序?
如果提出的方法可行,为什么不呢?只要记住(在你的脑海中某个地方,是的 :)) 在遥远的未来,有些事情可能会变得复杂,你将不得不寻找另一种通过无锈API突破的肮脏技巧,以允许你挂断电话。
这完全没有经过测试,但是当出现与您的黑名单匹配的呼叫时,您能否只需关闭并打开飞行模式?
除此之外,在kitkat版本之前,似乎可以使用以下方法: http://androidsourcecode.blogspot.in/2010/10/blocking-incoming-call-android.html
如果你正在进行JUnit测试,那么这就是方法;
mInstrumentation = InstrumentationRegistry.getInstrumentation();
mInstrumentation.getUiAutomation().executeShellCommand( "input keyevent " + KeyEvent.KEYCODE_ENDCALL );
它可能也可以在测试之外工作,但我还没有尝试过。
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