Skip to content

Commit

Permalink
feat: Android bluetooth support #210
Browse files Browse the repository at this point in the history
  • Loading branch information
sowens-csd committed Dec 11, 2021
1 parent 597c578 commit 0aba8a2
Show file tree
Hide file tree
Showing 9 changed files with 66 additions and 7 deletions.
5 changes: 5 additions & 0 deletions speech_to_text/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Changelog

## 5.4.0

### New
* Support for bluetooth headsets in Android

## 5.3.0

### New
Expand Down
2 changes: 1 addition & 1 deletion speech_to_text/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# speech_to_text

[![pub package](https://img.shields.io/badge/pub-v5.3.0-blue)](https://pub.dartlang.org/packages/speech_to_text) [![build status](https://github.com/csdcorp/speech_to_text/workflows/build/badge.svg)](https://github.com/csdcorp/speech_to_text/actions?query=workflow%3Abuild) [![codecov](https://codecov.io/gh/csdcorp/speech_to_text/branch/main/graph/badge.svg?token=4LV3HESMS4)](undefined)
[![pub package](https://img.shields.io/badge/pub-v5.4.0-blue)](https://pub.dartlang.org/packages/speech_to_text) [![build status](https://github.com/csdcorp/speech_to_text/workflows/build/badge.svg)](https://github.com/csdcorp/speech_to_text/actions?query=workflow%3Abuild) [![codecov](https://codecov.io/gh/csdcorp/speech_to_text/branch/main/graph/badge.svg?token=4LV3HESMS4)](undefined)

A library that exposes device specific speech recognition capability.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import io.flutter.embedding.engine.plugins.FlutterPlugin
import android.Manifest
import android.annotation.TargetApi
import android.app.Activity
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothHeadset
import android.bluetooth.BluetoothProfile
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Build
Expand Down Expand Up @@ -99,6 +102,10 @@ public class SpeechToTextPlugin :
private var resultSent: Boolean = false
private var speechRecognizer: SpeechRecognizer? = null
private var recognizerIntent: Intent? = null
private var bluetoothAdapter: android.bluetooth.BluetoothAdapter? = null
private var pairedDevices: Set<android.bluetooth.BluetoothDevice>? = null
private var activeBluetooth: android.bluetooth.BluetoothDevice? = null
private var bluetoothHeadset: BluetoothHeadset? = null
private var previousRecognizerLang: String? = null
private var previousPartialResults: Boolean = true
private var previousListenMode: ListenMode = ListenMode.deviceDefault
Expand Down Expand Up @@ -280,6 +287,7 @@ public class SpeechToTextPlugin :
if ( listenModeIndex == ListenMode.dictation.ordinal) {
listenMode = ListenMode.dictation
}
optionallyStartBluetooth()
setupRecognizerIntent(languageTag, partialResults, listenMode, onDevice )
handler.post {
run {
Expand All @@ -292,12 +300,37 @@ public class SpeechToTextPlugin :
debugLog("Start listening done")
}

private fun optionallyStartBluetooth() {
val lbt = bluetoothAdapter
val lpaired = pairedDevices
val lhead = bluetoothHeadset
if (null != lbt && null!= lhead && null != lpaired && lbt.isEnabled()) {
for (tryDevice in lpaired) {
//This loop tries to start VoiceRecognition mode on every paired device until it finds one that works(which will be the currently in use bluetooth headset)
if (lhead.startVoiceRecognition(tryDevice)) {
activeBluetooth = tryDevice;
break
}
}
}
}

private fun optionallyStopBluetooth() {
val lactive = activeBluetooth
val lbt = bluetoothHeadset
if (null != lactive && null != lbt ) {
lbt.stopVoiceRecognition(lactive)
activeBluetooth = null
}
}

private fun stopListening(result: Result) {
if (sdkVersionTooLow() || isNotInitialized() || isNotListening()) {
result.success(false)
return
}
debugLog("Stop listening")
optionallyStopBluetooth()
handler.post {
run {
speechRecognizer?.stopListening()
Expand Down Expand Up @@ -446,7 +479,7 @@ public class SpeechToTextPlugin :
activeResult = null
return
}

setupBluetooth()
createRecognizer()
} else {
debugLog("null context during initialization")
Expand All @@ -466,6 +499,26 @@ public class SpeechToTextPlugin :
activeResult = null
}

private fun setupBluetooth() {
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter()
pairedDevices = bluetoothAdapter?.getBondedDevices()

val mProfileListener: BluetoothProfile.ServiceListener = object : BluetoothProfile.ServiceListener {
override fun onServiceConnected(profile: Int, proxy: BluetoothProfile) {
if (profile == BluetoothProfile.HEADSET) {
bluetoothHeadset = proxy as BluetoothHeadset
}
}

override fun onServiceDisconnected(profile: Int) {
if (profile == BluetoothProfile.HEADSET) {
bluetoothHeadset = null
}
}
}
bluetoothAdapter?.getProfileProxy(pluginContext, mProfileListener, BluetoothProfile.HEADSET)
}

private fun Context.findComponentName(): ComponentName? {
val list: List<ResolveInfo> = packageManager.queryIntentServices(Intent(RecognitionService.SERVICE_INTERFACE), 0)
return list.firstOrNull()?.serviceInfo?.let { ComponentName(it.packageName, it.name) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
package="com.csdcorp.speech_to_text_example">
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.BLUETOOTH"/>
<queries>
<intent>
<action android:name="android.speech.RecognitionService" />
Expand Down
2 changes: 1 addition & 1 deletion speech_to_text/example/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ buildscript {
}

dependencies {
classpath 'com.android.tools.build:gradle:3.6.1'
classpath 'com.android.tools.build:gradle:7.0.3'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip
2 changes: 1 addition & 1 deletion speech_to_text/example/lib/repro.dart
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ class _MyHomePageState extends State<MyHomePage> {
void _onResult(html.SpeechRecognitionEvent event) {
var results = event.results;
if (null == results) return;
for (html.SpeechRecognitionResult recognitionResult in results) {
for (var recognitionResult in results) {
if (null == recognitionResult.length || recognitionResult.length == 0) {
continue;
}
Expand Down
2 changes: 1 addition & 1 deletion speech_to_text/example/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ packages:
path: ".."
relative: true
source: path
version: "5.3.0"
version: "5.4.0"
speech_to_text_platform_interface:
dependency: transitive
description:
Expand Down
2 changes: 1 addition & 1 deletion speech_to_text/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: speech_to_text
description: A Flutter plugin that exposes device specific speech to text recognition capability.
version: 5.3.0
version: 5.4.0
homepage: https://github.com/csdcorp/speech_to_text

environment:
Expand Down

0 comments on commit 0aba8a2

Please sign in to comment.