Skip to content

Commit b89b571

Browse files
committed
Updated Service Type config to use a Class type instead of reflexion over a String class name.
1 parent 3f73353 commit b89b571

File tree

3 files changed

+60
-85
lines changed

3 files changed

+60
-85
lines changed

app/src/main/java/com/chattylabs/demo/voice/MainActivity.java

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55
import android.media.AudioManager;
66
import android.os.Bundle;
77
import android.support.annotation.NonNull;
8-
import android.support.annotation.Nullable;
9-
import android.support.constraint.ConstraintLayout;
108
import android.support.v4.app.ActivityCompat;
119
import android.util.Log;
1210
import android.util.Pair;
@@ -28,9 +26,10 @@
2826
import com.chattylabs.sdk.android.common.PermissionsHelper;
2927
import com.chattylabs.sdk.android.common.Tag;
3028
import com.chattylabs.sdk.android.common.ThreadUtils;
29+
import com.chattylabs.sdk.android.voice.AndroidSpeechRecognizer;
3130
import com.chattylabs.sdk.android.voice.AndroidSpeechSynthesizer;
32-
import com.chattylabs.sdk.android.voice.ComponentConfig;
3331
import com.chattylabs.sdk.android.voice.ConversationalFlowComponent;
32+
import com.chattylabs.sdk.android.voice.GoogleSpeechRecognizer;
3433
import com.chattylabs.sdk.android.voice.GoogleSpeechSynthesizer;
3534
import com.chattylabs.sdk.android.voice.Peripheral;
3635
import com.chattylabs.sdk.android.voice.TextFilterForUrl;
@@ -58,23 +57,26 @@
5857
public class MainActivity extends DaggerAppCompatActivity
5958
implements ActivityCompat.OnRequestPermissionsResultCallback {
6059

61-
public static final String TAG = Tag.make(MainActivity.class);
60+
private static final String TAG = Tag.make(MainActivity.class);
6261

6362
// Constants
64-
public static final int CHECK = 3;
65-
public static final int LISTEN = 2;
66-
public static final int READ = 1;
63+
private static final int CHECK = 3;
64+
private static final int LISTEN = 2;
65+
private static final int READ = 1;
66+
67+
private static final String ANDROID = "Android";
68+
private static final String GOOGLE = "Google";
69+
// ...
6770

6871
private static LinkedHashMap<Integer, String> addonMap = new LinkedHashMap<>();
6972
static {
70-
addonMap.put(0, "Android");
71-
addonMap.put(1, "Google");
73+
addonMap.put(0, ANDROID);
74+
addonMap.put(1, GOOGLE);
7275
}
7376

74-
private static String ADDON_TYPE = "Android";
77+
private static String ADDON_TYPE = addonMap.get(0);
7578

7679
// Resources
77-
private ConstraintLayout root;
7880
private TextView execution;
7981
private Spinner actionSpinner;
8082
private Spinner addonSpinner;
@@ -86,7 +88,6 @@ public class MainActivity extends DaggerAppCompatActivity
8688
private ArrayAdapter<CharSequence> actionAdapter;
8789
private ArrayAdapter<String> addonAdapter;
8890
private CheckBox scoCheck;
89-
private Menu menu;
9091
private ThreadUtils.SerialThread serialThread;
9192

9293
// Components
@@ -136,23 +137,22 @@ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permis
136137
if (PermissionsHelper.isPermissionRequest(requestCode)) {
137138
if (PermissionsHelper.isPermissionGranted(grantResults)) {
138139
serialThread.addTask(() -> {
139-
//component = ConversationalFlowModule.provideComponent();
140140
component.updateConfiguration(builder ->
141141
builder .setGoogleCredentialsResourceFile(() -> R.raw.credential)
142142
.setRecognizerServiceType(() -> {
143143
switch (ADDON_TYPE) {
144-
case "Google":
145-
return ComponentConfig.RECOGNIZER_SERVICE_GOOGLE;
144+
case GOOGLE:
145+
return GoogleSpeechRecognizer.class;
146146
default:
147-
return ComponentConfig.RECOGNIZER_SERVICE_ANDROID;
147+
return AndroidSpeechRecognizer.class;
148148
}
149149
})
150150
.setSynthesizerServiceType(() -> {
151151
switch (ADDON_TYPE) {
152-
case "Google":
153-
return ComponentConfig.SYNTHESIZER_SERVICE_GOOGLE;
152+
case GOOGLE:
153+
return GoogleSpeechSynthesizer.class;
154154
default:
155-
return ComponentConfig.SYNTHESIZER_SERVICE_ANDROID;
155+
return AndroidSpeechSynthesizer.class;
156156
}
157157
})
158158
.build());
@@ -191,7 +191,6 @@ private void initActions() {
191191
});
192192
}
193193

194-
@Nullable
195194
private void representQueue(int index) {
196195
StringBuilder tx = null;
197196
boolean isChecking = false;
@@ -293,7 +292,7 @@ private void listen(int index) {
293292
@NonNull
294293
private String getErrorString(int i1) {
295294
switch (ADDON_TYPE) {
296-
case "Google":
295+
case GOOGLE:
297296
return GoogleSpeechSynthesizer.getErrorType(i1);
298297
default:
299298
return AndroidSpeechSynthesizer.getErrorType(i1);
@@ -316,8 +315,8 @@ private void readAll() {
316315
Pair<Integer, String> item = queue.get(i);
317316
if (item.first == READ) {
318317
play(item.second, i);
319-
// TODO: Check! How it continues speaking after listening?
320318
} else if (i == 0 && item.first == LISTEN) {
319+
// FIXME: Check why it continues speaking sometimes after listening
321320
listen(-1);
322321
}
323322
}
@@ -339,7 +338,6 @@ public void onResume() {
339338
}
340339

341340
private void initViews() {
342-
root = findViewById(R.id.root);
343341
execution = findViewById(R.id.execution);
344342
actionSpinner = findViewById(R.id.spinner);
345343
addonSpinner = findViewById(R.id.addon);
@@ -349,7 +347,7 @@ private void initViews() {
349347
proceed = findViewById(R.id.proceed);
350348
scoCheck = findViewById(R.id.bluetooth_sco);
351349

352-
//
350+
// Check if there is a Bluetooth device connected and setup the config for a Sco connection
353351
scoCheck.setOnCheckedChangeListener((buttonView, isChecked) -> {
354352
if (isChecked && !peripheral.get(Peripheral.Type.BLUETOOTH).isConnected()) {
355353
buttonView.setChecked(false);
@@ -364,6 +362,7 @@ private void initViews() {
364362
});
365363
});
366364
proceed.setEnabled(false);
365+
367366
// Create an ArrayAdapter of the actions
368367
actionAdapter = ArrayAdapter.createFromResource(this, R.array.actions, android.R.layout.simple_spinner_item);
369368
actionAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
@@ -383,6 +382,7 @@ public void onItemSelected(AdapterView<?> parent, View view, int position, long
383382
public void onNothingSelected(AdapterView<?> parent) {
384383
}
385384
});
385+
386386
// Create an ArrayAdapter of the addons
387387
List<String> addonList = Arrays.asList(addonMap.values().toArray(new String[addonMap.size()]));
388388
addonAdapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item,

sdk-conversational-flow-core/src/main/java/com/chattylabs/sdk/android/voice/ComponentConfig.java

Lines changed: 16 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,21 @@
11
package com.chattylabs.sdk.android.voice;
22

3-
import android.support.annotation.IntDef;
43
import android.support.annotation.RawRes;
54

6-
import java.lang.annotation.Retention;
7-
import java.lang.annotation.RetentionPolicy;
5+
import static com.chattylabs.sdk.android.voice.ConversationalFlowComponent.SpeechRecognizer;
6+
import static com.chattylabs.sdk.android.voice.ConversationalFlowComponent.SpeechSynthesizer;
87

98
public class ComponentConfig {
10-
public static final int SYNTHESIZER_SERVICE_ANDROID = 0x6e44ad;
11-
public static final int RECOGNIZER_SERVICE_ANDROID = 0x5a4ed1;
12-
public static final int SYNTHESIZER_SERVICE_GOOGLE = 0xaa88d6;
13-
public static final int RECOGNIZER_SERVICE_GOOGLE = 0xcd231a;
14-
15-
@Retention(RetentionPolicy.SOURCE)
16-
@IntDef(flag=true,
17-
value = {
18-
SYNTHESIZER_SERVICE_ANDROID,
19-
RECOGNIZER_SERVICE_ANDROID,
20-
SYNTHESIZER_SERVICE_GOOGLE,
21-
RECOGNIZER_SERVICE_GOOGLE
22-
})
23-
public @interface ServiceType {}
9+
static final String SYNTHESIZER_SERVICE_ANDROID = "AndroidSpeechSynthesizer";
10+
static final String RECOGNIZER_SERVICE_ANDROID = "AndroidSpeechRecognizer";
11+
static final String SYNTHESIZER_SERVICE_GOOGLE = "GoogleSpeechSynthesizer";
12+
static final String RECOGNIZER_SERVICE_GOOGLE = "GoogleSpeechRecognizer";
2413

2514
private LazyProvider<Boolean> bluetoothScoRequired;
2615
private LazyProvider<Boolean> audioExclusiveRequiredForSynthesizer;
2716
private LazyProvider<Boolean> audioExclusiveRequiredForRecognizer;
28-
private ServiceTypeLazyProvider recognizerServiceType;
29-
private ServiceTypeLazyProvider synthesizerServiceType;
17+
private LazyProvider<Class<? extends SpeechRecognizer>> recognizerServiceType;
18+
private LazyProvider<Class<? extends SpeechSynthesizer>> synthesizerServiceType;
3019
private RawResourceLazyProvider googleCredentialsResourceFile;
3120

3221
private ComponentConfig(Builder builder) {
@@ -50,13 +39,11 @@ public boolean isAudioExclusiveRequiredForRecognizer() {
5039
return audioExclusiveRequiredForRecognizer.get();
5140
}
5241

53-
@ServiceType
54-
public int getRecognizerServiceType() {
42+
public Class<? extends SpeechRecognizer> getRecognizerServiceType() {
5543
return recognizerServiceType.get();
5644
}
5745

58-
@ServiceType
59-
public int getSynthesizerServiceType() {
46+
public Class<? extends SpeechSynthesizer> getSynthesizerServiceType() {
6047
return synthesizerServiceType.get();
6148
}
6249

@@ -69,8 +56,8 @@ public static final class Builder {
6956
private LazyProvider<Boolean> bluetoothScoRequired;
7057
private LazyProvider<Boolean> audioExclusiveRequiredForSynthesizer;
7158
private LazyProvider<Boolean> audioExclusiveRequiredForRecognizer;
72-
private ServiceTypeLazyProvider recognizerServiceType;
73-
private ServiceTypeLazyProvider synthesizerServiceType;
59+
private LazyProvider<Class<? extends SpeechRecognizer>> recognizerServiceType;
60+
private LazyProvider<Class<? extends SpeechSynthesizer>> synthesizerServiceType;
7461
private RawResourceLazyProvider googleCredentialsResourceFile;
7562

7663
public Builder() {
@@ -100,12 +87,14 @@ public Builder setAudioExclusiveRequiredForRecognizer(LazyProvider<Boolean> lazy
10087
return this;
10188
}
10289

103-
public Builder setRecognizerServiceType(ServiceTypeLazyProvider lazyRecognizerServiceType) {
90+
public Builder setRecognizerServiceType(
91+
LazyProvider<Class<? extends SpeechRecognizer>> lazyRecognizerServiceType) {
10492
this.recognizerServiceType = lazyRecognizerServiceType;
10593
return this;
10694
}
10795

108-
public Builder setSynthesizerServiceType(ServiceTypeLazyProvider lazyRecognizerServiceType) {
96+
public Builder setSynthesizerServiceType(
97+
LazyProvider<Class<? extends SpeechSynthesizer>> lazyRecognizerServiceType) {
10998
this.synthesizerServiceType = lazyRecognizerServiceType;
11099
return this;
111100
}
@@ -128,10 +117,6 @@ public interface LazyProvider<T> {
128117
T get();
129118
}
130119

131-
public interface ServiceTypeLazyProvider {
132-
@ServiceType int get();
133-
}
134-
135120
public interface RawResourceLazyProvider {
136121
@RawRes int get();
137122
}

sdk-conversational-flow-core/src/main/java/com/chattylabs/sdk/android/voice/ConversationalFlowComponentImpl.java

Lines changed: 20 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717

1818
final class ConversationalFlowComponentImpl implements ConversationalFlowComponent {
1919

20-
2120
static class Instance {
2221
static SoftReference<ConversationalFlowComponent> instanceOf;
2322
static ConversationalFlowComponent get() {
@@ -46,8 +45,6 @@ private Instance(){}
4645
ConversationalFlowComponentImpl() {
4746
configuration = new ComponentConfig.Builder()
4847
.setBluetoothScoRequired(() -> false)
49-
.setRecognizerServiceType(() -> ComponentConfig.RECOGNIZER_SERVICE_ANDROID)
50-
.setSynthesizerServiceType(() -> ComponentConfig.SYNTHESIZER_SERVICE_ANDROID)
5148
.setAudioExclusiveRequiredForSynthesizer(() -> false)
5249
.setAudioExclusiveRequiredForRecognizer(() -> true)
5350
.build();
@@ -81,13 +78,11 @@ void setLogger(ILogger logger) {
8178

8279
@Override
8380
public String[] requiredPermissions() {
84-
return new String[]{Manifest.permission.RECORD_AUDIO};
81+
return new String[]{ Manifest.permission.RECORD_AUDIO };
8582
}
8683

87-
private <T> T newInstance(String className, Object... parameters) throws
88-
ClassNotFoundException, IllegalAccessException,
89-
InvocationTargetException, InstantiationException {
90-
Class cls = Class.forName(className);
84+
private <T> T newInstance(Class cls, Object... parameters) throws
85+
IllegalAccessException, InvocationTargetException, InstantiationException {
9186
//noinspection unchecked
9287
Constructor constructor = cls.getConstructors()[0];
9388
//noinspection unchecked
@@ -105,41 +100,36 @@ private void init(Application application) {
105100
}
106101
if (bluetoothSco == null) bluetoothSco = new BluetoothSco(application, audioManager, logger);
107102
try {
108-
String packageName = getClass().getPackage().getName();
109-
String className;
110103
if (speechSynthesizer == null) {
111-
switch (configuration.getSynthesizerServiceType()) {
104+
switch (configuration.getSynthesizerServiceType().getSimpleName()) {
112105
case ComponentConfig.SYNTHESIZER_SERVICE_GOOGLE:
113-
className = packageName + ".GoogleSpeechSynthesizer";
114-
speechSynthesizer = newInstance(className, application, configuration, audioManager,
115-
bluetoothSco, logger);
106+
speechSynthesizer = newInstance(configuration.getSynthesizerServiceType(),
107+
application, configuration, audioManager, bluetoothSco, logger);
116108
break;
117109
default:
118-
className = packageName + ".AndroidSpeechSynthesizer";
119-
speechSynthesizer = newInstance(className, application, configuration, audioManager,
120-
bluetoothSco, logger);
110+
speechSynthesizer = newInstance(configuration.getSynthesizerServiceType(),
111+
application, configuration, audioManager, bluetoothSco, logger);
121112
break;
122113
}
123114
}
124115
if (speechRecognizer == null) {
125-
switch (configuration.getRecognizerServiceType()) {
116+
switch (configuration.getRecognizerServiceType().getSimpleName()) {
126117
case ComponentConfig.RECOGNIZER_SERVICE_GOOGLE:
127-
className = packageName + ".GoogleSpeechRecognizer";
128-
speechRecognizer = newInstance(className, application, configuration, audioManager,
129-
bluetoothSco, logger);
118+
speechRecognizer = newInstance(configuration.getSynthesizerServiceType(),
119+
application, configuration, audioManager, bluetoothSco, logger);
130120
break;
131121
default:
132-
className = packageName + ".AndroidSpeechRecognizer";
133-
speechRecognizer = newInstance(className, application,
134-
configuration, audioManager, bluetoothSco, (SpeechRecognizerCreator) () ->
122+
speechRecognizer = newInstance(configuration.getSynthesizerServiceType(),
123+
application, configuration, audioManager, bluetoothSco,
124+
(SpeechRecognizerCreator) () ->
135125
android.speech.SpeechRecognizer.createSpeechRecognizer(application),
136126
logger);
137127
break;
138128
}
139129
}
140-
} catch (ClassNotFoundException | IllegalAccessException
141-
| InstantiationException | InvocationTargetException e) {
142-
logger.logException(e); throw new RuntimeException("Have you forgot to add addon the dependency?");
130+
} catch (Exception e) {
131+
logger.logException(e);
132+
throw new RuntimeException("Have you missed to configure the < addon > dependency?");
143133
}
144134
if (phoneStateHandler == null) phoneStateHandler = new PhoneStateHandler(application, logger);
145135
if (!phoneStateHandler.isPhoneStateReceiverRegistered()) {
@@ -164,9 +154,9 @@ public void setup(Context context, OnSetup onSetup) {
164154
speechSynthesizer.setup(synthesizerStatus -> {
165155
int androidRecognizerStatus = android.speech.SpeechRecognizer.isRecognitionAvailable(application) ?
166156
RecognizerListener.RECOGNIZER_AVAILABLE : RecognizerListener.RECOGNIZER_NOT_AVAILABLE;
167-
int speechRecognizerStatus = configuration.getRecognizerServiceType() ==
168-
ComponentConfig.RECOGNIZER_SERVICE_GOOGLE ?
169-
RecognizerListener.RECOGNIZER_AVAILABLE : androidRecognizerStatus;
157+
int speechRecognizerStatus = configuration.getRecognizerServiceType().getSimpleName().equals(
158+
ComponentConfig.RECOGNIZER_SERVICE_ANDROID) ? androidRecognizerStatus
159+
: RecognizerListener.RECOGNIZER_AVAILABLE;
170160
onSetup.execute(new Status() {
171161
@SuppressLint("MissingPermission")
172162
@Override

0 commit comments

Comments
 (0)