Displaying a String of a java class in an activity widget - java

I have an android app that consist of an activity and a java class that extends AsyncTask. So I have a String in the java class that called resFromServer
which I want to display it in a message in a suitable android widget like Alertdialog .
I want someone to help me in how to access that String from the activity
public class JSONTransmitter extends AsyncTask<JSONObject, JSONObject, JSONObject> {
String url = "http://192.168.1.8:89/Derdeery/b.php";
protected JSONObject doInBackground(JSONObject... data) {
JSONObject json = data[0];
HttpClient client = new DefaultHttpClient();
HttpConnectionParams.setConnectionTimeout(client.getParams(), 100000);
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().permitNetwork().build());
JSONObject jsonResponse = null;
HttpPost post = new HttpPost(url);
try {
StringEntity se = new StringEntity("json="+json.toString());
post.addHeader("content-type", "application/x-www-form-urlencoded");
post.setEntity(se);
HttpResponse response;
response = client.execute(post);
String resFromServer = org.apache.http.util.EntityUtils.toString(response.getEntity());
Log.i("Response from server", **resFromServer**);
}
catch (Exception e)
{ e.printStackTrace();}
return jsonResponse;
}
}
the activity
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
} }

Proper solution: create an instance of the AsyncTask and make a callback in order to catch the response into any Activity. All Activities which will implement this interface, can retrieve the result of the AsyncTask. This is more flexible and can be used by multiple Activities with just one single AsyncTask.
You have to create the instance and return the String response, in AsyncTask:
public class JSONTransmitter extends AsyncTask<JSONObject, Void, String> {
private AsyncCallback asyncCallback; // callback variable
// constructor
public JSONTransmitter(Context context) {
// attach the callback to any context
asyncCallback = (AsyncCallback) context;
}
// create the interface
public static interface AsyncCallback {
void onResponse(String res);
}
...
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
if (asyncCallback != null) {
// call the onResponse method for callback
asyncCallback.onResponse(result);
}
}
}
Then, you can implement to any Activity the callback by setting its Context as follows:
public class MainActivity extends Activity implements JSONTransmitter.AsyncCallback {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// set the Context to the AsyncTask when you create it
// in order to return here and execute the request
new JSONTransmitter(this).execute(...);
}
...
#Override
public void onResponse(String res) {
// handle the string response when it's called from onPostExecute()
Log.v("From_MainActivity", "AsyncTask returns this: "+res);
}
}
Therefore, you can do what you want in the Activity with resFromServer (result string) from AsyncTask class.

Pass your activity as parameter to your AsyncTask class constructor :
class MyAsyncTask extends AsyncTask<URL, Integer, Long> {
Activity mActivity;
public MyAsyncTask(Activity activity) {
mActivity = ativity;
}
Then update your activity:
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
int id = mActivity.findViewById(...);
}
You should not use the doInBackground method to update the activity.
Use the onPostExecute because it uses the main Thread.

Related

doInBackground not updating variable

I'm working on a basic android app that makes a POST with HttpURLConnection. I want to return the response Message from my Web API.
My MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TextView mTextView = findViewById(R.id.textView);
AsyncExample asyncExample = new AsyncExample();
asyncExample.execute();
mTextView.setText(asyncExample.getResponseMsg());
}
}
My AsyncExample.java
class AsyncExample extends AsyncTask<Void, Void, Void> {
private HttpURLConnection con;
private String responseMsg;
protected void onPreExecute() {
responseMsg = "empty message";
}
#Override
protected Void doInBackground(Void... params) {
String urlParameters = "param1=data1";
byte[] postData = urlParameters.getBytes(Charset.forName("UTF-8"));
int postDataLength = postData.length;
String request = "http://192.168.1.30:6262";
URL url = null;
try {
url = new URL(request);
con = (HttpURLConnection) url.openConnection();
con.setDoOutput(true);
con.setInstanceFollowRedirects(false);
con.setRequestMethod("POST");
con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
con.setRequestProperty("charset", "utf-8");
con.setRequestProperty("Content-Length", Integer.toString(postDataLength));
responseMsg = con.getResponseMessage();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public String getResponseMsg() {
return responseMsg;
}
}
After running the app, i get empty message in my TextView. Why it is not getting updated my doInBackground? Even if con.getResponseMessage() is null, it should be updated?
The problem is that your AsyncTask is executed asynchronously, while you try to retrieve the value immediately. You need to implement this a little bit differently. Either leverage the API of AsyncTask, sine it posts callbacks for your on the UI thread. You can update your TextView directly in your AsyncTask
class MyAwesomeAsyncTask extends AsyncTask<Void, Void, String> {
#Override
protected void onPreExecute() {
myTextView.setText("progress started");
}
#Override
protected String doInBackground(final Void... voids) {
String s = amazingCallToBackend();
return s;
}
#Override
protected void onPostExecute(final String s) {
myTextView.setText(s);
}
}
Or if you just want the value, you can pass a Callback to your async task that will deliver the value to you, something like that
interface Callback {
void onValueReceived(String value);
void onFailure();
}
class MyAwesomeAsyncTask extends AsyncTask<Void, Void, String> {
private Callback callback;
MyAwesomeAsyncTask(final Callback callback) {
this.callback = callback;
}
#Override
protected String doInBackground(final Void... voids) {
String s = amazingCallToBackend();
return s;
}
#Override
protected void onPostExecute(final String s) {
callback.onValueReceived(s);
}
}
Here's how you create it
Callback callback = new Callback() {
#Override
public void onValueReceived(final String value) {
}
#Override
public void onFailure() {
}
};
new MyAwesomeAsyncTask(callback).execute();
However, be careful because if for some reason your activity/fragment is gone/finished before your AsyncTask is done, this can cause memory leaks.
A quick Google search will tell you all you want about AsyncTask leaking memory :)
Your doInBackground method take time to execute. you are immediately calling mTextView.setText(asyncExample.getResponseMsg()); but asynctask has been not been finished yet. You need to wait until your doInBackground finish and then call that setText you can do it in onPostExecute method.
AsyncTask has 3 default method
1. On preexecute
2. Do in background
3. On post execute
post execute:
The response got from the doinbackground is in the post execute.
Here we can process the result . use the runnable method to update text view ui
Override the onPostExecute() Method to return the text. In the Main Activity create a method to update the TextView after completing the execution of the Async Task. It is coming blank as because the Main Thread is not paused its executing and setting the text View but the Async task has not yet finished executing and hence the String is empty. So wait for the Async Task to finish before setting the text view.
String str_result= new RunInBackGround().execute().get();
Refer to this for more information.
You can do it in a number of ways. I'd try to suggest you a way that would require negligible amount of changes to your existing code.
Declare the mTextView as a Global variable, Override onPostExecute() method inside your AsyncExample and update mTextView inside that onPostExecute() method with the value passed to it by the doInBackground() method [here, notice that responseMsg is returned at the end of doInBackground() ground which is caught as a String value (result) by the onPostExecute() method]. However, I also think that its a good idea to Override your onPreExecute() method.
In order to do so, your MainActivity.java should be as follows:
public class MainActivity extends AppCompatActivity {
TextView mTextView; //declare mTextView outside the onCreate() method as a Global String variable.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = findViewById(R.id.textView);
AsyncExample asyncExample = new AsyncExample();
asyncExample.execute();
}
}
Please make your asynctask an inner-class of the same activity and edit it as follows:
class AsyncExample extends AsyncTask<Void, Void, Void> {
private HttpURLConnection con;
private String responseMsg;
#Override // Its a good practice to Override the onPreExecute() method.
protected void onPreExecute() {
responseMsg = "empty message";
}
#Override
protected String doInBackground(String... params) {
String urlParameters = "param1=data1";
byte[] postData = urlParameters.getBytes(Charset.forName("UTF-8"));
int postDataLength = postData.length;
String request = "http://192.168.1.30:6262";
URL url = null;
try {
url = new URL(request);
con = (HttpURLConnection) url.openConnection();
con.setDoOutput(true);
con.setInstanceFollowRedirects(false);
con.setRequestMethod("POST");
con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
con.setRequestProperty("charset", "utf-8");
con.setRequestProperty("Content-Length", Integer.toString(postDataLength));
responseMsg = con.getResponseMessage();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return responseMsg; //return the value of responseMsg
}
#Override //override onPostExecute() method
protected void onPostExecute(String result) { //receive the value to be set to mTextView which is returned by the doInBackground() method.
mTextView.setText(result);
}
}
Try to do like this
MainActivity
public class MainActivity extends AppCompatActivity {
TextView mTextView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = findViewById(R.id.textView);
AsyncExample asyncExample = new AsyncExample(this,mTextView);
asyncExample.execute();
}
}
AsyncTask
class AsyncExample extends AsyncTask<Void, Void, Void> {
private HttpURLConnection con;
private String responseMsg;
private MainActivity mContext;
TextView mTextView;
public AsyncExample (MainActivity context, TextView textView) {
mContext = context;
mTextView = textView;
}
protected void onPreExecute() {
responseMsg = "empty message";
}
#RequiresApi(api = Build.VERSION_CODES.KITKAT)
#Override
protected Void doInBackground(Void... params) {
String urlParameters = "param1=data1";
byte[] postData = urlParameters.getBytes(StandardCharsets.UTF_8);
int postDataLength = postData.length;
String request = "http://192.168.1.30:6262";
URL url = null;
try {
url = new URL(request);
con = (HttpURLConnection) url.openConnection();
con.setDoOutput(true);
con.setInstanceFollowRedirects(false);
con.setRequestMethod("POST");
con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
con.setRequestProperty("charset", "utf-8");
con.setRequestProperty("Content-Length", Integer.toString(postDataLength));
responseMsg = con.getResponseMessage();
mContext.runOnUiThread(new Runnable() {
#Override
public void run() {
mTextView.setText(responseMsg);
}
});
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public String getResponseMsg() {
return responseMsg;
}
}

Java Interface Callback on Android

I am currently trying to make an android app that basically downloads strings from a url. But I want to make it object oriented. My mainActivity gets string from webService which downloads string when button is clicked. But I am not good at interfaces and callbacks. What should I do to make this code run?
public class MainActivity extends Activity implements WebServiceInterface{
private TextView textView;
private Button readWebPage;
private WebService service;
private WebServiceInterface webServiceInterface;
private String response;
/**
* Called when the activity is first created.
*/
#Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.TextView01);
readWebPage = (Button) findViewById(R.id.readWebpage);
service = new WebService();
readWebPage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
service.execute(new String[]{"http://google.com/"});
onSuccess(response);
}
});
}
#Override
public void onSuccess(String response) {
textView.setText(Html.fromHtml(response));
}
#Override
public void onFail(Exception ex) {
textView.setText(ex.getLocalizedMessage());
}
}
public class WebService extends AsyncTask<String, Void, String> {
private WebServiceInterface webServiceInterface;
#Override
protected String doInBackground(String... urls) {
String response = "";
for (String url : urls) {
DefaultHttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
try {
HttpResponse execute = client.execute(httpGet);
InputStream content = execute.getEntity().getContent();
BufferedReader buffer = new BufferedReader(
new InputStreamReader(content));
String s = "";
while ((s = buffer.readLine()) != null) {
response += s;
}
webServiceInterface.onSuccess(response);
} catch (Exception e) {
e.printStackTrace();
webServiceInterface.onFail(e);
}
}
return response;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
}
}
public interface WebServiceInterface {
void onSuccess(String response);
void onFail(Exception ex);
}
you need to create one public method for set webServiceInterface in WebService class like
public setWebServiceInterface (WebServiceInterface listener)
{
this.webServiceInterface =listener;
}
in MainActivity activity call this method and pass argument this
service.setWebServiceInterface (this);
in WebService class in onPostExecute Method call
webServiceInterface.onSuccess(s);
Add WebService (WebServiceInterface webServiceInterface) in your AsyncTask as a constructor.
service = new WebService(new WebServiceInterface (){
void onSuccess(String response){
//do your stuff
}
void onFail(Exception ex){
//do your stuff
}
});
and in your asynctask
public class WebService extends AsyncTask<String, Void, String> {
public WebService (WebServiceInterface webServiceInterface){
this.webinterface= webServiceInterface;
}
private WebServiceInterface webinterface;
#Override
protected String doInBackground(String... urls) {
String response = "";
for (String url : urls) {
DefaultHttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
try {
HttpResponse execute = client.execute(httpGet);
InputStream content = execute.getEntity().getContent();
BufferedReader buffer = new BufferedReader(
new InputStreamReader(content));
String s = "";
while ((s = buffer.readLine()) != null) {
response += s;
}
webinterface.onSuccess(response);
} catch (Exception e) {
e.printStackTrace();
webinterface.onFail(e);
}
}
return response;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
}
}
I have found the problem, it is because of runOnUiThread is missing.

Networking with Volley

Please could you help me with a network request I am trying here.
I have 2 Classes Network.class and MainActivity.class. I have a TextView in the MainActivity Class that I would like to be replaced with the text I get from the Network call in the Network Class. Problem I am currently having is I cant initiate the network call in the Network Class when the MainActivity Class is loaded when the application starts?
Below is the Code to MainActivity:
public class MainActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView tv = (TextView)findViewById(R.id.text);
String test = Network.userName;
tv.setText(test);
}
}
and below is the network class that I would like to do the network call and the response will need to replace the text in the TextView in the MainActivity Class.
Network Class:
public class Network extends Activity{
public static String userName;
private String jsonResponse;
String url_home = "http://www.someurl.com";
private void postData(final TextView tv) {
final RequestQueue request = Volley.newRequestQueue(this);
JsonObjectRequest postReq = new JsonObjectRequest(Request.Method.GET, url_home, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
jsonResponse = "";
for(int i = 0; i< response.length(); i++) {
String userName = response.getString("DOTWBannerHD");
System.out.println("++++++++++++++++++++++++++++++++++++++++++++userName = " + userName);
jsonResponse += userName;
System.out.println("++++++++++++++++++++++++++++++++++++++++++++JsonResponse = " + jsonResponse);
}
tv.setText(jsonResponse);
} catch (JSONException e){
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
System.out.println("Error [" + error + "]");
}
}) {
#Override
public Map getHeaders() throws AuthFailureError {
Map headers = new HashMap();
headers.put("Accept", "application/json");
System.out.println(headers);
return headers;
}
};
request.add(postReq);
}
}
I am very new to Android and am battling to call the postData method from the second activity, in the MainActivity? The issue I get is that the TextView has text hard coded in the XML but when I run the Application it is blank? It's like, either the response is blank, but I doubt its that because the code I put in the Network Class (System.out.println("++++++++++++++++++++++++++++++++++++++++++++userName = " + userName);) isn't showing up in the Terminal which makes me think that its not running the postData method at all or the response is not working but it just sets the TextView to blank?
You cannot change the GUI from an async-task.
As JsonObjectRequest works asynchronous you should run tv.setText(jsonResponse); on the main thread using:
runOnUiThread(new Runnable() {
public void run() {
tv.setText(jsonResponse);
}
});
Following up on my comment, the reason your are not seeing anything in the terminal is because you're not calling you postData method so it's never executed.
public class MainActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView tv = (TextView)findViewById(R.id.text);
Network network = new Network();
network.postData(tv);
}
}
and make Network a normal class not an Activity.
public class Network{
////The variables and your postData method here
}

Getting null pointer exception on getting Async Task JSON using Android

I'm getting a NullPointerException when I try to request a JSON with AsyncTask. I'm using loopj and AsyncTask
Here's my code:
String str = null;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new TheTask().execute();
}
class TheTask extends AsyncTask<Void, Void, String> {
#Override
protected String doInBackground(Void... params) {
try{
AsyncHttpClient client = new AsyncHttpClient();
client.addHeader("Authorization", "Token token=Wa5sfwP3ku7c15qkZTsd**");
client.get("http://*********.com/api/v1/***", new AsyncHttpResponseHandler() {
#Override
public void onSuccess(String response) {
str = response;
Log.v("==========RESULT==========", response);
}
});
} catch(Exception e){
Log.v("========== ERROR ==========", e.toString());
}
return str;
}
#Override
protected void onPostExecute(String result) {
TextView txt = (TextView) findViewById(R.id.textView1);
txt.setText("Result: " + result);
}
}
}
You are doing it wrong.
In your doInBackground() method you should use synchronous methods, and you are using asynchronous:
client.get("http://*********.com/api/v1/***", new AsyncHttpResponseHandler() {
#Override
public void onSuccess(String response) {
str = response;
Log.v("==========RESULT==========", response);
}
That's why your doInBackground() returns null, and you are trying to deal with null in onPostExecute()
You should use methods from class SyncHttpClient from Loopj-Async library.

Passing Value of Asynctask in Fragment

I have been working with passing the result created by the onPostExecute of AsyncTask in Fragment.
I know how to do it in Activity, like ((MyActivity)context).someMethod();
But how can I do this in Fragment?
I do ((MyFragment)contextOfAsyncTask).methodInFragment() but it gives me an error "Cannot cast from Context to MyFragment".
Here is my code in AsyncTask
class AsyncMethod extends AsyncTask{
ArrayList<MyObject> myVar= new ArrayList<MyObject>();
String result;
ListView lv;
Context contextOfAsyncTask;
public AsyncMethod(Context xc, ListView xl){
contextOfAsyncTask= xc;
lv = xl;
}
#Override
protected void onPreExecute() {
}
#Override
protected Void doInBackground(Void...param) {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(http://www.myurl.com/something.php);
HttpResponse httpResponse = httpclient.execute(httppost);
HttpEntity httpEntity = httpResponse.getEntity();
result = EntityUtils.toString(httpEntity);
return null; //EVERYTHING IS WORKING FINE HERE, AND I CAN GET THE VALUE
}
#Override
protected void onPostExecute(Void res) {
//it does not work here
((MyFragment)contextOfAsyncTask).methodInFragment(result);
}
It is look like you want to call method from AsyncTask
class YourTask extends AsyncTask<Void, Void, Void> {
private SomeFragment fragment;
YourTask(SomeFragment fragment) {
this.fragment = fragment;
}
#Override
protected Void doInBackground(Void... params)
{
//do whatever you want to do
}
#Override
protected void onPostExecute(Void res)
{
fragment.yourmethod();
}
}
i hope it help..

Categories