Hi, I'm a beginner developer of android app. I do this work for a University Exam. I read more documentation but I have a problem with show a progress dialog in my activity while the asynktask download a Json String from a server that then I have to put in a listview.
In my UI thread I call the Asynk task, but the thread continue to work and I can't use the result of the httpGet(that works fine).. I understand this using a Log.i(...)
Why the UI thread dosn't stop and attend the result?? What I do Wrong?
Please help me.
package my.pack;
import java.util.concurrent.ExecutionException;
import android.app.Activity;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
public class TestDialogActivity extends Activity
{
ProgressDialog dialog;
String url = "My URL";
String result= "init";
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
DownloadJsonDataTask task = (DownloadJsonDataTask) new DownloadJsonDataTask(result).
execute(url);
try {
String ris = task.get();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Log.i("GET",result);
}
public String requestInfoFromServer() {
String request = null;
HttpConnection http = HttpConnection.getInstance();
http.setHttpClient(url);
request = http.executeRequest();
return request;
}
private class DownloadJsonDataTask extends AsyncTask<String, Integer, String>
{
String Result;
protected void onPreExecute()
{
dialog = new ProgressDialog(TestDialogActivity.this);
dialog.setTitle("Download");
dialog.setMessage("Please wait...");
dialog.setIndeterminate(true);
dialog.show();
}
public DownloadJsonDataTask(String response) {
this.Result=response;
}
protected String doInBackground(String... urls) {
String urldisplay = urls[0];
Log.i("STRING URL:", urldisplay);
String result = requestInfoFromServer();
return Result;
}
protected void onPostExecute(String result) {
this.Result = result;
dialog.dismiss();
}
}
}
In addition to Samir Mangroliya.
task.get(); is a blocking call for the thread the method is called from. So using it on the main UI thread you're blocking it which is bad because downloading smth may take some seconds. So the system detects the UI thread is blocked for such a long term and terminates the app with ANR (application not responding) popup. To fix this move result processing to onPostExecute() of your AsyncTask (at least the result processing should be initiated at this point, you can call some host Activity's method here passing the result).
ahh I see the problem in the doInBackground(String... urls) function you have declared two different strings with similar names now since variable names are case sensitive it is perfectly legal to have one string named Result and the other named result as R and r are seen as two different characters so thus both have unique names. how ever while this is valid syntax; this is prone to logic errors. And I believe this is where you ran into problems. you did not assign any value to Result only to result by the end of the function call which again is valid syntax and doesn't point null variable as when you declared Resultit did put in a default value of an empty string. so it will compile and not throw a null pointer error because the variable is not null, even though there is is no string data in it the pointer is still pointing at a valid spot in the memory so as far as the compiler is concerned everything is good, it's not supposed to check on the contents of the string just pass it on. meanwhile the result variable which you do assign all the data to just before the end of the call gets loaded up with all the data you want. gets completely ignored until the end of the call as there are no further commands dealing with it.and then at the end of the call it gets garbage collected and the data is never passed on as it wasn't told to pass that variable only the Result one
make sense?
In your doInBackground() routine, save the downloaded result in the member variable Result. Then, in onPostExecute() you will need to read Result and update your UI.
eg:
private void updateUI(String jsondata)
{
foo = do.something.to.derive.some.data.from.jsondata.
TextView tv = findViewById(R.id.textview1);
tv.setText (foo);
}
private class DownloadJsonDataTask extends AsyncTask<String, Integer, String>
{
String Result = null;
...
protected String doInBackground(String... urls)
{
Result = requestInfoFromServer();
}
protected void onPostExecute(String result)
{
dialog.dismiss();
updateUI(Result);
}
}
Related
I want to create an AsyncTask that will handle my communication with the server (the client is the android app and the server is python).
My main activity will need, depends on user interaction, send data to the server.
How can I pass the string that changes all the time to the AsyncTask?
For example, I have this variable in my main activity:
String toSend = "Something"
The user pressed a button and now the string contains this data:
toSend = "After Button Pressed"
The question is how can I pass the always changing toSend string to the Async Task?
UPDATE:
I know how to create an AsyncTask. The AsyncTask will be started at the beginning of the activity. It is not a private class in the activity. The input to the AsyncTask is dinamically changing (based in user interacts). Is there a way to have a dinamically changing input to the task? Maybe pass it by ref?
By declaring your String as final you cannot change its value. So, Declare it as
final String toSend = "After Button Pressed";
Create a constructor in your AsyncTask class and send the inpur parameters within it,
Ex:
private class ExampleAsyncTask extends AsyncTask<Void,Void, Object>{
String inputString;
public ExampleAsyncTask(String inputString){
this.inputString = inputString;
}
#Override
protected void onPreExecute(){
}
#Override
protected Object doInBackground(String... params){
//call your server here by passing the variable (this.inputString)
return result;
}
#Override
protected void onPostExecute(Object result){
}
}
//your asynctask calling part should be like this
button.setOnClickListener(new View.OnCLickListener(){
new ExampleAsyncTask(this.toSend).execute();
});
I have problems with populating a spinner list with multiple Async Task to retrieve data.
The first question is to put show the progress dialog and hide it ? (Problem with multiple async task)
And is it correct to create and set new adapter every time ?
Here is my code
public void getEntities(Entity account) {
final ArrayList <Entity> entities = new ArrayList <Entity>();
Log.i(TAG, String.valueOf(account.getRelationships().size()));
for(final Relationship relationship : account.getRelationships()) {
new SOAPCall() {
#Override
protected void onPostExecute(String soapResponse) {
final DataMap dm = ParseSoapResponse.parseEntity(soapResponse);
Entity ent = new Entity(dm.getDataMapArrayList("items").get(0).getString("displayName"));
ent.setLogicalName(relationship.getReferenceEntity());
entities.add(ent);
spinnerAdapterEntities = new ArrayAdapter <Entity> (getApplicationContext(), android.R.layout.simple_spinner_item, entities);
spinnerAdapterEntities.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
_spinner_entities1.setAdapter(spinnerAdapterEntities);
}
}.execute(SoapRequest.getInstance(getBaseContext()).getRetrieveEntityRequest(relationship.getReferenceEntity(), "Entity"));
}
}
AsyncTasks are quite inefficient, so I would suggest using only one AsyncTask. That would solve all your current problems. You would show progress in onPreExecute, loop trough Relationships in doInBackground, update your adapter in onProgressUpdate and hide progress in onPostExecute.
Override your AsyncTask class with onPreExecute() and onPostExecute() methods.
Example :
private class DoSomething extends AsyncTask<Void, Void, Void> {
ProgressDialog pd;
#Override
protected void onPreExecute() {
pd = ProgressDialog.show(context, null, "Loading...");
}
#Override
protected Void doInBackground(Void... params) {
// Do something here...
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
pd.dismiss();
}
}
With a simple hack in your case, since it is a multiple AsyncTask, init your ProgressDialog in your SOAPCall constructor, and in onPostExecute() of every AsyncTask, check if ProgressDialog is null. If is not null, then call ProgressDialog.dismiss(), else, do nothing.
You do not set a new ADAPTER every time, it is hard to control the data source (ArrayList). Make a custom Spinner adapter, implement your own ArrayList update method, then call SpinnerAdapter.notifyDataSetChanged() when you update your array list.
P.S : It is a very bad practice, hence, do stick to ONE AsyncTask only.
I am calling an API through POST method and its constantly returning NULL. What could be the possible reason? I have posted the whole code. protected void onPostExecute(Void result) is actually getting NULL.
The structure of what you're doing is not right. You're using an AsyncTask with a return type of Void. The only possible value of type Void is null, so that's the only thing you can possibly get back in your onPostExecute() method. That's what happens when you return null from your doInBackground() method.
Void is appropriate for when generics force you to use a type, but you don't really need one. So you'd use it only when you don't actually need anything to be returned. In your case, where you're wanting to retrieve something that results from the call, you need a different type.
If all you want is to know whether it's succeeded or not, you could use Boolean, and have it return true when it succeeds (where you currently have return null), and false when it fails (in your catch blocks).
From the javadoc
The Void class is an uninstantiable placeholder class to hold a reference to the Class object representing the Java keyword void.
so result is always null.
You must change your asyncTask to return something different than Void
Something like :
private class MyTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
//Do request
return "response"; //return request's response as String
}
#Override
protected void onPostExecute(String result) {
if(result.equals("response")){
Toast.makeText(getApplicationContext(), "HTTP POST is working...", Toast.LENGTH_LONG).show();
} else{
Toast.makeText(getApplicationContext(), "Invalid POST req...", Toast.LENGTH_LONG).show();
}
}
}
I want to fetch audio metadata periodically like song name and artist name.
for that i am using media metadata retriever in Async-task.
So problems are
1) In AsyncTask class how can i assign text to Taxt-view.
2) How can i call that Async-task class within a specific time, like 30sec time interval.
3) There are some text which i need to fetch only once in a day. so how can check that when last time data was fetched? and also which is the best method to store that fetch data and use it to Listview?(i mean i need to store that that into database or any hashmap or array list?)
Here is metadata retriver code
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.afragment, container, false);
}
#Override
public void onStart() {
super.onStart();
initfrag();
}
private void initfrag() {
// TODO Auto-generated method stub
lv1=(ListView)getView().findViewById(R.id.list);
tv=(TextView)getView().findViewById(R.id.tv1);
tv1=(TextView)getView().findViewById(R.id.tv2);
LongOperation task=new LongOperation();
task.execute();
}
class LongOperation extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
MediaMetadataRetriever metaRetriever = new MediaMetadataRetriever();
String link = "http://xyz-radio-link.ogg";
metaRetriever.setDataSource(link, new HashMap<String, String>());
// get mp3 info
title = metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE);
artist = metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST);
metaRetriever.release();
refreshtext();
return null;
}
#Override
protected void onPostExecute(String result) {
}
#Override
protected void onPreExecute() {
}
#Override
protected void onProgressUpdate(Void... values) {
}
}
public void refreshtext() {
// TODO Auto-generated method stub
Typeface tf = Typeface.createFromAsset(getActivity().getAssets(),"fonts/Roboto-Regular.ttf");
tv.setTypeface(tf);
tv1.setTypeface(tf);
tv.setText(artist);
tv1.setText(title);
}
1) In AsyncTask class how can i assign text to Taxt-view.
You can't because you are not running on UIThread. IMHO best practice is to return this value to the UIThread using onPostExecute(). Another choice is to use runOnUIThread() with your own Runnable class.
2) How can i call that Async-task class within a specific time, like
30sec time interval.
You can use ScheduledExecutorService.
3) There are some text which i need to fetch only once in a day. so
how can check that when last time data was fetched?
Save the last time into your DB.
the best method to store that fetch data and use it to Listview?(i
mean i need to store that that into database or any hashmap or array
list?)
Subclass (extend) ArrayAdapter for your own needs, then you can directly use it to feed the ListView. Here's an example.
Using a handler, you could create a runnable to run every 30 seconds using postDelayed.
I am currently having trouble getting a value from an AsyncTask that gets data from a JSON connection. I have looked at a few examples, but mostly I have only seen posting results from AsyncTask.
First I have an object called Dog that only has a String, Name. I am trying to get the Name of the dog from the server.
Using the following code in my oncreate, I start the DogAsyncTask while assing in an URL called n and a Dog d_in.
Dog d_in = new Dog("DogName");
DogAsyncTask task = new DogAsyncTask(d_in);
String n = "www.dog.com";
task.execute(n);
Log.e("Out", d_in.getName());
My AsyncTask is as follows:
private class DogAsyncTask extends AsyncTask<String, Void, String> {
Dog d = null;
DogAsyncTask(Dog d){
this.d = d;
}
ProgressDialog mProgressDialog;
#Override
protected void onPostExecute(String result) {
d.setName(result);
Log.e("Dog", d.getName());
mProgressDialog.dismiss();
}
#Override
protected void onPreExecute() {
mProgressDialog = ProgressDialog.show(AsyncTestActivity.this, "Loading...", "Data is Loading...");
}
#Override
protected String doInBackground(String... name) {
//Go to url = name and then gets String below.
String outfromjson = "new dog name"; //This will be a function that gets a name from JSON
return outfromjson;
}
}
I tried using something like
Log.e("Out", task.d.getName());
but I keep getting the default name of the dog which is "DogName". How to I carry values out of AsyncTask?
OK, The thing what is happening here is:
You want to pass Dog as reference (pointers as in C / C++ / Objective-C),
and you want to reflect change in original variable using other variable.
but keep in mind that Java doesn't pass object by reference, Java passes objects by value (only value is transferred, another object is created and assigned value).
So what you can do is you can assign that result-holder object again as a value to the original object.
You can do the following,
Declare and implement an interface in your activity and then use it's methods as a callback from the onPostExecute method.