如何在点击通知时打开当前已打开的活动

11

我已经尝试了所有方法,但对我都没有用。我希望在点击通知时,能够打开或恢复应用程序并显示任何屏幕。

我使用了以下方法:

NotificationCompat.BigTextStyle notiStyle = new NotificationCompat.BigTextStyle();
        notiStyle.setBigContentTitle(team);
        notiStyle.bigText(message);

        Intent resultIntent = new Intent(this, MainDrawerActivity.class);
        resultIntent.putExtra("fromNotification", "notification");

        resultIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
                | Intent.FLAG_ACTIVITY_SINGLE_TOP);


        TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);



        stackBuilder.addNextIntent(resultIntent);


        PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0,
                PendingIntent.FLAG_UPDATE_CURRENT);

        int icon = R.mipmap.ic_launcher;


        return new NotificationCompat.Builder(this).setSmallIcon(icon)
                .setAutoCancel(true)

                .setContentIntent(resultPendingIntent).setContentTitle(team)
                .setContentText(message).setStyle(notiStyle).build(); 

你的意思是当你在后台时吗? - Quick learner
如果您打开的是前台活动,则会获取onNewIntent方法。 - Newbie Android
MainDrawerActivity是我的主抽屉布局类,所有其他的都有片段。 - sunil
请澄清一下:您想将应用程序带到前台,而不启动新的活动吗? - Kevin Krumwiede
是的,如果应用程序在后台运行,则它会打开并保持在相同的屏幕上。如果应用程序关闭,则重新打开。 - sunil
显示剩余6条评论
7个回答

17

若要将应用程序提升到前台而不启动新的活动,请触发其启动器意图。

此方法来自我的一个旧项目。

/**
 * Creates a new launcher intent, equivalent to the intent generated by
 * clicking the icon on the home screen.
 *
 * @return the launcher intent
 */
public static Intent newLauncherIntent(final Context context) {
    final Intent intent = new Intent(context, MainActivity.class);
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    intent.setAction(Intent.ACTION_MAIN);
    intent.addCategory(Intent.CATEGORY_LAUNCHER);
    return intent;
}

即使该标志已设置,此方法创建的意图不会在应用正在运行时启动新任务。

这是另一种获取启动器意图的方式。但是,我发现如果应用正在运行,该意图总是会启动一个新任务,这并不是您想要的。

final Intent intent = context.getPackageManager()
        .getLaunchIntentForPackage(BuildConfig.APPLICATION_ID);

非常感谢,你救了我的一天。它运行得很好。 - sunil
@sunil 我没有遇到过这种情况,但我也不能百分之百确定我测试了这种情况。我会调查一下。 - Kevin Krumwiede
我正在使用这个功能(通过运行按钮来运行应用程序),我认为它可以正常工作,但是当我尝试从“构建”>“构建APK”菜单中构建的APK进行运行/安装时,结果却不同。 - niczm25
哦,我的错,这个可以工作。我有一个不同的问题,为什么我印象中没有工作。它与通过启动器图标尝试恢复应用程序时应用程序重新启动有关。但是仍然意图启动新任务,我在解决我所说的问题时运行良好。感谢Kevin的帮助。+1。 - niczm25
那个标志对我起作用。 - Arbaz.in
显示剩余2条评论

1

您应该在Application类中拥有类似于以下内容的东西,以存储当前活动。

private BaseActivity mCurrentActivity = null;

public BaseActivity getCurrentActivity() {
    return mCurrentActivity;
}

public void setCurrentActivity(BaseActivity currentActivity) {
    this.mCurrentActivity = currentActivity;
}

然后,在您的处理通知服务类内部。
@Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        super.onMessageReceived(remoteMessage);

    BaseActivity currentActivity = ((App) this.getApplicationContext())
                               .getCurrentActivity();
        Intent intent;
        if (currentActivity instanceof ActivityA) {
            intent = new Intent(this, ActivityA.class);
        } else if (currentActivity instanceof ActivityB) {
            intent = new Intent(this, ActivityB.class);
        } else {
            intent = new Intent(this, MainActivity.class);
        }

        intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent,
                PendingIntent.FLAG_UPDATE_CURRENT);

    // your code...
}

如果您的应用程序被杀死,将调用默认活动,例如MainActivity。
否则,当您在前台或后台接收并点击推送通知消息时,当前活动将保持为默认活动,例如ActivityA和ActivityB。然后,您可以导航到其他活动或片段的任何位置。
我的建议是,最好使用Fragment,在从推送通知导航到特定屏幕方面更容易。

1
这对以下三种情况有效:
1.如果应用程序已打开并单击通知,则通知应从状态栏中删除。
2.如果应用程序处于打开但在后台的状态,则应恢复应用程序,并显示之前打开的任何屏幕。
3.如果应用程序关闭并单击状态栏中的通知,则应用程序应打开。
private final static int NORMAL = 0x00;
private final static int BIG_TEXT_STYLE = 0x01;
private static NotificationManager mNotificationManager;

在 onMessage 调用中。
mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
new CreateNotification(BIG_TEXT_STYLE, team, message).execute();

然后在GCMIntentService中声明以下类。 public class CreateNotification extends AsyncTask {

    int style = NORMAL;
    String team, message;

    public CreateNotification(int style, String team, String message) {
        this.style = style;
        this.team = team;
        this.message = message;

    }

    @Override
    protected Void doInBackground(Void... params) {
        Notification noti = new Notification();

        switch (style) {
        case BIG_TEXT_STYLE:
            noti = setBigTextStyleNotification(team, message);
            break;

        }

        noti.sound = (null);
        noti.defaults = 0;
        noti.sound = Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.beep);
        noti.flags |= Notification.FLAG_AUTO_CANCEL;

        mNotificationManager.notify(0, noti);

        return null;

    }
}

最后

private Notification setBigTextStyleNotification(String team, String message) {

    // Create the style object with BigTextStyle subclass.
    NotificationCompat.BigTextStyle notiStyle = new NotificationCompat.BigTextStyle();
    notiStyle.setBigContentTitle(team);
    notiStyle.bigText(message);


    Intent      resultIntent = getPackageManager()
            .getLaunchIntentForPackage(getPackageName());

    TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);

        // Adds the Intent that starts the Activity to the top of the stack.
    stackBuilder.addNextIntent(resultIntent);


    PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0,
            PendingIntent.FLAG_UPDATE_CURRENT);
    int icon = R.mipmap.ic_launcher;


    return new NotificationCompat.Builder(this).setSmallIcon(icon)
            .setAutoCancel(true)

            .setContentIntent(resultPendingIntent).setContentTitle(team)
            .setContentText(message).setStyle(notiStyle).build();
}

@Kevin Krumwiede的方法和你的代码是否工作方式相同?如果是,你更喜欢使用哪种方法? - niczm25
我正在使用我的方法,Intent intent = new Intent(this, MainDrawerActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); - sunil
我正在使用这个标志。 - sunil
PendingIntent pendingIntent = PendingIntent.getActivity(this, (int)System.currentTimeMillis(), intent, PendingIntent.FLAG_UPDATE_CURRENT); 待处理意图 pendingIntent = PendingIntent.getActivity(this, (int)System.currentTimeMillis(), intent, PendingIntent.FLAG_UPDATE_CURRENT); - sunil
我也尝试了上面的解决方案,使用Intent resultIntent = getPackageManager().getLaunchIntentForPackage(getPackageName());(通过运行按钮运行应用程序时可以工作),我认为它可以工作,但是当我尝试从“Build> Build Apk”菜单构建的apk运行/安装时,我得到了不同种类的结果。 - niczm25

0

如果您只想恢复应用程序状态,那么我建议您仅保留单个 Activity 并使用不同的 Fragment 来处理不同的屏幕。

在通知点击时,您需要在通知载荷中定义应用程序的入口点,该入口点决定下一步导航。

如果您只有一个 Activity,则可以将该 Activity 定义为入口点,在该 Activity 上,您可以决定是否要推送新的 Fragment。

或者,如果您正在使用 Firebase,则将所有通知作为后台通知推送,并且可以从 Activity 堆栈中获取顶部 Activity 并将该 Activity 设置为通知的入口点。但是,仍然存在问题,因为用户可能会在从设置入口点的 Activity 导航后单击通知,这又是一个问题。因此,我更喜欢采用第一种方法。


是的,我做过相同的事情... 使用一个活动和所有其他屏幕都是片段。 - sunil
如果您只有一个活动,则应在清单中将该活动定义为singleTask,因此当您的活动在后台时,单击通知将调用onNewIntent并附带新数据。 - VikasGoyal
谢谢,通过这种方式解决了问题。Intent intent = new Intent(this, MainDrawerActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);PendingIntent pendingIntent = PendingIntent.getActivity(this, (int)System.currentTimeMillis(), intent, PendingIntent.FLAG_UPDATE_CURRENT); - sunil
希望您也喜欢这个答案。 - VikasGoyal

0

通过这种方式,我们也可以实现上述结果:

            try {
            int icon;

                icon = R.mipmap.ic_launcher;


        int mNotificationId = 001;


            Intent intent = new Intent(this, MainDrawerActivity.class);
            intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);

            //FLAG_UPDATE_CURRENT is important
            PendingIntent pendingIntent = PendingIntent.getActivity(this, 
 (int)System.currentTimeMillis(), intent, 
PendingIntent.FLAG_UPDATE_CURRENT);


            NotificationCompat.Builder mBuilder = new 
 NotificationCompat.Builder(
                this);
        Notification notification = 
  mBuilder.setSmallIcon(icon).setTicker(json.getString("team")).setWhen(0)
                .setAutoCancel(true)
                .setContentTitle(json.getString("team"))
                .setStyle(new 
 NotificationCompat.BigTextStyle().bigText(json.getString("message")))
                .setContentIntent(pendingIntent)
                .setSound(Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.beep))


        NotificationManager notificationManager = (NotificationManager) 
  this.getSystemService(Context.NOTIFICATION_SERVICE);
        notificationManager.notify(mNotificationId, notification);




        } catch (Exception e) {
            e.printStackTrace();
        }

0
//I am using write now this can possible    
  NotificationManager notificationManager = (NotificationManager) context
                .getSystemService(Context.NOTIFICATION_SERVICE);
        Notification notification = new Notification(icon, message, when);

        Intent notificationIntent = new Intent(context, HomeActivity.class);

        notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
                | Intent.FLAG_ACTIVITY_SINGLE_TOP);

        PendingIntent intent = PendingIntent.getActivity(context, 0,
                notificationIntent, 0);

        notification.setLatestEventInfo(context, title, message, intent);
        notification.flags |= Notification.FLAG_AUTO_CANCEL;
        notificationManager.notify(0, notification);

我正在Eclipse中使用GCM。 - sunil

0
创建新的活动
public class FinishImmediateActivity extends AppCompatActivity {
  @Override protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    finish();
  }
}

添加到 manifest.xml 文件中

<activity android:name=".FinishImmediateActivity"/>

检查应用程序是否在运行中
public static boolean isMainActivityRunning() {
  ActivityManager activityManager = (ActivityManager) MyApp.getContext().getSystemService(Context.ACTIVITY_SERVICE);
  List<ActivityManager.RunningTaskInfo> tasksInfo = activityManager.getRunningTasks(Integer.MAX_VALUE);

  for (int i = 0; i < tasksInfo.size(); i++) {
    if (tasksInfo.get(i).baseActivity.getPackageName().equals(MyApp.getContext().getPackageName())) {
      return true;
    }
  }
  return false;
}

然后在通知意图中调用该活动。

Intent resultIntent = new Intent(this, isMainActivityRunning() ? FinishImmediateActivity.class : HomeActivity.class);

我应该在主抽屉或GCM意图通知中使用哪个类? - sunil
意图 resultIntent = new Intent(this, FinishImmediateActivity.class); - Hun
太好了,现在应用程序仍停留在同一页,但是当我点击通知时它没有打开。但是当我点击应用程序图标并打开时,应用程序会打开以前的屏幕。 - sunil
如果我想打开应用程序,我需要做什么? - sunil
请帮我一下。您的方法在应用程序打开并点击通知时运行良好,通知会被关闭。只有一件事情我需要注意,即当应用程序处于后台且点击通知时,应用程序应恢复。 - sunil

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接