Android Oreo及以上版本如何通过代码实现电话挂断?
Hey there, I’ve dealt with this exact problem when building a call-blocking app for newer Android versions—those old reflection tricks simply don’t work anymore because of strict permission restrictions. Let’s walk through the valid, supported alternatives you can use:
1. Call Screening Service (API 28+)
This is the official, recommended approach from Google for call blocking on Android Pie and above. It’s purpose-built for handling incoming calls and doesn’t rely on any restricted system permissions.
Implementation Steps:
- Create a class extending
CallScreeningService:public class MyCallScreeningService extends CallScreeningService { @Override public void onScreenCall(CallDetails callDetails) { // Replace this with your app's logic to decide if the call should be blocked boolean shouldBlock = true; if (shouldBlock) { // Reject and disallow the incoming call respondToCall(callDetails, new CallResponse.Builder() .setDisallowCall(true) .setRejectCall(true) .build()); } else { // Let the call proceed normally respondToCall(callDetails, new CallResponse.Builder() .setAllowCall(true) .build()); } } } - Register the service in your
AndroidManifest.xml:<service android:name=".MyCallScreeningService" android:permission="android.permission.BIND_SCREENING_SERVICE"> <intent-filter> <action android:name="android.intent.action.ANSWER_PHONE_CALL" /> </intent-filter> </service> - Request required runtime permissions:
Note: Android will automatically prompt users to set your app as the default call screening app the first time you use this service—this is a required step for it to work.if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_PHONE_STATE}, 1001); }
2. Accessibility Service (API 26-27)
For Android Oreo (API 26) and Pie (API 27) before Call Screening Service existed, your only viable option is to use an Accessibility Service. This requires users to manually enable accessibility for your app in system settings (a minor UX tradeoff, but it’s the only way).
Implementation Steps:
- Create a class extending
AccessibilityService:public class CallBlockAccessibilityService extends AccessibilityService { @Override public void onAccessibilityEvent(AccessibilityEvent event) { if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) { String packageName = event.getPackageName().toString(); // Target common phone app packages (adjust for OEM-specific dialers if needed) if (packageName.equals("com.android.phone") || packageName.equals("com.google.android.dialer")) { // Simulate pressing the system's "End Call" action performGlobalAction(GLOBAL_ACTION_CALL_END); } } } @Override public void onInterrupt() {} @Override protected void onServiceConnected() { super.onServiceConnected(); AccessibilityServiceInfo info = new AccessibilityServiceInfo(); info.eventTypes = AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED; info.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC; setServiceInfo(info); } } - Register the service in
AndroidManifest.xml:<service android:name=".CallBlockAccessibilityService" android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"> <intent-filter> <action android:name="android.accessibilityservice.AccessibilityService" /> </intent-filter> <meta-data android:name="android.accessibilityservice" android:resource="@xml/accessibility_service_config" /> </service> - Create the accessibility config file (
res/xml/accessibility_service_config.xml):
Add a user-friendly description in<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android" android:accessibilityEventTypes="typeWindowStateChanged" android:accessibilityFeedbackType="feedbackGeneric" android:accessibilityFlags="flagDefault" android:description="@string/accessibility_service_desc" />strings.xmlexplaining what the service does—users will see this when enabling accessibility for your app.
Why Your Original Approach Fails
Starting with Android Oreo, the MODIFY_PHONE_STATE permission is locked to system apps exclusively. Third-party apps can’t request or use it, no matter how you try to bypass lint checks. That’s exactly why your reflection of ITelephony.endCall() throws the permission error. The methods above are the only supported ways to block calls on modern Android versions.
内容的提问来源于stack exchange,提问作者user11068505




