diff --git a/android/app/src/main/java/io/github/transui/android/AppConfig.java b/android/app/src/main/java/io/github/transui/android/AppConfig.java
index 0eeabd0..0adbfa0 100644
--- a/android/app/src/main/java/io/github/transui/android/AppConfig.java
+++ b/android/app/src/main/java/io/github/transui/android/AppConfig.java
@@ -1,36 +1,23 @@
package io.github.transui.android;
final class AppConfig {
- final String remoteEndpoint;
- final String remoteModel;
- final String remoteKey;
- final String localEndpoint;
- final String localModel;
- final String localKey;
+ final String endpoint;
+ final String model;
+ final String apiKey;
final String prompt;
- final boolean remoteFirst;
AppConfig(
- String remoteEndpoint,
- String remoteModel,
- String remoteKey,
- String localEndpoint,
- String localModel,
- String localKey,
- String prompt,
- boolean remoteFirst) {
- this.remoteEndpoint = remoteEndpoint;
- this.remoteModel = remoteModel;
- this.remoteKey = remoteKey;
- this.localEndpoint = localEndpoint;
- this.localModel = localModel;
- this.localKey = localKey;
+ String endpoint,
+ String model,
+ String apiKey,
+ String prompt) {
+ this.endpoint = endpoint;
+ this.model = model;
+ this.apiKey = apiKey;
this.prompt = prompt;
- this.remoteFirst = remoteFirst;
}
boolean hasUsableEndpoint() {
- if (remoteFirst && !remoteEndpoint.isEmpty()) return true;
- return !localEndpoint.isEmpty();
+ return !endpoint.isEmpty();
}
}
diff --git a/android/app/src/main/java/io/github/transui/android/ConfigRepository.java b/android/app/src/main/java/io/github/transui/android/ConfigRepository.java
index 427e91f..b25a465 100644
--- a/android/app/src/main/java/io/github/transui/android/ConfigRepository.java
+++ b/android/app/src/main/java/io/github/transui/android/ConfigRepository.java
@@ -12,34 +12,38 @@ final class ConfigRepository {
ConfigRepository(Context context) {
preferences = context.getApplicationContext().getSharedPreferences(PREFS, Context.MODE_PRIVATE);
+ removeObsoleteLocalSettings();
}
AppConfig load() {
- String remoteKey = decryptOrEmpty(preferences.getString("remote_key", ""));
- String localKey = decryptOrEmpty(preferences.getString("local_key", ""));
return new AppConfig(
preferences.getString("remote_endpoint", ""),
preferences.getString("remote_model", ""),
- remoteKey,
- preferences.getString("local_endpoint", "http://localhost:8080"),
- preferences.getString("local_model", ""),
- localKey,
- preferences.getString("prompt", ""),
- preferences.getBoolean("remote_first", true));
+ decryptOrEmpty(preferences.getString("remote_key", "")),
+ preferences.getString("prompt", ""));
}
void save(AppConfig config) throws GeneralSecurityException, IOException {
- String remoteKey = SecretStore.encrypt(config.remoteKey);
- String localKey = SecretStore.encrypt(config.localKey);
preferences.edit()
- .putString("remote_endpoint", config.remoteEndpoint)
- .putString("remote_model", config.remoteModel)
- .putString("remote_key", remoteKey)
- .putString("local_endpoint", config.localEndpoint)
- .putString("local_model", config.localModel)
- .putString("local_key", localKey)
+ .putString("remote_endpoint", config.endpoint)
+ .putString("remote_model", config.model)
+ .putString("remote_key", SecretStore.encrypt(config.apiKey))
.putString("prompt", config.prompt)
- .putBoolean("remote_first", config.remoteFirst)
+ .apply();
+ }
+
+ private void removeObsoleteLocalSettings() {
+ if (!preferences.contains("local_endpoint")
+ && !preferences.contains("local_model")
+ && !preferences.contains("local_key")
+ && !preferences.contains("remote_first")) {
+ return;
+ }
+ preferences.edit()
+ .remove("local_endpoint")
+ .remove("local_model")
+ .remove("local_key")
+ .remove("remote_first")
.apply();
}
diff --git a/android/app/src/main/java/io/github/transui/android/MainActivity.java b/android/app/src/main/java/io/github/transui/android/MainActivity.java
index 78d1629..7f7b86e 100644
--- a/android/app/src/main/java/io/github/transui/android/MainActivity.java
+++ b/android/app/src/main/java/io/github/transui/android/MainActivity.java
@@ -10,7 +10,6 @@ import android.os.Bundle;
import android.provider.Settings;
import android.widget.Button;
import android.widget.EditText;
-import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;
@@ -20,14 +19,12 @@ import java.security.GeneralSecurityException;
public final class MainActivity extends Activity {
private static final int MICROPHONE_REQUEST = 1;
- private EditText remoteEndpoint;
- private EditText remoteModel;
- private EditText remoteKey;
- private EditText localEndpoint;
- private EditText localModel;
- private EditText localKey;
+ private static final String ACTION_LANGUAGE_SETTINGS = "android.settings.LANGUAGE_SETTINGS";
+
+ private EditText endpoint;
+ private EditText model;
+ private EditText apiKey;
private EditText prompt;
- private Switch remoteFirst;
private TextView providerStatus;
private Button microphone;
private ConfigRepository repository;
@@ -42,9 +39,7 @@ public final class MainActivity extends Activity {
findViewById(R.id.save).setOnClickListener(view -> saveConfig());
microphone.setOnClickListener(view -> requestMicrophone());
- findViewById(R.id.choose_provider).setOnClickListener(view -> {
- if (saveConfig()) openVoiceInputSettings();
- });
+ findViewById(R.id.language_settings).setOnClickListener(view -> openLanguageSettings());
}
@Override
@@ -60,39 +55,27 @@ public final class MainActivity extends Activity {
}
private void bindViews() {
- remoteEndpoint = findViewById(R.id.remote_endpoint);
- remoteModel = findViewById(R.id.remote_model);
- remoteKey = findViewById(R.id.remote_key);
- localEndpoint = findViewById(R.id.local_endpoint);
- localModel = findViewById(R.id.local_model);
- localKey = findViewById(R.id.local_key);
+ endpoint = findViewById(R.id.endpoint);
+ model = findViewById(R.id.model);
+ apiKey = findViewById(R.id.api_key);
prompt = findViewById(R.id.prompt);
- remoteFirst = findViewById(R.id.remote_first);
providerStatus = findViewById(R.id.provider_status);
microphone = findViewById(R.id.microphone);
}
private void showConfig(AppConfig config) {
- remoteEndpoint.setText(config.remoteEndpoint);
- remoteModel.setText(config.remoteModel);
- remoteKey.setText(config.remoteKey);
- localEndpoint.setText(config.localEndpoint);
- localModel.setText(config.localModel);
- localKey.setText(config.localKey);
+ endpoint.setText(config.endpoint);
+ model.setText(config.model);
+ apiKey.setText(config.apiKey);
prompt.setText(config.prompt);
- remoteFirst.setChecked(config.remoteFirst);
}
private boolean saveConfig() {
AppConfig config = new AppConfig(
- value(remoteEndpoint).trim(),
- value(remoteModel).trim(),
- value(remoteKey).trim(),
- value(localEndpoint).trim(),
- value(localModel).trim(),
- value(localKey).trim(),
- value(prompt),
- remoteFirst.isChecked());
+ value(endpoint).trim(),
+ value(model).trim(),
+ value(apiKey).trim(),
+ value(prompt));
try {
repository.save(config);
Toast.makeText(this, R.string.settings_saved, Toast.LENGTH_SHORT).show();
@@ -109,11 +92,17 @@ public final class MainActivity extends Activity {
}
}
- private void openVoiceInputSettings() {
+ private void openLanguageSettings() {
try {
- startActivity(new Intent(Settings.ACTION_VOICE_INPUT_SETTINGS));
- } catch (ActivityNotFoundException error) {
- Toast.makeText(this, R.string.voice_settings_unavailable, Toast.LENGTH_LONG).show();
+ startActivity(new Intent(ACTION_LANGUAGE_SETTINGS));
+ return;
+ } catch (ActivityNotFoundException ignored) {
+ // Older Android builds expose the combined Languages and input page here.
+ }
+ try {
+ startActivity(new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS));
+ } catch (ActivityNotFoundException ignored) {
+ Toast.makeText(this, R.string.language_settings_unavailable, Toast.LENGTH_LONG).show();
}
}
diff --git a/android/app/src/main/java/io/github/transui/android/TranscriptionClient.java b/android/app/src/main/java/io/github/transui/android/TranscriptionClient.java
index 9a02ac3..5436d6b 100644
--- a/android/app/src/main/java/io/github/transui/android/TranscriptionClient.java
+++ b/android/app/src/main/java/io/github/transui/android/TranscriptionClient.java
@@ -20,25 +20,10 @@ final class TranscriptionClient {
private volatile HttpURLConnection activeConnection;
Result transcribe(AppConfig config, byte[] wav) {
- Result remoteResult = null;
- if (config.remoteFirst && !config.remoteEndpoint.isEmpty()) {
- remoteResult = request(
- config.remoteEndpoint, config.remoteModel, config.remoteKey, config.prompt, wav);
- if (remoteResult.text != null) return remoteResult;
+ if (config.endpoint.isEmpty()) {
+ return Result.error("No transcription endpoint is configured", SpeechRecognizer.ERROR_CLIENT);
}
-
- if (!config.localEndpoint.isEmpty()) {
- Result localResult = request(
- config.localEndpoint, config.localModel, config.localKey, config.prompt, wav);
- if (localResult.text != null || remoteResult == null) return localResult;
- return Result.error(
- remoteResult.error + "; local: " + localResult.error,
- localResult.errorCode);
- }
-
- return remoteResult != null
- ? remoteResult
- : Result.error("No transcription endpoint is configured", SpeechRecognizer.ERROR_CLIENT);
+ return request(config.endpoint, config.model, config.apiKey, config.prompt, wav);
}
void cancel() {
diff --git a/android/app/src/main/res/layout/activity_main.xml b/android/app/src/main/res/layout/activity_main.xml
index a8397c4..b2524eb 100644
--- a/android/app/src/main/res/layout/activity_main.xml
+++ b/android/app/src/main/res/layout/activity_main.xml
@@ -48,51 +48,26 @@
+ android:text="@string/server" />
-
-
-
-
-
-
-
-
@@ -109,15 +84,6 @@
android:maxLines="3"
android:singleLine="false" />
-
-
+ android:text="@string/open_language_settings" />
diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml
index 5387ebc..4dbdbb1 100644
--- a/android/app/src/main/res/values/strings.xml
+++ b/android/app/src/main/res/values/strings.xml
@@ -5,22 +5,17 @@
Transui voice input
Selected as voice input
Select Transui as voice input
- REMOTE
- LOCAL
+ SERVER
REQUEST
- Remote endpoint
- Remote model
- Remote API key
- Local endpoint
- Local model
- Local API key
+ Transcription endpoint
+ Model
+ API key
Prompt
- Remote first, local fallback
Save settings
- Choose voice input
+ Open language settings
Allow microphone
Microphone allowed
Settings saved
Could not save API keys
- Voice input settings are unavailable
+ Language settings are unavailable