1

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?

halfer
  • 19,824
  • 17
  • 99
  • 186
codeinprogress
  • 3,193
  • 7
  • 43
  • 69
  • 1
    take a look for this question https://stackoverflow.com/questions/29339565/calling-rest-api-from-an-android-app – Amirouche Zeggagh Aug 25 '17 at 09:26
  • Found this as well: https://www.youtube.com/watch?v=xXkjfnhqRGI – codeinprogress Aug 25 '17 at 09:34
  • You could use 3rd party libraries like Volley or Retrofit to fetch data through REST API. Both of them work asynchronously on a separate thread and easier to implement – p.mathew13 Aug 25 '17 at 09:38
  • 1
    Yes, that is one way, but I do not want to go into dealing with third party libraries at this moment since I have started learning Android. So I was looking at some in house solutions. – codeinprogress Aug 25 '17 at 09:39

1 Answers1

0

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);
        }
    }

}
codeinprogress
  • 3,193
  • 7
  • 43
  • 69