Передавать данные уведомлений в текущую активность вместо открытия дома?

#android #android-activity #notifications #android-notifications

#Android #android-активность #уведомления #android-уведомления

Вопрос:

В моем приложении у меня есть HomeActivity приложение, которое запускает другие действия, давайте вызовем его SecondActivity . Всякий раз, когда пользователь выбирает уведомление, я запускаю CommentsActivity .

Всякий раз, когда приходит уведомление, и пользователь нажимает на баннер или нажимает на него в центре уведомлений, HomeActivity onNewIntent вызывается метод my, который запускает my . CommentsActivity Это нормально, за исключением того, что я не могу сохранить задний стек таким, каким он был до того, как пользователь нажал на уведомление, что означает, что если пользователь

 HomeActivity -> SecondActivity -> Taps Notification -> | Backstack is cleared and only HomeActivity remains -> CommentsActivity.
 

Поэтому, когда пользователь нажимает кнопку «Назад», они возвращаются домой.

Есть ли способ сделать так, чтобы мои SecondActivity onNewIntent вызывались, когда пользователь открывает уведомление, и они уже включены SecondActivity , вместо того, чтобы открывать задний стек? Поток пользователей, который я хочу, следующий:

 HomeActivity -> SecondActivity -> Taps Notification -> CommentsActivity (and backwards if the user presses the back button.
 

Имейте в виду, что я использую android:launchMode="singleTask" in my AndroidManifest для my HomeActivity , поэтому я не получаю несколько HomeActivity экземпляров при прослушивании уведомления.

Комментарии:

1. Небольшая хитрость, которая может помочь. Когда пользователь нажимает на уведомление, отправьте новое намерение SecondActivity и с этим намерением поместите некоторую строку. Во втором методе activity oncreate проверьте строку, и если это правда, просто запустите новое намерение прокомментировать действие из второго действия.

2. Я думал об этом взломе, но когда я говорю SecondActivity, у меня может быть еще 5 действий в заднем стеке, когда пользователь открывает уведомление, и все это нужно будет воссоздать (вместе с их позициями в RecyclerViews и data, что кажется не очень выполнимым), поэтому я былподумайте, есть ли способ заставить Android не открывать HomeActivity при каждом нажатии notificaiton и позволить текущей запущенной активности обрабатывать намерение.

Ответ №1:

Решение

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

  • Если пользователи впервые открывают приложение ( HomeActivity оно не существует в заднем стеке), запустите HomeActivity
  • В противном случае перенаправьте намерение на onNewIntent (намерение) текущего выполняемого действия (действие в верхней части стека)

Реализация

Шаг 1. Создайте класс с именем MyApp , который простирается от класса Application. Его цель — прослушивать весь жизненный цикл приложения.

 public class MyApp extends Application {

    public static final String EXTRA_ORIGINAL_INTENT = "EXTRA_ORIGINAL_INTENT";

    private final ActivityLifecycleCallbacksImpl callbacks = new ActivityLifecycleCallbacksImpl();

    @Override
    public void onCreate() {
        super.onCreate();
        registerActivityLifecycleCallbacks(callbacks);
    }

    public boolean isHomeActivityStarted() {
        return callbacks.isHomeActivityStarted();
    }

    public void routeIntentToCurrentRunningActivity(Intent original) {
        Activity activity = callbacks.getCurrentRunningActivity();
        Intent intent = new Intent(this, activity.getClass());
        intent.putExtra(EXTRA_ORIGINAL_INTENT, original);
        // Call onNewIntent() method of the activity at top of the stack.
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
        startActivity(intent);
    }

    private static final class ActivityLifecycleCallbacksImpl implements ActivityLifecycleCallbacks {
        public static final int INVALID_TASK_ID = -1;

        int homeActivityTaskId = INVALID_TASK_ID;
        Activity currentRunningActivity = null;

        @Override
        public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) {
        }

        @Override
        public void onActivityStarted(@NonNull Activity activity) {
        }

        @Override
        public void onActivityResumed(@NonNull Activity activity) {
            if (activity instanceof RouterActivity) {
                return;
            }

            currentRunningActivity = activity;
            if (activity instanceof HomeActivity) {
                homeActivityTaskId = activity.getTaskId();
            }
        }

        @Override
        public void onActivityPaused(@NonNull Activity activity) {
        }

        @Override
        public void onActivityStopped(@NonNull Activity activity) {
        }

        @Override
        public void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState) {
        }

        @Override
        public void onActivityDestroyed(@NonNull Activity activity) {
            if (activity instanceof RouterActivity) {
                return;
            }

            if (activity instanceof HomeActivity) {
                homeActivityTaskId = INVALID_TASK_ID;
            }
        }

        boolean isHomeActivityStarted() {
            return homeActivityTaskId != INVALID_TASK_ID;
        }

        @NonNull
        Activity getCurrentRunningActivity() {
            return currentRunningActivity;
        }
    }
}
 

Не забудьте добавить этот класс в файл манифеста.

Шаг 2. Создайте действие маршрутизатора с именем RouterActivity

 public class RouterActivity extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        MyApp myApp = (MyApp) getApplication();
        if (!myApp.isHomeActivityStarted()) {
            Intent intent = new Intent(this, HomeActivity.class);
            intent.putExtras(getIntent());
            startActivity(intent);
        } else {
            myApp.routeIntentToCurrentRunningActivity(getIntent());
        }

        finish();
        overridePendingTransition(0, 0);
    }
}
 

Шаг 3. Добавьте оба класса в файл манифеста

 <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.kotlinapp">

    <application
        android:name=".MyApp"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <activity android:name=".RouterActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".HomeActivity"
            android:launchMode="singleTask" />
        <activity android:name=".SecondActivity" />
        <activity android:name=".CommentsActivity" />
    </application>
</manifest>