I have an AsyncTask, that fills a custom List with parsed data from Internet.
In PostExecute I fill that List and get it ready to transfer it to a new Activity.
I do it this way:
#Override
protected void onPostExecute(List<VideoDataDescription> result)
{
super.onPostExecute(result);
MainActivity.progressDialog.dismiss();
context.startActivity(new Intent(context, ResultsQueryActivity.class));
}
where context
private Context context;
In LogCat after executing this code I get a Java.lang.NullPointerException.
Is this possible and correct to start an Activity as I do it?
UPD
I have added
private Context mContext;
public YoutubeAndYahooParser(Context context)
{
super();
this.mContext = context;
}
to initialize context and call
YoutubeAndYahooParser youtubeAndYahooParser = new YoutubeAndYahooParser(ResultsQueryActivity.this);
youtubeAndYahooParser.execute("my string to pass in asynctak");
After this in PostExecute
Intent intent = new Intent(mContext, ResultsQueryActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(intent);
I added new flag because of I have got in LogCat the next:
*Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?*
Am I right?
You should pass in the application context rather than a context from the local activity. I.e. use context.getApplicationContext() and save that in a local variable in your AsyncTask subsclass.
The code might looks something like this:
public class MyAsyncTask extends AsyncTask {
Context context;
private MyAsyncTask(Context context) {
this.context = context.getApplicationContext();
}
#Override
protected Object doInBackground(Object... params) {
...
}
#Override
protected void onPostExecute(List<VideoDataDescription> result) {
super.onPostExecute(result);
MainActivity.progressDialog.dismiss();
context.startActivity(new Intent(context, ResultsQueryActivity.class));
}
}
you'd call it like this:
new MyAsyncTask(context).execute();
I tried this just now ... it works in PostExecute Method!!!
Intent intent_name = new Intent();
intent_name.setClass(getApplicationContext(),DestinationClassName.class);
startActivity(intent_name);
But its better if you start a new Intent Based on the response(result) obtained from the previous activities.
This will eliminate the possibility of the error response from invoking the new intent.
Example if the previous activity was supposed to return Succesfully... or Welcome to allow the new intent to start, the i could check it out in this way
protected void onPostExecute(String result) {
if (result.equals("Succesfully...")){
context.startActivity(new Intent(context, Login_Activity.class));
Toast.makeText(context, result, Toast.LENGTH_LONG).show();
}else if (result.contains("Welcome")){
context.startActivity(new Intent(context, MainActivity.class));
}else {
Toast.makeText(context,result,Toast.LENGTH_LONG).show();
}
}
Related
Situation is: Through my fragment I m calling a function which is in another activity. And now I want that, from that function I intent to a completely different activity.
How can this be done?
class DemoFragAct extends Fragment{
...
calling();
}
class demoActivity extends Activity{
...
void calling(){
...
Intent i = new Intent(getActivity(),newAct.class);
startActivity(i);
}
}
class newAct extends Activity{...}
Null pointer exception is coming up.
If I understood the question correctly, simply start the new activity from your function, calling the parent activity:
Intent intent = new Intent(getActivity(), YourNewActivity.class);
startActivity(intent);
declare a member variable mContext at your base fragment.
protected Context mContext;
#Override
public void onAttach(Context context) {
super.onAttach(context);
mContext = context ;
}
#Override
public void onDetach() {
super.onDetach();
mContext = null;
}
So you can use your context variable anywhere without having a direct coupling with your holder activity
private void startSecondActivity(){
//your code above
Intent intent = new Intent(mContext, SecondActivity.class);
startActivity(intent);
}
Hint your fragment must be attached to its activity enable you to navigate to another activity
And as i wrote you as comment before ,with code must be some like this:
private void yourMethod(){
//your code above
Intent intent = new Intent(demoActivity.this, SecondActivity.class);
startActivity(intent);
}
I am unable to call an activity from async task, i have tried different ways but every time i get a null pointer exception in the log cat.
I have tried this.
#Override
protected void onPostExecute(String result) {
if(signedin==false)
{
Toast.makeText(XMPPClient.context, "authentication failed:", Toast.LENGTH_LONG).show();
}
Intent i = new Intent(getApplicationContext(), ProfileHome.class);
startActivity(i);
}
and this
#Override
protected void onPostExecute(String result) {
XMPPClient xmpp = new XMPPClient();
if(signedin==false)
{
Toast.makeText(XMPPClient.context, "authentication failed:", Toast.LENGTH_LONG).show();
}else
xmpp.startnewactivity();
}
And in XMPPClient.class
public void startnewactivity()
{
Intent i = new Intent(getApplicationContext(), ProfileHome.class);
startActivity(i);
}
How can i call an activity from async task, actually I want to call activity when async task finishes.
I believe the problem is here:
Intent i = new Intent(getApplicationContext(), ProfileHome.class);
Usually, using getApplicationContext() as a Context is a very bad idea unless you really know what are you doing. Instead, you should use the Context of the Activity that you want to start the new from. You can achieve this passing it as a value on .execute() or even storing the Context you get in the AsyncTask's constructor and store it, so you later can use it in your onPostExecute() method.
---- EDIT ----
This would be an example:
public class MyAsyncTask extends AsyncTask {
Context context;
private MyAsyncTask(Context context) { this.context = context; }
#Override
protected void onPostExecute(...) {
super.onPostExecute(result);
context.startActivity(new Intent(context, ProfileHome.class));
}
}
I have several activities that need to perform HTTP requests (send a JSON request a get another JSON object back).
My idea was to share one AsyncTask for all these requests. I am passing the Activity as a parameter so that I can call method once the execution of the request is finished.
I would like to pass one more parameter to my AsyncTask that would be the class of my Activity (MainActivity.class, SecondActivity.class) and then use that information to cast the Activity to the correct type and then later call on the method (would be the same method name for all activities).
I could also create an interface with my call back method, but I am not sure if I that would work neither.
Could this work or is my approach wrong here ?
Thanks for your feed-back.
My code:
public class HTTPReq extends AsyncTask {
private MainActivity callerActivity;
#Override
protected String doInBackground(Object... params) {
String data = (String) params[0];
String cookie = (String) params[1];
callerActivity = (MainActivity) params[2];
...
}
#Override
protected void onPostExecute(String result) {
callerActivity.ProcessHTTPReqAnswer(result);
super.onPostExecute(result);
}
}
Aswins answer isn't terrible but it's still not the most efficient way.
Declare an Interface that has a method for callback. Pass an instance of that interface to your asynctask then have the async task invoke it if its there as per my examples below
Interface:
public interface IMyCallbackInterface {
void onCallback(String result);
}
Async Task:
public MyAsyncTask extends AsyncTask<..., String> {
private IMyCallbackInterface mCallback;
public MyAsyncTask(..., IMyCallbackInterface callback) {
mCallback = callback;
}
protected String doInBackground(Object... params) {
....
}
protected void onPostExecute(String result) {
super.onPostExecute(result);
if (mCallback != null) {
mCallback.onCallback(result);
}
}
Activity:
public MyActivity extends Activity {
private void someMethod(){
new MyAsyncTask(..., new IMyCallbackInterface() {
public void onCallback(String result) {
//TODO use the result to do whatever i need
//I have access to my aactivity methods and member variables here
}
}.execute();
}
}
It is a wrong approach to do it like that. You should use BroadcastReceiver. Once a AsyncTask is done, sent the result out as a Broadcast. Each of the activity will be listen to the results they are interested in. This way no one needs to keep a reference to the activity which is dangerous.
Here is an example.
IntentFilter filter = new IntentFilter();
filter.addAction("result1");
LocalBroadcastManager.getInstance(getSupportActivity()).registerReceiver(new CustomBroadcastReceiver(), filter);
In the AsyncTask, do this
#Override
protected void onPostExecute(String result) {
Intent intent = new Intent("result1").putExtra(
"data", result);
LocalBroadcastManager.getInstance(getSupportActivity()).sendBroadcast(intent);
super.onPostExecute(result);
}
Back in the activity, do this
private class CustomBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
if ("result1".equalsIgnoreCase(intent.getAction())) {
String result = bundle.getString("data");
// Process the result here.
}
}
}
I have implemented a FragmentPagerAdapter of 4-lashes, and in each of them I load a fragment with a different view. In one of them, pressing an image executed a AsyncTask to obtain a series of data from a server and loads a new class through an intent on the onPostExecute() method.
I had this functionality in one activity and worked perfectly. Now to make the call from the fragment I have to make calls using a static mode of this class and I get error in the line of code 'startActivity(i)':
//AsyncTask
private static class CargarJSON extends AsyncTask<String, Void, String> {
Context mContext;
public CargarJSON(Context context) {
mContext = context;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
mProgressItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
mProgressItem.setVisible(true);
mProgressItem.setActionView(R.layout.actionbar_indeterminate_progress);
mProgressItem.expandActionView();
}
#Override
protected String doInBackground(String... params) {
String url = params[0];
String data = MetodosJSON.getHttpResponse(url);
MetodosJSON.parseaJSON2(data, IniSelCategoria.ac);
return params[1];
}
#Override
protected void onPostExecute(String titulo) {
super.onPostExecute(titulo);
// start new activity
Intent i = new Intent(mContext, PantallaInfo.class);
i.putExtra("title", titulo);
i.putExtra("URLser", urlSer);
**startActivity(i);**
mProgressItem.setVisible(false);
}
}
The mistake is:
Cannot make a static reference to the non-static method startActivity(Intent) from the type Activity
How do I make the method call 'startActivity(i)'?
Thank you very much.
Change it to
mContext.startActivity(i);
You need to use a context to call that method if not calling from an Activity. Luckily you are already passing a Context to the constructor.
Change your code with the below one.
Intent i = new Intent(mContext, PantallaInfo.class);
i.putExtra("title", titulo);
i.putExtra("URLser", urlSer);
mContext.startActivity(i); // call using Context instance
In my class, Main extends Activity, I've this:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case ...
case CREDENTIAL_VIEW:
new SetStatusProgressBar(this).execute();
And there is this nested class:
private class SetStatusProgressBar extends AsyncTask<String, Void, Boolean> {
private ProgressDialog dialog;
private Main ctx;
public SetStatusProgressBar(Main ctx) {
this.ctx = ctx;
dialog = new ProgressDialog(ctx);
}
// progress dialog to show user that contacting server.
protected void onPreExecute() {
this.dialog = ProgressDialog.show(ctx, null,
"Refreshing data from server...", true, false);
}
#Override
protected void onPostExecute(final Boolean success) {
//...
//statements that refresh UI
//...
if (dialog.isShowing()) {
dialog.dismiss();
timerProgressBarStop();
}
}
protected Boolean doInBackground(final String... args) {
//...
//statements to download data from server
//...
return true;
}
}
In the Main class I open a second Activity, in this way:
Intent myIntent = new Intent(Main.this, Credentials.class);
startActivityForResult(myIntent, CREDENTIAL_VIEW);
That second Activity returns to the Main activity in this way:
Intent intent = new Intent();
setResult(RESULT_OK, intent);
finish();
I don't understand why when I navigate from the second Activity to the Main, the ProgressDialog will show ONLY AFTER that the UI refreshes... In this way the Progress Dialog stays on the screen only for half second... and then hides! :( I'd like to see the ProgressDialog on top during all the download time!
Help, please.
Thank you all
Ok, first of all use getApplicationContext() instead of ctx variable. Using 'this' is not for good memory citizens.
Try updating progressDialog in onProgressUpdate(...) method.