'Should I use AsyncTask or IntentService for making a REST API call? [duplicate]

I am learning Android development and creating an app which calls a REST Service on button click which returns a famous quote from a movie. This quote will be shown on the screen (on TextView).

I have added the user permission to the manifest file:

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

This is my MainActivity.java code

public class MainActivity extends AppCompatActivity {
    private static final String LOGTAG = "info";
    private static final String QUOTES_API = "https://andruxnet-random-famous-quotes.p.mashape.com/?cat=movies&count=1";
    private static final String MASHAPE_KEY = "this-my-api-key";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button newQuoteBtn = (Button) findViewById(R.id.quotesBtn);

        newQuoteBtn.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                String quote = getQuote();
                Log.i(LOGTAG, quote);
                //the quote will be then shown on the text view
            }
        });
    }

    private String getQuote() {
        try {
            URL quotesURL = new URL(QUOTES_API);
            HttpsURLConnection conn = (HttpsURLConnection) quotesURL.openConnection();
            conn.setRequestProperty("X-Mashape-Key", MASHAPE_KEY);
            conn.setRequestProperty("Accept", "application/json");

            if(conn.getResponseCode() == 200) {
                InputStream inputStream = conn.getInputStream();
                InputStreamReader isReader = new InputStreamReader(inputStream, "UTF-8");

                BufferedReader buffReader = new BufferedReader(isReader);
                StringBuffer json = new StringBuffer(1024);
                String tmp="";
                while((tmp=buffReader.readLine())!=null) {
                    json.append(tmp).append("\n");
                }
                buffReader.close();

                JSONObject data = new JSONObject(json.toString());
                Log.i(LOGTAG, data.getString("quote"));
                return data.getString("quote");
            } else {
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

However when I click the button in the emulator app, nothing happens, it just adds the following message to the logcat

android.os.NetworkOnMainThreadException

From what I am reading, I cannot carry out networking operations on main thread and thats why we have to use AsyncTask. I know that I would need to create a new class which extends AsyncTask but I am still confused about few things:

Q1) Will the new class be an inner class for MainActivity.java or can it be a separate class file as well?

Q2) What will be the params for class GetQuotesClass extends AsyncTask<?, ?, ?> do I just send <void, void, void> ?

Q3) And how do I call it from my button click? Should I just do new GetQuotesClass().execute()?

I also read the following comment in another stack overflow thread

AsyncTask should not be used for network activity, because it's tied to the activity, but not the activity lifecycle. Rotating the device with this task is running will cause an exception and crash your app. Use an IntentService that drops data in the sqlite database instead

How can I proceed?



Solution 1:[1]

OK, I found out how to do this, here is the code (minus the API key and other stuff)

public class MainActivity extends AppCompatActivity {
    private static final String LOGTAG = "info";
    private static final String QUOTES_API = "https://andruxnet-random-famous-quotes.p.mashape.com/?cat=movies&count=1";
    private static final String MASHAPE_KEY = "myapikey";

    TextView quotesTextView, quotesSourceTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button newQuoteBtn = (Button) findViewById(R.id.quotesBtn);
        quotesTextView = (TextView) findViewById(R.id.quotesText);
        quotesSourceTextView = (TextView) findViewById(R.id.quotesSourceText);

        newQuoteBtn.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                new GetQuote().execute();
            }
        });
    }

    private class GetQuote extends AsyncTask<Void, Void, Void> {
        private String quote, quoteSource;

        @Override
        protected Void doInBackground(Void... voids) {
            try {
                URL quotesURL = new URL(QUOTES_API);
                HttpsURLConnection conn = (HttpsURLConnection) quotesURL.openConnection();
                conn.setRequestProperty("X-Mashape-Key", MASHAPE_KEY);
                conn.setRequestProperty("Accept", "application/json");

                if(conn.getResponseCode() == 200) {
                    InputStream inputStream = conn.getInputStream();
                    InputStreamReader isReader = new InputStreamReader(inputStream, "UTF-8");

                    BufferedReader buffReader = new BufferedReader(isReader);
                    StringBuffer json = new StringBuffer(1024);
                    String tmp="";
                    while((tmp=buffReader.readLine())!=null) {
                        json.append(tmp).append("\n");
                    }
                    buffReader.close();

                    JSONObject data = new JSONObject(json.toString());
                    Log.i(LOGTAG, data.getString("quote"));
                    quote = data.getString("quote");
                    quoteSource = data.getString("author");
                } else {
                    quote = "Response code: " + conn.getResponseCode();
                    quoteSource = "Mashape";
                }
            } catch (Exception e) {
                e.printStackTrace();
                quote = e.getMessage();
                quoteSource = "Exception Class";
            }
            return null;
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            quotesTextView.setText(quote);
            quotesSourceTextView.setText(quoteSource);
            super.onPostExecute(aVoid);
        }
    }

}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 codeinprogress