You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Android系统应用实现按钮控制TTS开关及跨APP唤起TTS方案问询

Hey there! Let's break down the implementation for both of your requirements—since you're working with a system-signed Android app, you have access to privileged APIs that regular apps don't, making these tasks totally feasible.

1. Implement TTS Toggle (Enable/Disable) in Your System App

First, we'll build a button that checks the current TTS state and toggles it with a tap. Here's a step-by-step approach:

Step 1: Check if TTS is Enabled

To determine if the system has an active TTS engine configured, read from secure system settings:

private boolean isTTSEnabled(Context context) {
    String defaultEngine = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.TTS_DEFAULT_ENGINE);
    return defaultEngine != null && !defaultEngine.isEmpty();
}

Step 2: Toggle TTS State on Button Click

As a system-signed app, you can modify secure settings to enable/disable the default TTS engine. Here's the click listener logic:

Button ttsToggleButton = findViewById(R.id.tts_toggle_btn);
TextToSpeech ttsInstance = null;

ttsToggleButton.setOnClickListener(v -> {
    boolean isEnabled = isTTSEnabled(getApplicationContext());
    
    if (isEnabled) {
        // Disable TTS: Clear the default engine
        Settings.Secure.putString(getContentResolver(), Settings.Secure.TTS_DEFAULT_ENGINE, "");
        // Stop ongoing playback and clean up the TTS instance
        if (ttsInstance != null) {
            ttsInstance.stop();
            ttsInstance.shutdown();
            ttsInstance = null;
        }
        ttsToggleButton.setText("Enable TTS");
    } else {
        // Enable TTS: Initialize with the first available engine
        ttsInstance = new TextToSpeech(getApplicationContext(), status -> {
            if (status == TextToSpeech.SUCCESS) {
                List<TextToSpeech.EngineInfo> engines = ttsInstance.getEngines();
                if (!engines.isEmpty()) {
                    Settings.Secure.putString(getContentResolver(), Settings.Secure.TTS_DEFAULT_ENGINE, engines.get(0).name);
                    // Optional: Set default language (handle unsupported cases)
                    int langResult = ttsInstance.setLanguage(Locale.getDefault());
                    if (langResult == TextToSpeech.LANG_MISSING_DATA || langResult == TextToSpeech.LANG_NOT_SUPPORTED) {
                        Log.w("TTS", "Default language not supported");
                    }
                }
            }
        });
        ttsToggleButton.setText("Disable TTS");
    }
});

Required Permission

Add this to your app's AndroidManifest.xml (only system-signed apps can use this permission):

<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
2. Trigger TTS/TalkBack from Other Apps

Regular apps can't modify system settings directly, so we'll use a broadcast-based approach to let them signal your system app to perform these actions.

Triggering TTS Toggle

  1. Register a Custom Broadcast Receiver in your system app's manifest (use a custom permission to restrict access to trusted apps):
<receiver android:name=".TTSToggleReceiver"
          android:permission="com.your.system.app.PERMISSION_TOGGLE_TTS">
    <intent-filter>
        <action android:name="com.your.system.app.ACTION_TOGGLE_TTS" />
    </intent-filter>
</receiver>

<!-- Define your custom restricted permission -->
<permission android:name="com.your.system.app.PERMISSION_TOGGLE_TTS"
            android:protectionLevel="signatureOrSystem" />
  1. Implement the Receiver to handle the toggle logic:
public class TTSToggleReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        // Reuse the isTTSEnabled and toggle logic from Section 1 here
        boolean isEnabled = isTTSEnabled(context);
        // ... perform the TTS toggle action ...
    }
}
  1. Other Apps Send the Broadcast (they need to declare your custom permission in their manifest):
Intent toggleIntent = new Intent("com.your.system.app.ACTION_TOGGLE_TTS");
context.sendBroadcast(toggleIntent);

Enabling/Disabling TalkBack

TalkBack is an accessibility service, so we'll manipulate secure settings to toggle it. Note that TalkBack's component name may vary by manufacturer—adjust if needed:

private void toggleTalkBack(Context context) {
    AccessibilityManager am = (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
    // Stock Android TalkBack component; adjust for custom skins
    ComponentName talkBackComponent = new ComponentName("com.google.android.marvin.talkback", 
                                                        "com.google.android.marvin.talkback.TalkBackService");
    
    boolean isTalkBackEnabled = am.isEnabled() && am.getEnabledAccessibilityServices().contains(talkBackComponent);
    
    String enabledServices = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
    if (isTalkBackEnabled) {
        // Disable TalkBack: Remove its component from the enabled list
        String updatedServices = enabledServices.replace(talkBackComponent.flattenToString(), "").replace("::", ":");
        Settings.Secure.putString(context.getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, updatedServices);
        // Turn off accessibility if no other services are active (optional)
        if (updatedServices.isEmpty()) {
            Settings.Secure.putInt(context.getContentResolver(), Settings.Secure.ACCESSIBILITY_ENABLED, 0);
        }
    } else {
        // Enable TalkBack: Add its component to the enabled list
        String updatedServices = enabledServices.isEmpty() 
            ? talkBackComponent.flattenToString() 
            : enabledServices + ":" + talkBackComponent.flattenToString();
        Settings.Secure.putString(context.getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, updatedServices);
        Settings.Secure.putInt(context.getContentResolver(), Settings.Secure.ACCESSIBILITY_ENABLED, 1);
    }
}

You can expose this TalkBack toggle via the same broadcast receiver pattern used for TTS.

Key Notes

  • Manufacturer Variations: TalkBack's package name might differ on non-stock Android. Use am.getInstalledAccessibilityServices() to fetch all available accessibility services and find the correct component.
  • System Signature: All these operations require your app to be signed with the system's platform key and have the necessary permissions.
  • User Experience: Always notify users when toggling accessibility features, as they drastically change device interaction.

内容的提问来源于stack exchange,提问作者Alien Geography

火山引擎 最新活动