voice icon indicating copy to clipboard operation
voice copied to clipboard

Voice.isAvailable() returns false on Android 11 - fix for Expo plugin.

Open vivekvrao opened this issue 3 years ago • 10 comments

Voice.isAvailable() returns empty list on Android 11 . Seems to be because of package visibility changes as discussed in https://github.com/react-native-voice/voice/issues/304 and can be fixed by making the addition to manifest below.

As of Expo build 42 - it is possible to use react-native-voice in Expo with custom Eas builds. But that doesn't allow for adding queries to the manifest. Can this be added in the expo plugin of the library?

I looked at - https://github.com/react-native-voice/voice/blob/master/plugin/src/withVoice.ts -but is not obvious how to do this.

https://developer.android.com/about/versions/11/privacy/package-visibility

Due to Android 11 change, you have to add below code in your manifest xml file.

<manifest...>
    <queries>
        <intent>
            <action android:name="android.speech.RecognitionService" />
        </intent>
    </queries>
   ...

Originally posted by @boolgom in https://github.com/react-native-voice/voice/issues/304#issuecomment-826747377

vivekvrao avatar Aug 21 '21 23:08 vivekvrao

I have tested this, works well!

rodolfobarretoweb avatar Sep 22 '21 14:09 rodolfobarretoweb

Hi all,

What is the ETA to get this into release? Right now, with expo config plugins, the fix is not working with latest release.

-thanks, DP

techpanga avatar Sep 25 '21 17:09 techpanga

Hi all

I'm facing the below issue while running the code. I just upgrade to android 11. Is the anything I missed, please help if any finding

Error: unexpected element queries found in manifest application

android/build.gradle

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    ext {
        buildToolsVersion = "30.0.2"
        minSdkVersion = 16
        compileSdkVersion = 30
        targetSdkVersion = 30
        googlePlayServicesVersion = "+"
        firebaseVersion = "+"
    }
    repositories {
        google()
        jcenter()
        mavenCentral()
    }
    dependencies {
        classpath("com.android.tools.build:gradle:3.5.2")
        classpath 'com.google.gms:google-services:4.3.4'
        classpath 'com.google.firebase:firebase-crashlytics-gradle:2.4.1'
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        mavenLocal()
        maven {
            // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
            url("$rootDir/../node_modules/react-native/android")
        }
        maven {
            // Android JSC is installed from npm
            url("$rootDir/../node_modules/jsc-android/dist")
        }

        google()
        jcenter()
        maven { url 'https://www.jitpack.io' }
    }
}

Added below code in the AndroidManifest.xml file

<!-- Image capture & Speech to Text fixes -->
      <queries>
        <intent>
            <action android:name="android.speech.RecognitionService" />
        </intent>
      </queries>

gradle-wrapper.properties

distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.0.1-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

vineelk8 avatar Nov 25 '21 08:11 vineelk8

Hi all,

What is the ETA to get this into release? Right now, with expo config plugins, the fix is not working with latest release.

-thanks, DP

hey did you ever get a fix? still not working for me

jimdog1001 avatar Jan 14 '22 21:01 jimdog1001

vivekvrao, I've managed to get some working code for the expo plugin. I've made a PR here. I have an NPM package you can use to test in the interim: @nonsenselearning/voice. Hope this helps!

tslater avatar Jun 30 '22 03:06 tslater

@nonsenselearning/voice

How did you get it to work?

aha85b avatar Jul 21 '22 04:07 aha85b

I made a PR above #396. Until that gets accepted, you can use my fork. This is what I put in my package.json:

{
...
  "dependencies": {
       "@nonsenselearning/voice": "^3.2.6",
    }
}

and then when you import:

 const  Voice = require('@nonsenselearning/voice').default

tslater avatar Jul 21 '22 15:07 tslater

I'm running on all latest versions of everything (literally started playing around with this today) and it still doesn't work. I followed the tutorials from here:

  • https://docs.expo.dev/development/getting-started/
  • https://github.com/react-native-voice/voice

I also added the following to my local config (because I found them here and in other places)

    <package android:name="com.google.android.googlequicksearchbox"/>
    <intent>
      <action android:name="android.speech.RecognitionService" />
    </intent>
    <intent>
      <action android:name="android.speech.SpeechRecognizer" />
    </intent>

with no result.

I even followed this to request for permissions in an expo-friendly way (https://docs.expo.dev/versions/v46.0.0/sdk/audio/), but also - with no result.

and my services list is still empty (it's a Promise these days btw)

WrRaThY avatar Aug 25 '22 20:08 WrRaThY

For react native cli add this in manifest <uses-permission android:name="android.permission.RECORD_AUDIO" /> <queries> <package android:name="com.google.android.googlequicksearchbox"/> </queries> queries> <intent> <action android:name="android.speech.RecognitionService" /> </intent> </queries> <queries> <intent> <action android:name="android.speech.SpeechRecognizer" /> </intent> </queries>

last step make sure google llc is installed on your device :) this worked for me

cdcHub avatar Apr 09 '23 01:04 cdcHub

Hello Expo users,

I wanted to share some updates regarding the config plugin by @tslater. I've made some enhancements, and thanks to the comment from @cdcHub, I've added additional values into the config plugin.

For react native cli add this in manifest <uses-permission android:name="android.permission.RECORD_AUDIO" /> <queries> <package android:name="com.google.android.googlequicksearchbox"/> </queries> queries> <intent> <action android:name="android.speech.RecognitionService" /> </intent> </queries> <queries> <intent> <action android:name="android.speech.SpeechRecognizer" /> </intent> </queries>

last step make sure google llc is installed on your device :) this worked for me

const {
  AndroidConfig,
  createRunOncePlugin,
  withAndroidManifest,
} = require("@expo/config-plugins");

const withAndroidPermissions = (config) => {
  return AndroidConfig.Permissions.withPermissions(config, [
    "android.permission.RECORD_AUDIO",
  ]);
};

const androidVoiceRecognitionIntent = {
  intent: {
    action: {
      $: {
        "android:name": "android.speech.RecognitionService",
      },
    },
  },
};

const androidSpeechRecognizerIntent = {
  intent: {
    action: {
      $: {
        "android:name": "android.speech.SpeechRecognizer",
      },
    },
  },
};

const googlequicksearchbox = {
  package: {
    $: { "android:name": "com.google.android.googlequicksearchbox" },
  },
};

const withAndroidManifestFixForAndroid11 = (config) => {
  return withAndroidManifest(config, async (config) => {
    let androidManifest = config.modResults.manifest;
    // @ts-ignore
    let queries = androidManifest["queries"] || [];
    queries.push(androidVoiceRecognitionIntent);
    queries.push(androidSpeechRecognizerIntent);
    queries.push(googlequicksearchbox);
    // @ts-ignore
    androidManifest["queries"] = queries;
    return config;
  });
};

const withVoice = (config) => {
  config = withAndroidPermissions(config);
  config = withAndroidManifestFixForAndroid11(config);
  return config;
};

module.exports = createRunOncePlugin(withVoice, "withVoiceCustom", "1.0.0");

You can add that custom plugin directly into app.json's plugin array

"plugins": [
  "./src/plugins/with-voice-custom.js"
],

erdemgonul avatar Jan 10 '24 22:01 erdemgonul