Please help me it should call again the server if the response code is 204 how to call?
String command = ("http://api.railwayapi.com/live/train/" + m_train_Number + "/doj/" + m_year + m_month + m_day + "/apikey/tc9sc898/");
new JSONTask().execute(command);
public class JSONTask extends AsyncTask<String, String, LiveStationModel>
{
LiveStationModel liveStationModel = null;
protected LiveStationModel doInBackground(String... params) {
IOException e;
MalformedURLException e2;
List<LiveStationModel> myList = null;
Throwable th;
JSONException e3;
HttpURLConnection connection = null;
BufferedReader reader = null;
try {
connection = (HttpURLConnection) new URL(params[0]).openConnection();
connection.connect();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
try {
StringBuffer buffer = new StringBuffer();
String str = "";
while (true) {
str = bufferedReader.readLine();
if (str == null) {
break;
}
buffer.append(str);
}
your can check that it onPostExecute method like:
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
//check your if condition here
}
public class JSONTask extends AsyncTask<String, String, LiveStationModel>
{
int resp;
-------
connection.connect();
resp = connection.getResponseCode();
--------
}
Now override onPostExecute like this,
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
if(resp == 204)
{
new JSONTask().execute(command);
}
else
{
//your code here
}
}
Use the if condition in onPostExecute method of AsyncTask.
in your onPostExecute method check you are getting expected result or not, if not than again call your new JSONTask().execute(command);
like
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
new JSONTask().execute(command);
}
This will check if the response is 204 or not but if you want to try another connection, disconnect current one and then make another connection with different url; because if you repeat your URL, you get the same results again and again(NO_CONTENT).
public class JSONTask extends AsyncTask<String, String, LiveStationModel>
{
LiveStationModel liveStationModel = null;
protected LiveStationModel doInBackground(String... params) {
IOException e;
MalformedURLException e2;
List<LiveStationModel> myList = null;
Throwable th;
JSONException e3;
HttpURLConnection connection = null;
BufferedReader reader = null;
try {
connection = (HttpURLConnection) new URL(params[0]).openConnection();
connection.connect();
if(connection.getResponseCode() == HttpURLConnection.HTTP_NO_CONTENT)
{
//do what you gonna do
}
if you want to repeat until you get the content
use a loop like this:
try {
int code = connection.getResponseCode();
while(code == 204)
{
connection = (HttpURLConnection) new URL(params[?]).openConnection(); // Different Parameter here
connection.connect();
....
}
Related
Using AsyncTask freezes my whole app. i have an icon that rotates while the Http action is happening in the background. but the app just freezes till it finishes that action. Is there an alternative?
The below class sends the JSON to the server, the server has multiple endpoints and stuff like that. now when calling class calls the execute() method, the app freezes until the task is complete.
public class Connector extends AsyncTask<String, Void, Void> {
private String ip = "http://192.168.1.127";
private String port = "5000";
private URL Url;
private JSONObject jsonObject;
private String method = "";
private StringBuilder output = new StringBuilder();
Connector(String url, JSONObject jsonObject, String method)
{
try {
this.method = method;
this.Url = new URL(ip+":"+port+url);
} catch (MalformedURLException e) {
e.printStackTrace();
}
this.jsonObject = jsonObject;
//Connect to URL
}
#Override
protected Void doInBackground(String... strings) {
try {
HttpURLConnection httpURLConnection = (HttpURLConnection) Url.openConnection();
Log.i("Data", "Data sent => " + jsonObject.toString());
try {
httpURLConnection.setDoOutput(true);
httpURLConnection.setDoInput(true);
httpURLConnection.setRequestMethod(method);
httpURLConnection.setRequestProperty("content-type", "application/json");
httpURLConnection.connect();
DataOutputStream outputStream = new DataOutputStream(httpURLConnection.getOutputStream());
if(jsonObject != null)
{
outputStream.writeBytes(jsonObject.toString());
outputStream.flush();
outputStream.close();
}
InputStreamReader inputStreamReader = new InputStreamReader((InputStream) httpURLConnection.getContent(), Charset.forName("UTF-8"));
BufferedReader reader = new BufferedReader(inputStreamReader);
String line = reader.readLine();
while(line != null)
{
output.append(line);
line = reader.readLine();
}
}finally {
httpURLConnection.disconnect();
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
String getMessge() {
Log.i("Data", "Data received <= " + output.toString());
return output.toString();
}
}
Please use Retrofit library.
You can find samples to use Retrofit easily.
https://www.journaldev.com/13639/retrofit-android-example-tutorial
This is one of them.
Hope it to help you. Thanks.
I looked up my error online and people are telling to run the networking stuff on another thread or asyncTask but i have no clue how to fix this...
So everything works, app launches but then crashed and tells me "android.os.NetworkOnMainThreadException"
Here is my code:
public class Activity2 extends AppCompatActivity {
private static final String TAG = Activity2.class.getSimpleName();
private TextView fileContent;
String endstring = "";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_2);
fileContent = (TextView) findViewById(R.id.content_from_server);
try {
loadstuff();
} catch (IOException e) {
e.printStackTrace();
}
}
private void loadstuff() throws IOException {
URL url = new URL("http://ipaddress/login.php"); // URL to your application
Map<String,Object> params = new LinkedHashMap<>();
params.put("username", "test"); // All parameters, also easy
params.put("password", "test");
StringBuilder postData = new StringBuilder();
// POST as urlencoded is basically key-value pairs, as with GET
// This creates key=value&key=value&... pairs
for (Map.Entry<String,Object> param : params.entrySet()) {
if (postData.length() != 0) postData.append('&');
postData.append(URLEncoder.encode(param.getKey(), "UTF-8"));
postData.append('=');
postData.append(URLEncoder.encode(String.valueOf(param.getValue()), "UTF-8"));
}
// Convert string to byte array, as it should be sent
byte[] postDataBytes = postData.toString().getBytes("UTF-8");
// Connect, easy
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
// Tell server that this is POST and in which format is the data
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setRequestProperty("Content-Length", String.valueOf(postDataBytes.length));
conn.setDoOutput(true);
conn.getOutputStream().write(postDataBytes);
// This gets the output from your server
Reader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
for (int c; (c = in.read()) >= 0;)
endstring = endstring + (char)c;
fileContent.setText(endstring);
}
}
This exception occurs from API 11 or Android version 3.0, such as the real name, the process of discussion of chain messages in the main process (hence the name MainThread), in previous histories this operation is allowed although it is not recommended, depending on the time the process is needed, ANR (Application Not Responding).
The ideal solution is called this way because it is the form indicated by the android community, to implement this solution we must implement an inheritance of the class AsyncTask, this class allows to perform operations in the background
You can use too some library like retrofit, coroutine etc..
let me know if you resolved this issue :)
Hi like Henrique says you need to use an AsyncTask, its a class inside your class something like this
public class NameOfTask extends AsyncTask<Void, Void, Boolean>{
#Override
protected Boolean doInBackground(Void... voids) {
/*your code goes here*/
return true;
}
#Override
protected void onPostExecute(final Boolean success) {
/*If you need to do something after the task*/
}
#Override
protected void onCancelled() {
//if cancel you may need to do something in here
}
}
And calling you just need to call the class that you created.
something like this:
NameOfTask task = new NameOfTask();
task.execute((Void)null);
public class Activity2 extends AppCompatActivity {
private static final String TAG = Activity2.class.getSimpleName();
private TextView fileContent;
String endstring = "";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_2);
fileContent = (TextView) findViewById(R.id.content_from_server);
new AsyncLoadStuff().execute()
}
private void loadstuff() throws IOException {
URL url = new URL("http://ipaddress/login.php"); // URL to your application
Map<String,Object> params = new LinkedHashMap<>();
params.put("username", "test"); // All parameters, also easy
params.put("password", "test");
StringBuilder postData = new StringBuilder();
// POST as urlencoded is basically key-value pairs, as with GET
// This creates key=value&key=value&... pairs
for (Map.Entry<String,Object> param : params.entrySet()) {
if (postData.length() != 0) postData.append('&');
postData.append(URLEncoder.encode(param.getKey(), "UTF-8"));
postData.append('=');
postData.append(URLEncoder.encode(String.valueOf(param.getValue()), "UTF-8"));
}
// Convert string to byte array, as it should be sent
byte[] postDataBytes = postData.toString().getBytes("UTF-8");
// Connect, easy
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
// Tell server that this is POST and in which format is the data
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setRequestProperty("Content-Length", String.valueOf(postDataBytes.length));
conn.setDoOutput(true);
conn.getOutputStream().write(postDataBytes);
// This gets the output from your server
Reader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
for (int c; (c = in.read()) >= 0;)
endstring = endstring + (char)c;
fileContent.setText(endstring);
}
}
You can do something like this ...
//Its may be a inner class
// LoadStuff inside this class, it will be executed on separated class
private class AsyncLoadStuff extends AsyncTask<String, String, String> {
#Override
protected String doInBackground(String... params) {
try {
loadstuff();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String result) {
//put load wait
}
}
I have cleaned and rebuild my code as well but still the issue is not solved.
Below is the code:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String result = null;
String stringUrl = "https://www.ecowebhosting.co.uk/";
DownloadTask downloadTask = new DownloadTask();
downloadTask.execute(stringUrl);
}
public class DownloadTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
String result = "";
URL url;
HttpURLConnection httpURLConnection = null;
try {
url = new URL(urls[0]);
//It is like opening a browser
httpURLConnection = (HttpURLConnection) url.openConnection();
InputStream in = httpURLConnection.getInputStream();
InputStreamReader reader = new InputStreamReader(in);
int data = reader.read();
while (data != -1) {
char currentChar = (char) data;
result = result + currentChar;
data = reader.read();
}
return result;
} catch (Exception e) {
e.printStackTrace();
return "Failed";
}
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
Log.i("Results",s);
}
}
}
The code is running fine but nothing is printed in the logs. The following is the log:
AsyncTask is an asynchronous process. So when you call Log.i("Result:", result);, the AsyncTask is not finished and result is still empty.
You should print your result from onPostExecute() method.
You can look on this page.
Here is some examples on how to implement an AsyncTask correctly:
https://www.upwork.com/hiring/mobile/why-you-should-use-asynctask-in-android-development/
How to use AsyncTask correctly in Android
Best
You only have to change code inside your doInBackGround
public class DownloadTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
String result;
String inputLine;
try {
URL myUrl = new URL(urls[0]);
HttpURLConnection connection =(HttpURLConnection)
myUrl.openConnection();
connection.setReadTimeout(150000);
connection.setConnectTimeout(15000);
connection.setRequestMethod("GET");
connection.connect();
InputStreamReader streamReader = new InputStreamReader(connection.getInputStream());
//Create a new buffered reader and String Builder
BufferedReader reader = new BufferedReader(streamReader);
StringBuilder stringBuilder = new StringBuilder();
//Check if the line we are reading is not null
while((inputLine = reader.readLine()) != null){
stringBuilder.append(inputLine);
}
//Close our InputStream and Buffered reader
reader.close();
streamReader.close();
//Set our result equal to our stringBuilder
result = stringBuilder.toString();
} catch (Exception e) {
e.printStackTrace();
return "error";
}
return result;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
Log.i("Results",s);
}
}
I want to use AsyncTask to connect with the server but I got error ondoInBackground. The error required that java.lang.string so how can I improve the code in Update()? How to insert "Return" in Update() method?
public void Update(final String urlString){
new Thread(new Runnable() {
public void run() {
try {
URL url = new URL(urlString);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setUseCaches(false);
connection.connect();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(connection.getOutputStream(), "UTF-8"));
writer.write("name=abc");
writer.close();
int responseCode = connection.getResponseCode();
if(responseCode == HttpURLConnection.HTTP_OK){
InputStream inputStream = connection.getInputStream();
StringBuilder stringBuilder = new StringBuilder();
String line;
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
while ((line = br.readLine()) != null) {
stringBuilder .append(line);
}
String result = stringBuilder .toString();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
public class MyAsyncTask extends AsyncTask<String,Void,String> {
#Override
protected void onPreExecute(){
super.onPreExecute();
}
#Override
protected String doInBackground(String...url) {
return Update(url[0]);
}
#Override
protected void onPostExecute(String result){
Log.d("TAG", result);
}
}
How to use AsyncTask with urlconnection which requird to insert return
You need to return a string in your Update() method
Also no need to use another Thread in your Update() method because AsyncTask already runs in the background
SAMPLE CODE
public String Update(final String urlString){
String result="";
try {
URL url = new URL(urlString);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setUseCaches(false);
connection.connect();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(connection.getOutputStream(), "UTF-8"));
writer.write("name=abc");
writer.close();
int responseCode = connection.getResponseCode();
if(responseCode == HttpURLConnection.HTTP_OK){
InputStream inputStream = connection.getInputStream();
StringBuilder stringBuilder = new StringBuilder();
String line;
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
while ((line = br.readLine()) != null) {
stringBuilder .append(line);
}
result = stringBuilder .toString();
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
public class MyAsyncTask extends AsyncTask<String,String,String> {
#Override
protected void onPreExecute(){
super.onPreExecute();
}
#Override
protected String doInBackground(String...url) {
return Update(url[0]);
}
#Override
protected void onPostExecute(String result){
Log.d("TAG", result);
}
}
Use the below code to start AsyncTask:
MyAsyncTask task = new MyAsyncTask();
task.execute(URL);
Note that: Using AsyncTask you should not create a new Thread in the Update(URL) method
extends AsyncTask<String,Void,String>
Here String means that AsynkTask waits for a String type in Return.
protected String doInBackground(String...url) {
return Update(url[0]);
}
Already in a separate thread. Just delete it from a method.
ps. Don't use AsynkTask for connections with the server. (it's an unstable thing with Activity lifecycle )
I have been working on this and I have hit a point where I dont know what to do. What I am trying to do is use one class to download and parse out a file into a string and then send that string to another class to parse out the JSON stuff. All the parts work fine by themselves and I have tested everything separately. I just dont know how to send the value to the Json parses to start the parsing.
So this is my filedownloader class.
public class JsonFileDownloader extends AsyncTask<String, Void, String> {
//used to access the website
String username = "admin";
String password = "admin";
public String ret = "";
#Override
protected String doInBackground(String... params) {
Log.d("Params ", params[0].toString());
readFromFile(params[0]);
return ret;
}
private String readFromFile(String myWebpage) {
HttpURLConnection urlConnection = null;
try {
//Get the url connection
URL url = new URL(myWebpage);
Authenticator.setDefault(new Authenticator() {
#Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password.toCharArray());
}
});
urlConnection = (HttpURLConnection) url.openConnection();
InputStream inputStream = urlConnection.getInputStream();
if (inputStream != null) {
ret = streamToString(inputStream);
inputStream.close();
Log.d("Final String", ret);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
return ret;
}
}
public static String streamToString(InputStream is) throws IOException {
StringBuilder sb = new StringBuilder();
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
String line;
while ((line = rd.readLine()) != null) {
sb.append(line);
}
return sb.toString();
}
public String getJsonData()
{
return ret;
}
}
This works fine I have tested it over and over with no errors.
The next is the Json parser which is like this.
public class JSONParser {
JSONObject jsonResponse;
String jsonData;
//Consturctor
public JSONParser()
{
//this.jsonData = jsonData;
// this.OutputData = outPutData;
}
public void parsesData(String promo,
ArrayList<String> pictureHTTP,
ArrayList<String> pathHTTP,
ArrayList<String> labelText) throws IOException {
//Build the Json String
JsonFileDownloader jfd = new JsonFileDownloader();
// jsonData = String.valueOf(jfd.execute(promo));
jfd.execute(promo);
//jfd.getResuts(jsonData);
//jsonData = jfd.ret;
Log.d("JsonData String = " , jsonData);
//Try to parse the data
try
{
Log.d("Jsondata " , jsonData);
//Creaate a new JSONObject ith the name/value mapping from the JSON string
jsonResponse = new JSONObject(jsonData);
//Returns the value mapped by the name if it exists and is a JSONArry
JSONArray jsonMainNode = jsonResponse.optJSONArray("");
//Proccess the JSON node
int lenghtJsonArrar = jsonMainNode.length();
for (int i = 0; i<lenghtJsonArrar; i++)
{
//Get object for each json node
JSONObject jsonChildNode = jsonMainNode.getJSONObject(i);
//Get the node values
//int song_id = Integer.parseInt(jsonChildNode.optString("song_id").toString());
String picture = jsonChildNode.optString("picture").toString();
String pathName = jsonChildNode.optString("path").toString();
String lableName = jsonChildNode.optString("label".toString());
//Debug Testing code
pictureHTTP.add(picture);
pathHTTP.add(pathName);
labelText.add(lableName);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
Now I know where the problem is occurring. When i try to assign a value to the jsonData it never is assigned so it is null and the system fails.
I have tried a few things after the jfd.exicute() but I just dont know how to get the value from the final string output into the jsonData.
Thank you for any help with this.
Alright, here is a pretty flexible pattern for the overall usage of using AsyncTask to download web content and getting the results from it back to the UI thread.
Step 1 Define an interface that will act as a message bus between the AsyncTask and where you want the data.
public interface AsyncResponse<T> {
void onResponse(T response);
}
Step 2 Create a generic AsyncTask extension that will take any URL and return the results from it. You basically had this already, but I made some tweaks. Most importantly, allowing the setting of the AsyncResponse callback interface.
public class WebDownloadTask extends AsyncTask<String, Void, String> {
private AsyncResponse<String> callback;
// Optional parameters
private String username;
private String password;
// Make a constuctor to store the parameters
public WebDownloadTask(String username, String password) {
this.username = username;
this.password = password;
}
// Don't forget to call this
public void setCallback(AsyncResponse<String> callback) {
this.callback = callback;
}
#Override
protected String doInBackground(String... params) {
String url = params[0];
return readFromFile(url);
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
if (callback != null) {
callback.onResponse(s);
} else {
Log.w(WebDownloadTask.class.getSimpleName(), "The response was ignored");
}
}
/******* private helper methods *******/
private String streamToString(InputStream is) throws IOException {
StringBuilder sb = new StringBuilder();
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
String line;
while ((line = rd.readLine()) != null) {
sb.append(line);
}
return sb.toString();
}
private String readFromFile(String myWebpage) {
String response = null;
HttpURLConnection urlConnection = null;
try {
//Get the url connection
URL url = new URL(myWebpage);
// Unnecessary for general AsyncTask usage
/*
Authenticator.setDefault(new Authenticator() {
#Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password.toCharArray());
}
});
*/
urlConnection = (HttpURLConnection) url.openConnection();
InputStream inputStream = urlConnection.getInputStream();
if (inputStream != null) {
response = streamToString(inputStream);
inputStream.close();
Log.d("Final String", response);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
}
return response;
}
}
Step 3 Go forth and use that AsyncTask wherever you wish. Here is an example. Note that if you do not use setCallback, you will be unable to get the data that came from the AsyncTask.
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WebDownloadTask task = new WebDownloadTask("username", "password");
task.setCallback(new AsyncResponse<String>() {
#Override
public void onResponse(String response) {
// Handle response here. E.g. parse into a JSON object
// Then put objects into some list, then place into an adapter...
Toast.makeText(getApplicationContext(), response, Toast.LENGTH_SHORT).show();
}
});
// Use any URL, this one returns a list of 10 users in JSON
task.execute("http://jsonplaceholder.typicode.com/users");
}
}