简体   繁体   中英

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM