290 | * If {@link #wsip} cannot be used as a hostname 291 | * in a {@link URI} (e.g. because it's null), then 292 | * this method will return null. 293 | *
294 | * 295 | * @return a valid uri, or null 296 | */ 297 | @Nullable 298 | private URI deriveURI() { 299 | URI uri = null; 300 | 301 | if (wsip != null && !wsip.isEmpty()) { 302 | try { 303 | uri = new URI("ws://" + wsip + ":8181/core"); 304 | } catch (URISyntaxException e) { 305 | e.printStackTrace(); 306 | } 307 | } else { 308 | uri = null; 309 | } 310 | return uri; 311 | } 312 | 313 | public void sendMessage(String msg) { 314 | // let's keep it simple eh? 315 | //final String json = "{\"message_type\":\"recognizer_loop:utterance\", \"context\": null, \"metadata\": {\"utterances\": [\"" + msg + "\"]}}"; 316 | final String json = "{\"data\": {\"utterances\": [\"" + msg + "\"]}, \"type\": \"recognizer_loop:utterance\", \"context\": null}"; 317 | 318 | try { 319 | if (mWebSocketClient == null || mWebSocketClient.getConnection().isClosed()) { 320 | // try and reconnect 321 | if (NetworkUtil.getConnectivityStatus(this) == NetworkUtil.NETWORK_STATUS_WIFI) { //TODO: add config to specify wifi only. 322 | connectWebSocket(); 323 | } 324 | } 325 | 326 | Handler handler = new Handler(); 327 | handler.postDelayed(new Runnable() { 328 | public void run() { 329 | // Actions to do after 1 seconds 330 | try { 331 | mWebSocketClient.send(json); 332 | } catch (WebsocketNotConnectedException exception) { 333 | showToast(getResources().getString(R.string.websocket_closed)); 334 | } 335 | } 336 | }, 1000); 337 | 338 | } catch (WebsocketNotConnectedException exception) { 339 | showToast(getResources().getString(R.string.websocket_closed)); 340 | } 341 | } 342 | 343 | /** 344 | * Showing google speech input dialog 345 | */ 346 | private void promptSpeechInput() { 347 | Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); 348 | intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, 349 | RecognizerIntent.LANGUAGE_MODEL_FREE_FORM); 350 | intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault()); 351 | intent.putExtra(RecognizerIntent.EXTRA_PROMPT, 352 | getString(R.string.speech_prompt)); 353 | try { 354 | startActivityForResult(intent, REQ_CODE_SPEECH_INPUT); 355 | } catch (ActivityNotFoundException a) { 356 | showToast(getString(R.string.speech_not_supported)); 357 | } 358 | } 359 | 360 | /** 361 | * Receiving speech input 362 | */ 363 | @Override 364 | protected void onActivityResult(int requestCode, int resultCode, Intent data) { 365 | super.onActivityResult(requestCode, resultCode, data); 366 | 367 | switch (requestCode) { 368 | case REQ_CODE_SPEECH_INPUT: { 369 | if (resultCode == RESULT_OK && null != data) { 370 | 371 | ArrayList37 | * TODO: Add error-aware callback for cases where the message is malformed. 38 | *
39 | * 40 | * @author Philip Cohn-Cort 41 | */ 42 | class MessageParser implements Runnable { 43 | 44 | private static final String TAG = "MessageParser"; 45 | 46 | @NonNull 47 | private final String message; 48 | @NonNull 49 | private final SafeCallback30 | * Note that the {@link #call(Object)} method in this class is 31 | * not allowed to throw exceptions. 32 | *
33 | * 34 | * @author Philip Cohn-Cort 35 | */ 36 | public interface SafeCallback
56 | * See
57 | * Android Design: Settings for design guidelines and the Settings
59 | * API Guide for more information on developing a Settings UI.
60 | */
61 | public class SettingsActivity extends AppCompatPreferenceActivity {
62 | /**
63 | * A preference value change listener that updates the preference's summary
64 | * to reflect its new value.
65 | */
66 | private static Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener = new Preference.OnPreferenceChangeListener() {
67 | @Override
68 | public boolean onPreferenceChange(Preference preference, Object value) {
69 | String stringValue = value.toString();
70 |
71 | if (preference instanceof ListPreference) {
72 | // For list preferences, look up the correct display value in
73 | // the preference's 'entries' list.
74 | ListPreference listPreference = (ListPreference) preference;
75 | int index = listPreference.findIndexOfValue(stringValue);
76 |
77 | // Set the summary to reflect the new value.
78 | preference.setSummary(
79 | index >= 0
80 | ? listPreference.getEntries()[index]
81 | : null);
82 |
83 | } else if (preference instanceof RingtonePreference) {
84 | // For ringtone preferences, look up the correct display value
85 | // using RingtoneManager.
86 | if (TextUtils.isEmpty(stringValue)) {
87 | // Empty values correspond to 'silent' (no ringtone).
88 | preference.setSummary(R.string.pref_ringtone_silent);
89 |
90 | } else {
91 | Ringtone ringtone = RingtoneManager.getRingtone(
92 | preference.getContext(), Uri.parse(stringValue));
93 |
94 | if (ringtone == null) {
95 | // Clear the summary if there was a lookup error.
96 | preference.setSummary(null);
97 | } else {
98 | // Set the summary to reflect the new ringtone display
99 | // name.
100 | String name = ringtone.getTitle(preference.getContext());
101 | preference.setSummary(name);
102 | }
103 | }
104 |
105 | } else {
106 | // For all other preferences, set the summary to the value's
107 | // simple string representation.
108 | preference.setSummary(stringValue);
109 | }
110 | return true;
111 | }
112 | };
113 |
114 | /**
115 | * Helper method to determine if the device has an extra-large screen. For
116 | * example, 10" tablets are extra-large.
117 | */
118 | private static boolean isXLargeTablet(Context context) {
119 | return (context.getResources().getConfiguration().screenLayout
120 | & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_XLARGE;
121 | }
122 |
123 | /**
124 | * Binds a preference's summary to its value. More specifically, when the
125 | * preference's value is changed, its summary (line of text below the
126 | * preference title) is updated to reflect the value. The summary is also
127 | * immediately updated upon calling this method. The exact display format is
128 | * dependent on the type of preference.
129 | *
130 | * @see #sBindPreferenceSummaryToValueListener
131 | */
132 | private static void bindPreferenceSummaryToValue(Preference preference, Boolean isIntValue) {
133 | // Set the listener to watch for value changes.
134 | preference.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListener);
135 |
136 | // Trigger the listener immediately with the preference's
137 | // current value.
138 | SharedPreferences preferences =
139 | PreferenceManager.getDefaultSharedPreferences(preference.getContext());
140 |
141 | String stringValue = "";
142 | if (isIntValue) {
143 | stringValue = String.valueOf(preferences.getInt(preference.getKey(), 0));
144 | } else {
145 | stringValue = preferences.getString(preference.getKey(), "");
146 | }
147 |
148 | sBindPreferenceSummaryToValueListener.onPreferenceChange(preference, stringValue);
149 | }
150 |
151 | private static void bindPreferenceSummaryToValue(Preference preference) {
152 | bindPreferenceSummaryToValue(preference, false);
153 | }
154 |
155 |
156 |
157 | @Override
158 | protected void onCreate(Bundle savedInstanceState) {
159 | super.onCreate(savedInstanceState);
160 | setupActionBar();
161 | }
162 |
163 | @Override
164 | public boolean onOptionsItemSelected(MenuItem item) {
165 | switch (item.getItemId()) {
166 | // Respond to the action bar's Up/Home button
167 | case android.R.id.home:
168 | NavUtils.navigateUpFromSameTask(this);
169 | return true;
170 | }
171 | return super.onOptionsItemSelected(item);
172 | }
173 |
174 | /**
175 | * Set up the {@link android.app.ActionBar}, if the API is available.
176 | */
177 | private void setupActionBar() {
178 | ActionBar actionBar = getSupportActionBar();
179 | if (actionBar != null) {
180 | // Show the Up button in the action bar.
181 | actionBar.setDisplayHomeAsUpEnabled(true);
182 | }
183 | }
184 |
185 | /**
186 | * {@inheritDoc}
187 | */
188 | @Override
189 | public boolean onIsMultiPane() {
190 | return isXLargeTablet(this);
191 | }
192 |
193 | /**
194 | * {@inheritDoc}
195 | */
196 | @Override
197 | @TargetApi(Build.VERSION_CODES.HONEYCOMB)
198 | public void onBuildHeaders(List
38 | * All constructors in this class require a context reference.
39 | * Make sure to clean up with {@link #shutDown()} when the context's
40 | * {@link Activity#onDestroy()} or {@link Service#onDestroy()} method is called.
41 | *
34 | * It should trigger connection and disconnection actions
35 | * on the appropriate handler, which for now is {@link MainActivity}.
36 | *
33 | * Use it like so:
34 | * {@code
35 | * Mockito.when(Log.v(anyString(), anyString())).then(new LogAnswer(System.out));
36 | * }
37 | *