Запуск действия из уведомления и передача данных на BackPressed

У меня в приложении есть 3 занятия:

MainMenuActivity -> ExecuteTrainingActivity -> ExecuteExerciseActivity.

Из MainMenuActivity в ExecuteTrainingActivity я передаю idExecution и idExercise для запроса ExecuteTrainingActivity и загружаю исходные данные.

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();
        }
    }
}

В третьем действии, ExecuteExerciseActivity, у меня есть TimerFragment, и когда TimerCountdown достигает 0, он открывает всплывающее окно с уведомлением, которое при нажатии открывает новую ExecuteExerciseActivity.

В этом TimerFragment я передаю в качестве Extras те же идентификаторы, поэтому я могу получить их в новом свежем 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());
}

Из этого нового свежего ExecuteExerciseActivity я хочу, чтобы система поддерживала тот же поток навигации для Activity, но когда я возвращаюсь с нового ExecuteExerciseActivity на ExecuteTrainingActivity, я не могу передать идентификаторы для запроса и загрузки ExecuteTrainingActivity.

Есть ли способ передать аргументы в BackPress? Является ли лучший подход заменой onBackPress созданием нового намерения и запуском нового действия?

** Мой манифест правильно использует parentActivityName.

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
0
78
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Сохраните свой запрос и идентификатор в SharedPreferences в onDestroy вашего ExecuteExerciseActivity, затем снова вытащите запрос и идентификатор в старом ExecuteTrainingActivity. onBackPressed запускает событие onDestroy жизненного цикла действия. Затем в onResume ExecuteTrainingActivity вытащите эти данные обратно.

В порядке! Сработало нормально!

Артур Олмос 20.01.2019 23:15

Я думаю, вы можете добиться этого, переопределив метод onOptionsItemSelected() ExecuteExerciseActivity. Попробуй это:

@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);
}

В Android, если ваше Activity запускает другое Activity и вы хотите передать данные в это Activity, вы должны добавить эти данные в качестве дополнений Intent.

Этот тип отправки данных Activity A to Activity B - это то, что вы уже используете.

Но для Activity B, возвращаясь к Activity A, на самом деле для этого есть встроенное решение, которое использует startActivityForResult(Intent, REQUEST_CODE) вместо startActivity(Intent).

Теперь в действии B вам просто нужно написать код:

@Override
public void onBackPressed()
{
     Intent resultIntent = getIntent();
     resultIntent.putExtra(EXTRA_NAME, extra_value);
     setResult(Activity.RESULT_OK, resultIntent);
     finish();
}

По сути, в действии B вы устанавливаете данные, которые хотите отправить обратно в действие A, которое запустило действие B, поскольку между этими двумя действиями существует связь.

Затем в своем действии A просто переопределите метод onActivityResult().

@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
        }
    }
}

Код запроса должен соответствовать REQUEST_CODE, который вы использовали для Activity B, поэтому Activity A знает, на какое действие следует ответить. Код результата - это просто быстрый способ категоризировать тип результата, который вы получаете от действия B, поскольку от действия B может быть возвращено более одного типа результата.

Это решение передачи данных лучше, чем создание нового намерения и запуск нового действия, потому что вам не нужно запускать новое действие. Ваше действие A уже существует, поэтому нет причин перестраивать весь макет, перезагружать все данные и иметь новое действие, существующее в стеке действий.

Поскольку ваше единственное намерение - передать данные из Activity B обратно в Activity A, которое его запустило, используйте startActivityForResult() и onActivityResult() для обработки этого типа совместного использования данных.

ActivityResult не работает с новым действием, созданным из уведомления! Новый Activity запускается как обычный startActivity, поэтому он не вызывает onActivityResult при обратном нажатии!

Артур Олмос 16.01.2019 16:58

Извините, я неправильно понял ваш вопрос. Есть еще некоторые части вопроса, которые мне неясны. Чтобы уточнить, у ExecuteExerciseActivity есть фрагмент с именем TimerFragment, который запускает уведомление с некоторыми дополнениями, заполненными его намерением для отправки в запускаемое действие. Затем, когда нажимается Notification, запускается новый ExecuteExerciseActivity, и вы хотите, чтобы он передавал данные обратно ... исходной ExecuteExerciseActivity, создавшей уведомление?

Jackey 17.01.2019 06:19

Другие вопросы по теме