Adding a functionality to consume the RESTful API that serves the model

Now we need to hit the API with the data on a click of the button. To achieve this, we need the flowing helper functions:

  • ByPostMethod: Accepts the URL as a String and returns the response as an InputStream.  This function takes the server URL string that we created using the Flask framework and returns the response from the server as an input stream:
InputStream ByPostMethod(String ServerURL) {

InputStream DataInputStream = null;
try {
URL url = new URL(ServerURL);

HttpURLConnection connection = (HttpURLConnection)
url.openConnection();
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setInstanceFollowRedirects(false);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/json");
connection.setRequestProperty("charset", "utf-8");
connection.setUseCaches (false);
DataOutputStream dos = new DataOutputStream(connection.getOutputStream());
dos.writeBytes(makeJSON().toString());
//flushes data output stream.
dos.flush();
dos.close();
//Getting HTTP response code
int response = connection.getResponseCode();
//if response code is 200 / OK then read Inputstream
//HttpURLConnection.HTTP_OK is equal to 200
if(response == HttpURLConnection.HTTP_OK) {
DataInputStream = connection.getInputStream();
}

} catch (Exception e) {
Log.e("ERROR CAUGHT", "Error in GetData", e);
}
return DataInputStream;

}
  • ConvertStreamToString: This function accepts InputStream and returns a String of the response. The input stream returned from the previous function is processed as a string object by the following function:
String ConvertStreamToString(InputStream stream) {

InputStreamReader isr = new InputStreamReader(stream);
BufferedReader reader = new BufferedReader(isr);
StringBuilder response = new StringBuilder();

String line = null;
try {

while ((line = reader.readLine()) != null) {
response.append(line);
}

} catch (IOException e) {
Log.e("ERROR CAUGHT", "Error in ConvertStreamToString", e);
} catch (Exception e) {
Log.e("ERROR CAUGHT", "Error in ConvertStreamToString", e);
} finally {

try {
stream.close();

} catch (IOException e) {
Log.e("ERROR CAUGHT", "Error in ConvertStreamToString", e);

} catch (Exception e) {
Log.e("ERROR CAUGHT", "Error in ConvertStreamToString", e);
}
}
return response.toString();
}
  • DisplayMessage: This functions updates the textbox with the response, which is the predicted value:
public void DisplayMessage(String a) 
{

value.setText(a);
}

A point to note is that whenever network calls are made on Android, it is a best practice to do it on a separate thread so it does not block the main user interface (UI) thread. So, we will write an inner class called MakeNetworkCall to achieve this:

private class MakeNetworkCall extends AsyncTask<String, Void, String> {

@Override
protected void onPreExecute() {
super.onPreExecute();
DisplayMessage("Please Wait ...");
}

@Override
protected String doInBackground(String... arg) {

InputStream is = null;
String URL = "http://10.0.2.2:5000/predict";
Log.d("ERROR CAUGHT", "URL: " + URL);
String res = "";

is = ByPostMethod(URL);

if (is != null) {
res = ConvertStreamToString(is);
} else {
res = "Something went wrong";
}
return res;
}

protected void onPostExecute(String result) {
super.onPostExecute(result);

DisplayMessage(result);
Log.d("COMPLETED", "Result: " + result);
}
}

Please note that we used http://10.0.2.2:5000/predict instead of http://127.0.0.1:5000/predict. This is done because in Android, when we use the emulator, it accesses the local host via 10.0.2.2 instead of 127.0.0.1. As the example is run on an emulator, we used 10.0.2.2.

Finally, we need to add the functionality to call the API on click of the button. So, within the oncreate() method, insert the following code after the button has been initialized. This will initiate a background thread to access the API on a click of the button:

estimate.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.i("CHECK", "CLICKED");

new MakeNetworkCall().execute("http://10.0.2.2:5000/predict", "Post");
}
});

We need to add permissions to use internet within the AndroidManifest.xml file. Place the following code inside the <manifest> tag:

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

Don't forget to run your Flask app. If you haven't already, make sure to run it within the conda environment activated:

set FLASK_APP=predict_api

flask run

That is all the code required to run and test the app on Android. Now run the app in the emulator, enter the details on the screen, hit the ESTIMATE VALUE button, and you'll get immediate results:

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset