You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决SearchView中createVoiceAppSearchIntent引发的PendingIntent崩溃?

SearchView语音搜索PendingIntent崩溃解决方案

问题情况

使用SearchView的createVoiceAppSearchIntent方法时,该方法仍沿用PendingIntent.FLAG_ONE_SHOT,在Target SDK 31及以上版本会触发崩溃,报错提示:

Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent. Strongly consider using FLAG_IMMUTABLE, only use FLAG_MUTABLE if some functionality depends on the PendingIntent being mutable, e.g. if it needs to be used with inline replies or bubbles.

崩溃日志:

Fatal Exception: java.lang.IllegalArgumentException: Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent.
Strongly consider using FLAG_IMMUTABLE, only use FLAG_MUTABLE if some functionality depends on the PendingIntent being mutable, e.g. if it needs to be used with inline replies or bubbles.
       at android.app.PendingIntent.checkFlags(PendingIntent.java:382)
       at android.app.PendingIntent.getActivityAsUser(PendingIntent.java:465)
       at android.app.PendingIntent.getActivity(PendingIntent.java:451)
       at android.app.PendingIntent.getActivity(PendingIntent.java:415)
       at androidx.appcompat.widget.SearchView.createVoiceAppSearchIntent(SearchView.java:1594)
       at androidx.appcompat.widget.SearchView.onVoiceClicked(SearchView.java:1251)
       at androidx.appcompat.widget.SearchView$5.onClick(SearchView.java:991)
       at android.view.View.performClick(View.java:7792)
       at android.view.View.performClickInternal(View.java:7769)
       at android.view.View.access$3800(View.java:910)
       at android.view.View$PerformClick.run(View.java:30218)
       at android.os.Handler.handleCallback(Handler.java:938)
       at android.os.Handler.dispatchMessage(Handler.java:99)
       at android.os.Looper.loopOnce(Looper.java:226)
       at android.os.Looper.loop(Looper.java:313)
       at android.app.ActivityThread.main(ActivityThread.java:8669)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1135)

解决办法

1. 升级AppCompat库版本

这是最推荐的方案,旧版AppCompat库的SearchView未适配Android 12+的PendingIntent强制要求。将AppCompat库升级到1.6.0及以上版本,新版会自动在创建PendingIntent时添加FLAG_IMMUTABLE,修复该崩溃问题。

在build.gradle(Module级)中更新依赖:

implementation 'androidx.appcompat:appcompat:1.6.0'
// 或更新到最新稳定版

2. 自定义SearchView重写方法

如果暂时无法升级库,可自定义SearchView并重写createVoiceAppSearchIntent方法,手动添加适配Android 12+的Flags:

public class FixedSearchView extends SearchView {
    public FixedSearchView(Context context) {
        super(context);
    }

    public FixedSearchView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected PendingIntent createVoiceAppSearchIntent() {
        Intent voiceIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
        voiceIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
        voiceIntent.putExtra(RecognizerIntent.EXTRA_PROMPT, getContext().getString(R.string.search_voice_prompt));

        int flags = PendingIntent.FLAG_ONE_SHOT;
        // 适配Android 12+
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            flags |= PendingIntent.FLAG_IMMUTABLE;
        }
        return PendingIntent.getActivity(getContext(), 0, voiceIntent, flags);
    }
}

之后在布局文件中使用自定义的FixedSearchView替代原SearchView即可。

3. 反射临时修复(不推荐)

若以上两种方案都无法实施,可通过反射修改SearchView内部的PendingIntent,但反射存在兼容性风险,仅作临时应急:

// 在SearchView初始化后调用
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
    try {
        Field field = SearchView.class.getDeclaredField("mVoicePendingIntent");
        field.setAccessible(true);
        PendingIntent oldPi = (PendingIntent) field.get(yourSearchViewInstance);
        Intent intent = oldPi.getIntent();
        // 重新创建带FLAG_IMMUTABLE的PendingIntent
        PendingIntent newPi = PendingIntent.getActivity(
                getContext(), 
                0, 
                intent, 
                PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE
        );
        field.set(yourSearchViewInstance, newPi);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 01:55:16