hello im using Android Studio an im trying to retrieve a json from a class with asynctask but i can retrieve the data obtained to the main thread if if create a getter to obtaind data variable it's null and i get an error in runtime can you help me please?
this is the code:
(mainactivity)
Tarea tarea= new Tarea(URL_DATA,Request.toString(),this);
tarea.execute();
texto.setText((CharSequence) tarea.getData());
(class)
public class Tarea extends AsyncTask {
ProgressDialog progressDialog;
String MyURL,MJson;
volatile String data="";
public String getData() {
return data;
}
public Tarea(String myURL, String mJson, Context contexto) {
this.contexto = contexto;
this.MJson=mJson;
this.MyURL=myURL;
}
Context contexto;
#Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog=new ProgressDialog(contexto);
progressDialog.setMessage("Buscando Paqueterias, por favor espera un momento...");
progressDialog.show();
}
#Override
protected Object doInBackground(Object[] objects) {
if(MyURL!=null&&MJson!=null) {
try {
URL url = new URL(MyURL.toString());
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
conn.setRequestProperty("Accept", "application/json");
conn.setDoOutput(true);
conn.setDoInput(true);
JSONObject MyJson = new JSONObject(MJson);
DataOutputStream os = new DataOutputStream(conn.getOutputStream());
os.writeBytes(MyJson.toString());
os.flush();
os.close();
//Log.i("Status",String.valueOf(conn.getResponseCode()));
//Log.i("MSG", conn.getResponseMessage());
InputStream in = conn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(in);
int inputStreamData = inputStreamReader.read();
while (inputStreamData != -1) {
char current = (char) inputStreamData;
inputStreamData = inputStreamReader.read();
data += current;
}
} catch (Exception e) {
e.printStackTrace();
}
progressDialog.dismiss();
}else {
Log.i("Error...","Alguna de las variables MyURL o MJson esta vacia...");
}
return data;
}
#Override
protected void onPostExecute(Object o) {
super.onPostExecute(o);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.i("REs",data);
}
}
i can print the LOG but i cant send it to the mainactivity to manupulate the json
You can do this with the help of callback approach.
Steps
1. Create an interface
2. Create an inner class on activity implement that interface.
3. Pass the instance of inner class to "Tarea" constructor.
4. Use constructor variable to communicate with activity.
You can also do the with different approach by overriding onPostExecute.
Use below code..
Tarea tarea= new Tarea(URL_DATA,Request.toString(),this) {
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
}
};
Related
Hello i'm new to android studio and i have code which is showing recycler view list from json data. Now i want to open items in new activity.I want to open item from recyclerview and show image and some text in new activity. I need solution code.
I have tried some ways but it doesn't work.
This is my code:
public class MainActivity extends AppCompatActivity {
public static final int CONNECTION_TIMEOUT = 10000;
public static final int READ_TIMEOUT = 15000;
private RecyclerView mRVFishPrice;
private AdapterFish mAdapter;
SwipeRefreshLayout mSwipeRefreshLayout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSwipeRefreshLayout = (SwipeRefreshLayout)findViewById(R.id.swifeRefresh);
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
new AsyncFetch().execute();
}
});
new AsyncFetch().execute();
}
private class AsyncFetch extends AsyncTask<String, String, String> {
ProgressDialog pdLoading = new ProgressDialog(MainActivity.this);
HttpURLConnection conn;
URL url = null;
#Override
protected void onPreExecute() {
super.onPreExecute();
//this method will be running on UI thread
pdLoading.setMessage("\tLoading...");
pdLoading.setCancelable(false);
pdLoading.show();
}
#Override
protected String doInBackground(String... params) {
try {
url = new URL("https://MYURL.com");
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return e.toString();
}
try {
// Setup HttpURLConnection class to send and receive data from php and mysql
conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(READ_TIMEOUT);
conn.setConnectTimeout(CONNECTION_TIMEOUT);
conn.setRequestMethod("GET");
// setDoOutput to true as we recieve data from json file
conn.setDoOutput(true);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
return e1.toString();
}
try {
int response_code = conn.getResponseCode();
// Check if successful connection made
if (response_code == HttpURLConnection.HTTP_OK) {
// Read data sent from server
InputStream input = conn.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
StringBuilder result = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
result.append(line);
}
// Pass data to onPostExecute method
return (result.toString());
} else {
return ("unsuccessful");
}
} catch (IOException e) {
e.printStackTrace();
return e.toString();
} finally {
conn.disconnect();
}
}
#Override
protected void onPostExecute(String result) {
//this method will be running on UI thread
mSwipeRefreshLayout.setRefreshing(false);
pdLoading.dismiss();
List<DataFish> data=new ArrayList<>();
pdLoading.dismiss();
try {
JSONArray jArray = new JSONArray(result);
for(int i=0;i<jArray.length();i++){
JSONObject json_data = jArray.getJSONObject(i);
DataFish fishData = new DataFish();
fishData.fishImage= json_data.getString("fish_img");
fishData.fishName= json_data.getString("fish_name");
fishData.catName= json_data.getString("cat_name");
fishData.sizeName= json_data.getString("size_name");
fishData.price= json_data.getInt("price");
data.add(fishData);
}
mRVFishPrice = (RecyclerView)findViewById(R.id.fishPriceList);
mAdapter = new AdapterFish(MainActivity.this, data);
mRVFishPrice.setAdapter(mAdapter);
mRVFishPrice.setLayoutManager(new LinearLayoutManager(MainActivity.this));
} catch (JSONException e) {
Toast.makeText(MainActivity.this, e.toString(), Toast.LENGTH_LONG).show();
}
}
}
}
I expect to open item from recyclerview list in new activity and show image item and some text.
You can archive this by passing an instance of the interface in your adapter class and implement that interface in your activity.
refer this to get insights link
Sample Snippets
Declare interface:
public interface AdapterCallback {
void onFishClick(DataFish item);
}
Pass interface instance via setup your adapter in activity.
new AdapterFish(MainActivity.this, data, new AdapterCallback() {
#Override
void onfishClick(DataFish item) {
// herer do your work
}
});
In your adapter constructor
private AdapterCallback callback;
AdapterFish(Context contex, data, AdapterCallback callback) {
...
this.callback = callback;
}
define click listener in a holder and inside a method call callback.onFishCall(selectedItem);
OnBindViewHolder(...) {
holder.button.onClicklistener(new OnClickListener{
...
if(callback != null) { // for null check
callback.onFishClikc(item);
}
});
}
I am trying to fetch data from thingspeak api and I am taking Input for channel id and passing it on URL. But I have to check if the url is responding or not, if it is responding than go ahead with the code else user have to change channel id.
Error I am getting is 'int java.lang.String.length()' on a null object reference
and
W/System.err: java.io.FileNotFoundException: https://api.thingspeak.com/channels/497971/feeds.json?results=1
This is invalid url if I change it to
https://api.thingspeak.com/channels/497970/feeds.json?results=1
This will work
Code I am trying is
public class MainActivity extends AppCompatActivity {
TextView a, b;
String result = "";
String field1,field2,field3;
private int count = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
a = (TextView) findViewById(R.id.a);
b = (TextView) findViewById(R.id.b);
new CountDownTimer(100000, 10000) {
#Override
public void onTick(long l) {
DownloadTask task = new DownloadTask();
task.execute("https://api.thingspeak.com/channels/497970/feeds.json?results=1");
}
#Override
public void onFinish() {
}
}.start();
}
public class DownloadTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
URL url;
result = "";
HttpURLConnection urlConnection = null;
try {
url = new URL(urls[0]);
urlConnection = (HttpURLConnection) url.openConnection();
InputStream in = urlConnection.getInputStream();
InputStreamReader reader = new InputStreamReader(in);
int data = reader.read();
while (data != -1) {
char current = (char) data;
result += current;
data = reader.read();
}
return result;
} catch (MalformedURLException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(final String result) {
super.onPostExecute(result);
search(result);
}
public void search(String result) {
try {
JSONObject jsonObject = new JSONObject(result);
JSONObject fieldinfo = jsonObject.getJSONObject("channel");
String ff1 = fieldinfo.optString("field1","No Value");
String ff2 = fieldinfo.optString("field2","No Value");
JSONArray weatherInfo = jsonObject.getJSONArray("feeds");
JSONObject legsobject = weatherInfo.getJSONObject(0);
field1 = legsobject.getString("field1");
field2 = legsobject.getString("field2");
a.setText(ff1);
c.setText(field1);
} catch (JSONException e1) {
e1.printStackTrace();
}
}
}
}
Here is the Image of error
The issue here is that you are not taking into account that HTTP connections sometimes do fail, like in this case. And it fails because the channel id does not exist.
When you set a correct channel id, the URL is also correct because the resource exists and therefore you get the desired results.
However, when you set a wrong channel id the HTTP request fails (because that URL does not exist). Regardless of this, you are attempting to read the response and that's when it all blows up.
When you make an HTTP request to a server, it responds with a status code indicating what happened with your request. You are completely ignoring this status code.
Look at the headers that a request to that URL throws using:
curl -i https://api.thingspeak.com/channels/497971/feeds.json?results=1:
HTTP/1.1 400 Bad Request
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
Connection: close
Status: 400 Bad Request
... [Shortened] ...
You can learn all about HTTP status codes in a simple Google search but the summary is that it is a number between 100 and 599 that indicates:
Request successfully handled: when it is between 200 and 299.
Request could not be handled, it failed: when it is between 400 and 499.
The request failed because the server basically blew up: (> 500).
In order to retrieve this status code, you need to call the getResponseCode() method of the urlConnection instance.
Only when the status code is successful (between 200 and 299) the call to urlConnection.getInputStream() will succeed. In case of error you need to call urlConnection.getErrorStream().
So in order to fix your code, you need to do something like this:
#Override
protected String doInBackground(String... urls) {
URL url;
result = "";
HttpURLConnection urlConnection = null;
try {
url = new URL(urls[0]);
// Open the conection
urlConnection = (HttpURLConnection) url.openConnection();
// Retrieve status code
int statusCode = urlConnection.getResponseCode();
// Determine whether the request was handled successfully or not
boolean success = (statusCode >= 200) && (statusCode < 300);
InputStream in;
if(success) {
// Read the response when request was handled successfully
in = urlConnection.getInputStream();
} else {
// Read the error stream when the request failed
in = urlConnection.getErrorStream();
}
InputStreamReader reader = new InputStreamReader(in);
int data = reader.read();
while (data != -1) {
char current = (char) data;
result += current;
data = reader.read();
}
return result;
} catch (MalformedURLException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
} finally {
// Close the connection
if(urlConnection != null) {
urlConnection.disconnect();
}
}
return null;
}
First of all, don't forget to close the connection once you are done (I included the disconnection in the finally {} block).
If you debug or log that code, you will see that the status code you are receiving is 400. That is the HTTP status code for Bad Request, indicating that your request is not correct and you need to fix it. If you analyze the content of the result variable, you will see that the value equals to -1.
Therefore in the onPostExecute callback you should make sure the value is different than -1 before attempting to deserialize it, since otherwise it will blow up again.
You can fix your onPostExecute callback like this:
#Override
protected void onPostExecute(final String result) {
super.onPostExecute(result);
if(result.equals(-1)) {
// Do something else, show an error to the user indicating the channel id is wrong
} else {
// Since there is no error, you can proceed with the deserialization of the response
search(result);
}
}
I hope it helps and that it was clear enough.
Cheers!
As you described you need to update your code like
public class MainActivity extends AppCompatActivity {
TextView a, b;
String result = "";
String field1,field2,field3;
private int count = 0;
int channelId=497970;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
a = (TextView) findViewById(R.id.a);
b = (TextView) findViewById(R.id.b);
startCounter(channelId);
}
public void startCounter(int channelId){
new CountDownTimer(100000, 10000) {
#Override
public void onTick(long l) {
DownloadTask task = new DownloadTask();
task.execute("https://api.thingspeak.com/channels/"+channelId+"/feeds.json?results=1");
}
#Override
public void onFinish() {
}
}.start();
}
public class DownloadTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
URL url;
result = "";
HttpURLConnection urlConnection = null;
try {
url = new URL(urls[0]);
urlConnection = (HttpURLConnection) url.openConnection();
InputStream in = urlConnection.getInputStream();
InputStreamReader reader = new InputStreamReader(in);
int data = reader.read();
while (data != -1) {
char current = (char) data;
result += current;
data = reader.read();
}
return result;
} catch (FileNotFoundException e){
startCounter(channelId+1);
}
catch (MalformedURLException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(final String result) {
super.onPostExecute(result);
search(result);
}
public void search(String result) {
try {
JSONObject jsonObject = new JSONObject(result);
JSONObject fieldinfo = jsonObject.getJSONObject("channel");
String ff1 = fieldinfo.optString("field1","No Value");
String ff2 = fieldinfo.optString("field2","No Value");
JSONArray weatherInfo = jsonObject.getJSONArray("feeds");
JSONObject legsobject = weatherInfo.getJSONObject(0);
field1 = legsobject.getString("field1");
field2 = legsobject.getString("field2");
a.setText(ff1);
c.setText(field1);
} catch (JSONException e1) {
e1.printStackTrace();
}
}
}
}
So here in Java I've written a typical class, to send json to a rest server. (I'll include the whole class below for clarity.) So that's a file "Fetcher.java"
Now for the callback you need an interface. The interface is trivial, just one function with a string.
public interface FetcherInterface {
public void fetcherDone(String result);
}
Annoyingly you need a whole file for that, "FetcherInterface.java"
So this interface is nothing but "one callback with a string". Often all you need is just "one callback with no arguments".
In fact ........ are there some sort of standard interfaces I can use, or something like that?
It seems kind of annoying to have to put in a whole interface for such a simple "standard" interface.
What's the deal on this? What's the javaly solution?
It seems you CAN NOT put it in the same file:
Perhaps I misunderstand something there. If you could put it in the same file, that would be convenient at least.
(Lambdas are not yet practically available. Anyway, sometimes you want an interface.)
Just for clarity, here's how you call the class
JSONObject j = new JSONObject();
try {
j.put("height", 2.1);
j.put("width", 2.5);
j.put("command", "blah");
} catch (JSONException e) {
e.printStackTrace();
}
new Fetcher("mobile/login", j, new FetcherInterface() {
#Override
public void fetcherDone(String result) {
Log.d("DEV","all done");
doSomething(result);
}
}
).execute();
or indeed
public class HappyClass extends Activity implements FetcherInterface {
...
private void someCall() {
JSONObject j = new JSONObject();
try {
j.put("height", 2.1);
j.put("width", 2.5);
j.put("command", "blah");
} catch (JSONException e) {
e.printStackTrace();
}
new Fetcher("mobile/data", j, this).execute();
devBlank();
}
#Override
public void fetcherDone(String result) {
Log.d("DEV","all done" +result);
doSomething(result);
}
Here's the whole class... Fetcher.java file
public class Fetcher extends AsyncTask<Void, Void, String> {
private String urlTail;
private JSONObject jsonToSend;
private FetcherInterface callback;
// initializer...
Fetcher(String ut, JSONObject toSend, FetcherInterface cb) {
urlTail = ut;
jsonToSend = toSend;
callback = cb;
}
#Override
protected String doInBackground(Void... params) {
HttpURLConnection urlConnection = null; // declare outside try, to close in finally
BufferedReader reader = null; // declare outside try, to close in finally
String rawJsonResultString = null;
String json = jsonToSend.toString();
Log.d("DEV","the json string in Fetcher is " +json);
try {
URL url = new URL("https://falcon.totalfsm.com/" + urlTail);
Log.d("DEV","the full URL in Fetcher is " +url);
// open a json-in-the-body type of connection.......
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("POST");
urlConnection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
urlConnection.setDoOutput(true);
urlConnection.setDoInput(true);
urlConnection.setConnectTimeout(5000);
// urlConnection.setDoOutput(false); // can be important?
urlConnection.connect();
OutputStream os = urlConnection.getOutputStream();
os.write(json.getBytes("UTF-8"));
os.close();
// annoyingly, you have to choose normal versus error stream...
InputStream inputStream;
int status = urlConnection.getResponseCode();
if (status != HttpURLConnection.HTTP_OK)
inputStream = urlConnection.getErrorStream();
else
inputStream = urlConnection.getInputStream();
if (inputStream == null) { // nothing to do.
return null;
}
StringBuffer buffer = new StringBuffer();
reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) { // adding newlines makes debugging easier
buffer.append(line + "\n");
}
if (buffer.length() == 0) { // stream was empty
return null;
}
rawJsonResultString = buffer.toString();
return rawJsonResultString;
} catch (IOException e) {
Log.e("PlaceholderFragment", "Error ", e);
return null;
} finally{
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
Log.e("PlaceholderFragment", "Error closing stream", e);
}
}
}
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
Log.d("DEV", "Fetcher done");
if (s==null) {
Log.d("DEV","applying anti-null measures in Fetcher!");
s = "message from app communications layer: 'null' returned from servers for that call at " +urlTail;
}
callback.fetcherDone(s);
}
}
I feel bad answering my own question, but as there were no other answers this info may be helpful.
DaveNewton and Rowtang have supplied the exact answers here:
(Point 1) If you want a genuinely public interface, it goes in its own file. That's how Java works. There's no alternative.
(Point 2) Normally, use protected interface and declare the interface inside the class. It can then be used throughout the app.
So...
public class Fetcher extends AsyncTask<Void, Void, String> {
protected interface FetcherInterface {
public void fetcherDone(String result);
}
private String urlTail;
private JSONObject jsonToSend;
private FetcherInterface callback;
Fetcher(String ut, JSONObject toSend, FetcherInterface cb) {
urlTail = ut;
jsonToSend = toSend;
callback = cb;
}
#Override
protected String doInBackground(Void... params) {
....
(c# programmers would maybe call it "IFetcher".)
I have PostData class to transmit data lat, long,mac,.. to the server which is being sent to it from the service class. In PostData class, the data is being processed with the aid of AsyncTask and HttpURLConnection.
Now I have a new activity where the user can send query to the server. To reach that I have to get ArrayList<Integer> from the server and create a something like checkbox list, where the user can select the desirable items then the data will be sent to the server to retrieve a result.
Can I implement a new Asyntask and HttpURLConnection to achieve that or I have to use my AsynTask and HttpURLCOnnection in the POstData class?
I appreciate any help.
My PostData class:
public class PostData {
String jSONString;
private AsyncTaskCallback callback;
public PostData(AsyncTaskCallback callback) {
this.callback = callback;
}
public String getjSONString() {
return jSONString;
}
public void setjSONString(String jSONString) {
this.jSONString = jSONString;
}
public void post_data(String jSONString, Context context) {
this.jSONString = jSONString;
new MyAsyncTask(context).execute(jSONString);
}
class MyAsyncTask extends AsyncTask<String, Integer, ArrayList<Integer>> {
final Context mContext;
ArrayList<Integer> routes = new ArrayList<Integer>();
double distance;
public MyAsyncTask(Context context) {
mContext = context;
}
#Override
protected ArrayList<Integer> doInBackground(String... params) {
BufferedReader reader = null;
try {
URL myUrl = new URL(
"https://bustracker.rhcloud.com/webapi/test");
HttpURLConnection conn = (HttpURLConnection) myUrl
.openConnection();
conn.setRequestMethod("POST");
conn.setDoOutput(true);
conn.setConnectTimeout(10000);
conn.setReadTimeout(10000);
conn.setRequestProperty("Content-Type", "application/json");
conn.connect();
DataOutputStream wr = new DataOutputStream(
conn.getOutputStream());
wr.writeBytes(params[0]);
wr.close();
StringBuilder sb = new StringBuilder();
reader = new BufferedReader(new InputStreamReader(
conn.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
Gson gson = new Gson();
StopsJSON data = gson.fromJson(sb.toString(), StopsJSON.class);
routes = data.getRoutes();
distance = data.getDistance();
System.out.println("The output of the StringBulder: "
+ sb.toString());
} catch (IOException e) {
e.printStackTrace();
return null;
} finally {
if (reader != null) {
try {
reader.close();
return null;
} catch (Exception e) {
e.printStackTrace();
}
}
}
return null;
}
protected void onPostExecute(ArrayList<Integer> result) {
if (routes != null && !routes.isEmpty()) {
callback.onAsyncTaskFinished(routes, distance);
}else{
Log.e("123", "Avoiding null pointer, the routes are null!!!");
}
}
}
}
This may set you on a path of some code refactoring, but for general good practice regarding REST requests you should look into Volley, or Retrofit, (also another SO question regarding retrofit that might help).
these libraries are very efficient performance-wise, and in the long run will save you a lot of grief, they take care of the background threading, and you won't necessarily need to explicitly use HttpUrlConnection.
Hope this helps.
Edit :
To further answer your question - if you do wish to specifically use AsyncTask - you should use the PostData class as a general purpose class, in your case for the network operations (might also possibly want to make it a Singleton, and give it a more general name).
and yes your implementation looks like you should be able to use it, and any corrections\changes\additions should be made in the AsyncTask itself under PostData, no need for another general class, if need be - you can just add more inner AsyncTask subclasses.
my (very very general) direction would be:
public class NetworkData {
String jSONString;
private AsyncTaskCallback callback;
public NetworkData(AsyncTaskCallback callback) {
this.callback = callback;
}
public String getjSONString() {
return jSONString;
}
public void setjSONString(String jSONString) {
this.jSONString = jSONString;
}
//let's say this is for post requests...
public void postData(String jSONString, Context context) {
this.jSONString = jSONString;
new MyPostTask(context).execute(jSONString);
}
//let's say this is for get requests...
public void getData(String jSONString, Context context) {
this.jSONString = jSONString;
new MyGetTask(context).execute(jSONString);
}
class MyPostTask extends AsyncTask<String, Integer, ArrayList<Integer>> {
final Context mContext;
ArrayList<Integer> routes = new ArrayList<Integer>();
double distance;
public MyPostTask(Context context) {
mContext = context;
}
#Override
protected ArrayList<Integer> doInBackground(String... params)
{
try
{
//do you stuff for post requests...
} catch (IOException e)
{
//...
}
finally
{
//...
}
}
}
class MyGetTask extends AsyncTask<String, Void, ArrayList<Object>> {
final Context mContext;
ArrayList<Object> routes = new ArrayList<Object>();
public MyPostTask(Context context) {
mContext = context;
}
#Override
protected ArrayList<Object> doInBackground(String... params)
{
try
{
//do you stuff for get requests...
}
catch (IOException e)
{
//...
}
finally
{
//...
}
}
}
}
If you do choose to use Volley or Retrofit, then keep using the general class structure and just modify it's utilities and replace the requset format (i.e. instead of the AsyncTask parts).
This the most bizarre problem I have ever seen. I get "No product available" although there are products in my database.
Here my service:
public class AllProductsService {
private String URL = "xxxx";
Gson gson;
public AllProductsService(int page) {
gson = new Gson();
URL = URL + "?page=" + Integer.toString(page);
}
private InputStream sendRequest(URL url) throws Exception {
try {
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.connect();
if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
return urlConnection.getInputStream();
}
} catch (Exception e) {
throw new Exception("");
}
return null;
}
public List<Product> getProducts() {
try {
InputStream inputStream = sendRequest(new URL(URL));
if(inputStream != null) {
InputStreamReader reader = new InputStreamReader(inputStream);
return gson.fromJson(reader, new TypeToken<List<Product>>(){}.getType());
}
}
catch (Exception e) {
}
return null;
}
}
And my AsyncTask class:
private class AllProductsTask extends AsyncTask<Void, Void, List<Product>> {
#Override
protected void onPreExecute() {
setSupportProgressBarIndeterminateVisibility(true);
}
#Override
protected List<Product> doInBackground(Void... params) {
AllProductsService allProductsService = new AllProductsService(current_page);
List<Product> liste = allProductsService.getProducts();
if (liste != null && liste.size() >= 1)
return liste;
return new ArrayList<Product>();
}
protected void onPostExecute(java.util.List<Product> result) {
setSupportProgressBarIndeterminateVisibility(false);
if (result.isEmpty() && isInternetPresent && current_page < 2) {
Crouton.makeText(MainActivity.this, "No product available!", Style.ALERT).show();
}
//populate adapter
}
}
When I call the URL from the browser, results are displayed correctly. I also try with a different URL with the same code and it works fine. I don't know why.
I think problem is; you are returning the
new ArrayList<Product>();
in doInBackground() of Asynctask which is null. You should return the liste here. or place the return new ArrayList<Product>(); in else condition
I found the solution: just have to remove the slash at the end of the URL. Thank you #trevor-e. Knowing the HTTP code status help me.