Using Retrofit 2.0 to extract information from a network API

I'm a newcomer in Java programming and in the past few days i've been experimenting with a basic English to Greek speech translation app purely to help me learn some (more advanced) concepts. Here is a picture of the interface.

So far I've gotten the speech recognition to work for both languages and I've decided to use MyMemory's API as a REST API for translation. I'm using Retrofit 2.0.0-beta2 to turn the HTTP API into a Java interface.

At the moment I'm simply trying to extract the translation of a word/phrase from MyMemory and place it in a text field inside my application.

Currently, I have three classes in my project:

  • TranslateAPI (Interface)
  • TranslatedData
  • MainActivity
  • TranslateAPI

    public interface TranslateAPI {
        @GET("get")
        void getTranslation(@Query("q") String request, Callback<TranslatedData> cb);
    }
    

    TranslatedData

    public class TranslatedData {
        String translatedText;
    
        public String getTranslatedText(){
            return translatedText;
        }
    }
    

    MainActivity (Relevant Code)

            public void translate(String toTranslate){
            String request = "=" + toTranslate + "&langpair=" + langPair;
            Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl("http://api.mymemory.translated.net/")
                    .build();
            TranslateAPI service = retrofit.create(TranslateAPI.class);
            service.getTranslation(request, new Callback<TranslatedData>() {
                @Override
                public void onResponse(Response<TranslatedData> response, Retrofit retrofit) {
                    System.out.println("Success");
                    //handle success
                }
    
                @Override
                public void onFailure(Throwable t) {
                    System.out.println("Failure");
                    //handle failure
                }
            });        
        }
    

    A few questions arise here. First of all, the app crashes because of the translate() method and I can't undestand why (my debugging skills in android are still non-existent). Can anyone please help me figure out why?

    Secondly, how exactly do i parse the response from the server?

    Does my code have any other flaw that prevents the app from working/crashes it?

    I apologize if my question is poor or straightforward, i'm still new to Android and i've found most tutorials about Retrofit vague and confusing due to the fact that half the guides are writen in Retrofit 1.x and the other half 2.0.


    Retrofit provides annotations to build proper calls, by the way, in this special case you need to build this kind of URI:

    http://api.mymemory.translated.net/get?q=hola&langpair=ES|EN

    The parameter value of langpair includes the character: | which need to be escaped (I've spend some time with that), that could be the reason of the crash.

    You can easily fix it set that parameter as encoded in the signature of your Retrofit 2 API declaration:

    @GET("/get")
    Call<TranslatedData> getTranslation(
        @Query("q") String textToTranslate, 
        @Query(value = "langpair", encoded = true) 
    String languagePair);
    

    Then encode the parameter value:

    mService.getTranslation(textToTranslate, URLEncoder.encode(fromLanguage + "|" + toLanguage))
        .enqueue(new Callback<TranslatedData>() {
    

    Also you had some errors in your response entity, the object that contains the translatedText property is a JsonObject called responseData , you need to set the proper entities:

    class TranslatedData {
        ResponseData responseData;
    }
    
    class ResponseData {
        String translatedText;
    }
    

    I post you the whole file of the TranslateApi.java , I've test it and works ;)

    package com.example.alex.finalproject;
    
    import java.net.URLEncoder;
    import retrofit.Call;
    import retrofit.Callback;
    import retrofit.GsonConverterFactory;
    import retrofit.Response;
    import retrofit.Retrofit;
    import retrofit.http.GET;
    import retrofit.http.Query;
    
    class TranslatedData {
        ResponseData responseData;
    }
    
    class ResponseData {
        String translatedText;
    }
    
    public class TranslateAPI {
        private static final String ENDPOINT = "http://api.mymemory.translated.net";
        public final static String SPANISH = "ES";
        public final static String ENGLISH = "EN";
    
    
        private final TranslateService mService;
    
        public interface TranslateService {
            @GET("/get")
            Call<TranslatedData> getTranslation(
                @Query("q") String textToTranslate,
                @Query(value = "langpair", encoded = true)
            String languagePair);
        }
    
        public TranslateAPI() {
            Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl(ENDPOINT)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
    
            mService = retrofit.create(TranslateService.class);
        }
    
        public void translate(final String textToTranslate, final String fromLanguage, final String toLanguage) {
            mService.getTranslation(textToTranslate, URLEncoder.encode(fromLanguage + "|" + toLanguage))
                .enqueue(new Callback<TranslatedData>() {
    
                    @Override
                    public void onResponse(Response<TranslatedData> response, Retrofit retrofit) {
                        String output =
                            String.format("Translation of: %s, %s->%s = %s", textToTranslate,
                                fromLanguage, toLanguage, response.body().responseData.translatedText);
    
                        System.out.println("Result: " + output);
                    }
    
                    @Override public void onFailure(Throwable t) {
                        System.out.println("[DEBUG]" + " RestApi onFailure - " + "");
                    }
                });
        }
    }
    

    You can call the translate method in this way:

    translateAPI.translate("hola", TranslateAPI.SPANISH, TranslateAPI.ENGLISH);
    

    My console result:

    I/System.out(31427): Result: Translation of: hola, ES->EN = hello
    

    On Android Studio, at the bottom, you have the Android Monitor , where you can find stacktraces with errors and more information, errors will be highlighted with red there.

    Android监视器

    To parse a response from the server with Retrofit 2.0 you need to specify a converter. Example: if you would like to use Gson as your Entity converter first you have to add that dependency into your build.gradle file.

    compile 'com.squareup.retrofit:converter-gson:2.0.0-beta2'
    

    Then you have to specify it into your Retrofit adapter:

     Retrofit marvelApiAdapter = new Retrofit.Builder()
        .baseUrl(END_POINT)
        .addConverterFactory(GsonConverterFactory.create(new Gson()))
        .client(client)
        .build();
    

    If not you'll get a crash. Maybe the best suggestion would be that you should use Retrofit 1.9 by now, which is stable, the second version is in beta version at the moment of writing. On the other hand in this link you'll find a nice guide of how to migrate from the 1.9 version to the 2.0 version, in case that you are following 1.9 tutorials, which is probably :)

    链接地址: http://www.djcxy.com/p/29506.html

    上一篇: Android Retrofit我没有收到JSON

    下一篇: 使用Retrofit 2.0从网络API中提取信息