Difference between revisions of "Android API Calls With Retrofit"

From ESE205 Wiki
Jump to: navigation, search
(added initial stuff)
 
(added everything else)
Line 17: Line 17:
 
   android:usesCleartextTraffic="true"
 
   android:usesCleartextTraffic="true"
  
 +
Now you are ready to build interact with the internet.
  
 +
Next you want to navigate to the activity_main.xml file. Here we want to add the views that the user will interact with. For the purposes of this app just add a textview and a button with ids. You can use the code below.
  
[[Category:Tutorials]]
+
  <?xml version="1.0" encoding="utf-8"?>
 +
  <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
 +
      xmlns:app="http://schemas.android.com/apk/res-auto"
 +
      xmlns:tools="http://schemas.android.com/tools"
 +
      android:layout_width="match_parent"
 +
      android:layout_height="match_parent"
 +
      tools:context=".MainActivity">
 +
      <TextView
 +
          android:id="@+id/textview1"
 +
          android:layout_width="wrap_content"
 +
          android:layout_height="wrap_content"
 +
          android:text="Hello World!"
 +
          app:layout_constraintTop_toTopOf="parent"
 +
          app:layout_constraintLeft_toLeftOf="parent"
 +
          app:layout_constraintRight_toRightOf="parent"
 +
          app:layout_constraintBottom_toTopOf="@+id/button1" />
 +
      <Button
 +
          android:id="@+id/button1"
 +
          android:layout_width="wrap_content"
 +
          android:layout_height="wrap_content"
 +
          android:layout_marginBottom="280dp"
 +
          android:text="Refresh"
 +
          app:layout_constraintBottom_toBottomOf="parent"
 +
          app:layout_constraintEnd_toEndOf="parent"
 +
          app:layout_constraintHorizontal_bias="0.498"
 +
          app:layout_constraintLeft_toLeftOf="parent"
 +
          app:layout_constraintRight_toRightOf="parent"
 +
          app:layout_constraintStart_toStartOf="parent" />
 +
  </android.support.constraint.ConstraintLayout>
 +
 
 +
We will use the button to fire off our API calls and we will use the textview to display the information we receive from the api call.
 +
 
 +
Next let's navigate to our MainActivity Java class. In this class we need to initialize a TextView, a Button variable, and a String url variable. In the on create attach the xml elements to our variables using findViewByID. If you are unfamiliar on how to do this, please google it or check the source code. Create a method known as getInfo and pass the textview into it. Using this method we will perform the API call and we will edit the text to display the information we receive from the API call.
 +
 
 +
Now lets finally get into how to use RetroFit. We will create a RetrofitClientInstance class that will return an instance of Retrofit. We will pass our app context and our string into the method. The following code can be pretty much copy and pasted. It will create an instance of RetroFIt using the url we passed in and it will print the Http Logs to the android studio console log.
 +
 
 +
<source>
 +
    private static final String TAG = "RetrofitClientInstance";
 +
    private static Retrofit sRetrofit;
 +
 
 +
    public static Retrofit getRetrofitInstance(Context context, String url){
 +
 
 +
        Log.d(TAG, "getRetrofitInstance: HTTPClient");
 +
 
 +
        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
 +
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
 +
        OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();
 +
 
 +
        if(sRetrofit == null){
 +
            sRetrofit = new retrofit2.Retrofit.Builder()
 +
                    .baseUrl(url)
 +
                    .client(client)
 +
                    .addConverterFactory(GsonConverterFactory.create())
 +
                    .build();
 +
        }
 +
 
 +
        return sRetrofit;
 +
 
 +
    }
 +
</source>
 +
 
 +
Next we will create an interface for RetroFit. Create an interface class and call it GetDataService. You can take a look at this [guide | https://square.github.io/retrofit/] for more information about exactly how the syntax goes. Every method you add to this interface will be able to be called by your retrofit instance. It will make calls to the url you passed into your retroFit instance. Within the method, the top line will specify the type of request (GET or POST) and the sub url to target. The second line of the method will specify the structure of the response and also allow you to specify exactly what to send in your request.
 +
 
 +
We will be using the Quotes on Design [API | https://quotesondesign.com/api-v4-0/]. This API is nice because we will not need to use any tokens. We can focus on just the query and response. Our query has two fields we need to fill filter[orderby] and filter[posts_per_page]. So we will create a getQuote method that returns a list of quote objects and takes in a hash map of queries.
 +
 
 +
<source>
 +
@GET("wp-json/posts")
 +
Call<List<Quote>> getQuote(@QueryMap Map<String, String> query);
 +
</source>
 +
 
 +
You should be getting an error because there is no quote class. Let's create that now. Perusing through the site we can see that all API calls will return a json object that includes an ID, title, content, and link. Our java class will need all of these. To make it easier, you can take an example son from the api call and paste it into a json to pojo generator like [here | https://codebeautify.org/json-to-java-converter]. This is the class.
 +
 
 +
<source>
 +
public class Quote {
 +
    private float ID;
 +
    private String title;
 +
    private String content;
 +
    private String link;
 +
 
 +
 
 +
    // Getter Methods
 +
 
 +
    public Quote(){}
 +
 
 +
    public Quote(float ID, String title, String content, String link) {
 +
        this.ID = ID;
 +
        this.title = title;
 +
        this.content = content;
 +
        this.link = link;
 +
    }
 +
 
 +
    public float getID() {
 +
        return ID;
 +
    }
 +
 
 +
    public String getTitle() {
 +
        return title;
 +
    }
 +
 
 +
    public String getContent() {
 +
        return content;
 +
    }
 +
 
 +
    public String getLink() {
 +
        return link;
 +
    }
 +
 
 +
    // Setter Methods
 +
 
 +
    public void setID(float ID) {
 +
        this.ID = ID;
 +
    }
 +
 
 +
    public void setTitle(String title) {
 +
        this.title = title;
 +
    }
 +
 
 +
    public void setContent(String content) {
 +
        this.content = content;
 +
    }
 +
 
 +
    public void setLink(String link) {
 +
        this.link = link;
 +
    }
 +
}
 +
</source>
 +
 
 +
Now we've finally got everything together. Let's head back to the MainActivity class. and fill in the getInfo method. You can copy and paste the code below:
 +
 
 +
<source>
 +
Log.d(TAG, "getInfo: Started getInfo");
 +
 
 +
        //create the query map
 +
        Map<String, String> data = new HashMap<>();
 +
        data.put("filter[orderby]", "rand");
 +
        data.put("filter[posts_per_page]", "1");
 +
 
 +
        //create the retrofit instance and use our getQuote method
 +
        GetDataService service = RetrofitClientInstance.getRetrofitInstance(this, url).create(GetDataService.class);
 +
        Call<List<Quote>> call = service.getQuote(data);
 +
 
 +
        //call the enqueue method to get the results of our call
 +
        call.enqueue(new Callback<List<Quote>>() {
 +
            @Override
 +
            public void onResponse(Call<List<Quote>> call, Response<List<Quote>> response) {
 +
                Log.d(TAG, "onResponse: Success");
 +
                //parse through our resulting list of quotes and change the text in our text view
 +
                for(Quote i: response.body()){
 +
                    t.setText(i.getContent());
 +
                }
 +
 
 +
            }
 +
 
 +
            @Override
 +
            public void onFailure(Call<List<Quote>> call, Throwable t) {
 +
                //report the failure to the log and add a toast message explaining that you failed miserably
 +
                Log.d(TAG, "onFailure: " + t.toString());
 +
                Toast.makeText(MainActivity.this, "Getting Quote Failed", Toast.LENGTH_SHORT).show();
 +
            }
 +
        });
 +
</source>
 +
 
 +
Now that everything is added, connect your app to an emulator or your android phone. Press the button and the text on the textview should change. If it doesn't, it's your fault.
 +
 
 +
You're Welcome.
 +
 
 +
 
 +
[[Category:HowTos]]
 
[[Category:Android]]
 
[[Category:Android]]

Revision as of 11:02, 19 April 2019

This tutorial will guide you through the process of calling an api using an android library called Retrofit. This tutorial will be limited to the api call and will not take you through the finer points of design or string parsing. It also will not show you how to create your own api but if you did create your own you could use this library to call it.

Download Android Studio Create New Project with Blank activity. Set the targeted API level to 21. First we want to add the libraries we will be using to our android app. You will need to go to the app's build.gradle file. This can be found under the Gradle Scripts Directory. Note that there are two build.gradle files. One if for your application and one is for your project. The app build.gradle will have the android compilesdkversion near the top. Add the following lines under dependencies to add the proper libraries. You may get a prompt to sync your project after adding these. Go ahead and do so.

 implementation 'com.squareup.retrofit2:retrofit:2.5.0'
 implementation 'com.squareup.retrofit2:converter-gson:2.5.0'
 implementation 'com.squareup.okhttp3:logging-interceptor:3.12.1'

We'll be using the internet so we also need to declare this in our app manifest. Navigate to the manifest directory and open the AndroidManifest.xml file. Above the application tag you wan to add this line

 <uses-permission android:name="android.permission.INTERNET" />

Now if your api is using cleartext traffic (any url that is Http instead of Https) then you also want to add the filling line to the application tag.

 android:usesCleartextTraffic="true"

Now you are ready to build interact with the internet.

Next you want to navigate to the activity_main.xml file. Here we want to add the views that the user will interact with. For the purposes of this app just add a textview and a button with ids. You can use the code below.

 <?xml version="1.0" encoding="utf-8"?>
 <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     tools:context=".MainActivity">
     <TextView
         android:id="@+id/textview1"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:text="Hello World!"
         app:layout_constraintTop_toTopOf="parent"
         app:layout_constraintLeft_toLeftOf="parent"
         app:layout_constraintRight_toRightOf="parent"
         app:layout_constraintBottom_toTopOf="@+id/button1" />
     <Button
         android:id="@+id/button1"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_marginBottom="280dp"
         android:text="Refresh"
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintHorizontal_bias="0.498"
         app:layout_constraintLeft_toLeftOf="parent"
         app:layout_constraintRight_toRightOf="parent"
         app:layout_constraintStart_toStartOf="parent" />
 </android.support.constraint.ConstraintLayout>

We will use the button to fire off our API calls and we will use the textview to display the information we receive from the api call.

Next let's navigate to our MainActivity Java class. In this class we need to initialize a TextView, a Button variable, and a String url variable. In the on create attach the xml elements to our variables using findViewByID. If you are unfamiliar on how to do this, please google it or check the source code. Create a method known as getInfo and pass the textview into it. Using this method we will perform the API call and we will edit the text to display the information we receive from the API call.

Now lets finally get into how to use RetroFit. We will create a RetrofitClientInstance class that will return an instance of Retrofit. We will pass our app context and our string into the method. The following code can be pretty much copy and pasted. It will create an instance of RetroFIt using the url we passed in and it will print the Http Logs to the android studio console log.

    private static final String TAG = "RetrofitClientInstance";
    private static Retrofit sRetrofit;

    public static Retrofit getRetrofitInstance(Context context, String url){

        Log.d(TAG, "getRetrofitInstance: HTTPClient");

        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();

        if(sRetrofit == null){
            sRetrofit = new retrofit2.Retrofit.Builder()
                    .baseUrl(url)
                    .client(client)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
        }

        return sRetrofit;

    }

Next we will create an interface for RetroFit. Create an interface class and call it GetDataService. You can take a look at this [guide | https://square.github.io/retrofit/] for more information about exactly how the syntax goes. Every method you add to this interface will be able to be called by your retrofit instance. It will make calls to the url you passed into your retroFit instance. Within the method, the top line will specify the type of request (GET or POST) and the sub url to target. The second line of the method will specify the structure of the response and also allow you to specify exactly what to send in your request.

We will be using the Quotes on Design [API | https://quotesondesign.com/api-v4-0/]. This API is nice because we will not need to use any tokens. We can focus on just the query and response. Our query has two fields we need to fill filter[orderby] and filter[posts_per_page]. So we will create a getQuote method that returns a list of quote objects and takes in a hash map of queries.

@GET("wp-json/posts")
Call<List<Quote>> getQuote(@QueryMap Map<String, String> query);

You should be getting an error because there is no quote class. Let's create that now. Perusing through the site we can see that all API calls will return a json object that includes an ID, title, content, and link. Our java class will need all of these. To make it easier, you can take an example son from the api call and paste it into a json to pojo generator like [here | https://codebeautify.org/json-to-java-converter]. This is the class.

public class Quote {
    private float ID;
    private String title;
    private String content;
    private String link;


    // Getter Methods

    public Quote(){}

    public Quote(float ID, String title, String content, String link) {
        this.ID = ID;
        this.title = title;
        this.content = content;
        this.link = link;
    }

    public float getID() {
        return ID;
    }

    public String getTitle() {
        return title;
    }

    public String getContent() {
        return content;
    }

    public String getLink() {
        return link;
    }

    // Setter Methods

    public void setID(float ID) {
        this.ID = ID;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public void setLink(String link) {
        this.link = link;
    }
}

Now we've finally got everything together. Let's head back to the MainActivity class. and fill in the getInfo method. You can copy and paste the code below:

Log.d(TAG, "getInfo: Started getInfo");

        //create the query map
        Map<String, String> data = new HashMap<>();
        data.put("filter[orderby]", "rand");
        data.put("filter[posts_per_page]", "1");

        //create the retrofit instance and use our getQuote method
        GetDataService service = RetrofitClientInstance.getRetrofitInstance(this, url).create(GetDataService.class);
        Call<List<Quote>> call = service.getQuote(data);

        //call the enqueue method to get the results of our call
        call.enqueue(new Callback<List<Quote>>() {
            @Override
            public void onResponse(Call<List<Quote>> call, Response<List<Quote>> response) {
                Log.d(TAG, "onResponse: Success");
                //parse through our resulting list of quotes and change the text in our text view
                for(Quote i: response.body()){
                    t.setText(i.getContent());
                }

            }

            @Override
            public void onFailure(Call<List<Quote>> call, Throwable t) {
                //report the failure to the log and add a toast message explaining that you failed miserably
                Log.d(TAG, "onFailure: " + t.toString());
                Toast.makeText(MainActivity.this, "Getting Quote Failed", Toast.LENGTH_SHORT).show();
            }
        });

Now that everything is added, connect your app to an emulator or your android phone. Press the button and the text on the textview should change. If it doesn't, it's your fault.

You're Welcome.