🗣 An overlay that gets your user’s voice permission and input as text in a customizable UI

Overview

Voice Overlay for Android

Platform Android License: MIT Android Arsenal

Overview

Voice overlay helps you turn your user's voice into text, providing a polished UX while handling for you the necessary permission.

       

Demo

You can clone this repo, then run the Demo project by doing ./gradlew app:installDebug and launching the application:

Installation

The Voice overlay is available as a gradle dependency via JCenter. To install it, add the following line to your app's build.gradle:

dependencies {
    // [...]
    implementation 'com.algolia.instantsearch:voice:1.0.0-beta02'
    // [...]
}

Usage

Basic usage

  1. In your Activity, check if you have the permission and show the appropriate Dialog:
if (!isRecordAudioPermissionGranted()) {
    VoicePermissionDialogFragment().show(supportFragmentManager, "DIALOG_PERMISSION")
} else {
    VoiceInputDialogFragment().show(supportFragmentManager, "DIALOG_INPUT")
}

See it implemented in the demo app.

This will display the permission dialog if the RECORD_AUDIO permission was not yet granted, then the voice input dialog once the permission is granted.

Once the user speaks, you will get their input back by implementing VoiceSpeechRecognizer.ResultsListener:

override fun onResults(possibleTexts: Array<out String>) {
    // Do something with the results, for example:
    resultView.text = possibleTexts.firstOrNull()?.capitalize()
}

See it implemented in the demo app.

When the permission is not granted

If the user didn't accept the permission, you should explain the permission's rationale. If they deny the permission, you need to guide them into manually enabling it if they want to use the voice-input feature.

Voice overlay makes it easy to handle all these cases:

override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults)
    if (Voice.isRecordPermissionWithResults(requestCode, grantResults)) {
        when {
            Voice.isPermissionGranted(grantResults) -> showVoiceDialog()
                shouldExplainPermission() -> showPermissionRationale(getPermissionView())
                else -> Voice.showPermissionManualInstructions(getPermissionView())
        }
    }
    // [...] eventual handling of other permissions requested by your app 
}

See it implemented in the demo app.

This will display the permission rationale when the user doesn't allow it, and the manual instructions in case they denied it.

Customization

You can customize your voice overlay in the following ways:

Behavior

Several options let you adapt the voice overlay's behavior to your needs.

Suggestions

You can provide suggestions of what the user could say, to give them some examples.

voiceInputDialogFragment.setSuggestions(
    "64GB Smartphone",
    "Red running shoes",
    "Cheap TV screen"
)

AutoStart

You can prevent the overlay from automatically listening to user input.

/// Requires the user to click the mic to start listening. 
voiceInputDialogFragment.autoStart = false
// [...]
// you can also start listening programmatically with
voiceInputDialogFragment.start()

Copy text

You can change any text displayed in the overlay by overriding its resource in your strings.xml:

<!-- VoiceInputDialogFragment -->
<string name="input_title_listening">Listening…</string>
<string name="input_subtitle_listening">Say something like:</string>
<string name="input_title_error">Sorry, we didn\'t quite get that.</string>
<string name="input_subtitle_error">Try repeating your request.</string>
<string name="input_hint_error">Try again</string>

<!-- VoicePermissionDialogFragment -->
<string name="permission_title">You can use voice search to find products.</string>
<string name="permission_subtitle">May we access your device’s microphone to enable voice search?</string>
<string name="permission_button_allow">Allow microphone access</string>
<string name="permission_button_reject">No</string>

<!-- Rationale/Try Again -->
<string name="permission_rationale">Voice search requires this permission.</string>
<string name="permission_button_again">Request again?</string>

<!-- Manual Instructions -->
<string name="permission_enable_rationale">Permission denied, allow it to use voice search.</string>
<string name="permission_button_enable">Allow recording</string>
<string name="permission_enable_instructions">On the next screen, tap Permissions then Microphone.</string>

Layouts

You can replace the voice overlay's layouts by your own, as long as they respect the following structure:

Permission

Create a layout called voice_input.xml with

  • A ViewGroup container with id @+id/voicePermission
  • A View with id @+id/close for closing the overlay when clicked
  • A TextView with id @+id/title
  • A TextView with id @+id/subtitle

Input

Create a layout called voice_permission.xml with

  • A ViewGroup container with id @+id/voiceInput
  • A VoiceMicrophone with id @+id/microphone to handle the voice input
  • A TextView with id @+id/suggestions to display eventual suggestions
  • A View with id @+id/close for closing the overlay when clicked
  • A TextView with id @+id/title
  • A TextView with id @+id/subtitle
  • An eventual TextView with id @+id/hint to display a hint on error
  • An eventual RippleView with id @+id/ripple if you want to keep the animation

Getting Help

Getting involved

License

The VoiceOverlay is available under the MIT license. See the LICENSE file for more info.

Comments
  • Separate voice input from presenting fragment

    Separate voice input from presenting fragment

    Main feature:

    • Separate VoiceInput from VoiceDialogFragment acting as its presenter

    Other features:

    • Improve wrapping API to expose some SpeechRecognizer settings

    Fixes:

    • 1b5f5a1 - avoid race condition in a defensive programming way (@q-litzler let me know your thoughts on this!)

    Refactor:

    • Improve layouts
    • Simplify some logic, use templated Strings
    opened by PLNech 1
  • Feat/v2

    Feat/v2

    Voice library V2

    • [x] Integrate @q-litzler's ripple design

    • [x] Refactor Fragments to Kotlin

    • VoiceDialogFragment:

      • [x] Improve state handling
      • [x] Refactor suggestions handling (support vararg params, simpler logic)
      • [x] Centralize UI Updates
      • [x] Remove unneccesary logs
      • [x] Better errors
    • PermissionDialogFragment:

      • [x] Simplify while converting (LOC /2)
    • [x] Move demo's helper functions in the library as Voice.foo()

    opened by PLNech 1
  • refact: library revamp

    refact: library revamp

    • Update Kotlin version to 1.4.31
    • Replace deprecated plugin kotlin-android-extension
    • Migrate from android support to androidx
    • Disable stop listening button click for Android 9 and 10 (due to this bug)
    • Replace deprecated release process
    opened by Aallam 0
  • refactor: optional suggestions

    refactor: optional suggestions

    Feat

    • Make suggestions optional (adapting subtitle when any)

    UI

    • Hide "Try again" when the user clicks the button but already uttered something

    Style

    • Block body to avoid returning sth
    opened by PLNech 0
  • Feature/update coroutines and dependencies

    Feature/update coroutines and dependencies

    Use latest coroutine version and API change. Tie coroutine lifecycle to attach / detach method calls. General dependencies update Change min SDK to 14

    opened by q-litzler 0
  • Feat/customization

    Feat/customization

    • Expose autoStop
    • Expose Extension functions whenever valuable

      e.g. I felt turning isPermissionGranted(grantResult: IntArray) into IntArray.isPermissionGranted() would make sense, but only if done consistently with isRecordPermissionWithResults. As both Int.isRecordPermissionWithResults(grantResults: IntArray) and IntArray.isRecordPermissionWithResults(requestCode: Int) would feel weird, I stuck with staticness for both functions.

    • Add @JVMOverloads when it improves Java DX
    opened by PLNech 0
  • feat: Instructions for manual enabling of permission

    feat: Instructions for manual enabling of permission

    Feature

    Flow for manual enabling of recording permission.

    • Implementation in app, with default UI:
    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (Voice.isRecordPermissionWithResults(requestCode, grantResults)) {
            when {
                Voice.isPermissionGranted(grantResults) -> showVoiceDialog()
                Voice.shouldExplainPermission(this) -> Voice.showPermissionRationale(getPermissionView(), this)
                else -> Voice.showPermissionManualInstructions(getPermissionView())
            }
        }
    }
    
    • Users can customize the rationale's message/CTA (whyAllow, buttonAllow), and the manual instructions' message/CTA/instructions (whyEnable, buttonEnable, howEnable)
    • If one wants a different UI, they can call Voice.openAppSettings() from their own UI logic

    Questions

    • As showPermissionRationale and showPermissionManualInstructions have two overloads for String and StringRes parameters, default arguments caused an Overload resolution ambiguity. The solution I found was a third overload with the minimum amount of arguments, but let me know if you have a better approach!

    • WDYT of refactoring all those as Activity.* extension methods? I feel it improves DX by allowing this.showX() instead of Voice.showX(this), but might pollute the scope/prevent discoverability (for example with Activity.openAppSettings()). @q-litzler what's your take on this?

    • Documenting overloads results in duplicated documentation. Is there a way to avoid that or is it a necessary evil? :thinking:

    opened by PLNech 0
  • feat(VoiceDialogFragment): Persist suggestions

    feat(VoiceDialogFragment): Persist suggestions

    Persistence of VoiceDialogFragment's state. I considered persisting VoiceInput.State too, but realized that it would require moving away from

        override fun onPause() {
            super.onPause()
            input.stopVoiceRecognition()
        }
    
        override fun onResume() {
            super.onResume()
            input.startVoiceRecognition()
        }
    

    to a more complicated handling of state. I feel it doesn't deserve the added complexity, as on fragment recreation we likely want to listen anyway (if there was an error/pause before the change, what's the value that restoring this state brings versus just listening again for input?)

    opened by PLNech 0
  • refactor: Permission dialog now uses arguments.

    refactor: Permission dialog now uses arguments.

    • Use arguments instead of public variables in fragment
    • I'm more in favor of camel casing const variables: RequestPermissionAudio rather than REQUEST_PERMISSION_AUDIO No need to yell (caps) and I always found that Kotlin required a more "smooth" approach 😆
    opened by q-litzler 0
  • Feature/feat/kotlin guidelines

    Feature/feat/kotlin guidelines

    Sorry about the "feature/feat".

    Should have been just "feature", which is the default name proposed by git flow.

    Takeaway:

    • 4 spaces continuation indent instead of 8 (please 🙏 )
    • Use object instead of class with a companion object
    • Line breaks after class declaration
    • Line breaks in constructor parameters
    • Use = Unit for non empty methods
    • Use = ... Syntax for function with simple return values (see Voice)
    opened by q-litzler 0
  • v2.1: Some fixes and a demo app

    v2.1: Some fixes and a demo app

    Update: separated VoiceInput from presenter, see #5 Refactoring:

    • Update import value
    • Leverage requireActivity in PDF

    API Improvements:

    • only require List in VDF's listener

    Fixes:

    • fix missing negation in Voice.hasRecordPermission
    opened by PLNech 0
Releases(1.1.0)
Owner
Algolia
Open source tools for building search. Learn more at community.algolia.com
Algolia
Make your native android Dialog Fancy and Gify. A library that takes the standard Android Dialog to the next level with a variety of styling options and Gif's. Style your dialog from code.

FancyGifDialog-Android Prerequisites Add this in your root build.gradle file (not your module build.gradle file): allprojects { repositories { ...

Shashank Singhal 522 Jan 2, 2023
Android has a built in microphone through which you can capture audio and store it , or play it in your phone. There are many ways to do that but with this dialog you can do all thats with only one dialog.

# Media Recorder Dialog ![](https://img.shields.io/badge/Platform-Android-brightgreen.svg) ![](https://img.shields.io/badge/Android-CustomView-blue.sv

Abdullah Alhazmy 73 Nov 29, 2022
AlertDialog for Android, a beautiful and material alert dialog to use in your android app.

AlertDialog for Android, a beautiful and material alert dialog to use in your android app. Older verion of this library has been removed

Akshay Masram 124 Dec 28, 2022
Sleek dialogs and bottom-sheets for quick use in your app

⭐ ‎‎‎‏‏‎ ‎Offers a range of beautiful sheets (dialogs & bottom sheets) for quick use in your project. Includes many ways to customize sheets.

Maximilian Keppeler 835 Dec 25, 2022
An easy-to-use Android library that will help you to take screenshots of specif views of your app and save them to external storage (Including API 29 Q+ with Scope Storage)

???? English | ???? Português (pt-br) ???? English: An easy to use Library that will help you to take screenshots ?? of the views in your app Step 1.

Thyago Neves Silvestre 2 Dec 25, 2021
Extremely useful library to validate EditText inputs whether by using just the validator for your custom view or using library's extremely resizable & customisable dialog

Extremely useful library for validating EditText inputs whether by using just the validator (OtpinVerification) for your custom view or using library's extremely resizable & customisable dialog (OtpinDialogCreator)

Ehma Ugbogo 17 Oct 25, 2022
⭐ ‎‎‎‏‏‎ ‎Offers a range of beautiful sheets (dialogs & bottom sheets) for quick use in your project. Includes many ways to customize sheets.

Sheets Sleek dialogs and bottom-sheets for quick use in your app. Choose one of the available sheets or build custom sheets on top of the existing fun

Maximilian Keppeler 838 Dec 30, 2022
[Deprecated] This project can make it easy to theme and custom Android's dialog. Also provides Holo and Material themes for old devices.

Deprecated Please use android.support.v7.app.AlertDialog of support-v7. AlertDialogPro Why AlertDialogPro? Theming Android's AlertDialog is not an eas

Feng Dai 468 Nov 10, 2022
SweetAlert for Android, a beautiful and clever alert dialog

Sweet Alert Dialog SweetAlert for Android, a beautiful and clever alert dialog 中文版 Inspired by JavaScript SweetAlert Demo Download ScreenShot Setup Th

书呆子 7.3k Dec 30, 2022
😍 A beautiful, fluid, and extensible dialogs API for Kotlin & Android.

Material Dialogs View Releases and Changelogs Modules The core module is the fundamental module that you need in order to use this library. The others

Aidan Follestad 19.5k Dec 29, 2022
Make a Popup appear long pressing on a view and handle drag-release events on its elements

LongPressPopup You can try the demo app on google play store. https://play.google.com/store/apps/details?id=rm.com.longpresspopupsample Or see the ful

Riccardo Moro 253 Dec 29, 2022
A highlight lib and also it can be a simple popup window lib for android

HighlightPro 中文 HighlightPro is a highlight library for android and also it can be a simple popup window library for android. Features: One or more hi

heyangyang 192 Jan 2, 2023
An beautiful and easy to use dialog library for Android

An beautiful and easy to use dialog library for Android

ShouHeng 22 Nov 8, 2022
🗣 An overlay that gets your user’s voice permission and input as text in a customizable UI

Overview Voice overlay helps you turn your user's voice into text, providing a polished UX while handling for you the necessary permission. Demo You c

Algolia 228 Nov 25, 2022
Extensible Android mobile voice framework: wakeword, ASR, NLU, and TTS. Easily add voice to any Android app!

Spokestack is an all-in-one solution for mobile voice interfaces on Android. It provides every piece of the speech processing puzzle, including voice

Spokestack 57 Nov 20, 2022
Dark-souls-overlay - Stream overlay for e.g. a death counter in dark souls

(Dark Souls) Text Overlay Stream-overlay to include in Dark-Souls sessions for e

Florian Mötz 0 Dec 15, 2022
Ask Permission - Simple RunTime permission manager

Ask Permission https://kishanjvaghela.github.io/Ask-Permission/ Simple RunTime permission manager How to use Add url to your gradle file compile 'com.

Kishan Vaghela 77 Nov 18, 2022
AndroidPermissions 4.2 0.0 Java Android M was added to check Permission. but Permission check processing is so dirty.

Android Permissions Checker Android M was added to check Permission. but Permission check processing is so dirty. This Project is to be simple, Checki

Steve SeongUg Jung 340 Nov 11, 2022
Ask Permission - Simple RunTime permission manager

Ask Permission https://kishanjvaghela.github.io/Ask-Permission/ Simple RunTime permission manager How to use Add url to your gradle file compile 'com.

Kishan Vaghela 77 Nov 18, 2022
Location-permission-handler - Location Permission Handler For Android

Location Permission Handler Easy way to check location permissions for Android 9

null 1 Feb 1, 2022