25 Nov 2009, 13:11
Generic-user-small

Kristof Leroux (1 post)

Hi,

I have read the book with much joy, but now i am playing with the code examples and the translate application just doesn’t work… the problem is in the TranslateTask.java.

The first problem i solved.

     int nbytes = con.getContentLength();
     char[] buffer = new char[nbytes]; // #chars <= #bytes

nbytes always returned -1, so creating an array of size -1 threw an exception… that’s fixed now (i’m running jdk1.6)!

But the second problem i can’t solve:

The first http connection receives a correct json object, but the second call to the google webservice returns this:

HTTP/1.1 200 OK Cache-Control: no-cache, no-store, max-age=0, must-revalidate Pragma: no-cache Expires: Fri, 01 Jan 1990 00:00:00 GMT Date: Wed, 25 Nov 2009 00:42:26 GMT Content-Type: text/javascript; charset=utf-8 X-Backend-Content-Length: 1

It just receive the headers and so a JSONException is thrown. Anyone any ideas ?

Thanks in advance, I really want this example to work…

Greetings, Kristof Leroux

30 Nov 2009, 03:31
Generic-user-small

James Weston (1 post)

Hey there, I was a little frustrated by this and looked into it. getContentLength() is returning -1 because “the field isn’t set” according to the docs. InputStreamReader.read() will return -1 only if it has reached the end of the stream. Just place this code in right after you declare your InputStreamReader object. ***NOTE: there is a much better solution I’m sure, this is just a quick fix ;)

int i;
         while (true) {
        	 i = reader.read();   // reader is your InputStreamReader object
        	 if (i == -1)
        		 break;
        	 translation += (char)i;
         }

You’ll still need to parse the string to get your desired result, so do this:

JSONObject jsonObject = new JSONObject(translation);
         translation = jsonObject.getJSONObject("responseData")
               .getString("translatedText")
               .replace("&#39;", "'")
               .replace("&amp;", "&");

</code>

Here’s the entire class:

/***
 * Excerpted from "Hello, Android! 2e",
 * published by The Pragmatic Bookshelf.
 * Copyrights apply to this code. It may not be used to create training material, 
 * courses, books, articles, and the like. Contact us if you are in doubt.
 * We make no guarantees that this code is fit for any purpose. 
 * Visit http://www.pragmaticprogrammer.com/titles/eband2 for more book information.
***/
package org.example.translate;

import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import org.json.JSONException;
import org.json.JSONObject;
import android.util.Log;

public class TranslateTask implements Runnable {

   private static final String TAG = "TranslateTask";
   private final Translate translate;
   private final String original, from, to;

   TranslateTask(Translate translate, String original, String from,
         String to) {
      this.translate = translate;
      this.original = original;
      this.from = from;
      this.to = to;
   }

   public void run() {
      // Translate the original text to the target language
      String trans = doTranslate(original, from, to);
      translate.setTranslated(trans);

      // Then translate what we got back to the first language.
      // Ideally it would be identical but it usually isn't.
      String retrans = doTranslate(trans, to, from); // swapped
      translate.setRetranslated(retrans);
   }
   /**
    * Call the Google Translation API to translate a string from one
    * language to another. For more info on the API see:
    * http://code.google.com/apis/ajaxlanguage
    */
   private String doTranslate(String original, String from,
         String to) {
      String translation = translate.getResources().getString(
            R.string.translation_error);
      HttpURLConnection con = null;
      Log.d(TAG, "doTranslate(" + original + ", " + from + ", "
            + to + ")");
      try {
         // Check if task has been interrupted
         if (Thread.interrupted()) {
        	 throw new InterruptedException();
         }
         // Build RESTful query for Google API
         String q = URLEncoder.encode(original, "UTF-8");
         URL url = new URL(
               "http://ajax.googleapis.com/ajax/services/language/translate"
                     + "?v=1.0" + "&q=" + q + "&langpair=" + from
                     + "%7C" + to);
         con = (HttpURLConnection) url.openConnection();
         con.setReadTimeout(10000 /* milliseconds */);
         con.setConnectTimeout(15000 /* milliseconds */);
         con.setRequestMethod("GET");
         con.addRequestProperty("Referer",
               "http://www.pragprog.com/titles/eband/hello-android");
         con.setDoInput(true);

         // Start the query
         con.connect();
         // Check if task has been interrupted
         if (Thread.interrupted()) {
        	 throw new InterruptedException();
         }

         // Read results from the query
         InputStreamReader reader = new InputStreamReader(
               con.getInputStream(), "UTF-8");
         translation = "";
         int i;
         while (true) {
        	 i = reader.read();
        	 if (i == -1)
        		 break;
        	 translation += (char)i;
         }
         JSONObject jsonObject = new JSONObject(translation);
         translation = jsonObject.getJSONObject("responseData")
               .getString("translatedText")
               .replace("&#39;", "'")
               .replace("&amp;", "&");
         reader.close();
      } catch (IOException e) {
         Log.e(TAG, "IOException", e);
      } catch (JSONException e) {
         Log.e(TAG, "JSONException", e);
      } catch (InterruptedException e) {
         Log.d(TAG, "InterruptedException", e);
      } finally {
         if (con != null) {
            con.disconnect();
         }
      }
      // All done
      Log.d(TAG, "   -> returned " + translation);
      return translation;
   }
}

</code>

02 Dec 2009, 16:30
Burnette_ed_pragsmall

Ed Burnette (1316 posts)

This fix works for me:

“I just noticed the Translate sample has stopped working. It may be because of a change in the Google Translate API I’m using. To fix the problem, edit TranslateTask.java and look for the lines that say:

// Read results from the query
InputStreamReader reader = new InputStreamReader(
   con.getInputStream(), "UTF-8");
int nbytes = con.getContentLength();
char[] buffer = new char[nbytes]; // #chars <= #bytes
int nchars = reader.read(buffer);
String payload = String.valueOf(buffer, 0, nchars);
reader.close();

This was not printed in the book, but was instead part of the sample code on the web site.

The problem is that nbytes is coming back as -1 now, which causes an exception on “new char[nbytes]”. This makes the translation never finish. Change it to this:

// Read results from the query
BufferedReader reader = new BufferedReader(
   new InputStreamReader(con.getInputStream(), "UTF-8"));
String payload = reader.readLine();
reader.close();

and it will work again. Don’t forget to add an import for java.io.BufferedReader.

(I know, you could make this a little more robust by reading more than one line but I’ll leave that as an exercise for the reader.)”

[ Copied from http://forums.pragprog.com/forums/67/topics/3403 ]

03 Jan 2010, 02:40
Generic-user-small

George Alto (1 post)

Ed - two comments for you.

First, you’re right about this code not being in the book. But that statement reminded me about how this part of your book was very annoying. We get all the way to the end of the Translate example and you don’t provide how to access the last file. You should have at least put in a link to tell the user how/where to get it. I obviously figured it out but it took me some time.

Second and more important. Once I figured out the link I went and got the source for the file and tried to get the Translate example to work. It didn’t work. I’ve been trying to get it to work for a few days now. I finally decided to come to this site and look in this forum and see if anyone else has had this problem. I find this thread and see you posted on December 2nd (1 month ago). So why haven’t you updated the actual source file on the website for TranslateTask? If you had, I wouldn’t have wasted these last few days trying to figure this out.

I don’t mean to be too critical. But it’s small quality things like this that go a long way!

15 Jan 2010, 14:05
Burnette_ed_pragsmall

Ed Burnette (1316 posts)

Critical is good! I appreciate the feedback. Keep it coming.

Based on this and other responses, for the next edition I’m leaning towards including every single line of the examples in the printed book. It’ll make the book a little longer, but I’ve learned that many people would like to see the whole thing in one place (and those that don’t can skip over it).

For your convenience (and future searchers) here’s the full patched code for TranslateTask.java. The original can also be found at:

http://media.pragprog.com/titles/eband2/code/Translate/src/org/example/translate/TranslateTask.java

and as part of:

http://www.pragprog.com/titles/eband2/source_code

package org.example.translate;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;

import org.json.JSONException;
import org.json.JSONObject;

import android.util.Log;

public class TranslateTask implements Runnable {
   private static final String TAG = "TranslateTask";
   private final Translate translate;
   private final String original, from, to;

   TranslateTask(Translate translate, String original, String from,
         String to) {
      this.translate = translate;
      this.original = original;
      this.from = from;
      this.to = to;
   }

   public void run() {
      // Translate the original text to the target language
      String trans = doTranslate(original, from, to);
      translate.setTranslated(trans);

      // Then translate what we got back to the first language.
      // Ideally it would be identical but it usually isn't.
      String retrans = doTranslate(trans, to, from); // swapped
      translate.setRetranslated(retrans);
   }

   /**
    * Call the Google Translation API to translate a string from one
    * language to another. For more info on the API see:
    * http://code.google.com/apis/ajaxlanguage
    */
   private String doTranslate(String original, String from,
         String to) {
      String result = translate.getResources().getString(
            R.string.translation_error);
      HttpURLConnection con = null;
      Log.d(TAG, "doTranslate(" + original + ", " + from + ", "
            + to + ")");

      try {
         // Check if task has been interrupted
         if (Thread.interrupted())
            throw new InterruptedException();

         // Build RESTful query for Google API
         String q = URLEncoder.encode(original, "UTF-8");
         URL url = new URL(
               "http://ajax.googleapis.com/ajax/services/language/translate"
                     + "?v=1.0" + "&q=" + q + "&langpair=" + from
                     + "%7C" + to);
         con = (HttpURLConnection) url.openConnection();
         con.setReadTimeout(10000 /* milliseconds */);
         con.setConnectTimeout(15000 /* milliseconds */);
         con.setRequestMethod("GET");
         con.addRequestProperty("Referer",
               "http://www.pragprog.com/titles/eband2/hello-android");
         con.setDoInput(true);

         // Start the query
         con.connect();

         // Check if task has been interrupted
         if (Thread.interrupted())
            throw new InterruptedException();

         // Read results from the query
         BufferedReader reader = new BufferedReader(
               new InputStreamReader(con.getInputStream(), "UTF-8"));
         String payload = reader.readLine();
         reader.close();

         // Parse to get translated text
         JSONObject jsonObject = new JSONObject(payload);
         result = jsonObject.getJSONObject("responseData")
               .getString("translatedText")
               .replace("&#39;", "'")
               .replace("&amp;", "&");

         // Check if task has been interrupted
         if (Thread.interrupted())
            throw new InterruptedException();

      } catch (IOException e) {
         Log.e(TAG, "IOException", e);
      } catch (JSONException e) {
         Log.e(TAG, "JSONException", e);
      } catch (InterruptedException e) {
         Log.d(TAG, "InterruptedException", e);
         result = translate.getResources().getString(
               R.string.translation_interrupted);
      } finally {
         if (con != null) {
            con.disconnect();
         }
      }

      // All done
      Log.d(TAG, "   -> returned " + result);
      return result;
   }
}
24 Jun 2010, 17:33
Generic-user-small

KathyJ (3 posts)

I copy/pasted Ed’s code above into a TranslateTask.java file in my project (under src/org.example/translate). Immediately I got Eclipse errors on two lines (multiple errors for each line of code). The only idea I had is that perhaps some “escapes” are needed on the multiple double quotes, but since those aren’t in the code above I’m at a loss to understand why they are suddenly needed. Once I added those, I found that the second line was missing a closing double quote and a closing parenthesis. Now the project runs, but there are errors and the translation doesn’t happen. A quick glance at the LogCat shows it is throwing a MalformedURLException. I haven’t had time yet to sort this out, but I post this now in case someone else has already dealt with it.

Follow-up: The code in Ed’s post is incorrect on these two lines, probably as a result of Textile markup formatting changes. The code found by following the link works fine.

1.

 URL url = new URL(
               "<a href="http://ajax.googleapis.com/ajax/services/language/translate">http://ajax.googleapis.com/ajax/services/language/translate</a>" 
                     + "?v=1.0" + "&q=" + q + "&langpair=" + from
                     + "%7C" + to);

2.

con.addRequestProperty("Referer",
               "<a href="http://www.pragprog.com/titles/eband2/hello-android&quot;)">http://www.pragprog.com/titles/eband2/hello-android&quot;)</a>;
24 Jun 2010, 19:57
Burnette_ed_pragsmall

Ed Burnette (1316 posts)

You’re right, sorry about the markup problems. I used the pre and code formatting tags but it’s still putting in the extra markup. The two strings should be “http://ajax.googleapis.com/ajax/services/language/translate” and “http://www.pragprog.com/titles/eband2/hello-android”, respectively.

09 Feb 2011, 13:03
Generic-user-small

Marwen (1 post)

Hi, When i try to enter a word in the text field, a virtual keyboard displayed in the bottom of the screen but i can’t see the translation word because it is hidden by that keyboard.So how can i hide this keyboard ?

19 May 2011, 01:07
Burnette_ed_pragsmall

Ed Burnette (1316 posts)

These are the droids you’re looking for, but activity has moved on to a newer edition. To better serve you, I’m asking everyone to use the forum for the latest edition of Hello, Android instead of this forum, even if you have an older edition of the book.

If you refer to a specific chapter, section, or page number, be sure to include the edition and printing number so we’ll know what you’re referring to. The 3rd edition forum can be found here:

  • http://forums.pragprog.com/forums/152

Thanks, –Ed

18 Jan 2013, 05:22
Generic-user-small

Rahul Suresh (1 post)

Hey Ed that was really a great comment. Most often I see authors ignore criticism. You took it the positive way. Great going Man. And thanks a lot for sharing the full patched code as those who were finding trouble with the code earlier can find it useful.

  You must be logged in to comment