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

Android语音转文本字符串匹配计数功能实现求助

语音转文本后对比文本统计相同内容数量的解决方案

原代码存在的问题

  • 对比逻辑执行时机错误:在调用startActivityForResult后立即执行对比,此时语音识别尚未完成,tvText内容为空,无法得到有效结果。
  • 循环边界错误:内层循环使用s1.length()作为终止条件,应该使用s2.length(),否则会出现数组越界或漏匹配的情况。
  • 字符重复统计:直接嵌套循环对比字符会重复计算同一字符的匹配次数(比如目标文本中的同一个字符多次匹配语音文本中的同一字符),不符合常规统计需求。
  • Intent参数错误:重复设置EXTRA_LANGUAGE,提示语应该使用EXTRA_PROMPT参数。

修正后的完整代码

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.speech.RecognizerIntent;
import android.util.Log;
import android.view.View;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

public class Mic extends AppCompatActivity {

    protected static final int RESULT_SPEECH = 1000;
    private ImageButton btnspeak;
    private TextView tvText, tvText1;

    @Override
    protected void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.mic);

        tvText1 = findViewById(R.id.textView7);
        tvText = findViewById(R.id.tvText);
        btnspeak = findViewById(R.id.btnspeak);

        btnspeak.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
                intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
                intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault());
                // 修正提示语参数
                intent.putExtra(RecognizerIntent.EXTRA_PROMPT, "Hi Speak Something");
                try {
                    tvText.setText("");
                    startActivityForResult(intent, RESULT_SPEECH);
                } catch (ActivityNotFoundException e) {
                    Toast.makeText(getApplicationContext(), "Your device doesn't support speech to text", Toast.LENGTH_LONG).show();
                    e.printStackTrace();
                }
            }
        });
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        switch (requestCode) {
            case RESULT_SPEECH:
                if (resultCode == Activity.RESULT_OK && null != data) {
                    ArrayList<String> text = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
                    String speechResult = text.get(0);
                    tvText.setText(speechResult);

                    // 语音识别完成后再执行对比统计
                    String targetText = tvText1.getText().toString().trim();
                    if (!targetText.isEmpty() && !speechResult.isEmpty()) {
                        int matchCount = calculateMatchCount(targetText, speechResult);
                        // 显示统计结果,可替换为其他展示方式
                        Toast.makeText(this, "相同内容数量:" + matchCount, Toast.LENGTH_SHORT).show();
                        Log.d("MatchCount", "相同内容数量:" + matchCount);
                    }
                }
                break;
        }
    }

    /**
     * 计算两个文本的相同内容数量,支持字符级和单词级两种统计方式
     * @param targetText 目标文本(tvText1的内容)
     * @param speechResult 语音识别结果文本(tvText的内容)
     * @return 相同内容的数量
     */
    private int calculateMatchCount(String targetText, String speechResult) {
        // --- 方式1:字符级统计(统计每个字符在两个文本中出现的最小次数之和)---
        Map<Character, Integer> targetCharCount = new HashMap<>();
        for (char c : targetText.toCharArray()) {
            targetCharCount.put(c, targetCharCount.getOrDefault(c, 0) + 1);
        }

        Map<Character, Integer> speechCharCount = new HashMap<>();
        for (char c : speechResult.toCharArray()) {
            speechCharCount.put(c, speechCharCount.getOrDefault(c, 0) + 1);
        }

        int matchCount = 0;
        for (Map.Entry<Character, Integer> entry : targetCharCount.entrySet()) {
            char c = entry.getKey();
            if (speechCharCount.containsKey(c)) {
                matchCount += Math.min(entry.getValue(), speechCharCount.get(c));
            }
        }

        // --- 方式2:单词级统计(按空格分割单词,统计相同单词数量,可忽略大小写)---
        /*
        String[] targetWords = targetText.trim().split("\\s+");
        String[] speechWords = speechResult.trim().split("\\s+");
        Set<String> targetWordSet = new HashSet<>(Arrays.asList(targetWords));
        int matchCount = 0;
        for (String word : speechWords) {
            String lowerWord = word.toLowerCase();
            if (targetWordSet.contains(lowerWord)) {
                matchCount++;
                // 如果需要去重统计(同一单词只算一次),取消下面注释
                // targetWordSet.remove(lowerWord);
            }
        }
        */

        return matchCount;
    }
}

说明

  • 对比逻辑移至onActivityResult方法,确保语音识别完成后再执行统计。
  • 提供了两种统计方式:字符级和单词级,可根据需求注释/启用对应代码块。
  • 修正了Intent的提示语参数,避免覆盖语言设置。
  • 使用trim()处理文本,避免空字符干扰统计。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 14:50:44