Android Speech Recognition Insufficient Permission

2019-06-19 08:50发布

I am trying to implement speech recognition without the standard dialog (it is working fine with the dialog).

I am getting error code 9 as soon as I try to start listening.

My device is an LG G Stylo (running Android 6.0).

Manifest:

<manifest package="example.com.myapplication"
      xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<application
 .....

(also tried adding INTERNET permission even though that shouldn't be necessary since offline recognition should be working)

build.gradle:

compileSdkVersion 23
buildToolsVersion "23.0.2"

defaultConfig {
    applicationId "example.com.appname"
    minSdkVersion 19
    targetSdkVersion 23
    versionCode 1
    versionName "1.0"
}

Speech recognition code:

private SpeechRecognizer speechRecognizer;

protected void onCreate(Bundle savedInstanceState) {
  speechRecognizer = SpeechRecognizer.createSpeechRecognizer(this);
  speechRecognizer.setRecognitionListener(new speech_listener());
  Intent intent = new intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
  intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
     RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
  intent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE,
       getApplication().getPackageName());
  intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 1);
  intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.ENGLISH);
  speechRecognizer.startListening(intent);

Listener (inner) class:

class speech_listener implements RecognitionListener
{
  public void onReadyForSpeech(Bundle params){}
  public void onBeginningOfSpeech(){}
  public void onRmsChanged(float rmsdB){}
  public void onBufferReceived(byte[] buffer){}
  public void onEndOfSpeech(){}
  public void onError(int error){
    Log.d("Speech", "error: " + error);
  }
  public void onResults(Bundle results)
  {
    ArrayList data = results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
    String answer = (String)data.get(0);
    processAnswer(answer);
  }
  public void onPartialResults(Bundle partialResults){}
  public void onEvent(int eventType, Bundle params){}
}

Any insight would be appreciated.

3条回答
迷人小祖宗
2楼-- · 2019-06-19 09:08

although the answer is out there, you have to put it together from many pieces. What has worked for me (I was getting the same error):

  • add the permission into you manifest: <uses-permission android:name="android.permission.RECORD_AUDIO" />
  • from my logcat, I got a strong feeling the following permission is also necessary: <uses-permission android:name="android.permission.BLUETOOTH" /> try to add it if everything else fails
  • in newer versions of android, you also have to request your permission from the user during runtime. It is crucial to do this at the right spot, you cannot run the request for permission just from anywhere in your code, it has to be run from the UI Thread. For me the following worked:

    void doPermAudio()
    {
        int MY_PERMISSIONS_RECORD_AUDIO = 1;
        MainActivity thisActivity = this;
    
       if (ContextCompat.checkSelfPermission(this,
            Manifest.permission.RECORD_AUDIO)
            != PackageManager.PERMISSION_GRANTED) {
    
               ActivityCompat.requestPermissions(thisActivity,
                    new String[]{Manifest.permission.RECORD_AUDIO},
                    MY_PERMISSIONS_RECORD_AUDIO);
            }
        }
    }
    
    // in main activity's onCreate
    protected void onCreate(Bundle savedInstanceState) {
        this.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    doPermAudio();
                }
            }
         });
    }
    
  • also, what has been mentioned elsewhere, you may get the error 9 for declaring a wrong package name when starting the listening intent, as it seems many people have copied their function from a sample from the web, where the package name is explicitly written out:

    void listen()
    {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
                intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
                String pkg = getApplication().getPackageName();
                intent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, pkg);
    
                sr.startListening(intent);
    
            }
        });
    }
    
查看更多
劫难
3楼-- · 2019-06-19 09:10

On Android 6 this permission is one of dangerous ones which means you need to ask user to confirm it (actually acquire it). Check this and this for more details.

查看更多
贪生不怕死
4楼-- · 2019-06-19 09:14

Adding to Sam's answer: When you're developing your app on Android 6, you might not be prompted to approve the "dangerous" Record Audio (Microphone) permission, so you need to manually open up the app in Settings and grant the permission.

Screenshot of manually granting app permission

查看更多
登录 后发表回答