2

Я создаю простое приложение. То, что я в настоящее время обнаружил, что, когда я открываю мое приложение, следующее разрешение было установлено в .gradle папки:Отключить разрешения для определенной активности в приложении

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

Однако мое приложение имеет вторую деятельность под названием Gvoice.java, который затем опирается на Googles речи текст.

Я обнаружил, что если я сохраню вышеуказанные разрешения в папке .gradle, мое основное окно активности прекрасно работает с pocketsphinx. Однако моя активность Gvoice дает мне сообщение «Не удается открыть микрофон».

Но я обнаружил, что если я удалю три разрешения в папке .gradle. Моя основная деятельность больше не делает то, что я хочу, но мое второе действие под названием Gvoice теперь корректно преобразует речь в текст и не дает мне сообщение «Can not open microphone».

Есть ли простой способ исправить эту проблему, поскольку я считаю, что она определенно должна быть связана с разрешениями микрофона. Также обратите внимание, что всякий раз, когда я возвращаюсь к основному действию, необходимо назначать разрешения, и когда я нахожусь в другом действии вне основного действия, ему необходимо отключить разрешение (или, альтернативно, если есть другой способ сделать это).

Можно ли установить разные разрешения для различных действий в файле манифеста?

Ниже я обновил, что у меня до сих пор, пожалуйста, посмотрите:

public class PocketSphinxActivity extends Activity implements RecognitionListener 
{ 

private static final String KWS_SEARCH = "wakeup"; 

/* Keyword we are looking for to activate menu */ 
private static final String KEYPHRASE = "open voice command"; //adjust this keyphrase here and in string! 

private SpeechRecognizer recognizer; 
private HashMap<String, Integer> captions; 

ListView lv; 
TextView tv; 
EditText a; 
Button b; 
Button c; 

Boolean isDone = false; 

@Override 
public void onCreate(Bundle state) { 
    super.onCreate(state); 

    // Prepare the data for UI 
    captions = new HashMap<String, Integer>(); 
    captions.put(KWS_SEARCH, R.string.kws_caption); 
    setContentView(R.layout.main); 
    ((TextView) findViewById(R.id.caption_text)) 
      .setText("Preparing the recognizer"); 

    lv = (ListView) findViewById(R.id.lvVoiceReturn); 
    tv = (TextView) findViewById(R.id.result_text); 
    a = (EditText) findViewById(R.id.TFusername); 
    b = (Button) findViewById(R.id.bVoice); 
    c = (Button)findViewById(R.id.Blogin); 

    // Recognizer initialization is a time-consuming and it involves IO, 
    // so we execute it in async task 

    new AsyncTask<Void, Void, Exception>() { 
     @Override 
     protected Exception doInBackground(Void... params) { 
      try { 
       Assets assets = new Assets(PocketSphinxActivity.this); 
       File assetDir = assets.syncAssets(); 
       setupRecognizer(assetDir); 
      } catch (IOException e) { 
       return e; 
      } 
      return null; 
     } 

     @Override 
     protected void onPostExecute(Exception result) { 
      if (result != null) { 
       ((TextView) findViewById(R.id.caption_text)) 
         .setText("Failed to init recognizer " + result); 
      } else { 
       switchSearch(KWS_SEARCH); 
      } 
     } 
    }.execute(); 
//line added...///////////////////////// 
    a.addTextChangedListener(new TextWatcher() { 
     @Override 
     public void beforeTextChanged(CharSequence s, int start, int count, int after) { 

     } 

     @Override 
     public void onTextChanged(CharSequence s, int start, int before, int count) { 
      if (s.toString().trim().equalsIgnoreCase("open voice command")) { 
       // 
       //Do your stuff here OR button.performClick() 
       // 

       //DELAY 
       Handler handler = new Handler(); 
       handler.postDelayed(new Runnable() { 
        @Override 
        public void run() { 
         if (!isDone) { 
          b.performClick(); 
          isDone = true; 
         } 
        } 
       }, 500); 
      } 
     } 

     @Override 
     public void afterTextChanged(Editable s) { 

     } 
    }); 
//////////////////////////////////////// 
} 

@Override 
public void onDestroy() { 
    super.onDestroy(); 
    recognizer.cancel(); 
    recognizer.shutdown(); 
} 

/** 
* In partial result we get quick updates about current hypothesis. In 
* keyword spotting mode we can react here, in other modes we need to wait 
* for final result in onResult. 
*/ 
@Override 
public void onPartialResult(Hypothesis hypothesis) { 
    if (hypothesis == null) 
     return; 

    String text = hypothesis.getHypstr(); 
    //((TextView) findViewById(R.id.result_text)).setText(text); 
    ((EditText) findViewById(R.id.TFusername)).setText(text); 
} 

/** 
* This callback is called when we stop the recognizer. 
*/ 
@Override 
public void onResult(Hypothesis hypothesis) { 
    //((TextView) findViewById(R.id.result_text)).setText(""); 
    ((EditText) findViewById(R.id.TFusername)).setText(""); 
    if (hypothesis != null) { 
     String text = hypothesis.getHypstr(); 
     makeText(getApplicationContext(), text, Toast.LENGTH_SHORT).show(); 


    //a.setText((String) tv.getText()); 
     //tv = TextView.getText().toString(); 
    } 
} 

@Override 
public void onBeginningOfSpeech() { 
} 

/** 
* We stop recognizer here to get a final result 
*/ 
@Override 
public void onEndOfSpeech() { 
    if (!recognizer.getSearchName().equals(KWS_SEARCH)) 
     switchSearch(KWS_SEARCH); 
} 

private void switchSearch(String searchName) { 
    recognizer.stop(); 

    // If we are not spotting, start listening with timeout (10000 ms or 10 seconds). 
    if (searchName.equals(KWS_SEARCH)) 
     recognizer.startListening(searchName); 
    else 
     recognizer.startListening(searchName, 10000); 

    String caption = getResources().getString(captions.get(searchName)); 
    ((TextView) findViewById(R.id.caption_text)).setText(caption); 
} 

private void setupRecognizer(File assetsDir) throws IOException { 
    // The recognizer can be configured to perform multiple searches 
    // of different kind and switch between them 

    recognizer = defaultSetup() 
      .setAcousticModel(new File(assetsDir, "en-us-ptm")) 
      .setDictionary(new File(assetsDir, "cmudict-en-us.dict")) 

        // To disable logging of raw audio comment out this call (takes a lot of space on the device) 
      .setRawLogDir(assetsDir) 

        // Threshold to tune for keyphrase to balance between false alarms and misses 
      .setKeywordThreshold(1e-45f) 

        // Use context-independent phonetic search, context-dependent is too slow for mobile 
      .setBoolean("-allphone_ci", true) 

      .getRecognizer(); 
    recognizer.addListener(this); 

    /** In your application you might not need to add all those searches. 
    * They are added here for demonstration. You can leave just one. 
    */ 

    // Create keyword-activation search. 
    recognizer.addKeyphraseSearch(KWS_SEARCH, KEYPHRASE); 

} 

@Override 
public void onError(Exception error) { 
    ((TextView) findViewById(R.id.caption_text)).setText(error.getMessage()); 
} 

@Override 
public void onTimeout() { 
    switchSearch(KWS_SEARCH); 
} 

//Assign button clicks to go to a new activity: 
public void onButtonClick_1(View v){ 
    if (v.getId() == R.id.bVoice){ 
     String str_1 = a.getText().toString(); 

     //Go to the relevant page if any part of the phrase or word entered in the 'EditText' field contains 'command' which is not case sensitive 
     if (str_1.toLowerCase().contains("command")) { 
      Intent userintent = new Intent(PocketSphinxActivity.this, Gvoice.class); 

      startActivity(userintent); 
     } else { 
      Toast.makeText(getApplicationContext(), "Incorrect Information", Toast.LENGTH_SHORT).show(); 
     } 
    } 
} 
+0

Для использования микрофона вам необходимо иметь запись AUDIO, это требование. У вас не может быть такого разрешения для записи голоса, и если требуется, чтобы его отправляли в облако, вам также нужен интернет.И в зависимости от того, какая версия Android, на которой вы работаете, будет меняться, поскольку Andoroid M изменил структуру разрешений. Если его до android M вы не можете изменить свое разрешение во время выполнения вообще. Также не забудьте очистить свои ресурсы. – JoxTraex

+0

Похоже, вы не выпускаете ресурсы микрофона в основной деятельности. Вы можете опубликовать соответствующий исходный код. – ozbek

+0

Я опубликовал исходный код для основного действия, второе действие - просто простая речь в текстовой активности на данный момент, кстати, я бегу на Nexus 6p (Android M) –

ответ

0

В моем комментарии Я сказал:

Использование noHistory не решение, в большинстве случаев это работает. Когда ваше приложение больше не находится на переднем плане, по таким причинам, как входящий звонок, вы не хотите, чтобы ваш пользовательский интерфейс был потерян, вы хотите, чтобы он был приостановлен. Правильное управление onPause и onResume является основным основополагающим требованием, что использование noHistory будет временно предотвращено для вас.

Ниже приведен пример того, как вы управляете объектом recognizer, когда ваше приложение приостановлено и впоследствии возобновлено.

@Override 
protected void onResume() { 
    super.onResume(); 

    if (recognizer == null) { 
     // Set up recognizer again 
    } 
} 

@Override 
protected void onPause() { 
    super.onPause(); 

    if (recognizer != null) { 
     recognizer.cancel(); 
     recognizer.shutdown(); 
     recognizer = null; 
    } 
} 

Хотя разрушив ваше приложение каждый раз, когда он приостановленную, рассосется решением отпуская микрофон и распознаватель ресурс, это не то, что вы хотите сделать - вы хотите, чтобы корректно управлять жизненным циклом приложения перейдя в фоновый режим и снова выйдя на передний план, без ресурсов, на которые вы держите (например, микрофон), что вызывает проблему для других приложений.

+0

Я согласен, мой ответ был отчасти прав, но да, я могу полностью понять, что вы имеете в виду, и, следовательно, даже при нажатии кнопки «Назад» в моем приложении теперь я могу видеть всю историю действий, а не уничтожать то, что было сделано раньше. –

+0

Прохладный. Я добавил недостающую строку, в которой 'распознаватель' должен был быть установлен на' null' в 'onPause()' – brandall

+0

Привет, @brandall, если бы вы могли помочь мне с другим вопросом, который приводит к тому, что вы мне помогли? https://stackoverflow.com/questions/43177064/enable-push-to-talk-microphone-permission-on-android-app –

-1

Я понял, альтернативный метод является добавить следующее в мой файл манифеста android:noHistory="true" это, кажется, очистить историю из основной стек активности, и теперь onClickListener работает во втором действии.

Альтернативы поместить следующую строку в нижней части моего файла MainActivity который является onPause метода, который @brandall предложил:

@Override 
protected void onPause() { 
super.onPause(); 
finish(); 
} 
+0

Единственная проблема, которую я могу сейчас увидеть с помощью этого метода, это то, что он не позволит мне вернуться к основному виду деятельности, есть ли у людей какие-либо другие альтернативы, поскольку мне нужно идти вернуться к основной деятельности время от времени с помощью кнопки нажмите и т.д.? –

+0

Это не то, что я имел в виду в своем комментарии. Я добавлю ответ. – brandall