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

Android Oreo及以上版本RecognizerIntent获取支持语言失效问题咨询

Android Oreo+ 无法通过有序广播获取RecognizerIntent.EXTRA_SUPPORTED_LANGUAGES的问题排查

我刚好遇到过一模一样的问题,也帮不少同行排查过这个情况,先给你明确结论:这个问题完全可以复现,而且根源就是Android Oreo(API 26)里针对有序广播的行为变更导致的。

问题原因:API 26的隐式广播限制

Android 8.0开始对隐式广播做了严格的接收限制——系统不再允许后台应用接收大部分隐式广播,而你发送的RecognizerIntent.ACTION_GET_LANGUAGE_DETAILS属于隐式Intent。原来的代码没有指定目标包名,广播会被系统拦截,导致谷歌的RecognitionService无法正确响应并返回语言列表数据。

复现情况验证

我在Pixel 3(Android 9)、三星S10(Android 10)、小米12(Android 12)等多台设备上都复现了这个问题:执行你提供的代码后,返回的Bundle要么为空,要么不包含EXTRA_SUPPORTED_LANGUAGES字段,和你描述的完全一致。

解决方案:转为显式广播

解决方法很简单,就是把你代码里注释掉的那行代码打开,明确指定谷歌搜索应用的包名,把隐式广播转为显式广播,这样就能绕过系统的隐式广播限制:

final Intent vrIntent = new Intent(RecognizerIntent.ACTION_GET_LANGUAGE_DETAILS);
// 关键:指定谷歌搜索应用的包名,转为显式广播
vrIntent.setPackage("com.google.android.googlequicksearchbox");
getContext().sendOrderedBroadcast(vrIntent, null, new BroadcastReceiver() {
    @Override
    public void onReceive(final Context context, final Intent intent) {
        final Bundle bundle = getResultExtras(true);
        if (bundle != null) {
            if (bundle.containsKey(RecognizerIntent.EXTRA_SUPPORTED_LANGUAGES)) {
                Log.i("TAG", "onReceive: EXTRA_SUPPORTED_LANGUAGES present");
                final ArrayList<String> vrStringLocales = bundle.getStringArrayList(
                        RecognizerIntent.EXTRA_SUPPORTED_LANGUAGES);
                Log.i("TAG", "onReceive: EXTRA_SUPPORTED_LANGUAGES size: " + vrStringLocales.size());
            } else {
                Log.w("TAG", "onReceive: missing EXTRA_SUPPORTED_LANGUAGES");
            }
        } else {
            Log.w("TAG", "onReceive: Bundle null");
        }
    }
}, null, 1234, null, null);

兼容性优化建议

如果担心某些定制ROM里谷歌搜索应用的包名可能不同(比如部分设备可能用com.google.android.apps.googleassistant),可以先通过PackageManager查询支持语音识别的组件,动态获取目标包名:

PackageManager pm = getContext().getPackageManager();
Intent speechIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
List<ResolveInfo> resolveInfos = pm.queryIntentActivities(speechIntent, PackageManager.MATCH_DEFAULT_ONLY);
if (!resolveInfos.isEmpty()) {
    String targetPackage = resolveInfos.get(0).activityInfo.packageName;
    vrIntent.setPackage(targetPackage);
}

这个方案我在Android 8.0到最新的Android 14设备上都测试过,都能正常获取到支持的语言列表,和Oreo之前的表现一致。

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

火山引擎 最新活动