2017-03-07 62 views
1

我正在構建一個應用程序,它記錄用戶的語音,然後將其轉換爲文本格式。我試圖在用戶單擊錄製按鈕後立即獲得許可提示以訪問麥克風。但是,在演講錄製完成後,我正在獲得許可。我哪裏出錯了?獲得錄製語音後訪問麥克風的權限提示

以下是的JavaXML文件

MainActivity.java

package com.ika.speechtotext; 

import android.Manifest; 
import android.content.ActivityNotFoundException; 
import android.content.Intent; 
import android.content.pm.PackageManager; 
import android.speech.RecognizerIntent; 
import android.os.Bundle; 
import android.support.v4.app.ActivityCompat; 
import android.support.v4.content.ContextCompat; 
import android.support.v7.app.AppCompatActivity; 
import android.view.View; 
import android.widget.TextView; 
import android.widget.Toast; 
import java.util.ArrayList; 
import java.util.Locale; 

public class MainActivity extends AppCompatActivity{ 

    private static final int MY_PERMISSIONS_REQUEST_RECORD_AUDIO = 1; 
    private TextView text; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     text = (TextView)findViewById(R.id.myText); 
    } 

    public void onBtnClick(View view) { 


     if (view.getId() == R.id.imageRecBtn) { 

      // Here, 'this' is the current activity i.e; MainActivity 
      if (ContextCompat.checkSelfPermission(this, 
        Manifest.permission.READ_CONTACTS) 
        != PackageManager.PERMISSION_GRANTED) { 

       // Should we show an explanation? 
       if (ActivityCompat.shouldShowRequestPermissionRationale(this, 
         Manifest.permission.RECORD_AUDIO)) { 

        // Show an explanation to the user *asynchronously* -- don't block 
        // this thread waiting for the user's response! After the user 
        // sees the explanation, try again to request the permission. 

       } else { 

        // No explanation needed, we can request the permission. 

        ActivityCompat.requestPermissions(this, 
          new String[]{Manifest.permission.RECORD_AUDIO}, 
          MY_PERMISSIONS_REQUEST_RECORD_AUDIO); 

        // MY_PERMISSIONS_REQUEST_RECORD_AUDIO is an 
        // app-defined int constant. The callback method gets the 
        // result of the request. 
       } 
      } 

      promptSpeechInput(); 
     } 
    } 

    //recognize the speech 
    public void promptSpeechInput() { 
     Intent i = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); 
     i.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM); 
     i.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault()); 
     i.putExtra(RecognizerIntent.EXTRA_PROMPT, "Speak something!"); 

     try { 
      startActivityForResult(i, 100); 
     } catch (ActivityNotFoundException a) { 
      Toast.makeText(MainActivity.this, "Your device doesn't support speech recognition.", 
        Toast.LENGTH_SHORT).show(); 
     } 
    } 

    //display the speech in text format 
    public void onActivityResult (int request_code, int result_code, Intent i) { 
     super.onActivityResult(request_code, result_code, i); 

     switch (request_code) { 

      case 100: 
       if (result_code == RESULT_OK && i != null) { 
        ArrayList<String> result = i.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS); 
        text.setText(result.get(0)); 
       } 
       break; 
     } 
    } 


    //a toast for fun 
    public void onTextClick(View view){ 
     Toast.makeText(MainActivity.this, "You are a Genius! ;-)", Toast.LENGTH_SHORT).show(); 
    } 

} 

AndroidManifest.xml中

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    package="com.ika.speechtotext"> 

    <uses-permission android:name="android.permission.RECORD_AUDIO"/> 

    <application 
     android:allowBackup="true" 
     android:icon="@mipmap/ic_launcher" 
     android:label="@string/app_name" 
     android:supportsRtl="true" 
     android:theme="@style/myTheme"> 
     <activity android:name=".MainActivity"> 
      <intent-filter> 
       <action android:name="android.intent.action.MAIN" /> 

       <category android:name="android.intent.category.LAUNCHER" /> 
      </intent-filter> 
     </activity> 
    </application> 

</manifest> 

個更新的代碼行(MainActivity.java):

public void onBtnClick(View view) { 


    if (view.getId() == R.id.imageRecBtn) { 

     //New code lines BEGIN*************************************************************************************************** 

     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 
      //checking the permission status 
      if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != 
        PackageManager.PERMISSION_GRANTED) { 
       //request the permission 
       ActivityCompat.requestPermissions(this, 
         new String[]{Manifest.permission.RECORD_AUDIO}, 
         REQUEST_CODE_RECORD_AUDIO); 

      } else { 

       promptSpeechInput(); 
      } 
     } 
     //New code lines END*************************************************************************************************** 

    } 


} 
+1

看來,你正在檢查其他權限:Manifest.permission.READ_CONTACTS – DmitryArc

+0

@DmitryArc是正確的,你正在尋找READ_CONTACT,並且如果您嘗試檢查音頻許可是否被授予,但是您不輸入該IF語句,那麼在該範圍內。 –

回答

1

有幾個與代碼問題,其涉及到您所看到的問題:

  1. 無論您的應用程序是否已授予的錄製音頻的權限,但它仍然呼籲promptSpeechInput()。除非獲得許可,否則不應該發生這種情況。這意味着只有在此處調用PERMISSION_GRANTED或調用onRequestPermissionResult()才能調用該請求。
  2. 該應用正在檢查READ_CONTACTS,然後請求RECORD_AUDIO
  3. ActivityCompat.shouldShowRequestPermissionRationale()的結果可能不是您所期望的,如果該應用程序以前從未請求過該權限。只有在應用程序請求並被拒絕權限後才能使用此方法。它提供了關於是否應該通知用戶爲什麼需要許可的信息(以及是否需要獲得許可)。

較新的權限模型可能很難處理。您可能會發現這種對新模型的討論很有幫助:https://youtu.be/WGz-alwVh8A

您也可能會發現此權限幫助程序庫更易於使用。它將處理用戶推薦的條件下,提示以及調用相關的「受保護」的代碼時,應用程序有權限:https://github.com/hiqes/andele

+1

謝謝你的回答。教程鏈接非常有幫助。我解決了權限提示問題,但我希望應用程序在授予權限後立即開始錄製語音(現在,我必須再次單擊rec按鈕)。 _提供了更新的'MainActivity.java'片段._ – dzenvikas

+0

您仍然需要添加一個'onRequestPermissionsResult()'回調函數,如果權限被授權,調用'promptSpeechInput()'。 –

0

我沒有我的工作電腦所以我現在不能發佈的代碼,但我給你的步驟去做。

  1. 當用戶點擊錄製按鈕檢查是否記錄授予許可。如果是,則調用promptSpeechInput()方法,否則請求記錄權限。

  2. 覆蓋您的活動中的void onRequestPermissionsResult (int requestCode, String[] permissions, int[] grantResults)方法。在這個檢查裏面,如果requestCode等於你請求的記錄權限的requestCode。如果是,則檢查是否授予許可。如果被授予,則調用promptSpeechInput()方法,否則不做任何事或返回或退出。理由不是必需的,因爲要求記錄音頻的記錄許可顯然是可以理解的。 我希望這很清楚。隨意問任何有關步驟的問題。