语音按键不能调用谷歌语音助手问题分析


当适配好语音遥控器之后,按下语音按键发送 KEYCODE_SEARCH 按键事件,如果安装了谷歌的套件以及谷歌的语音助手GoogleKatniss.apk,那么会调用谷歌的语音助手进行搜索,效果如下图。
在这里插入图片描述
搜索结果
但是遇到一个问题,就是按了语音按键之后,没有反应,不会弹出上面的界面。

流程分析

通过打印分析,按下语音按键之后,按键事件 KEYCODE_SEARCH 会传递到frameworks/base/core/java/com/android/internal/policy/PhoneWindow.java 里面

        case KeyEvent.KEYCODE_SEARCH: {
            /*
             * Do this in onKeyUp since the Search key is also used for
             * chording quick launch shortcuts.
             */
            if (getKeyguardManager().inKeyguardRestrictedInputMode()) {
                break;
            }
            if (event.isTracking() && !event.isCanceled()) {
                launchDefaultSearch(event);
            }
            return true;
        }

接着跑到 launchDefaultSearch(event) 里面,接着看下 launchDefaultSearch(event) 的代码

/**
 * Helper method for adding launch-search to most applications. Opens the
 * search window using default settings.
 *
 * @return true if search window opened
 */
private boolean launchDefaultSearch(KeyEvent event) {
    if (getContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK)
            && !isTvUserSetupComplete()) {
        // If we are in Setup or Post-Setup update mode on TV, consume the search key
        return false;
    }
    boolean result;
    final Callback cb = getCallback();
    if (cb == null || isDestroyed()) {
        result = false;
    } else {
        sendCloseSystemWindows("search");
        int deviceId = event.getDeviceId();
        SearchEvent searchEvent = null;
        if (deviceId != 0) {
            searchEvent = new SearchEvent(InputDevice.getDevice(deviceId));
        }
        try {
            result = cb.onSearchRequested(searchEvent);
        } catch (AbstractMethodError e) {
            Log.e(TAG, "WindowCallback " + cb.getClass().getName() + " does not implement"
                    + " method onSearchRequested(SearchEvent); fa", e);
            result = cb.onSearchRequested();
        }
    }
    if (!result && (getContext().getResources().getConfiguration().uiMode
            & Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_TELEVISION) {
        // On TVs, if the app doesn't implement search, we want to launch assist.
        Bundle args = new Bundle();
        args.putInt(Intent.EXTRA_ASSIST_INPUT_DEVICE_ID, event.getDeviceId());
        return ((SearchManager)getContext().getSystemService(Context.SEARCH_SERVICE))
                .launchLegacyAssist(null, UserHandle.myUserId(), args);
    }
    return result;
}

通过注释我们可以看到,If we are in Setup or Post-Setup update mode on TV, consume the search key
,意思当我们的电视还在类似开机向导初始化设置的话,就把这个key event 消费掉(就是把这个按键事件丢弃掉,不做处理)。如果没有被消费掉的话,会往下跑,On TVs, if the app doesn’t implement search, we want to launch assist. 这句话的意思是,在电视上,如果没有app实现了搜索功能,我们想要启动 assist (类似谷歌语音助手)。于是会跑到 launchLegacyAssist 里面。
在 frameworks/base/services/core/java/com/android/server/search/SearchManagerService.java 里面
launchLegacyAssist 的实现是这样的

@Override
public boolean launchLegacyAssist(String hint, int userHandle, Bundle args) {
    ComponentName comp = getLegacyAssistComponent(userHandle);
    if (comp == null) {
        return false;
    }
    long ident = Binder.clearCallingIdentity();
    try {
        Intent intent = new Intent(Intent.ACTION_ASSIST);
        intent.setComponent(comp);
        IActivityManager am = ActivityManager.getService();
        return am.launchAssistIntent(intent, ActivityManager.ASSIST_CONTEXT_BASIC, hint,
                userHandle, args);
    } catch (RemoteException e) {
    } finally {
        Binder.restoreCallingIdentity(ident);
    }
    return true;
}

这个函数先通过 getLegacyAssistComponent 获取到包含 Intent.ACTION_ASSIST action 的包名和activity name,然后去启动它,就达到最开始的图示效果。

private ComponentName getLegacyAssistComponent(int userHandle) {
    try {
        userHandle = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
                Binder.getCallingUid(), userHandle, true, false, "getLegacyAssistComponent", null);
        IPackageManager pm = AppGlobals.getPackageManager();
        Intent assistIntent = new Intent(Intent.ACTION_ASSIST);
        ResolveInfo info =
                pm.resolveIntent(assistIntent,
                        assistIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
                        PackageManager.MATCH_DEFAULT_ONLY, userHandle);
        if (info != null) {
            return new ComponentName(
                    info.activityInfo.applicationInfo.packageName,
                    info.activityInfo.name);
        }
    } catch (RemoteException re) {
        // Local call
        Log.e(TAG, "RemoteException in getLegacyAssistComponent: " + re);
    } catch (Exception e) {
        Log.e(TAG, "Exception in getLegacyAssistComponent: " + e);
    }
    return null;
}

在这里插入图片描述
我们可以看到 GoogleKatniss.apk 里面的 com.google.android.katniss.search.SearchActivity 是有android.intent.action.ASSIST的action,所以按下语音按键之后,启动的就是这个activity。

那为什么按下语音按键不启动谷歌语音助手?

上面我们分析到,按键有可能会被消费掉,接下来我们看一下 isTvUserSetupComplete() 这个函数

/**
 * Check if Setup or Post-Setup update is completed on TV
 * @return true if completed
 */
private boolean isTvUserSetupComplete() {
    boolean isTvSetupComplete = Settings.Secure.getInt(getContext().getContentResolver(),
            Settings.Secure.USER_SETUP_COMPLETE, 0) != 0;
    isTvSetupComplete &= Settings.Secure.getInt(getContext().getContentResolver(),
            Settings.Secure.TV_USER_SETUP_COMPLETE, 0) != 0;
    return isTvSetupComplete;
}

在 isTvUserSetupComplete() 里面就是查询 Settings.Secure.USER_SETUP_COMPLETE 的值和 Settings.Secure.TV_USER_SETUP_COMPLETE 的值,当这两个属性的值都不为0的时候,返回true,表示电视用户的初始化设置已经完成了。
这两个属性是在 frameworks/base/core/java/android/provider/Settings.java 里面定义的

    /**
     * Whether the current user has been set up via setup wizard (0 = false, 1 = true)
     * @hide
     */
    public static final String USER_SETUP_COMPLETE = "user_setup_complete";

    /**
     * Whether the current user has been set up via setup wizard (0 = false, 1 = true)
     * This value differs from USER_SETUP_COMPLETE in that it can be reset back to 0
     * in case SetupWizard has been re-enabled on TV devices.
     *
     * @hide
     */
    public static final String TV_USER_SETUP_COMPLETE = "tv_user_setup_complete";

我们可以通过adb shell来查询这两个属性的值

settings get secure user_setup_complete

settings get secure tv_user_setup_complete

设置这两个属性的值

settings put secure user_setup_complete 1

settings put secure tv_user_setup_complete 1

查询到 user_setup_complete 的值为0,tv_user_setup_complete 的值为1,那么isTvUserSetupComplete() 的返回值是false。

private boolean launchDefaultSearch(KeyEvent event) {
    if (getContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK)
            && !isTvUserSetupComplete()) {
        // If we are in Setup or Post-Setup update mode on TV, consume the search key
        return false;
    }

那么就会跑到 return false,所以语音按键事件就被消费掉,自然也就启动不了谷歌语音助手了。只要把Settings.Secure.USER_SETUP_COMPLETE 的值设为1,就可以正常启动了。

好了,先简单分析到这里了~~~

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
ZS语音识别,多语言语音识别,语音控制软件,同时支持汉语,英语,日语等10种语言,内置几十种常用语音控制功能,还支持自定义语音控制命令! ZS语音识别,采用先进的语音识别系统基于Google语音引擎,能够准确地对多语言进行识别,让您输入速度倍增,不再因不会打字而烦恼!CantonSoft针对粤语,提供了独立的更正词库,能够更好地提高识别能力! 官方网站:http://voice.cantonsoft.net/ 广东软件网:http://www.cantonsoft.net/ 软件使用帮助 (联网支持:voice.cantonsoft.net/help/) --------------------------------------------------------------------------------------- 软件安装与更新: 1.全新安装 第一次安装只需运行setup.exe,安装程序会自动检测系统环境并自动安装必要组件 2.软件更新 可以通过本程序托盘菜单的检查更新或直接进入官网查看最新版本(当前版本可以在关于窗口查看),从官网下载最新安装包后,只需直接安装便可完成更新,用户设置并不会丢失! 语音识别功能: 本软件提供了语音到文字的转换功能 1.启动软件后,像使用输入法一样,将鼠标定位到要输入文本的位置 2.按下语音输入键进行录音 3.录音完毕后,再次按下语音输入键确认 4.等待软件进行识别处理 5.识别完成后,识别内容会输出到光标位置上,如出现识别失败提示,请按下语音输入键重新尝试 6.语音输入设置(v1.2新增): 语音输入设置能够调整输入模式和语音输入按键 语音控制功能: 本软件提供了利用语音操作电脑的功能 1.开启语音控制: 勾选"开启语音控制"复选框即可开启 2.激活语音控制: 你可以用麦克风跟电脑打声招呼,或拍下手掌来激活语音控制,待系统出现声音提示或右下方托盘处出现气泡提示时,大声说出您的控制命令(每次只能识别一条控制命令,控制命令可以查看语音控制设置面板的识别内容) 3.命令识别: 软件会自动判断您是否已说完控制语句,并会对您说出的命令进行识别 4.执行命令: 当您的控制命令被正确识别后,系统便会作出相应操作,本次语音控制结束,您可以继续重复进行第二步操作,直到语音控制功能被关闭 5.命令识别失败: 若您说出的控制命令并不存在,或软件识别错误,软件将会出现"命令无法识别"的提示,您可以返回第二步再次进行语音控制 6.语音控制设置: 您可以在软件界面右下方或系统托盘打开语音控制设置面板 在语音控制面板里可以对软件进行如下调整: 1.调整麦克风灵敏度:用于判断何时激活或结束语音控制 2.调整基本命令:更改对软件内置控制命令的识别内容(软件对默认识别内容作有优化,拥有极高的识别率) 3.调整自定义命令:增加或删除自定义的语音控制命令,命令提示符可以进行大部分系统功能,详情请参阅联网支持 温馨提示: 1.按下右上角X按钮会使程式最小化至系统托盘,最小化后您仍然可以继续使用语音输入键进行识别操作,如需完全退出程式,请右键右下角托盘图标,单击退出选项!) 2.语音控制对应当前选中的语音,命令识别内容不同的文字对应不同的语言:粤语-繁体中文,普通话-简体中文,英语-英文,日语-日文,例如使用普通话无法对使用繁体中文的命令进行识别! 3.当语音识别正在进行时,无法进行语音控制控制,反之亦然,开启语音控制功能后,仍然可以按下语音输入键进行语音识别 4.软件功能只会在联网状态下生效,建议拥有2M以上宽带
Google键盘 4.0 资源大小:18.513MB 应用简介 Google键盘(Google Keyboard)让文字输入变得既智能又轻松。在滑行输入模式下,只需用手指在字母上滑动,然后移开手指即可完成一个字词的输入,并且无需使用空格键。在语音输入模式下,您可以随时随地输入自己想说的话。Google键盘(Google Keyboard)具备强大的字词识别和下一字词预测功能,有助于您在所有 Android 设备上更快、更准确地输入文字。Google键盘(Google Keyboard)主要功能:滑行输入(提供动态浮动预览)语音输入可提供下一字词建议,并补全当前字词支持 26 种语言的词典高级键盘布局适用于各种 Android 设备(平板电脑和手机)Google键盘(Google Keyboard)4.0.21203.1613964 ···• 全新的 Material Design 主题背景• 改进了输入建议和拼写更正的设计• 修正了一些错误并提升了稳定性Google键盘(Google Keyboard)3.2.19987.1523112 ···• 利用从Google应用和服务中收集的数据完善了输入建议和更正功能• 改善了多种语言(包括西班牙语)的输入建议功能• 优化调整了麦克风键和逗号键的位置• 修正了多个错误,并提升了稳定性Google键盘(Google Keyboard)3.2.19977.1520383 ···• 利用从Google应用和服务中收集的数据完善了输入建议和更正功能• 改善了多种语言(包括西班牙语)的输入建议功能• 优化调整了麦克风键和逗号键的位置• 修正了多个错误,并提升了稳定性Google键盘(Google Keyboard)3.2.19963.1491898:• 利用从Google应用和服务中收集的数据完善了输入建议和更正功能• 改善了多种语言(包括西班牙语)的输入建议功能• 优化调整了麦克风键和逗号键的位置• 修正了多个错误,并提升了稳定性Google键盘(Google Keyboard)3.1.19653.1284735:• 利用从Google应用和服务中收集的数据完善了输入建议和更正功能• 改善了多种语言(包括西班牙语)的输入建议功能• 优化调整了麦克风键和逗号键的位置• 修正了多个错误,并提升了稳定性Google键盘(Google Keyboard)3.1.19633.1257820:• 使用Google应用和服务的数据来改进输入建议和拼写纠正功能• 按键时显示弹出式动画• 修复了多项错误,并提高了稳定性Google键盘(Google Keyboard)3.0.19423.1102675a:• 使用Google应用和服务的数据来改进输入建议和拼写纠正功能• 按键时显示弹出式动画• 修复了多项错误,并提高了稳定性Google键盘(Google Keyboard)3.0.19373.1072412a:• 加入了一个全新的高级选项,以便切换键盘颜色(白色和蓝色)• 修复了多项错误,并提高了稳定性Google键盘(Google Keyboard)2.0.19133.927933a:• 加入了一个全新的高级选项,以便切换键盘颜色(白色和蓝色)• 修复了多项错误,并提高了稳定性Google键盘(Google Keyboard)2.0.19123.914326a版更新信息:1、针对不同尺寸的屏幕(4英寸、7英寸和10英寸)改进了标点符号配置。2、置入了表情符号输入点和布局(KitKat 及更高版本)3、消除了按键操作时的蓝色状态4、新增了可自动填补空格的滑行输入模式(输入时不必移开手指,只需滑过空格键即可)5、针对部分语言添加并调整了键盘布局。6、修复了多项错误,提高了稳定性。Google键盘(Google Keyboard)2.0.19003.893803a版更新信息:此版本从Android 4.4中提取,更改了部分的表情,输入体验更加的顺滑。Google键盘(Google Keyboard)1.1.1881.801980版更新信息:1、添加长按数字平板布局顶行。2、调谐键盘布局的一些语言。3、错误修正和稳定性方面的改进。Google键盘(Google Keyboard)1.1.1880.793830版更新信息:1、添加长按数字平板布局顶行。2、调谐键盘布局的一些语言。3、错误修正和稳定性方面的改进。Google键盘(Google Keyboard)1.0.1870.703320版更新信息:1、调整了一些设备上的按键振动强度。2、修正了设置、语言切换和其他方面的若干错误。 更多简介»
要实现一个智能语音助手,需要完成以下几个步骤: 1. 语音识别:将用户的语音转换成文本。 2. 自然语言处理:将用户的文本理解成意思,例如提取关键词、分析语法等。 3. 逻辑处理:根据用户输入的意图,执行相应的操作,例如查询天气、播放音乐等。 4. 语音合成:将执行结果转换成语音输出。 其中,第1步和第4步可以使用Python中的SpeechRecognition和pyttsx3库实现,第2步可以使用自然语言处理库NLTK和spaCy等,第3步可以根据具体需求选择不同的API或自行编写代码实现。 以下是一个简单的示例,实现了语音识别和语音合成的功能,可以与语音助手进行简单的对话: ```python import speech_recognition as sr import pyttsx3 # 初始化语音合成引擎 engine = pyttsx3.init() # 初始化语音识别器 r = sr.Recognizer() # 获取系统麦克风列表 mic_list = sr.Microphone.list_microphone_names() # 选择要使用的麦克风 mic_index = 0 # 初始化麦克风 mic = sr.Microphone(device_index=mic_index) # 设置语音合成引擎的参数 engine.setProperty('voice', 'zh') while True: # 捕获语音输入 with mic as source: r.adjust_for_ambient_noise(source) audio = r.listen(source) # 将语音转换成文本 try: text = r.recognize_google(audio, language='zh-CN') print('你说:', text) except sr.UnknownValueError: print('无法识别输入的语音') continue # 处理用户输入 if text == '你好': engine.say('你好,有什么可以帮助您的?') elif text == '天气怎么样': engine.say('今天天气晴朗,气温适中。') elif text == '再见': engine.say('好的,祝您一天愉快。') break else: engine.say('抱歉,我不知道您在说什么。') engine.runAndWait() ``` 这个程序可以通过麦克风捕获用户的语音输入,将语音转换成文本进行处理,然后将处理结果转换成语音输出。用户可以通过说出“你好”、“天气怎么样”、“再见”等指令来与语音助手进行简单的对话。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值