Reputation: 51
I'm using a makeServiceCall to get JSON data from TheMovieDB API.
As they don't have a list of movie id's I have to for loop through id's.
String JSONString = httpHandler.makeServiceCall("https://api.themoviedb.org/3/movie/" +
i +
"?api_key=" + API_KEY);
i = id
API_KEY = my API key.
As I'm looping through the URL I get IOExceptions for some of the calls.
I/System.out: ID: 152
I/System.out: ID: 160
I/System.out: ID: 165
I/System.out: ID: 168
I/System.out: ID: 171
E/HttpHandler: IOException: https://api.themoviedb.org/3/movie/181?api_key=b692b9da86f1cf0c1b623ea6e2770101
E/HttpHandler: IOException: https://api.themoviedb.org/3/movie/184?api_key=b692b9da86f1cf0c1b623ea6e2770101
E/HttpHandler: IOException: https://api.themoviedb.org/3/movie/185?api_key=b692b9da86f1cf0c1b623ea6e2770101
E/HttpHandler: IOException: https://api.themoviedb.org/3/movie/186?api_key=b692b9da86f1cf0c1b623ea6e2770101
E/HttpHandler: IOException: https://api.themoviedb.org/3/movie/187?api_key=b692b9da86f1cf0c1b623ea6e2770101
E/HttpHandler: IOException: https://api.themoviedb.org/3/movie/188?api_key=b692b9da86f1cf0c1b623ea6e2770101
E/HttpHandler: IOException: https://api.themoviedb.org/3/movie/189?api_key=b692b9da86f1cf0c1b623ea6e2770101
E/HttpHandler: IOException: https://api.themoviedb.org/3/movie/190?api_key=b692b9da86f1cf0c1b623ea6e2770101
E/HttpHandler: IOException: https://api.themoviedb.org/3/movie/191?api_key=b692b9da86f1cf0c1b623ea6e2770101
E/HttpHandler: IOException: https://api.themoviedb.org/3/movie/192?api_key=b692b9da86f1cf0c1b623ea6e2770101
Some of the IOExceptions are just URL's that came back as null, as
{"status_code":34,"status_message":"The resource you requested could not be found."}
How can I slow down the for loop to not exceed the API call limit?
HttpHandler:
package com.example.zdroa.yplex;
import android.util.Log;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
public class HttpHandler {
private static final String TAG = HttpHandler.class.getSimpleName();
public HttpHandler() {
}
public String makeServiceCall(String reqUrl) {
String response = null;
try {
URL url = new URL(reqUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
// read the response
InputStream in = new BufferedInputStream(conn.getInputStream());
response = convertStreamToString(in);
} catch (MalformedURLException e) {
Log.e(TAG, "MalformedURLException: " + e.getMessage());
} catch (ProtocolException e) {
Log.e(TAG, "ProtocolException: " + e.getMessage());
} catch (IOException e) {
Log.e(TAG, "IOException: " + e.getMessage());
} catch (Exception e) {
Log.e(TAG, "Exception: " + e.getMessage());
}
return response;
}
private String convertStreamToString(InputStream is) {
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line;
try {
while ((line = reader.readLine()) != null) {
sb.append(line).append('\n');
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return sb.toString();
}
}
My calls are made inside of an AsyncTask
class getWorkingIdsFromAPI extends AsyncTask<Void, Void, Void> {
ArrayList<String> alPersonType;
public getWorkingIdsFromAPI(ArrayList<String> arrayList) {
alPersonType = new ArrayList<>(arrayList);
}
@Override
protected Void doInBackground(Void... params) {
final HttpHandler httpHandler = new HttpHandler();
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
for (int i = 0; i < 200; i++) { //20000
String JSONString = httpHandler.makeServiceCall("https://api.themoviedb.org/3/movie/" + i + "?api_key=" + API_KEY);
if (JSONString != null) {
try {
JSONObject jsonObject = new JSONObject(JSONString);
JSONArray jsonArray = jsonObject.getJSONArray("genres");
boolean cont = true;
for (int a = 0; a < jsonArray.length(); a++) {
JSONObject jsonObject1 = jsonArray.getJSONObject(a);
String string = jsonObject1.getString("name");
for (int b = 0; b < alPersonType.size(); b++) {
if (string.equals(alPersonType.get(b))) {
cont = false;
}
}
}
if (cont) {
String id = String.valueOf(jsonObject.getInt("id"));
System.out.println("ID: " + id);
switch (id.length()) {
case 1:
id = "0000" + id;
break;
case 2:
id = "000" + id;
break;
case 3:
id = "00" + id;
break;
case 4:
id = "0" + id;
break;
}
switch (i) {
case 1:
STRING_LIST_OF_IDS = STRING_LIST_OF_IDS + id;
break;
default:
STRING_LIST_OF_IDS = ", " + STRING_LIST_OF_IDS + id;
break;
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}
}
, 3000);
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
//add STRING_LIST_OF_IDS
getStringOfIdsFromDB();
}
}
Upvotes: 1
Views: 1900
Reputation: 881
You are doing it wrong as timer task will be repeated after each 3000 ms, it will execute all the request in the loop. you can change your code something like this.
ArrayList<String> alPersonType;
i=0; // initialise your variable once instead of each time in task
public getWorkingIdsFromAPI(ArrayList<String> arrayList) {
alPersonType = new ArrayList<>(arrayList);
}
@Override
protected Void doInBackground(Void... params) {
final HttpHandler httpHandler = new HttpHandler();
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
if(i < 200) { String JSONString = httpHandler.makeServiceCall("https://api.themoviedb.org/3/movie/" + i + "?api_key=" + API_KEY);
if (JSONString != null) {
try {
JSONObject jsonObject = new JSONObject(JSONString);
JSONArray jsonArray = jsonObject.getJSONArray("genres");
boolean cont = true;
for (int a = 0; a < jsonArray.length(); a++) {
JSONObject jsonObject1 = jsonArray.getJSONObject(a);
String string = jsonObject1.getString("name");
for (int b = 0; b < alPersonType.size(); b++) {
if (string.equals(alPersonType.get(b))) {
cont = false;
}
}
}
if (cont) {
String id = String.valueOf(jsonObject.getInt("id"));
System.out.println("ID: " + id);
switch (id.length()) {
case 1:
id = "0000" + id;
break;
case 2:
id = "000" + id;
break;
case 3:
id = "00" + id;
break;
case 4:
id = "0" + id;
break;
}
switch (i) {
case 1:
STRING_LIST_OF_IDS = STRING_LIST_OF_IDS + id;
break;
default:
STRING_LIST_OF_IDS = ", " + STRING_LIST_OF_IDS + id;
break;
}
}
} catch (JSONException e) {
e.printStackTrace();
}i++;//increase the counter
}
}
}
}
, 3000);return null;
}
Also you can have a different Approach with Thread.sleep() change your doin background like below
@Override
protected Void doInBackground(Void... params) {
final HttpHandler httpHandler = new HttpHandler();
for (int i = 0; i < 200; i++) {try {
Thread.sleep(400);} catch (InterruptedException e) {
e.printStackTrace();}
String JSONString = httpHandler.makeServiceCall("https://api.themoviedb.org/3/movie/" + i + "?api_key=" + API_KEY);
if (JSONString != null) {
try {
JSONObject jsonObject = new JSONObject(JSONString);
JSONArray jsonArray = jsonObject.getJSONArray("genres");
boolean cont = true;
for (int a = 0; a < jsonArray.length(); a++) {
JSONObject jsonObject1 = jsonArray.getJSONObject(a);
String string = jsonObject1.getString("name");
for (int b = 0; b < alPersonType.size(); b++) {
if (string.equals(alPersonType.get(b))) {
cont = false;
}
}
}
if (cont) {
String id = String.valueOf(jsonObject.getInt("id"));
System.out.println("ID: " + id);
switch (id.length()) {
case 1:
id = "0000" + id;
break;
case 2:
id = "000" + id;
break;
case 3:
id = "00" + id;
break;
case 4:
id = "0" + id;
break;
}
switch (i) {
case 1:
STRING_LIST_OF_IDS = STRING_LIST_OF_IDS + id;
break;
default:
STRING_LIST_OF_IDS = ", " + STRING_LIST_OF_IDS + id;
break;
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
;
return null;
}
Upvotes: 1
Reputation: 51
Put a Thread.sleep(duration); just after the loop start.
try {
Thread.sleep(400);
} catch (InterruptedException e) {
e.printStackTrace();
}
Takes a 400 ms. sleep every loop cycle.
Upvotes: 0