So, I'm trying to run the simplest AsyncTask possible: it doesn't accept parameters, it just runs a function, gets the result string and displays is. And no matter what I try, I get this error:
java.lang.ClassCastException: java.lang.Object[] cannot be cast to java.lang.Void[] at (...)$AsyncTaskRunner.doInBackground
The AsyncTask:
private class AsyncTaskRunner extends AsyncTask<Void, Void, String> {
#Override
protected void onPreExecute() {
resultText.setText("");
progressBar.setVisibility(View.VISIBLE);
}
#Override
protected String doInBackground(Void... params) {
return "test";
}
#Override
protected void onPostExecute(String result) {
progressBar.setVisibility(View.GONE);
resultText.setText(result);
}
}
And this is how I call it:
buttonCalculate.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if (AsyncTaskRunner != null) {
AsyncTaskRunner.cancel(true);
}
AsyncTaskRunner = new AsyncTaskRunner();
AsyncTaskRunner.execute();
}
});
What am I doing wrong here?
OK, so curiously it works if I call it like this:
AsyncTask<Void, Void, String> asyncTaskRunner = new AsyncTaskRunner();
asyncTaskRunner.execute();
Related
Here is my problem. I have created a asyncTask to link to my database and send and receive information using JSON.
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
progressDialog.dismiss();
returnValues = dataParsed.split("\\s+");
mainActivity.getValue(this is the function that calls anotherfunction in
asyncTask)
Log.v("ARRAY LENGTH", String.valueOf(returnValues.length));
}
public String[] returnmyString(){
//return mySaveData;
Log.v("ARRAY LENGTH 2", String.valueOf(returnValues.length));
return returnValues;
}
I create the asyncTask object within my activity based class and then call that object.execute. My problem is that my code will continue to run once calling the object.execute and one of the lines calls a function within the asyncTask class before it is done executing all the code.
process.activitySave(1); //<---Process is the object for the asyncTask class
process.ContextSave(this,ServerURLSource,myParameters);
process.execute()
changedData = process.returnmyString(); //<-- this is the line of code that gets implemented that returns a null value
I have tried creating a Mainactivity object in the asyncTask class and then calling a function then that retrieves the value but my app crashes when I do this. any help would be appreciated. I would like to put some sort of listener in the mainactivity class as it seems I cannot reference any of the functions from my mainactivity class in my asyncTask class.
This is the function within the asyncTask to return the value:
public String[] returnmyString(){
//return mySaveData;
Log.v("ARRAY LENGTH", String.valueOf(returnValues.length));
return returnValues;
}
Method 1 is the basic, anonymous inner class implementation. Because of the inner AsyncTask class is not static class, you can access to the CustomActivity's properties from that implementation.
In Method 2, AsyncClass implemented separately. If you gave your activity to this class, it can be call back your desired method after execution. This method, for our example is the #setChangedData method. CustomAsyncTask call backs the #setChangedData in the #onPostExecute.
public class CustomActivity extends AppCompatActivity {
String mChangedData;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Method 1 - change data into the anonymously implemented AsyncTask class
new AsyncTask<Integer, Void, Void>() {
#Override
protected Void doInBackground(Integer... params) {
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
CustomActivity.this.mChangedData = "foo"; // this changes mChangedData as "foo"
}
}.execute(1);
// Method 2 - change data into the custom AsyncTask class
new CustomAsyncTask(this).execute(2);
}
public void setChangedData(String changedData){
this.mChangedData = changedData;
}
static class CustomAsyncTask extends AsyncTask<Integer, Void, Void> {
CustomActivity mActivity;
public CustomAsyncTask(CustomActivity activity) {
this.mActivity = activity;
}
#Override
protected Void doInBackground(Integer... params) {
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
mActivity.setChangedData("bar");
}
}
}
And, as method 3, if you want to separate you Activity and AsyncTask more loosely, this is the handler method:
public class CustomActivity extends AppCompatActivity {
private String mChangedData;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
CustomAsyncTask task = new CustomAsyncTask();
task.setOnDataChangedListener(new CustomAsyncTask.OnDataChangedListener() {
#Override
public void onDataChanged(String data) {
mChangedData = data;
}
});
task.execute(1);
}
private static class CustomAsyncTask extends AsyncTask<Integer, Void, Void> {
private OnDataChangedListener onDataChangedListener;
#Override
protected Void doInBackground(Integer... params) {
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
if(onDataChangedListener != null) {
onDataChangedListener.onDataChanged("foo");
}
}
void setOnDataChangedListener(OnDataChangedListener onDataChangedListener) {
this.onDataChangedListener = onDataChangedListener;
}
interface OnDataChangedListener {
void onDataChanged(String data);
}
}
}
class activity and splash.class. In the first (which execute the main program), has asynctask (it will be call several time) retrieving data. The second activity is a splash screen which run until the data are downloaded.
public class splash extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash_screen);
startHeavyProcessing();
}
private void startHeavyProcessing(){
new LongOperation().execute("");
}
private class LongOperation extends AsyncTask<String, String, String> {
Intent i = new Intent(splash.this, MainActivity.class);
#Override
protected String doInBackground(String... params) {
startActivity(i);
return "";
}
protected void onPostExecute(String result) {
}
protected void onPreExecute() {
}
protected void onProgressUpdate() {}
}
}
I would like to finish spalash activity, when MainActivity finished to retrieve data in its doInBackground. Once done, I would run MainActivity only.
Try this!
private class LongOperation extends AsyncTask<String, String, String> {
#Override
protected String doInBackground(String... params) {
return "";
}
protected void onPostExecute(String result) {
if(result != null){
}
Intent i = new Intent(splash.this, MainActivity.class);
startActivity(i);
}else {
Log.e("DOWNLOAD ERRO");
}
protected void onPreExecute() {
}
protected void onProgressUpdate() {}
}
In my app, when I call new RetrieveFirstThreeArtUrl().execute() doInBackground isn't getting called.. does anyone know why? This code was working a few days ago, so I have no idea what's going on..
public class RetrieveFirstThreeArtUrl extends AsyncTask<String, Void, Void> {
static final String APIURL = "http://ws.audioscrobbler.com/2.0/?method=album.getinfo&api_key=2ead17554acf667f27cf7dfd4c368f15&artist=%s&album=%s";
static final String APIURL_ARTIST = "http://ws.audioscrobbler.com/2.0/?method=artist.getinfo&api_key=2ead17554acf667f27cf7dfd4c368f15&artist=%s";
#Override
public void onPreExecute() {
super.onPreExecute();
Log.v("", "Pre");
}
#Override
public Void doInBackground(String... args) {
Log.v("", "Background");
return null;
}
#Override
public void onPostExecute(Void args) {
list = (ListView) rootView.findViewById(R.id.list);
adapter = new LiveAdapter(LiveStreamFragment.this.getActivity(), oslist, LiveStreamFragment.this, list);
list.setAdapter(adapter);
}
}
Replace your code with this
before calling RetrieveFirstThreeArtUrl method, write these two lines
static final String APIURL = "http://ws.audioscrobbler.com/2.0/?method=album.getinfo&api_key=2ead17554acf667f27cf7dfd4c368f15&artist=%s&album=%s";
static final String APIURL_ARTIST = "http://ws.audioscrobbler.com/2.0/?method=artist.getinfo&api_key=2ead17554acf667f27cf7dfd4c368f15&artist=%s";
And than call method RetrieveFirstThreeArtUrl, one more thing, use protected instead of public
public class RetrieveFirstThreeArtUrl extends AsyncTask<String, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
Log.v("", "Pre");
}
#Override
protected void onPostExecute(Void result) {
list = (ListView) rootView.findViewById(R.id.list);
adapter = new LiveAdapter(LiveStreamFragment.this.getActivity(), oslist, LiveStreamFragment.this, list);
list.setAdapter(adapter);
}
#Override
protected Void doInBackground(String... params) {
Log.v("", "Background");
return null;
}
}
I have an AsyncTask class SearchForQuestions that is called from an Activity QuizMap. When looping through an array in SearchForQuestions I can't find the correct context for toast to appear within the AsynTask.
The standard Toast.makeText(getApplicationContext(), "This is Toast!!!", Toast.LENGTH_SHORT).show(); gives error getApplicationContext() undefined.
I have tried some of the solutions to this offerred by SO, most of them are listed here and concern getting UiThread and running on that.
I can't get this to work however. Here's example code snippets of what i have tried. I have put a method in QuizMap and try calling it from SearchForQuestions but SearchForQuestions isn't recognised. How can I get around this? )Still a newbie at java...)
// QuizMap activity
public class QuizMap extends FragmentActivity
implements OnMarkerClickListener {
private GoogleMap map;
private static final String TAG = "QuizMap"; // debugging
...
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_quizmap);
map = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map))
.getMap();
...
}
// make toast inside AsyncTask
public void showNotNearToast(final String toast) {
QuizMap.this.runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(QuizMap.this, "This is Toast!!!", Toast.LENGTH_SHORT).show();
}});
}
.
// SearchForQuestions class
private class SearchForQuestions extends AsyncTask<String, Void, DataHandler> {
// checks for proximity to question locations
Location location =
locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
#Override
protected DataHandler doInBackground(String... pointsList) {
String result = pointsList[0];
...
}
#Override
protected void onPostExecute(DataHandler result) {
ArrayList<String> resultsArray = result.results;
Integer numPoints = resultsArray.size();
for (int i =0;i<numPoints;i++){
String[] pointDetails = resultsArray.get(i).split("::");
...
// we can make use of the Android distanceTo function to calculate the distances
float distance = location.distanceTo(fixedLoc);
if (i > DIST) { // this is UCL
showNotNearToast("My Message"); // showNotNearToast undefined
if (distance < DIST) {
...
}
};
I'm going t close this question. I haven't solved my problem but the number of answers provided that apparently work in other situations suggest there's something else going on. I'm going to re-structure the classes to get around having to call from within AsyncTask.
Just Toast it, why do you want to create a function for it? onPostExecute() is already on UI thread.
You are not able to access because inner Class can not call functions of Outer class unless you pass instance of the outer class.
Call your toast in onPostExecute
Create an interface for a callback.
public interface ToastCallback {
public void invoke(String text);
}
Your AsyncTask constructor
private ToastCallback toastCallback;
public SearchQuestions(ToastCallback callback) {
this.toastCallback = callback;
}
// in doInBackground() {
toastCallback.invoke("Toast from background");
}
In Your Activity,
private void showNotNearToast(String text) {
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), text, Toast.LENGTH_SHORT).show();
}
});
}
public class MyToastCallback implements ToastCallback {
#Override
public void invoke(String text) {
showNotNearToast(text);
}
}
// Asynctask call
new SearchQuestion(new MyTosatCallback()).execute(<Your params here>);
Try this from inside your AsyncTask:
myActivity.this.runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(activity, "Hello", Toast.LENGTH_SHORT).show();
}
});
Where you have your
showNotNearToast("My Message"); // showNotNearToast undefined
Replace myActivity with the name of your Activity.
(Ab)use the publishProgress method
private class ToastAsyncTask extends AsyncTask<Void, String, Void>{
#Override
protected Void doInBackground(Void... voids) {
SystemClock.sleep(1000);
publishProgress("Toast msg string");
SystemClock.sleep(1000);
return null;
}
#Override
protected void onProgressUpdate(String... values) {
Toast.makeText(getApplicationContext(), values[0], Toast.LENGTH_SHORT).show();
}
}
**UPDATE: ** since you are having problems with context for some reason, use this version. Tough the implementation above works for me.
private class ToastAsyncTask extends AsyncTask<Void, String, Void> {
private WeakReference<Context> contextRef;
public ToastAsyncTask(Context context) {
contextRef = new WeakReference<Context>(context);
}
#Override
protected Void doInBackground(Void... voids) {
SystemClock.sleep(1000);
publishProgress("Toast msg string");
SystemClock.sleep(1000);
return null;
}
#Override
protected void onProgressUpdate(String... values) {
if (contextRef.get() != null) {
Toast.makeText(contextRef.get(), values[0], Toast.LENGTH_SHORT).show();
} else {
// The context was destroyed.. check what you are doing
}
}
}
Use it like this
new ToastAsyncTask(MainActivity.this).execute();
Pass the activity into the AsyncTask. See below.
private class SearchForQuestions extends AsyncTask<String, Void, DataHandler> {
Activity activity;
public void SearchForQuestions(Activity activity){
this.activity = activity;
}
//... rest of the code
public class QuizMap extends FragmentActivity implements OnMarkerClickListener {
/*...*/
new SearchForQuestions(this).execute();
/*...*/
/*When calling the toast:*/
Toast.makeText(this.activity, "This is Toast!!!", Toast.LENGTH_SHORT).show();
I am trying to make a simple task in background and show a progress bar while it is being done.
This is the code for the main (and the only) Activity:
public class Login extends Activity {
public static ProgressDialog progressDialog;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
(...)
this.getWindow().requestFeature(Window.FEATURE_PROGRESS);
this.getWindow().setFeatureInt(Window.FEATURE_PROGRESS, Window.PROGRESS_VISIBILITY_ON);
progressDialog = new ProgressDialog(activity);
progressDialog.setMessage("Sending data...");
progressDialog.setCancelable(false);
(...)
// In some onClick Eevent..
JSONObject result = new Urltasks().execute(...).get();
(...)
}
}
This is the code for the activity:
class Urltasks extends AsyncTask<String, Integer, JSONObject>{
protected void onPreExecute() {
System.out.println("Inicia onPreExecute");
Login.progressDialog.show();
}
protected void onPostExecute(String result) {
Login.progressDialog.dismiss();
}
protected JSONObject doInBackground(String... arg0) {
// Some work being done. I do not use Login.progressDialog here
}
}
With this code the ProgressDialog shows up when the task ends, and it doesn't dismiss.
Problem is here:
JSONObject result = new Urltasks().execute(...).get();
Calling get() on an AsyncTask blocks the current thread, i.e. your UI thread, until the AsyncTask is executed. Therefore the progress dialog cannot run. Remove the get().
To obtain the result of the AsyncTask, you can e.g. pass in a listener callback to the asynctask that gets notified when the result is available:
class YourAsyncTask extends AsyncTask<ParamType, ProgressType, ResultType> {
private YourResultListener mListener;
interface YourResultListener {
void onResultAvailable(ResultType result);
}
YourAsyncTask(YourResultListener listener) {
mListener = listener;
}
#Override protected ResultType doInBackground(ParamType... params) {
//...
}
#Override protected void onPostExecute(ResultType result) {
mListener.onResultAvailable(result);
}
}
You can use it like:
mProgressDialog.show();
new YourAsyncTask(new YourResultListener() {
#Override void onResultAvailable(ResultType result) {
mProgressDialog.dismiss();
// use result
}).execute(params);
Personally I like to keep user interface elements such as progress dialogs decoupled from async tasks.
Don't put your progress dialog in your log in class. Keep it in the async task
this is how you show your dialog
progressDialog = ProgressDialog.show(yourActivityHERE.this, "",
"Loading... please wait.");
Edited this for you:
class Urls extends AsyncTask<String, Integer, JSONObject>{
ProgressDialog progressDialog;
protected void onPreExecute() {
progressDialog = ProgressDialog.show(yourActivityHERE.this, "",
"Loading... please wait.");
}
protected void onPostExecute(String result) {
progressDialog.dismiss();
}
protected JSONObject doInBackground(String... arg0) {
// Some work being done. I do not use Login.progressDialog here
}
}
create the constructor in your Urltasks sending the context of the calling class.
then use that context to create the progress dialog in the preExecute of your Urltasks
class Urltasks extends AsyncTask<String, Integer, JSONObject>{
Context mContext;
public static ProgressDialog progressDialog;
public UrlTasks(Context c){
mContext=c;
}
protected void onPreExecute() {
progressDialog = new ProgressDialog(mContext);
progressDialog.setMessage("Sending data...");
progressDialog.setCancelable(false);
progressDialog.show();
}
protected void onPostExecute(String result) {
progressDialog.dismiss();
}
protected JSONObject doInBackground(String... arg0) {
// Do your work here
}
}