Intent onPostExecute() AsyncTask - java

Im running an AsyncTask in an inner class and once complete within the onPostExecute() I want to use an intent to pass values to another activity however I have two errors that im not sure how to fix.
The errors occur on the setResult() line at RESULT_OK and the finish() line explaining that these two actions cannot occur outside of an activity. How would i use this intent in the onPostExecute of the 'AsyncTask'?
Code:
protected void onPostExecute(Void result)
{
// TODO Auto-generated method stub
super.onPostExecute(result);
Intent intent = new Intent();
intent.putExtra("jobs", jobStatus);
intent.putExtra("requestsSent", requests);
setResult(RESULT_OK, intent);
finish();
}

you need use Context of Activity class like following for finish method:
YourActivity.this.finish()
and RESULT_OK exists on activity class, so you need:
Activity.RESULT_OK
so your code must be like following:
Intent intent = new Intent();
intent.putExtra("jobs", jobStatus);
intent.putExtra("requestsSent", requests);
setResult( Activity.RESULT_OK, intent);
YourActivity.this.finish()

setResult and finish() are method of Activity class. You will need activity context for the same
http://developer.android.com/reference/android/app/Activity.html.
Now pass the Activity context to the constructor of AsyncTask
new TheTask(ActivityName.this).execute(params);
Then
Context mContext;
public TheTask(Context context)
{
mContext = context;
}
If AsyncTask is an inner class of the Activity you can use ActivityName.this
((Activity) mContext).setResult(Activity.RESULT_OK, intent);
((Activity) mContext).finish();

Related

How do you pass data back and forth between activities in Android?

I have two activities that should pass data back and forth to each other using intents. I'm not sure where to place some of the puts and gets though.
For Activity1 (MainActivity), I have a button, and on press it creates an intent, and then puts it to Activity2, then starts it using startActivity(intent).
btn.setOnClickListener((v) -> {
Intent intent = new Intent(this, Activity2.class);
intent.putExtra("test", testClass);
startActivity(intent);
});
Then in Activity2, I get that information in the onCreate() function using getIntent.
Now what I want to do is have a button in Activity2 that will pass data to Activity1, but won't necessarily "start/show" the activity.
So I'm wondering how this can be done.
My idea is to have the following similar to before:
Activity2:
btn.setOnClickListener((v) -> {
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra("info", info);
});
But I'm confused about two things
Can I do this without starting the activity right away
Where would I do the getIntent call in MainActivity to retrieve this data
You can use startActivityForResult to start Activity2 and receive a result back to Activity1
Activity 1
int LAUNCH_ACTIVITY_TWO = 1;
Intent i = new Intent(this, Activity2.class);
i.putExtra("test", testClass);
startActivityForResult(i, LAUNCH_ACTIVITY_TWO);
//onActivityResult
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == LAUNCH_ACTIVITY_TWO) {
if(resultCode == Activity.RESULT_OK){
String result=data.getStringExtra("result");
}
}
}
Activity 2
Intent returnIntent = new Intent();
returnIntent.putExtra("result", result);
setResult(Activity.RESULT_OK, returnIntent);
finish();
Full Activity 1 code:
public class MainActivity extends AppCompatActivity {
public static int LAUNCH_ACTIVITY_TWO = 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn = (Button) findViewById(R.id.btn);
btn.setOnClickListener((v) -> {
Intent i = new Intent(this, Activity2.class);
i.putExtra("test", testClass);
startActivityForResult(i, LAUNCH_ACTIVITY_TWO);
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == LAUNCH_ACTIVITY_TWO) {
if(resultCode == Activity.RESULT_OK){
String result= data.getStringExtra("result");
}
}
}
}
Full Activity 2 code:
public class Activity2 extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(getIntent().getExtras() != null) {
// Get intent extras from Activity 1
}
Button btn = (Button) findViewById(R.id.btn);
btn.setOnClickListener((v) -> {
Intent returnIntent = new Intent();
returnIntent.putExtra("result", result);
setResult(Activity.RESULT_OK, returnIntent);
finish();
});
}
}
You can for example create a list in activity2 to which you add the data you want to pass to activity1. Before starting activity1 you get the values out of your array and add them as extras to the input.
You can have the data added to a JSONObject and use a serializer so you don't have to add your items all by yourself.
If you want to pass your data to activity1 without starting it,so activity1 processes the data, that is not possible. Activity doesnt execute anything while you are in activity2, for such cases you use fragments.
If you use fragments you can put all data in a viewmodel which is bound to the activity instead of each fragment.
There are several ways you can achieve this pending on what type of data you're looking at passing.
If it's an entire class object then make the class parcable. You can copy and paste the class in this website http://www.parcelabler.com/ and it auto formats it for you. All you do is pass it as an intent extra.
If you're looking at data that needs an action performed on it and then passed to another activity I would suggest using and intent service. You can perform certain actions pending the intents received in the service.
If you're looking at performing certain actions only after XYZ has occurred in your application then used shared preferences. These can be accessed anywhere quite easily.
Lastly, if you're using bulk data consistently that needs to remain persistent, use a local database storage and just query when you need to.
You can use SharedPreferences or static variables/fields for that.

Starting an Activity from a Notification and passing data onBackPressed

I have 3 Activities on the app:
MainMenuActivity -> ExecuteTrainingActivity -> ExecuteExerciseActivity.
From MainMenuActivity to ExecuteTrainingActivity, I'm passing an idExecution and an idExercise for ExecuteTrainingActivity query and load the initial data.
ExecuteTrainingActivity onCreate:
#Override
protected void onCreate(Bundle savedInstanceState) {
//...
initialize();
setupRecyclerView(exercises);
}
private void initialize() {
Bundle extras = getIntent().getExtras();
if (extras != null) {
if (extras.containsKey("id_execution")) {
idExecution = extras.getLong("id_execution");
idExercise = extras.getLong("id_exercise");
execution = queryExecution(idExecution);
} else {
insertExecution();
}
}
}
In the 3rd activity, ExecuteExerciseActivity, I have a TimerFragment that, and when TimerCountdown reaches 0, it opens a Notification popup, that when clicked open an fresh ExecuteExerciseActivity.
On this TimerFragment, I'm passing as Extras the same ids, so I can get them in the new fresh ExecuteExerciseActivity:
public class TimerFragment extends Fragment {
//...
private void showNotification(){
Intent intent = new Intent(getActivity(), ExecuteExerciseActivity.class);
intent.putExtra("id_execution", idExecution);
intent.putExtra("id_exercise", idExercise);
intent.putExtra("position", position);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(getActivity());
stackBuilder.addNextIntentWithParentStack(intent);
PendingIntent pendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
/*=== CHECK IF NOTIFICATION CHANNEL IS ACTIVE ===*/
boolean ok = isNotificationChannelEnabled(getActivity(), Constants.CHANNEL_ID);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(requireNonNull(getActivity()), Constants.CHANNEL_ID)
.setSmallIcon(R.drawable.d77)
.setContentTitle("Teste Notificação")
.setContentText("Ababa")
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setContentIntent(pendingIntent)
.setAutoCancel(true);
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(getActivity());
notificationManager.notify(0, mBuilder.build());
}
From this new fresh ExecuteExerciseActivity, I want to make the system maintain the same navigation flow of Activities, but when I backpress from the new ExecuteExerciseActivity to ExecuteTrainingActivity, i can't pass the Id's for the ExecuteTrainingActivity query and load.
Is there a way to pass arguments onBackPress?
Is the best approach override onBackPress creating a new intent and a starting a new Activity?
**My manifest is using parentActivityName correctly.
Save your query and id into a SharedPreferences in onDestroy of your ExecuteExerciseActivity then pull out the query and id again in the old ExecuteTrainingActivity. onBackPressed triggers onDestroy event of an activity's life cycle. Then in the onResume of ExecuteTrainingActivity pull this data back out.
I think you can achieve this by overriding onOptionsItemSelected() method of ExecuteExerciseActivity. Try this:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
Intent intent = new Intent(this, ExecuteExerciseActivity.class);
//Add the extras to the intent
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
In Android, if your Activity starts another Activity and want to pass data to that Activity, you would add those data as Intent extras.
This Activity A to Activity B type of sending data is something you're using already.
But for Activity B back to Activity A, there's actually a built-in solution for this, which is through startActivityForResult(Intent, REQUEST_CODE) instead of startActivity(Intent).
Now in Activity B, you simply have to code:
#Override
public void onBackPressed()
{
Intent resultIntent = getIntent();
resultIntent.putExtra(EXTRA_NAME, extra_value);
setResult(Activity.RESULT_OK, resultIntent);
finish();
}
Basically, in Activity B, you're setting the data you want to send back to the Activity A that started Activity B, since there's a connection between these two Activities.
Next, in your Activity A, just override the onActivityResult() method.
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE) {
if (resultCode == RESULT_OK) {
// get data through data.getIntExtra() and etc
}
}
}
The request code needs to match the REQUEST_CODE you used for Activity B, so Activity A knows which Activity to respond to. The result code is just a quick way for you to categorize the type of result you're getting back from Activity B, since there might be more than one type of result being returned from Activity B.
This solution of passing data is better than creating a new Intent and starting a new Activity because you don't need to start a new Activity. Your Activity A already exists, so there's no reason to rebuild the entire layout, reload all the data, and have a new Activity existing on the Activity stack.
Since your only intention is to pass data from Activity B back to the Activity A that started it, use startActivityForResult() and onActivityResult() to handle this type of data sharing.

Calling a method from another Activity (call Fragment)

I have called method:
protected void ask(){
Fragment newContent = new QuestionsFragment();
((MainActivity) getActivity()).switchContent(newContent, R.string.questions, MenuFragment.questions_id, BottomActionBarMode.QUESTIONS);
}
MainActivity:
https://docs.google.com/file/d/0B30eXgoSJlFsczNSdkE5Qnc5eG8/edit?usp=sharing
Error:
08-21 17:16:28.574: E/AndroidRuntime(26360): FATAL EXCEPTION: main
08-21 17:16:28.574: E/AndroidRuntime(26360): java.lang.ClassCastException: com.chiv.successteritory.activities.AskLikeQuestionDetailsActivity cannot be cast to com.chiv.successteritory.activities.MainActivity
how to call? thanks in advance
If you are on MainActivity and starts the AskLikeQuestionDetailsActivity, it's not guaranteed that MainActivity is still there, as the OS can garbage collect any Activities on background.
If you want change a Fragment on MainActivity after the ask() method is called on AskLikeQuestionDetailsActivity, I would suggest you to do the following:
On MainActivity, instead of calling startActivity to start AskLikeQuestionDetailsActivity, call startActivityForResult and override the onActivityResult method to change the Fragment depending on the result received.
On AskLikeQuestionDetailsActivity's ask(), call setResult with Activity.RESULT_OK and a configured Intent to send some information back to MainActivity, then call finish() (if you have to exit the AskLikeQuestionDetailsActivity Activity right away).
Is it clear? Hope it helps.
In ask() AskLikeQuestionDetailsActivity:
Intent intent = new Intent(getActivity(), MainActivity.class);
int condition = 1;
intent.putExtra("condition", condition);
startActivity(intent);
In onCreate() MainActivity.class:
Bundle extras = getIntent().getExtras();
if (extras != null) {
showQuestions();
}

Android: setResult not working

Scenario: I have a MainActivity.java, OtherPageForFragments.java and a fragment which is on OtherPageForFragments.java
In MainActivity.java, I have written the following code to start an activity and get result in
onActivityResult(int requestCode, int resultCode, Intent data)
is
startActivityForResult(new Intent(this, OtherPageForFragments.class),REQUEST_CODE_MAP);
In the onDestroy() of the fragment class, i have written this:
public void onDestroyView() {
// TODO Auto-generated method stub
super.onDestroyView();
mlocManager.removeUpdates(this);
Intent intent = new Intent();
intent.putExtra("Latitude", passLatLng.latitude);
intent.putExtra("Longitude", passLatLng.longitude);
getActivity().setResult(Activity.RESULT_OK, intent);
getActivity().finish();
}
Now, I want my result in the MainActivity class. So, i have written the following code in the onActivityResult method:
if (resultCode == Activity.RESULT_OK && requestCode == REQUEST_CODE_MAP)
{
tost("2");
double lat=data.getExtras().getDouble("Latitude");
double lng=data.getExtras().getDouble("Longitude");
tost(lat + " -- " + lng);
}
The Problem: the resultCode getting returned is not Activity.RESULT_OK and the Intent I am getting is null.
What to do? Thanks
getActivity().setResult(Activity.RESULT_OK, intent);
getActivity().finish();
this code shouldn't be in onDestroy. onDestroy happens after the activity is already finished, and onActivityResult was called.
this code needs to in the code that closes the activity/fragment,
like on back key pressed, or a close button onClick
Try this:
Intent data = new Intent();
intent.putExtra("Latitude", passLatLng.latitude);
intent.putExtra("Longitude", passLatLng.longitude);
if (getParent() == null) {
setResult(Activity.RESULT_OK, data);
} else {
getParent().setResult(Activity.RESULT_OK, data);
}
getActivity().finish();
maybe you need clarify the launch modes for both activities. normally they should be "standard", if there is "singleTop" ... attributes in your activity manifest file. you need pay more attention.
For me removing flag Intent.FLAG_ACTIVITY_NEW_TASK for lauch intent resolved the issue
The method finish() is called before setResult()
Try overiding onBackPressed() method like this
override fun onBackPressed() {
setResult(RESULT_OK)
super.onBackPressed()
}

pass Intent to function throws NullPointerException

In an Android I would like to pass an Intent Object to a function, but consistently get a NullPointerException.
I could not find any source citing that this is not possible.
basically I have this:
public Intent intent;
/**
* Called when the activity is first created.
*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
intent = getIntent();
int check = elsewhere.chk_intent(intent); //<=THROWS ERROR
}
chk_intent() performs some functions on data transmitted with the intent, especieally if some extra fields are present.
I tried to move getIntent() into this function, but this is not allowed.
Any help would be much appreciated
Is this activity called by another activity? The intent will not be null only if previous activity supplies an intent to the current activity:
// previous activity
Intent intent = new Intent(FirstActivity.class, SecondActivity.class);
int value = 10;
intent.putIntExtra("key", value);
startActivity(intent);
// use this if want to return data
//startActivityForResult(intent);
If this activity is the starting (main) activity or it is not called by any previous activity, then getIntent() is null, you need to initialize your own new Intent object.
// current activity in onCreate() method
if(getIntent() == null) {
Intent intent = new Intent();
int check = elsewhere.chk_intent(intent);
}

Categories