如何隐藏系统默认通话UI并使用自定义UI发起通话?
Got it, let's break down why your custom in-call UI isn't replacing the default system one, even when you're using TelecomManager to place calls. The main issues here are incorrect extra values and missing setup steps for your custom call service.
Key Mistakes in Your Current Code
First, let's spot the obvious error: you're passing a boolean value to TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, but this extra expects a PhoneAccountHandle object, not a boolean. That's a critical misstep—the system can't associate your custom UI with the call without a valid account handle.
Step-by-Step Fixes
1. Register Your Custom InCallService in Manifest
Your app needs to declare an InCallService that provides the custom UI, and the system has to recognize it. Add this to your AndroidManifest.xml:
<service android:name=".YourCustomInCallService" android:permission="android.permission.BIND_IN_CALL_SERVICE"> <!-- This meta-data tells the system this service provides an in-call UI --> <meta-data android:name="android.telecom.IN_CALL_SERVICE_UI" android:value="true" /> <intent-filter> <action android:name="android.telecom.InCallService" /> </intent-filter> </service>
Replace .YourCustomInCallService with the actual class name of your custom in-call service.
2. Create & Register a Custom PhoneAccount
The system uses PhoneAccount to identify which app should handle calls. You need to create one and register it with TelecomManager:
// Get your service's component name ComponentName componentName = new ComponentName(getPackageName(), YourCustomInCallService.class.getName()); // Create a unique handle for your account PhoneAccountHandle phoneAccountHandle = new PhoneAccountHandle(componentName, "custom_call_account_id"); // Build the PhoneAccount with necessary capabilities PhoneAccount phoneAccount = PhoneAccount.builder(phoneAccountHandle, "Custom Call UI") .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER | PhoneAccount.CAPABILITY_VIDEO_CALLING) .build(); // Register the account with TelecomManager TelecomManager telecomManager = (TelecomManager) getSystemService(Context.TELECOM_SERVICE); telecomManager.registerPhoneAccount(phoneAccount);
Run this code once (like in your app's onCreate method) to register the account.
3. Correct the PlaceCall Extras
Now fix your dialing code to pass the valid PhoneAccountHandle instead of a boolean:
TelecomManager telecomManager = (TelecomManager) getSystemService(Context.TELECOM_SERVICE); Uri uri = Uri.fromParts("tel", phonenumber, null); Bundle extras = new Bundle(); // Tell the system to use your service's UI extras.putBoolean(TelecomManager.METADATA_IN_CALL_SERVICE_UI, true); // Pass the registered PhoneAccountHandle here extras.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, phoneAccountHandle); try { telecomManager.placeCall(uri, extras); } catch (SecurityException e) { e.printStackTrace(); // Handle missing permissions (see next step) }
4. Ensure Required Permissions
Make sure you've requested and granted these permissions (dynamic request is needed for Android 6.0+):
android.permission.CALL_PHONEandroid.permission.READ_PHONE_STATE- For Android 10+:
android.permission.ACCESS_NOTIFICATION_POLICY(to manage call notifications)
5. Set Your App as Default Call App (Critical for Some Devices)
On many devices, you'll need to set your app as the default calling app in system settings:
- Go to Settings > Apps > Default apps > Phone app
- Select your app from the list
This ensures the system prioritizes your custom UI over the default one.
Final Notes
If you still see the default UI after these steps, double-check:
- Your
InCallServiceclass properly overrides methods likeonCallAddedto launch your custom UI - The
PhoneAccountHandleyou pass inplaceCallmatches the one you registered - No other default call app is overriding your settings
内容的提问来源于stack exchange,提问作者Prabh

