Верните действие singleInstance обратно с помощью уведомления

У меня есть обычная активность, назовем ее А, и это первая активность, представленная пользователю при открытии приложения. У действия A есть кнопка, которая запускает действие, назовем его B, с launchMode, установленным в singleInstance в манифесте. Действие B выполняет некоторую обработку.

Пользователи могут нажать кнопку «Домой» и снова открыть приложение, которое представит им начальное действие, также известное как действие A. Если пользователи снова нажмут кнопку (в действии A), им будет представлено действие B. В случае, активность B не будет перезапущена, т. е. onCreate не будет вызываться, так как это singleInstance, чего я и хочу.

Я хочу, чтобы пользователям было проще вернуться к действию B после его начала, если они нажмут кнопку "Домой". Итак, я создал постоянное уведомление, которое позволяет пользователям возвращать действие B. Текущее уведомление будет отменено после завершения действия B.

Теперь к проблеме: щелчок по текущему уведомлению снова воссоздает действие B, т. Е. onCreate вызывается снова. Я не знаю, почему поведение здесь отличается от нажатия кнопки в действии A. Вот как я создал уведомление:

Intent notifyIntent = new Intent(mContext, CallActivity.class);

PendingIntent notifyPendingIntent = PendingIntent.getActivity(
        mContext, 0, notifyIntent, PendingIntent.FLAG_NO_CREATE);

NotificationCompat.Builder builder = new NotificationCompat.Builder(mContext, CHANNEL_ID)
        .setSmallIcon(R.drawable.baseline_call_white_18)
        .setContentTitle(title)
        .setContentText(text)
        .setOngoing(true)
        .setPriority(NotificationCompat.PRIORITY_HIGH)
        .setContentIntent(notifyPendingIntent);

NotificationManagerCompat notificationManager = NotificationManagerCompat.from(mContext);
notificationManager.notify(NOTIFICATION_ID, builder.build());

Может ли кто-нибудь сказать мне, почему это не работает и как я могу заставить его работать так, как я описал?

ИЗМЕНИТЬ

Вот фрагмент моего манифеста:

<application
    android:name="com.mnm.caller.IMApplication"
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher"
    android:supportsRtl="true"
    android:theme="@style/AppTheme"
    tools:ignore="GoogleAppIndexingWarning">
    <activity
        android:name="com.mnm.caller.activities.SplashActivity"
        android:configChanges="orientation|keyboardHidden"
        android:noHistory="true"
        android:screenOrientation="portrait"
        android:theme="@style/AppTheme.Splash">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>

    </activity>


    <activity
        android:name="com.mnm.caller.activities.LoginActivity"
        android:configChanges="orientation|keyboardHidden"
        android:theme="@style/AppTheme.NoTitleBar"
        android:screenOrientation="portrait" />

    <activity
        android:name="com.mnm.caller.activities.HomeActivity"
        android:configChanges="orientation|keyboardHidden"
        android:theme="@style/AppTheme.NoTitleBar"
        android:screenOrientation="portrait" />

    <activity
        android:name="com.mnm.caller.activities.CallActivity"
        android:configChanges="orientation|keyboardHidden"
        android:launchMode="singleInstance"
        android:screenOrientation="portrait"
        android:theme="@style/AppTheme.NoTitleBar" />


    <service
        android:name="com.mnm.caller.services.IMFirebaseMessagingService"
        android:stopWithTask="false">
        <intent-filter>
            <action android:name="com.google.firebase.MESSAGING_EVENT" />
        </intent-filter>
    </service>

</application>

person m2008m1033m    schedule 10.03.2019    source источник
comment
В целом такой подход неверен. Специальные режимы запуска singleTask и singleInstance следует использовать только в особых ситуациях. Пожалуйста, опубликуйте свой манифест, и я могу предложить альтернативу.   -  person David Wasser    schedule 11.03.2019
comment
@DavidWasser Я обновил свой вопрос манифестом, не могли бы вы взглянуть на него.   -  person m2008m1033m    schedule 11.03.2019
comment
Ваш единственный экземпляр Activity на самом деле не запускается в отдельной задаче, потому что вы не указали taskAffinity в манифесте. Это означает, что Android игнорирует специальный режим запуска и рассматривает это как обычный Activity. Если бы вы на самом деле запускали 2 отдельные задачи, вы бы увидели 2 отдельные записи в списке недавних задач, каждая из которых имела бы одинаковое имя и значок. Это может запутать ваших пользователей. Это лишь некоторые из причин, по которым не следует использовать специальные режимы запуска singleInstance и singleTask. У них много побочных эффектов.   -  person David Wasser    schedule 12.03.2019
comment
Если пользователь помещает приложение в фоновом режиме с Activity B сверху, почему не должно отображаться Activity B, когда пользователь снова запускает приложение? Пожалуйста, объясните ваши требования к навигации, и, возможно, мы сможем помочь вам с правильным решением.   -  person David Wasser    schedule 12.03.2019
comment
@DavidWasser Спасибо за ваш ответ. На самом деле я разрабатываю приложение для звонков. Активность A — это домашний экран, а B — активность вызова. Я хочу, чтобы пользователи возвращались на главный экран во время звонка, поэтому я намеренно и сознательно решил создать два экземпляра приложения в недавних приложениях (вы можете увидеть точное поведение в телефонном приложении по умолчанию на Android).   -  person m2008m1033m    schedule 12.03.2019


Ответы (2)


В комментарии вы написали:

На самом деле я разрабатываю приложение для звонков. Активность A — это домашний экран, а B — активность вызова. Я хочу, чтобы пользователи возвращались на главный экран во время звонка, поэтому я намеренно и сознательно решил создать два экземпляра приложения в последних приложениях (вы можете увидеть точное поведение в телефонном приложении по умолчанию на Android).

Если это так, вы, вероятно, хотите иметь 2 отдельные задачи, между которыми можно переключаться. Для этого нужно использовать taskAffinity. Ваш CallActivity должен иметь режим запуска singleTask или singleInstance, и вы должны установить android:taskAffinity="call" или что-то в этом роде. Чтобы не сбивать пользователей с толку, вы также должны указать другой android:label и другой android:icon для CallActivity, чтобы эта задача, появившаяся в списке недавних задач, выглядела иначе, чем остальная часть вашего приложения. Убедитесь, что при запуске CallActivity вы также установили FLAG_ACTIVITY_NEW_TASK. Вы также должны установить этот флаг при сборке файла Notification.

person David Wasser    schedule 13.03.2019
comment
Я попробовал ваше решение, это именно то, что я хотел! - person m2008m1033m; 14.03.2019

Вам нужно установить FLAG_ACTIVITY_SINGLE_TOP в экземпляр Intent (в вашем случае notifyIntent) перед созданием объекта PendingIntent.

Другими словами:

Intent notifyIntent = new Intent(mContext, CallActivity.class).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);

PendingIntent notifyPendingIntent = PendingIntent.getActivity(
        mContext, 0, notifyIntent, PendingIntent.FLAG_NO_CREATE);

NotificationCompat.Builder builder = new NotificationCompat.Builder(mContext, CHANNEL_ID)
        .setSmallIcon(R.drawable.baseline_call_white_18)
        .setContentTitle(title)
        .setContentText(text)
        .setOngoing(true)
        .setPriority(NotificationCompat.PRIORITY_HIGH)
        .setContentIntent(notifyPendingIntent);

NotificationManagerCompat notificationManager = NotificationManagerCompat.from(mContext);
notificationManager.notify(NOTIFICATION_ID, builder.build());
person nstosic    schedule 10.03.2019