Async Task: class should be static or leaks might occur - java

I am trying to make a function that returns a json (using org.json dependencies) from a http request.
To do this in Android Java, it is necessary to create a AsyncTask
public class MainActivity extends AppCompatActivity {
TextView resultQuery;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
resultQuery = findViewById(R.id.resultQuery);
try {
new sendUrl().execute();
} catch (Exception e) {
e.printStackTrace();
resultQuery.setText("Erro: " + e);
Toast.makeText(this, "Erro" + e, Toast.LENGTH_SHORT).show();
}
}
private class sendUrl extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params){
try {
call_me();
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
#Override
protected void onPostExecute(String message){
Toast.makeText(MainActivity.this, "PostExecute", Toast.LENGTH_SHORT).show();
}
}
public void call_me() throws Exception {
String url = "https://api.github.com/users/leonanml";
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
// optional default is GET
con.setRequestMethod("GET");
//add request header
con.setRequestProperty("User-Agent", "Mozilla/5.0");
int responseCode = con.getResponseCode();
//System.out.println("\nSending 'GET' request to URL : " + url);
Toast.makeText(this, "Response Code : " + responseCode, Toast.LENGTH_SHORT).show();
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
//print in String
//System.out.println(response.toString());
//Read JSON response and print
JSONObject myResponse = new JSONObject(response.toString());
//System.out.println("result after Reading JSON Response");
//System.out.println("id: "+myResponse.getString("login"));
resultQuery.setText(response.toString());
}}
Currently my "sendUrl" class is giving a warning :
This AsyncTask class should be static or leaks might occur (com.muller.httprequest.MainActivity.sendUrl) Inspection info:A static
field will leak contexts.

When you use an inner class that is not static, it can't be collected by the garbage collection so it's gonna keep using memory, easy fix is to just make the inner class static or make it out of the activity class.

Related

How do I get the Value out of my Class into my TextViewField

At the moment I am trying to make an Android App with Android Studio with GET and POST data into/from an API.
My problem at the moment is that I want to have the response of the POST request displayed in my app. For this I made the TextView TW_Rueckgabe. I also made another Method just for this so it can Display the Request which is
public String returnString() {
return fetching_data;
}
but the response is not saved in TW_Rueckgabe.
MainActivity.java
final TextView[] TW_Rueckgabe = {findViewById(R.id.textViewRueckgabe)};
Button sendBtn = findViewById(R.id.sendBtn);
sendBtn.setOnClickListener(v -> {
String POST_url = "http://dphost.ddns.net:1573/cool/post.php";
String requestData = "data=" + TW_Benutzername.getText().toString();
POSTRequestTask test = (POSTRequestTask) new POSTRequestTask().execute(POST_url, requestData);
TW_Rueckgabe[0].setText(test.fetching_data);
});
POSTRequestTask Class:
class POSTRequestTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
String url = params[0];
String requestData = params[1];
String response = "";
try {
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
// add request header
con.setRequestMethod("POST");
con.setDoOutput(true);
// add request data
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
wr.writeBytes(requestData);
wr.flush();
wr.close();
int responseCode = con.getResponseCode();
System.out.println("\nSending 'POST' request to URL : " + url);
System.out.println("Response Code : " + responseCode);
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer responseBuffer = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
responseBuffer.append(inputLine);
}
in.close();
response = responseBuffer.toString();
} catch (IOException e) {
e.printStackTrace();
}
return response;
}
#Override
protected void onPostExecute(String result) {
// print result
System.out.println("\n\n\n" + result + "\n\n\n");
fetching_data = result;
}
public String returnString() {
return fetching_data;
}
}
I tried to make a new Object and then save the Variable from the Object, didn't work.
interface Callback {
void onResponse(String response);
}
MainActivity {
private Callback callback = new Callback() {
#Override
void onResponse(String response) {
TW_Rueckgabe[0].setText(test.fetching_data);
}
}
sendBtn.setOnClickListener(v -> {
String POST_url = "http://dphost.ddns.net:1573/cool/post.php";
String requestData = "data=" + TW_Benutzername.getText().toString();
POSTRequestTask test = new POSTRequestTask(callback).execute(POST_url, requestData);
});
}
class POSTRequestTask(Callback callback) extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
// do your request as you're doing now and return the result
}
#Override
protected void onPostExecute(String result) {
// callback interface method call here
callback.onResponse(result)
}
}

android returning a JSONObject from a static method + network on main thread

I have this method which is giving a network on main thread. I want to make this api call on a separate thread using asynctask.
However, the business logic prohibits me to use non static methods. The code is:
public static JSONObject acceptOrder(String orderId, Integer loadsToAccept) throws IOException{
BufferedReader reader = null;
JSONObject resultOrder = null;
AsyncTask asyncTask = new AsyncTask() {
#Override
protected Object doInBackground(Object[] objects) {
return null;
}
};
HttpURLConnection conn = (HttpURLConnection) new URL(GlobalConfig.getInstance().GetGoVulcanConfig().getUrl() + "/api/Order/ProcessAcceptedOrder?acceptedLoads=" + loadsToAccept + "&haulerId=" + GlobalConfig.getInstance().GetGoVulcanConfig().getHaulerId() + "&orderId=" + orderId).openConnection();
conn.setDoOutput(true);
//conn.setFixedLengthStreamingMode(jsonString.length());
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/json");
conn.setRequestProperty("Accept","application/json");
InputStream inputStream = conn.getInputStream();
StringBuffer buffer = new StringBuffer();
if (inputStream == null) {
// Nothing to do.
return null;
}
reader = new BufferedReader(new InputStreamReader(inputStream));
String inputLine;
while ((inputLine = reader.readLine()) != null)
buffer.append(inputLine);
if (buffer.length() == 0) {
// Stream was empty. No point in parsing.
return null;
}
try {
resultOrder = new JSONObject(buffer.toString());
}catch (JSONException ex){
Log.d(ex.getMessage(), "acceptOrder: ");
}
conn.disconnect();
reader.close();
return resultOrder;
}
How can I do this?
This is the form that i do to request POST or GET, I hope can help you
1) I have my class with all the request
public class RequestManager {
public static class requestPostExample extends AsyncTask<String, Void, String>{
Context context;
int exampleId;
String exampleData;
//interface to get the response in the activity
Public AsynkTaskRespone response = null;
public requestPostExample(Context context, int exampleID, String exampleData){
this.context = context;
this.exampleId = exampleID;
this.exampleData = exampleData;
}
#Override
protected String doInBackground(String... params) {
try {
String urlString = "yourUrl";
URL url = new URL(urlString);
//the variables and data you want to send by POST
String postData = "exampleID="+exampleID+"&exampleData="+exampleData;
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("POST");
OutputStream os = connection.getOutputStream();
os.write(postData.getBytes());
StringBuilder responseSB = new StringBuilder();
int result = connection.getResponseCode();
BufferedReader br;
// 401 - 422 - 403 - 500
if (result == 401 || result == 422 || result == 403 || result == 404 || result == 500){
br = new BufferedReader(new InputStreamReader(connection.getErrorStream()));
}else {
br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
}
while ( (JSON_STRING = br.readLine()) != null)
responseSB.append(JSON_STRING+ "\n");
// Close streams
br.close();
return responseSB.toString().trim();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
#Override
protected void onPostExecute(String result) {
Log.d("Result:", result);
//send the result to interface;
response.resultPostExample(result);
}
}
2) Here is the Interface
public interface AsynkTaskRespone {
void resultPostExample(String result);
}
3) Now in the activity
public class MainActivity extends AppCompatActivity implements AsynkTaskResponse {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Start Request
RequestManager.requestPostExample requestPostExample = new RequestManager.requestPostExample(this, exampleID, exampleData);
requestPostExample.response = this;
requestPostExample.execute();
}
#Override
public void resultPostExample(String result){
//here you get the result of the asynktask
}
}

Run code in AsyncTask stucking UI

I'm trying a copule of days to figure it out, without success,
Target: get use country by IP using asyncTask without stucking UI, and save it into string parm.
Problem: The UI doen't move until the asyncTask finish it job :/
MainActivity ,onCreate method:
.......
JSONObject jsonObject;
try {
jsonObject = new getJSONObjectFromURL(LoginActivity.this).execute("http://ip-api.com/json").get();
if (jsonObject != null) {
if (!jsonObject.getString("status").equals("success"))
throw new InterruptedException();
Log.d(TAG, "onCreate: jsonObject.tostring:" + jsonObject.toString());
countryLocation = jsonObject.getString("country");
Log.d(TAG, "onCreate: countryByIP " + countryLocation);
}
if (!isNetworkAvailable()/* || countryLocation == null*/)
Toast.makeText(MainActivity.this, "Please enable data.", Toast.LENGTH_SHORT).show();
//in button click redo all that code for no internet connection,.
} catch (InterruptedException | ExecutionException | JSONException e) {
e.printStackTrace();
}
asyncTask:
public class getJSONObjectFromURL extends AsyncTask<Object, Object, JSONObject> {
private Context context;
public getJSONObjectFromURL(Context context) {
this.context = context;
}
#Override
protected JSONObject doInBackground(Object... params) {
HttpURLConnection urlConnection = null;
URL url = null;
try {
url = new URL((String) params[0]);
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setReadTimeout(10000 /* milliseconds */);
urlConnection.setConnectTimeout(15000 /* milliseconds */);
urlConnection.setDoOutput(true);
urlConnection.connect();
BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()));
String jsonString;
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
sb.append(line + "\n");
}
br.close();
jsonString = sb.toString();
return new JSONObject(jsonString);
} catch (JSONException | IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(JSONObject result) {
//Update the String..
}
}
Everything works perfect, i get the Json, able to read the Country from it, but MainActivity waiting for the onPostExecute to continue.
You are running your AsyncTask in a synchrounous state.
jsonObject = new getJSONObjectFromURL(LoginActivity.this).execute("http://ip-api.com/json").get();
By calling get() you are waiting until the Task has finished it's job. Do not use get() if you want to have a truly asynchronous process. You can use a callback to get notified.

Why I am getting null pointer exception even though there is value show when println?

This is a function of class A where i pass my value to a class name confirm to its register function.
private void registerOrder() {
confirm.register(id);
}
This is class confirm. In this class i have plan to post data inside the server. There is no mistakes in the url. I have println this code " System.out.println("wei" + getPostDataString(postDataParams));" and i have gotten my value. But the system says null pointer. Is there any mistakes in other pats of the code?
public class confirm {
private static final String REGISTER_URL =
"http://192.168.43.214/apexStore2/confirm.php";
public static void register(String id) {
class RegisterUser extends AsyncTask<String, Void, String> {
ProgressDialog loading;
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
loading.dismiss();
}
#Override
protected String doInBackground(String... params) {
HashMap<String, String> data = new HashMap<>();
data.put("product_id",params[0]);
String result = sendPost(REGISTER_URL,data);
return result;
}
}
RegisterUser ru = new RegisterUser();
ru.execute(String.valueOf(id));
}
public static String sendPost(String requestURL,
HashMap<String, String> postDataParams) {
URL url;
String response = " ";
try {
url = new URL(requestURL);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded");
conn.setRequestProperty("Content-Length", "" +
Integer.toString(getPostDataString(postDataParams).getBytes().length));
conn.setRequestProperty("Content-Language", "en-US");
conn.setReadTimeout(15000);
conn.setConnectTimeout(15000);
conn.setDoInput(true);
conn.setDoOutput(true);
OutputStream os = conn.getOutputStream();
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(os, "UTF-8"));
writer.write(getPostDataString(postDataParams));
System.out.println("wei" + 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();
}
}
You have an instance variable, which is never assigned to:
ProgressDialog loading;
and it is used in
protected void onPostExecute(String s) {
super.onPostExecute(s);
loading.dismiss(); // expect NPE
}
Reading your code I supose the null pointer exception appears when you call confirm.register(id).
If you want to use a class in a static manner you need to declare it as a final class:
public final class confirm {...}
For you it should work. Nevertheless you can also solve your problem without using the final identifier by creating an instance of your class:
confirm conf = new confirm();
conf.register(id);
I also have seen that your class name begins with a lowercase letter. It is recomended to create the classes names begining with a capital letter.
If it doesn't solve your error please, pastate the error information here.

Show progress bar while downloading JSON - Android

I am downloading a very huge JSON and it takes a lot of time.
I want to show the percentage of data I have downloaded.
I searched and found how to display progress if downloading a file but not JSON.
Here is how I am downloading JSON
private String getStringFromURL(String url) {
String string = null;
try {
HttpClient client = new DefaultHttpClient();
url = url.replace(" ", "%20");
url = url.replace("|", "%7C");
HttpGet get = new HttpGet(url);
HttpResponse response = client.execute(get);
if (response.getStatusLine().getStatusCode() == 200) {
String result = EntityUtils.toString(response.getEntity(),
HTTP.UTF_8);
if (result.toLowerCase().contains("invalid"))
return null;
result = result.replace("\r", "");
result = result.replace("\n", "").replace("\t", "\\t")
.replace("\b", "\\b").replace("\f", "\\f")
.replace("&", "\\&").replace("\'", "\\'")
.replace(";", "\\;").replace("?", "\\?")
.replace("*", "\\*");
string = result;
}
} catch (Exception e) {
e.printStackTrace();
}
return string;
}
You better to use AsyncTask to download data. There is a sample code below. I did not test it but it should work.
private class FetchJsonTask extends AsyncTask<Void, Void, String> {
private ProgressDialog progressDialog;
private Context context;
public FetchJsonTask(Context context) {
this.context = context;
}
#Override
protected void onPreExecute() {
// set up progress dialog
progressDialog = new ProgressDialog(context);
progressDialog.setIndeterminate(true);
progressDialog.setMessage("Please wait...");
// show it
progressDialog.show();
}
#Override
protected String doInBackground(Void... params) {
// These two need to be declared outside the try/catch
// so that they can be closed in the finally block.
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
// Will contain the raw JSON response as a string.
String jsonStr = null;
try {
// Construct the URL somehow
URL url = createURL();
// Create the request to MuslimSalat.com, and open the connection
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
// Read the input stream into a String
InputStream inputStream = urlConnection.getInputStream();
StringBuffer buffer = new StringBuffer();
if (inputStream == null) {
// Nothing to do.
return null;
}
reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
// Since it's JSON, adding a newline isn't necessary (it won't affect parsing)
// But it does make debugging a *lot* easier if you print out the completed
// buffer for debugging.
buffer.append(line + "\n");
}
if (buffer.length() == 0) {
// Stream was empty. No point in parsing.
return null;
}
jsonStr = buffer.toString();
} catch (IOException e) {
Log.e(LOG_TAG, "Error ", e);
// If the code didn't successfully get the data, there's no point in attemping
// to parse it.
return null;
} finally{
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
Log.e(LOG_TAG, "Error closing stream", e);
}
}
}
return jsonStr;
}
#Override
protected void onPostExecute(String jsonString) {
// jsonString is your result use it somehow.
Log.d(LOG_TAG, "Json result: " + jsonString);
// dismiss the progress because downloading process is finished.
progressDialog.dismiss();
}
}
You can call it from your activity, fragment etc.
FetchJsonTask fetchJsonTask = new FetchJsonTask(context);
fetchJsonTask.execute();

Categories