From ee5c75e10aad5c7fb1819dd7b50891e675d08e77 Mon Sep 17 00:00:00 2001 From: Aditya Mehra Date: Sat, 6 Jun 2020 21:39:41 +0000 Subject: [PATCH] Add support for Bigscreen STT using android's inbuilt speech engine --- AndroidManifest.xml | 1 + res/drawable/ic_mic_black.xml | 9 +++ res/layout/activity_bigscreen.xml | 10 ++++ res/values/strings.xml | 4 ++ .../BigscreenPlugin/BigscreenActivity.java | 58 ++++++++++++++++++- .../BigscreenPlugin/BigscreenPlugin.java | 23 +++++++- 6 files changed, 102 insertions(+), 3 deletions(-) create mode 100644 res/drawable/ic_mic_black.xml diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 8114573b..16cdf2b3 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -37,6 +37,7 @@ + diff --git a/res/drawable/ic_mic_black.xml b/res/drawable/ic_mic_black.xml new file mode 100644 index 00000000..b22ad75f --- /dev/null +++ b/res/drawable/ic_mic_black.xml @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/res/layout/activity_bigscreen.xml b/res/layout/activity_bigscreen.xml index 873e3b85..5fa02ad4 100644 --- a/res/layout/activity_bigscreen.xml +++ b/res/layout/activity_bigscreen.xml @@ -25,6 +25,16 @@ android:src="@drawable/ic_arrow_upward_black_24dp" android:theme="@style/DisableableButton" /> + + Select Right Down + Mic Bigscreen remote Use your device as a remote for Plasma Bigscreen + To share microphone input from your phone you need to give access to the phone\'s audio input + Speech Choose theme @@ -381,4 +384,5 @@ light dark + diff --git a/src/org/kde/kdeconnect/Plugins/BigscreenPlugin/BigscreenActivity.java b/src/org/kde/kdeconnect/Plugins/BigscreenPlugin/BigscreenActivity.java index 9209b919..9d88f764 100644 --- a/src/org/kde/kdeconnect/Plugins/BigscreenPlugin/BigscreenActivity.java +++ b/src/org/kde/kdeconnect/Plugins/BigscreenPlugin/BigscreenActivity.java @@ -21,16 +21,29 @@ package org.kde.kdeconnect.Plugins.BigscreenPlugin; +import android.Manifest; +import android.app.Activity; +import android.content.Intent; import android.os.Bundle; +import android.speech.RecognizerIntent; +import android.speech.SpeechRecognizer; +import android.util.Log; +import android.view.View; import org.kde.kdeconnect.BackgroundService; +import org.kde.kdeconnect.UserInterface.MainActivity; +import org.kde.kdeconnect.UserInterface.PermissionsAlertDialogFragment; import org.kde.kdeconnect.UserInterface.ThemeUtil; import org.kde.kdeconnect_tp.R; import androidx.appcompat.app.AppCompatActivity; +import java.util.ArrayList; + public class BigscreenActivity extends AppCompatActivity { + private static final int REQUEST_SPEECH = 100; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -39,14 +52,57 @@ public class BigscreenActivity extends AppCompatActivity { final String deviceId = getIntent().getStringExtra("deviceId"); - BackgroundService.RunWithPlugin(this, deviceId, org.kde.kdeconnect.Plugins.BigscreenPlugin.BigscreenPlugin.class, plugin -> runOnUiThread(() -> { + if (!SpeechRecognizer.isRecognitionAvailable(this)) { + findViewById(R.id.mic_button).setEnabled(false); + findViewById(R.id.mic_button).setVisibility(View.INVISIBLE); + } + + BackgroundService.RunWithPlugin(this, deviceId, BigscreenPlugin.class, plugin -> runOnUiThread(() -> { findViewById(R.id.left_button).setOnClickListener(v -> plugin.sendLeft()); findViewById(R.id.right_button).setOnClickListener(v -> plugin.sendRight()); findViewById(R.id.up_button).setOnClickListener(v -> plugin.sendUp()); findViewById(R.id.down_button).setOnClickListener(v -> plugin.sendDown()); findViewById(R.id.select_button).setOnClickListener(v -> plugin.sendSelect()); findViewById(R.id.home_button).setOnClickListener(v -> plugin.sendHome()); + findViewById(R.id.mic_button).setOnClickListener(v -> { + if (plugin.hasMicPermission()) { + activateSTT(); + } else { + new PermissionsAlertDialogFragment.Builder() + .setTitle(plugin.getDisplayName()) + .setMessage(R.string.bigscreen_optional_permission_explanation) + .setPositiveButton(R.string.ok) + .setNegativeButton(R.string.cancel) + .setPermissions(new String[]{Manifest.permission.RECORD_AUDIO}) + .setRequestCode(MainActivity.RESULT_NEEDS_RELOAD) + .create().show(getSupportFragmentManager(), null); + } + }); })); } + + public void activateSTT() { + Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); + intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM); + intent.putExtra(RecognizerIntent.EXTRA_PROMPT, R.string.bigscreen_speech_extra_prompt); + startActivityForResult(intent, REQUEST_SPEECH); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == REQUEST_SPEECH) { + if (resultCode == Activity.RESULT_OK && data != null) { + ArrayList result = data + .getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS); + if (result.get(0) != null) { + final String deviceId = getIntent().getStringExtra("deviceId"); + BackgroundService.RunWithPlugin(this, deviceId, BigscreenPlugin.class, plugin -> runOnUiThread(() -> { + plugin.sendSTT(result.get(0)); + })); + } + } + } + } } diff --git a/src/org/kde/kdeconnect/Plugins/BigscreenPlugin/BigscreenPlugin.java b/src/org/kde/kdeconnect/Plugins/BigscreenPlugin/BigscreenPlugin.java index a7528605..f365b472 100644 --- a/src/org/kde/kdeconnect/Plugins/BigscreenPlugin/BigscreenPlugin.java +++ b/src/org/kde/kdeconnect/Plugins/BigscreenPlugin/BigscreenPlugin.java @@ -22,6 +22,7 @@ package org.kde.kdeconnect.Plugins.BigscreenPlugin; +import android.Manifest; import android.app.Activity; import android.content.Intent; import android.graphics.drawable.Drawable; @@ -41,9 +42,11 @@ import static org.kde.kdeconnect.Plugins.MousePadPlugin.KeyListenerView.SpecialK public class BigscreenPlugin extends Plugin { private final static String PACKET_TYPE_MOUSEPAD_REQUEST = "kdeconnect.mousepad.request"; + private final static String PACKET_TYPE_BIGSCREEN_STT = "kdeconnect.bigscreen.stt"; @Override public boolean onCreate() { + optionalPermissionExplanation = R.string.bigscreen_optional_permission_explanation; return device.getDeviceType().equals(Device.DeviceType.Tv); } @@ -85,11 +88,11 @@ public class BigscreenPlugin extends Plugin { } @Override - public String[] getSupportedPacketTypes() { return new String[0]; } + public String[] getSupportedPacketTypes() { return new String[]{PACKET_TYPE_BIGSCREEN_STT}; } @Override public String[] getOutgoingPacketTypes() { - return new String[]{PACKET_TYPE_MOUSEPAD_REQUEST}; + return new String[]{PACKET_TYPE_MOUSEPAD_REQUEST, PACKET_TYPE_BIGSCREEN_STT}; } @Override @@ -97,6 +100,15 @@ public class BigscreenPlugin extends Plugin { return context.getString(R.string.pref_plugin_bigscreen); } + public String[] getOptionalPermissions() { + return new String[]{Manifest.permission.RECORD_AUDIO}; + } + + public Boolean hasMicPermission() { + return isPermissionGranted(Manifest.permission.RECORD_AUDIO); + } + + public void sendLeft() { NetworkPacket np = new NetworkPacket(PACKET_TYPE_MOUSEPAD_REQUEST); np.set("specialKey", SpecialKeysMap.get(KeyEvent.KEYCODE_DPAD_LEFT)); @@ -133,4 +145,11 @@ public class BigscreenPlugin extends Plugin { np.set("specialKey", SpecialKeysMap.get(KeyEvent.KEYCODE_F4)); device.sendPacket(np); } + + public void sendSTT(String content) { + NetworkPacket np = new NetworkPacket(PACKET_TYPE_BIGSCREEN_STT); + np.set("type", "stt"); + np.set("content", content); + device.sendPacket(np); + } }