2 * Copyright (C) 2012-2022 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
9 #include "SpeechRecognitionAndroid.h"
11 #include "speech/ISpeechRecognitionListener.h"
12 #include "speech/SpeechRecognitionErrors.h"
13 #include "utils/log.h"
15 #include "platform/android/activity/JNIMainActivity.h"
16 #include "platform/android/activity/XBMCApp.h"
17 #include "platform/android/speech/SpeechRecognitionListenerAndroid.h"
21 #include <androidjni/Context.h>
22 #include <androidjni/Intent.h>
23 #include <androidjni/IntentFilter.h>
24 #include <androidjni/PackageManager.h>
25 #include <androidjni/RecognizerIntent.h>
26 #include <androidjni/SpeechRecognizer.h>
29 std::shared_ptr
<speech::ISpeechRecognition
> speech::ISpeechRecognition::CreateInstance()
31 return std::make_shared
<CSpeechRecognitionAndroid
>(CXBMCApp::Get());
34 CSpeechRecognitionAndroid::CSpeechRecognitionAndroid(const CJNIContext
& context
)
39 CSpeechRecognitionAndroid::~CSpeechRecognitionAndroid()
43 void CSpeechRecognitionAndroid::StartSpeechRecognition(
44 const std::shared_ptr
<speech::ISpeechRecognitionListener
>& listener
)
46 if (CJNISpeechRecognizer::isRecognitionAvailable(m_context
))
48 if (CJNIContext::checkCallingOrSelfPermission("android.permission.RECORD_AUDIO") ==
49 CJNIPackageManager::PERMISSION_GRANTED
)
51 std::unique_lock
<CCriticalSection
> lock(m_speechRecognitionListenersMutex
);
52 m_speechRecognitionListeners
.emplace_back(
53 std::make_unique
<CSpeechRecognitionListenerAndroid
>(listener
, *this));
56 // speech recognizer init must be called from the main thread:
57 // https://developer.android.com/reference/android/speech/SpeechRecognizer
58 jni::CJNIMainActivity::runNativeOnUiThread(RegisterSpeechRecognitionListener
, this);
62 CLog::LogF(LOGERROR
, "Permission RECORD_AUDIO is not granted");
63 listener
->OnError(speech::RecognitionError::INSUFFICIENT_PERMISSIONS
);
68 CLog::LogF(LOGERROR
, "Speech recognition service is not available");
69 listener
->OnError(speech::RecognitionError::SERVICE_NOT_AVAILABLE
);
73 void CSpeechRecognitionAndroid::RegisterSpeechRecognitionListener(void* thiz
)
75 CSpeechRecognitionAndroid
* sra
= static_cast<CSpeechRecognitionAndroid
*>(thiz
);
77 CJNISpeechRecognizer speechRecognizer
=
78 CJNISpeechRecognizer::createSpeechRecognizer(sra
->m_context
);
80 std::unique_lock
<CCriticalSection
> lock(sra
->m_speechRecognitionListenersMutex
);
81 speechRecognizer
.setRecognitionListener(*(sra
->m_speechRecognitionListeners
.back()));
84 CJNIIntent intent
= CJNIIntent(CJNIRecognizerIntent::ACTION_RECOGNIZE_SPEECH
);
85 intent
.putExtra(CJNIRecognizerIntent::EXTRA_LANGUAGE_MODEL
,
86 CJNIRecognizerIntent::LANGUAGE_MODEL_FREE_FORM
);
88 speechRecognizer
.startListening(intent
);
91 void CSpeechRecognitionAndroid::SpeechRecognitionDone(
92 jni::CJNIXBMCSpeechRecognitionListener
* listener
)
94 std::unique_lock
<CCriticalSection
> lock(m_speechRecognitionListenersMutex
);
95 for (auto it
= m_speechRecognitionListeners
.begin(); it
!= m_speechRecognitionListeners
.end();
98 if ((*it
).get() == listener
)
100 m_speechRecognitionListeners
.erase(it
);