I have this code to request an URL and show the result on the screen by a TextView. this is my code:
public class AsyncronoustaskAndroidExample extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.asyncronoustask_android_example);
final Button GetServerData = (Button) findViewById(R.id.GetServerData);
GetServerData.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
String serverURL = "http://androidexample.com/media/webservice/getPage.php";
new LongOperation().execute(serverURL);
}
});
}
private class LongOperation extends AsyncTask<String, Void, Void> {
private final HttpClient Client = new DefaultHttpClient();
private String Content;
private String Error = null;
private ProgressDialog Dialog = new ProgressDialog(AsyncronoustaskAndroidExample.this);
TextView uiUpdate = (TextView) findViewById(R.id.output);
protected void onPreExecute() {
uiUpdate.setText("Output : ");
}
protected Void doInBackground(String... urls) {
try {
// Server url call by GET method
HttpGet httpget = new HttpGet(urls[0]);
ResponseHandler<String> responseHandler = new BasicResponseHandler();
Content = Client.execute(httpget, responseHandler);
} catch (ClientProtocolException e) {
Error = e.getMessage();
cancel(true);
} catch (IOException e) {
Error = e.getMessage();
cancel(true);
}
return null;
}
protected void onPostExecute(Void unused) {
// NOTE: You can call UI Element here.
if (Error != null) {
uiUpdate.setText("Output : "+Error);
} else {
uiUpdate.setText("Output : "+Content);
}
}
}
}
But when the URL is invalid, my program stop, I tried to show an error message but I can't. please help me!
thank so much.
Please check your log cat. Mostly you must be getting an IllegalStateException. If it is the case you have got to catch that too.
If you want to check your url is valid or invalid you need to use URL. Here's the example.
URL url;
try {
url = new URL(urls[0]);
HttpGet httpGet = new HttpGet(url.toString());
} catch (MalformedURLException e1) {
e1.printStackTrace();
}
Related
I want to use a DefaultHttpClient/HttpGet asynctask to grab the JSON from the school's site. But I want to request it from within the Fragment.
How can I do that without failing?
This is what I already tried:
public class RequestData extends AsyncTask<String, Void, Void> {
private final HttpClient Client = new DefaultHttpClient();
private String Content;
private Context context;
private String Error = null;
private ProgressDialog Dialog;
public RequestData(Context context) {
this.context = context;
}
protected void onPreExecute() {
Dialog = new ProgressDialog(context);
Dialog.setMessage("Downloading source..");
Dialog.show();
}
protected Void doInBackground(String... urls) {
try {
HttpGet httpget = new HttpGet(urls[0]);
ResponseHandler<String> responseHandler = new BasicResponseHandler();
Content = Client.execute(httpget, responseHandler);
} catch (ClientProtocolException e) {
Error = e.getMessage();
cancel(true);
} catch (IOException e) {
Error = e.getMessage();
cancel(true);
}
return null;
}
protected void onPostExecute(Void unused) {
Dialog.dismiss();
if (Error != null) {
Toast.makeText(context, Error, Toast.LENGTH_LONG).show();
} else {
Toast.makeText(context, "Source: " + Content, Toast.LENGTH_LONG).show();
}
}
}
Which is called by this:
RequestData request = new RequestData(getSherlockActivity());
request.execute(getBaseURL() + "phpinfo.php");
This is my first async task, which gets called first, it gets data from server and then onPostExecute it executes other async task, which downloads and sets image.
private class GetData extends AsyncTask<String, Void, Void> {
private final HttpClient client = new DefaultHttpClient();
private String content;
private String error = null;
#Override
protected void onPreExecute() {
}
#Override
protected void onProgressUpdate(Void... progress) {
}
#Override
protected Void doInBackground(String... params) {
try {
HttpGet httpget = new HttpGet(params[0]);
ResponseHandler<String> responseHandler = new BasicResponseHandler();
content = client.execute(httpget, responseHandler);
} catch (ClientProtocolException e) {
error = e.getMessage();
cancel(true);
} catch (IOException e) {
error = e.getMessage();
cancel(true);
}
return null;
}
#Override
protected void onPostExecute(Void result) {
if (error == null) {
try {
JSONObject dataDishes = new JSONObject(content);
Log.d("DISHES", dataDishes.toString());
ArrayList<DishModel> dishData = new ArrayList<DishModel>();
for (int i = 0; i < 8; i++) {
DishModel model = new DishModel();
model.setName("Company " + i);
model.setDesc("desc" + i);
//TODO: set data img
new GetImage(model).execute("http://example.com/" + (i + 1) + ".png");
dishData.add(model);
}
ListView listAllDishes = (ListView) getView().findViewById(R.id.listView);
DishRowAdapter adapterAllDishes = new DishRowAdapter(getActivity(),
R.layout.dish_row, dishData);
listAllDishes.setAdapter(adapterAllDishes);
} catch (JSONException e) {
Log.d("DISHES", e.toString());
}
} else {
Log.e("DISHES", error);
}
}
}
This is another async task, it downloads image and onPostExecute it sets image to passed model.
private class GetImage extends AsyncTask<String, Void, Void> {
private DishModel model;
private Bitmap bmp;
public getImage(DishModel model) {
this.model = model;
}
#Override
protected void onPreExecute() {
}
#Override
protected void onProgressUpdate(Void... progress) {
}
#Override
protected Void doInBackground(String... params) {
try {
URL url = new URL(params[0]);
Log.d("DISHES", params[0]);
try {
bmp = BitmapFactory.decodeStream(url.openConnection().getInputStream());
} catch (IOException e) {
Log.d("DISHES", e.toString());
}
} catch (MalformedURLException e) {
Log.d("DISHES", e.toString());
}
return null;
}
#Override
protected void onPostExecute(Void result) {
model.setPhoto(bmp);
}
}
It works if I do both data/image download proccess in one AsyncTask doInBackground(String... params), but it doesnt when I split data and image downloading into seperate async tasks. Furthermore I dont get any exceptions or errors.
UPDATE: Images shows up when i switch views..
At first, getImage and getData are classes, and classes names in Java are capitalized.
Technically, you can run another AsyncTask from onProgressUpdate() or onPostExecute() - https://stackoverflow.com/a/5780190/1159507
So, try to put the breakpoint in second AsyncTask call and debug is it called.
I have used AsyncTask with Activity, And it gave me desired result without any failure.
Now I need to use AsyncTask with Fragments. In Fragments AsyncTask is not updating UI. I got an answer here. I tried that logic in my code but still I'm not able to update UI after getting response from servlet. Your help will be very appreciated.
Code what I have tried:
public class FragmentMyProfile extends Fragment
{
TextView txtViewUserFullName;
SharedPreferences shrdPref;
String currentUserFirstName = "", currentUserEmail = "";
String URL = "http://10.0.2.2:8080/iGnite_Survey/GetUserDetailsServlet";
String jsonObjectReceivedFromServer = "";
public FragmentMyProfile()
{
// empty constructor required for fragment subclass
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View rootView = inflater.inflate(R.layout.fragment_my_profile, container, false);
shrdPref = rootView.getContext().getSharedPreferences("shrdPref", Context.MODE_PRIVATE);
txtViewUserFullName = (TextView) rootView.findViewById(R.id.textViewUserFullName);
//get current user first name, default value is ""
currentUserFirstName = shrdPref.getString(String.valueOf(R.string.curentLoggedInUserFirstName), "");
currentUserEmail = shrdPref.getString(String.valueOf(R.string.curentLoggedInUserEmail), "");
//display current user first name
if(!currentUserFirstName.equals(""))
{
txtViewDisplayUserFirstName.setText("Welcome "+currentUserFirstName);
}
else
{
txtViewDisplayUserFirstName.setText(String.valueOf(R.string.welcomeUser));
}
//get all user details from server
GetUserDetailsAsyncTask getUserDetailsAsyncTask = new GetUserDetailsAsyncTask (new FragmentCallback()
{
#Override
public void onTaskDone(String output)
{
//txtViewUserFullName.setText(output);
}
});
getUserDetailsAsyncTask.execute(new String[] { URL });
return rootView;
}
public interface FragmentCallback
{
public void onTaskDone(String output);
}
//------------------------------------------------------------------------------
public class GetUserDetailsAsyncTask extends AsyncTask<String, Void, String>
{
private FragmentCallback mFragmentCallback;
public GetUserDetailsAsyncTask (FragmentCallback fragmentCallback)
{
mFragmentCallback = fragmentCallback;
}
#Override
protected String doInBackground(String... urls)
{
String output = null;
for (String url : urls)
{
output = sendDataToServer(url);
}
return output;
}
#Override
protected void onPostExecute (String output)
{
super.onPostExecute(output);
mFragmentCallback.onTaskDone();
txtViewUserFullName.setText("output");
}
private String sendDataToServer(String url)
{
String output = null;
try
{
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("user_email", currentUserEmail));
httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
// Execute HTTP Post Request
HttpResponse response = httpClient.execute(httpPost);
HttpEntity httpEntity = response.getEntity();
output = EntityUtils.toString(httpEntity);
}
catch (ClientProtocolException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
return output;
}
}
}
You have to use the inter-fragment communication concept to update the UI Thread from the fragment asynctask i.e INTERFACE
Please refer this tutorial with source code to understand it better : Handle Android AsyncTask Configuration Change Using Fragment
This is my function that is in LoginActivity.java.So onclick of button i am calling this function.
public void postHttpRequest(String userId,String pass,TextView error){
RequestClient reqClient = new RequestClient(LoginActivity.this);
String AppResponse = null;
try {
url = "myurl";
Log.d("URL", url);
AppResponse = reqClient.execute().get();
String status = ValidateLoginStatus.checkLoginStatus(AppResponse);
Log.d("Status recived", status);
if(status.equals("200")){
saveInformation(userId,pass);
startingActivity(HOST_URL);
}else{
error.setText("Incorrect UserName or Password");
}
} catch (Exception e) {
Log.e("Exception Occured", "Exception is "+e.getMessage());
}
}
From this function i am calling a AsynkTask for Http Communication.So onclick of button when i am geeting the response then my processDialog in opening just for one sec.I want as i click the buttoon my processDialog should get open utill i got the response
public class RequestClient extends AsyncTask<String, Void, String>{
ProgressDialog pDialog;
Context context;
public RequestClient(Context c) {
context = c;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(context);
pDialog.setMessage("Authenticating user...");
pDialog.show();
}
#Override
protected String doInBackground(String... aurl){
String responseString="";
DefaultHttpClient httpClient=new DefaultHttpClient();
try {
HttpClient client = new DefaultHttpClient();
HttpGet get = new HttpGet(LoginActivity.url);
HttpResponse responseGet = client.execute(get);
HttpEntity resEntityGet = responseGet.getEntity();
if (resEntityGet != null) {
responseString = EntityUtils.toString(resEntityGet);
Log.i("GET RESPONSE", responseString);
}
} catch (Exception e) {
Log.d("ANDRO_ASYNC_ERROR", "Error is "+e.toString());
}
Log.d("ANDRO_ASYNC_ERROR", responseString);
httpClient.getConnectionManager().shutdown();
return responseString;
}
#Override
protected void onPostExecute(String response) {
super.onPostExecute(response);
if(pDialog!=null)
pDialog.dismiss();
}
}
So please suggest me what changes i have to make so that processDialog should display properly in the center of the device
//add style in your progressbialog
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(context);
pDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
pDialog.setMessage("Authenticating user...");
if (pDialog != null && !pDialog.isShowing()) {
pDialog.show();
}
}
AsyncTask return value only after using get() method
Drawing from the above link
Calling the get() method of AsyncTask will block the main thread and wait for the result to be returned. This effectively makes using an AsyncTask become a synchronous operation in which case there's no point in using an AsyncTask.
The only reason I can think of to use the get() method would be from a thread other than the main (UI) thread although I can't think of many reasons to do that.
On Button click
RequestClient reqClient = new RequestClient(LoginActivity.this,new TheInterface() {
#Override
public void theMethod(String result) {
Log.i("Result =",result);
}
});
reqClient.execute(url); // no get(). pass url to doInBackground()
In your activity class
public interface TheInterface {
public void theMethod(String result);
}
}
AsyncTask
public class RequestClient extends AsyncTask<String, Void, String>{
ProgressDialog pDialog;
Context context;
TheInterface listener;
public RequestClient(Context c,TheInterface listen) {
context = c;
listener = listen;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(context);
pDialog.setMessage("Authenticating user...");
pDialog.show();
}
#Override
protected String doInBackground(String... aurl){
String responseString="";
HttpClient client;
try {
HttpClient client = new DefaultHttpClient();
HttpGet get = new HttpGet(aurl[0]); // url
HttpResponse responseGet = client.execute(get);
HttpEntity resEntityGet = responseGet.getEntity();
if (resEntityGet != null) {
responseString = EntityUtils.toString(resEntityGet);
Log.i("GET RESPONSE", responseString);
}
} catch (Exception e) {
Log.d("ANDRO_ASYNC_ERROR", "Error is "+e.toString());
}
Log.d("ANDRO_ASYNC_ERROR", responseString);
client.getConnectionManager().shutdown();
return responseString;
}
#Override
protected void onPostExecute(String response) {
super.onPostExecute(response);
pDialog.dismiss();
if (listener != null)
{
listener.theMethod(result);
}
}
}
It seems that your button code is not correct, because it's async, but you are trying to use it as standart sync code.
Try to move this code into onPostExecute:
String status = ValidateLoginStatus.checkLoginStatus(response);
Log.d("Status recived", status);
if(status.equals("200")){
saveInformation(userId,pass);
startingActivity(HOST_URL);
}else{
error.setText("Incorrect UserName or Password");
}
and make this button click code:
public void postHttpRequest(String userId,String pass,TextView error){
RequestClient reqClient = new RequestClient(LoginActivity.this);
String AppResponse = null;
try {
url = "myurl";
Log.d("URL", url);
reqClient.execute();
} catch (Exception e) {
Log.e("Exception Occured", "Exception is "+e.getMessage());
}
}
i just started with android and i'm working on a simple app that should download contents of a html file. I'm using AsyncTask as suggested, but i'm encountering one problem. In the following code (i followed a tutorial code), i get tv cannot be resolved for the onPostExecute method. How to access the downloaded file? Thank You:
public class FlashResults extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView tv = new TextView(this);
setContentView(tv);
readWebpage(tv);
}
protected class DownloadPage extends AsyncTask<String, Void, String> {
protected String doInBackground(String... urls) {
String responseStr = null;
try {
for (String url : urls) {
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpGet get = new HttpGet(url);
HttpResponse httpResponse = httpClient.execute(get);
HttpEntity httpEntity = httpResponse.getEntity();
responseStr = EntityUtils.toString(httpEntity);
}
} catch (UnsupportedEncodingException e) {
} catch (ClientProtocolException e) {
} catch (IOException e) {
}
return responseStr;
}
protected void onPostExecute(String result) {
tv.setText(result);
}
}
public void readWebpage(View v) {
DownloadPage task = new DownloadPage();
task.execute(new String[] { "http://seznam.cz" });
}
}
All of the other answers suggested so far will work. However, I would add in a couple of other notes:
if you are only accessing the TextView tv inside this onCreate and the DownloadPage acitivity, you can limit access to tv by giving it directly to the DownloadPage's constructor
for something as useful as a DownloadPage AsyncTask, i usually remove it from being an inner class of any activity and instead put it in a public class called "Utils" that can be used by many other activities as needed. (modularity in code)
if you are going to use an inner class (perfectly legal), it's always good practice to make it private and static for what you're doing.
Something like this:
public class FlashResults extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView tv = new TextView(this);
setContentView(tv);
readWebpage(tv);
}
public void readWebpage(View v) {
DownloadPage task = new DownloadPage(tv);
task.execute(new String[] { "http://seznam.cz" });
}
private static class DownloadPage extends AsyncTask<String, Void, String> {
private TextView textView;
public DownloadPage(TextView tv){
textView = tv;
}
protected String doInBackground(String... urls) {
String responseStr = null;
try {
for (String url : urls) {
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpGet get = new HttpGet(url);
HttpResponse httpResponse = httpClient.execute(get);
HttpEntity httpEntity = httpResponse.getEntity();
responseStr = EntityUtils.toString(httpEntity);
}
} catch (UnsupportedEncodingException e) {
} catch (ClientProtocolException e) {
} catch (IOException e) {
}
return responseStr;
}
protected void onPostExecute(String result) {
if (textView != null) {
textView.setText(result);
}
}
}
}
}
One approach is to do as the other answers suggest and make tv instance level. Alternatively you can make a TextView field within your AsyncTask and pass a reference into the constructor:
...
public void readWebpage(TextView v) {
DownloadPage task = new DownloadPage(v);
task.execute(new String[] { "http://seznam.cz" });
}
...
protected class DownloadPage extends AsyncTask<String, Void, String> {
protected String doInBackground(String... urls) {
...
}
TextView tv = null;
public DownloadPage(TextView tv){
this.tv = tv;
}
...
}
If you want a variable to be accessible outside of a method, you need to declare it outside a method. This is a basic programming concept called scope.
Change your code to look like this:
public class FlashResults extends Activity {
private TextView tv;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
tv = new TextView(this);
setContentView(tv);
readWebpage(tv);
}
and it will be available to anything inside FlashResults.
Try making the text view class-level variable.
private TextView tv;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
tv = new TextView(this);
setContentView(tv);
readWebpage(tv);
}
The other option would be declaring your AsyncTask anonymous, declaring the TextView as final in the same method body as your declaration of the task.
Cheers
You have to make tv a feild to make it accessible from a subclass.
public class FlashResults extends Activity {
TextView tv;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
tv = new TextView(this);
setContentView(tv);
readWebpage(tv);
}
protected class DownloadPage extends AsyncTask<String, Void, String> {
protected String doInBackground(String... urls) {
String responseStr = null;
try {
for (String url : urls) {
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpGet get = new HttpGet(url);
HttpResponse httpResponse = httpClient.execute(get);
HttpEntity httpEntity = httpResponse.getEntity();
responseStr = EntityUtils.toString(httpEntity);
}
} catch (UnsupportedEncodingException e) {
} catch (ClientProtocolException e) {
} catch (IOException e) {
}
return responseStr;
}
protected void onPostExecute(String result) {
tv.setText(result);
}
}
public void readWebpage(View v) {
DownloadPage task = new DownloadPage();
task.execute(new String[] { "http://seznam.cz" });
}
}