📜 ⬆️ ⬇️

Chuck Norris and Google Glass - what is in common, but ...

Recently, I (unspeakably flooded) had the chance to buy Google Glass through the Explorers Program. One had only to order, as the next morning the postman woke me up with a knock at the maiden - the package for you. Without washing or brushing your teeth ...

In the evening there was an opportunity to program. Having studied a couple of examples and setting up the environment - I got down to business. There was an idea to write an application that will pull out a joke about Chuck Norris from a web service, parse JSON, and read aloud.


So, let's begin.
')
Voice activation:


Our jokes will be activated by voice command. To do this, define the service in the manifest:

<service android:name="com.chucknorris.JokeService" android:icon="@drawable/icon" android:label="@string/app_name" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="com.google.android.glass.action.VOICE_TRIGGER"/> </intent-filter> <meta-data android:name="com.google.android.glass.VoiceTrigger" android:resource="@xml/voice_trigger_start"/> </service> 


The key element here, unlike conventional android applications, is VoiceTrigger.

xml / voice_trigger_start looks simple:

 <?xml version="1.0" encoding="utf-8"?> <trigger keyword="@string/chuck_norris_joke" /> 


Finally, the line that sets the phrase, which, in turn, our service starts:

 <string name="chuck_norris_joke">say Chuck Norris joke</string> 


Note: according to the rules that Google puts forward with respect to activation phrases - they must begin with a verb. I personally do not really like this rule, but the shoemaker has no right to judge above the boot. It's just that a lot of phrases will start with “show”, “get”, “say”, “start”
More detail here

Now that we have defined VoiceTrigger, our service will start if we say “ok glass, say Chuck Norris joke”
By the way, Activity can also be launched using a voice command. A piece of the manifesto will be:

  <activity android:name="com.google.android.glass.sample.waveform.WaveformActivity" > <intent-filter> <action android:name="com.google.android.glass.action.VOICE_TRIGGER" /> </intent-filter> <meta-data android:name="com.google.android.glass.VoiceTrigger" android:resource="@xml/voice_trigger_start" /> </activity> 


Service stuffing

I'd like to talk about Card and LiveCard, but some other time. Our joke will not show anything, just be joking out loud.

Once you need to pull the joke from an online resource, we will not forget to declare this intention in AndroidManifest.xml:
 <uses-permission android:name="android.permission.INTERNET"/> 


In UI Thread, it is forbidden to climb the Internet, we will create AsyncTask for this purpose

doInBackground makes a request for a web service:

  HttpClient client = new DefaultHttpClient(); HttpGet getRequest = new HttpGet(); try { // construct a URI object getRequest.setURI(new URI(urls[0])); } catch (URISyntaxException e) { Log.e("URISyntaxException", e.toString()); } // buffer reader to read the response BufferedReader in = null; // the service response HttpResponse response = null; try { // execute the request response = client.execute(getRequest); } catch (ClientProtocolException e) { Log.e("ClientProtocolException", e.toString()); } catch (IOException e) { Log.e("IO exception", e.toString()); } try { in = new BufferedReader(new InputStreamReader(response.getEntity().getContent())); } catch (IllegalStateException e) { Log.e("IllegalStateException", e.toString()); } catch (IOException e) { Log.e("IO exception", e.toString()); } StringBuffer buff = new StringBuffer(""); String line = ""; try { while ((line = in.readLine()) != null) { buff.append(line); } } catch (IOException e) { Log.e("IO exception", e.toString()); return e.getMessage(); } try { in.close(); } catch (IOException e) { Log.e("IO exception", e.toString()); } 


then parse JSON:

  String joke = ""; try { JSONObject jObject = new JSONObject(buff.toString()); joke = jObject.getJSONObject("value").getString("joke"); } catch (JSONException e) { Log.e("JSON exception", e.toString()); } 


ok glass say shos


AsyncTask provides the onPostExecute method. So, when the request is completed and the joke is received, pulled out of the JSON shell - it's time to say it out loud. Android kindly helps us not only to recognize the speech but also to pronounce the text using TextToSpeech.

TextToSpeech is initialized in the service and passed to AsyncTask via the constructor parameter.
  tts = new TextToSpeech(this, new TextToSpeech.OnInitListener(){ @Override public void onInit(int i) { //TODO -     } }); 


in onPostExecute, call the new readOutLoud method
  protected void onPostExecute(String joke) { if (exception != null) { return; } readOutLoud(joke); } 


reading jokes out loud:
  private void readOutLoud(String joke) { tts.speak(joke, TextToSpeech.QUEUE_FLUSH, null); } 


Debugging and Debugging

Now it remains to connect the glasses via USB, build apk, align, sign, deploy (IDE will do everything for us). No Activity is needed.

so drum roll
- “ok glass, say Chuck Norris Joke”
“Chuck Norris can read from an input stream.”

Instead of an afterword


Taking this opportunity, I want to thank www.icndb.com . I think we should make a similar service with jokes about Stirlitz. If I have time, I'll do it.

About voice playback

for sure there are additional settings for the speed of reading and / or voice. On OS X they are.

Returning to the point "and what to show"

A small fragment that allows you to create a static card with a picture on the left and the text of the joke:

  private void publishJokeCard(String joke) { Card card = new Card(ctx); card.setText(joke); card.addImage(R.drawable.chuck); TimelineManager.from(ctx).insert(card); } 


A little more about the cards - the next time, you need to understand a bit. While I was writing one application - I hit on my glasses - and there already is a new version of the SDK. The benefit of someone on the forum shared his experience that the update came out a day ago (at that time). How cards look like here

Pictures

The icon is not difficult to prepare - the main requirement is white, on a transparent background and 50x50 pixels.

The picture for the card - well, in principle, any, but better - about a third of the size of the width of the card and the full size of the card height.
Lastly, I can say that not all jokes are equally decent. So as not to introduce the user to the confusion - it is better to add to the URL "? Type = nerdy".

Code

If anyone is interested, the whole code
Official examples here.

Source: https://habr.com/ru/post/207716/


All Articles