Is there an Alternative for AsyncTask using HttpUrlConnection - java

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.

Related

Reading three URLs sequentially

I have 3 url's of pages which content has a json structure. I must read a page from an url in an async task.
How can I read the 3 urls sequentially, so that I can work with the 3 json's maintaining their order?
private class JsonTask extends AsyncTask<String, String, String> {
protected void onPreExecute() {
super.onPreExecute();
}
protected String doInBackground(String... params) {
HttpURLConnection connection = null;
BufferedReader reader = null;
try {
URL url = new URL(params[0]); //params[0] = my first url
connection = (HttpURLConnection) url.openConnection();
connection.connect();
InputStream stream = connection.getInputStream();
reader = new BufferedReader(new InputStreamReader(stream));
StringBuffer buffer = new StringBuffer();
String line = "";
while ((line = reader.readLine()) != null) {
buffer.append(line + "\n");
}
return buffer.toString();
//read also the second and the third url
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
#Override
protected void onPostExecute(String result) {
// ... do something with the first json
// ... do something with the second json
// ... do something with the third json
}
}
Just move the logic for mapping one URL to JSON out into a method, and call it for each argument you pass in. Then, modify your AsyncTask so it outputs List<String> and not String from doInBackground().
protected List<String> doInBackground(String... params) {
final List<String> out = new ArrayList<>(paramas.length);
for(String url : params) {
out.add(downloadJson(url));
}
return out;
}
#Override
protected void onPostExecute(List<String> results) {
//A list of your JSON results...
}
private String downloadJson(String url) {
HttpURLConnection connection = null;
BufferedReader reader = null;
try {
connection = (HttpURLConnection) new URL(url).openConnection();
connection.connect();
InputStream stream = connection.getInputStream();
reader = new BufferedReader(new InputStreamReader(stream));
StringBuilder buffer = new StringBuilder();
String line = "";
while ((line = reader.readLine()) != null) {
buffer.append(line).append("\n");
}
return buffer.toString();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return "{}"; //Default to an empty JSON object
}

Read html code of website using AsyncTask

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

Getting Response code as 400 from geo location api

I am trying to use geo location api to get lattitude and longitude of the location. So for this I created a project on developer console and created an api key. I used this api key with this api https://www.googleapis.com/geolocation/v1/geolocate?key=YOUR_API_KEY
So this when I executed the request in postman it works well.
But when I tried to execute same request in an app its giving response as response code 400.
Response code 400 as per developer guide
https://developers.google.com/maps/documentation/geolocation/intro#errors
shows it comes when the api key is wrong. But how the key works in postman and not in the app?
Here is the code for server request:
public JSONObject sendPostRequest1(String data) {
try {
URL url = new URL(api);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("POST");
// con.setRequestProperty("content-type", "application/x-www-form-urlencoded");
con.setDoOutput(true);
con.setDoInput(true);
OutputStreamWriter writer = new OutputStreamWriter(con.getOutputStream());
try {
writer.write(data);
} catch (Exception e) {
Log.e("Exception111", e.toString());
}
writer.close();
int responseCode = con.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK || responseCode == HttpURLConnection.HTTP_CREATED) {
StringBuilder sb = new StringBuilder();
BufferedReader reader = new BufferedReader(new InputStreamReader(con.getInputStream()));
String line = "";
while ((line = reader.readLine()) != null) {
sb.append(line);
}
reader.close();
Log.d("ServerResponse", new String(sb));
String output = new String(sb);
return new JSONObject(output);
} else {
Log.e("Exception", "" + responseCode);
}
}
catch (JSONException je)
{
je.printStackTrace();
return Excpetion2JSON.getJSON(je);
}
catch(IOException e)
{
}
return null;
}
Async Task :
public class GetLocationAsyncTask extends AsyncTask<String, Void, JSONObject> {
String api;
JSONObject jsonParams;
Context mContext;
private ProgressDialog loadingDialog;
private String number,code;
public GetLocationsCallBack getLocationsCallBack;
public GetLocationAsyncTask(Context context,GetLocationsCallBack getLocationsCallBack) {
this.mContext = context;
this.getLocationsCallBack = getLocationsCallBack;
}
public interface GetLocationsCallBack {
void doPostExecute(ArrayList<Location> list);
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected JSONObject doInBackground(String... params) {
try {
api = "https://www.googleapis.com/geolocation/v1/geolocate?key=AIzaSyCArRAX4oHdfFWrTWhXrOVBQtbs";
jsonParams = new JSONObject();
jsonParams.put("cellId", params[0]);
jsonParams.put("locationAreaCode",params[1]);
ServerRequest request = new ServerRequest(api, jsonParams);
return request.sendPostRequest1(jsonParams.toString());
} catch (Exception ue) {
return Excpetion2JSON.getJSON(ue);
}
} //end of doInBackground
#Override
protected void onPostExecute(JSONObject response) {
super.onPostExecute(response);
if(response.has("location"))
{
try {
Location location = new Location();
location.setLattitude(response.getString("lat"));
location.setLongitude(response.getString("lng"));
ArrayList<Location> locations = location.getLocationArrayList();
locations.add(location);
}
catch (JSONException je)
{
Log.d("JsonException",je.toString());
}
}
if (loadingDialog.isShowing())
loadingDialog.dismiss();
}
}
Executing async task:
TelephonyManager telephonyManager = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
GsmCellLocation cellLocation = (GsmCellLocation)telephonyManager.getCellLocation();
int cellid= cellLocation.getCid();
int celllac = cellLocation.getLac();
Log.d("CellLocation", cellLocation.toString());
Log.d("GSM CELL ID", String.valueOf(cellid));
Log.d("GSM Location Code", String.valueOf(celllac));
GetLocationAsyncTask getLocationAsyncTask = new GetLocationAsyncTask(MainActivity.this,MainActivity.this);
getLocationAsyncTask.execute(String.valueOf(cellid),String.valueOf(celllac));
Whats going wrong with this? Please help. Thank you..
You have to tell the receiving side that it is json that you send
con.setRequestProperty("Content-Type", "application/json; charset=UTF-8");

POST data not sent via HttpURLConnection

I'm trying to send POST request via HttpURLConnection, here is the code
public class BackgroundTask extends AsyncTask<String, Void, Void> {
Context context;
Activity activity;
StringBuffer str = null;
int responseCode;
String responseMessage;
public BackgroundTask(Context context) {
this.context = context;
this.activity = (Activity) context;
}
#Override
protected Void doInBackground(String... params) {
HttpURLConnection connection = null;
OutputStream outputStream = null;
InputStream inputStream = null;
BufferedReader reader = null;
BufferedWriter writer = null;
String method = params[1];
if(method.equals("post")) {
try {
URL url = new URL(params[0]);
connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
outputStream = connection.getOutputStream();
writer = new BufferedWriter(new OutputStreamWriter(outputStream, "UTF-8"));
String data = URLEncoder.encode(params[2] + "=" + params[3], "UTF-8");
writer.write(data);
responseCode = connection.getResponseCode();
responseMessage = connection.getResponseMessage();
inputStream = connection.getInputStream();
reader = new BufferedReader(new InputStreamReader(inputStream));
str = new StringBuffer();
String line = "";
while ((line = reader.readLine()) != null) {
str.append(line);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (connection != null)
connection.disconnect();
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (writer != null) {
try {
writer.flush();
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
} else if(method.equals("get")) {
}
return null;
}
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
}
#Override
protected void onPostExecute(Void aVoid) {
TextView txt = (TextView) activity.findViewById(R.id.txt);
if(str != null)
txt.setText(str.toString());
Toast.makeText(activity, responseMessage, Toast.LENGTH_LONG).show();
}
}
responseCode is 200 which means everything went OK, however it says Undefined index: id
id is well defined inside php file
$user = User::find_by_id($_POST['id']);
echo json_encode($user);
and it works fine when I send post request from an html file yet when i send it from application it says id undefined which means that POST data is not sent.
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
BackgroundTask myTask = new BackgroundTask(MainActivity.this);
myTask.execute(link, "post", "id", "5");
}
});
this is how i instantiate asynctask object inside main activity
UPDATE: when i send not encoded string it works fine!
writer.write("id=5"); // works perfectly!
what is wrong with URLEncoder i use in the code?
I believe you have a problem in this line:
String data = URLEncoder.encode(params[2] + "=" + params[3], "UTF-8");
You are url-encoding the = as well as the params, that's why the server cannot recognise the form fields. Try to encode the params only:
String data = URLEncoder.encode(params[2], "UTF-8") + "=" + URLEncoder.encode(params[3], "UTF-8");
The reason is that URL encoding is for passing special characters like = in the value(or key). Basically, the server will split and parse the key-value pairs with & and = before doing the decoding. And when you url-encode the = character, the server simply couldn't recognise it during the split and parse phase.
When i need to communicate with the server i use this
Server Class
public static String sendPostRequest(String requestURL,
HashMap<String, String> postDataParams) {
URL url;
String response = "";
try {
url = new URL(requestURL);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(15000);
conn.setConnectTimeout(15000);
conn.setRequestMethod("POST");
conn.setDoInput(true);
conn.setDoOutput(true);
OutputStream os = conn.getOutputStream();
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(os, "UTF-8"));
writer.write(getPostDataString(postDataParams));
writer.flush();
writer.close();
os.close();
int responseCode = conn.getResponseCode();
if (responseCode == HttpsURLConnection.HTTP_OK) {
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
response = br.readLine();
} else {
response = "Error Registering";
}
} catch (Exception e) {
e.printStackTrace();
}
return response;
}
private static String getPostDataString(HashMap<String, String> params) throws UnsupportedEncodingException {
StringBuilder result = new StringBuilder();
boolean first = true;
for (Map.Entry<String, String> entry : params.entrySet()) {
if (first)
first = false;
else
result.append("&");
result.append(URLEncoder.encode(entry.getKey(), "UTF-8"));
result.append("=");
result.append(URLEncoder.encode(entry.getValue(), "UTF-8"));
}
return result.toString();
}
OtherClass
//Run this inside an Asynctask
HashMap<String,String> data = new HashMap<>();
data.put("id", id);
String serverResponce = Server.sendPostRequest(URL,data);

Http Get using Android HttpURLConnection

I'm new to Java and Android development and try to create a simple app which should contact a web server and add some data to a database using a http get.
When I do the call using the web browser in my computer it works just fine. However, when I do the call running the app in the Android emulator no data is added.
I have added Internet permission to the app's manifest. Logcat does not report any problems.
Can anyone help me to figure out what's wrong?
Here is the source code:
package com.example.httptest;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
public class HttpTestActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView tv = new TextView(this);
setContentView(tv);
try {
URL url = new URL("http://www.mysite.se/index.asp?data=99");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.disconnect();
tv.setText("Hello!");
}
catch (MalformedURLException ex) {
Log.e("httptest",Log.getStackTraceString(ex));
}
catch (IOException ex) {
Log.e("httptest",Log.getStackTraceString(ex));
}
}
}
Try getting the input stream from this you can then get the text data as so:-
URL url;
HttpURLConnection urlConnection = null;
try {
url = new URL("http://www.mysite.se/index.asp?data=99");
urlConnection = (HttpURLConnection) url
.openConnection();
InputStream in = urlConnection.getInputStream();
InputStreamReader isw = new InputStreamReader(in);
int data = isw.read();
while (data != -1) {
char current = (char) data;
data = isw.read();
System.out.print(current);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
}
You can probably use other inputstream readers such as buffered reader also.
The problem is that when you open the connection - it does not 'pull' any data.
Here is a complete AsyncTask class
public class GetMethodDemo extends AsyncTask<String , Void ,String> {
String server_response;
#Override
protected String doInBackground(String... strings) {
URL url;
HttpURLConnection urlConnection = null;
try {
url = new URL(strings[0]);
urlConnection = (HttpURLConnection) url.openConnection();
int responseCode = urlConnection.getResponseCode();
if(responseCode == HttpURLConnection.HTTP_OK){
server_response = readStream(urlConnection.getInputStream());
Log.v("CatalogClient", server_response);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
Log.e("Response", "" + server_response);
}
}
// Converting InputStream to String
private String readStream(InputStream in) {
BufferedReader reader = null;
StringBuffer response = new StringBuffer();
try {
reader = new BufferedReader(new InputStreamReader(in));
String line = "";
while ((line = reader.readLine()) != null) {
response.append(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return response.toString();
}
To Call this AsyncTask class
new GetMethodDemo().execute("your web-service url");
I have created with callBack(delegate) response to Activity class.
public class WebService extends AsyncTask<String, Void, String> {
private Context mContext;
private OnTaskDoneListener onTaskDoneListener;
private String urlStr = "";
public WebService(Context context, String url, OnTaskDoneListener onTaskDoneListener) {
this.mContext = context;
this.urlStr = url;
this.onTaskDoneListener = onTaskDoneListener;
}
#Override
protected String doInBackground(String... params) {
try {
URL mUrl = new URL(urlStr);
HttpURLConnection httpConnection = (HttpURLConnection) mUrl.openConnection();
httpConnection.setRequestMethod("GET");
httpConnection.setRequestProperty("Content-length", "0");
httpConnection.setUseCaches(false);
httpConnection.setAllowUserInteraction(false);
httpConnection.setConnectTimeout(100000);
httpConnection.setReadTimeout(100000);
httpConnection.connect();
int responseCode = httpConnection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
BufferedReader br = new BufferedReader(new InputStreamReader(httpConnection.getInputStream()));
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
sb.append(line + "\n");
}
br.close();
return sb.toString();
}
} catch (IOException e) {
e.printStackTrace();
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
if (onTaskDoneListener != null && s != null) {
onTaskDoneListener.onTaskDone(s);
} else
onTaskDoneListener.onError();
}
}
where
public interface OnTaskDoneListener {
void onTaskDone(String responseData);
void onError();
}
You can modify according to your needs. It's for get
If you just need a very simple call, you can use URL directly:
import java.net.URL;
new URL("http://wheredatapp.com").openStream();
Simple and Efficient Solution : use Volley
StringRequest stringRequest = new StringRequest(Request.Method.GET, finalUrl ,
new Response.Listener<String>() {
#Override
public void onResponse(String){
try {
JSONObject jsonObject = new JSONObject(response);
HashMap<String, Object> responseHashMap = new HashMap<>(Utility.toMap(jsonObject)) ;
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d("api", error.getMessage().toString());
}
});
RequestQueue queue = Volley.newRequestQueue(context) ;
queue.add(stringRequest) ;
A more contemporary way of doing it on a separate thread using Tasks and Kotlin
private val mExecutor: Executor = Executors.newSingleThreadExecutor()
private fun createHttpTask(u:String): Task<String> {
return Tasks.call(mExecutor, Callable<String>{
val url = URL(u)
val conn: HttpURLConnection = url.openConnection() as HttpURLConnection
conn.requestMethod = "GET"
conn.connectTimeout = 3000
conn.readTimeout = 3000
val rc = conn.responseCode
if ( rc != HttpURLConnection.HTTP_OK) {
throw java.lang.Exception("Error: ${rc}")
}
val inp: InputStream = BufferedInputStream(conn.inputStream)
val resp: String = inp.bufferedReader(UTF_8).use{ it.readText() }
return#Callable resp
})
}
and now you can use it like below in many places:
createHttpTask("https://google.com")
.addOnSuccessListener {
Log.d("HTTP", "Response: ${it}") // 'it' is a response string here
}
.addOnFailureListener {
Log.d("HTTP", "Error: ${it.message}") // 'it' is an Exception object here
}
URL url = new URL("https://www.google.com");
//if you are using
URLConnection conn =url.openConnection();
//change it to
HttpURLConnection conn =(HttpURLConnection )url.openConnection();

Categories

Resources