打开 Activity 在应用程序关闭时单击通知按钮

Open Activity on notification button click when app is closed

我试图在用户单击我的通知中的按钮时打开 MainActivity,而该应用仅 运行 在后台提供服务。单击按钮时,将在 Service class:

中触发这些行
Intent openApp = new Intent(this, MainActivity.class);
openApp.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(openApp);

我已经检查过了,线被触发了,所以对按钮的点击反应没有问题,但是 Activity 打不开。

有什么建议吗?为什么这对我不起作用,我怎样才能让它起作用?

编辑

有人要求我提供更多代码,所以在 Service 中的 onStartCommand() 中,如果它以 intent 中的停止动作开始,我调用 killService() 方法,它会杀死 Service,启动 MainActivity 并做一些其他的事情:

if (action != null && action.equals(ACTION_STOP_SERVICE)) {
    killService();
}

要设置 Notifications 按钮,我使用此代码:

Intent stopActionIntent = new Intent(this, TimerService.class);
        stopActionIntent.setAction(ACTION_STOP_SERVICE);
        PendingIntent stopActionPendingIntent = PendingIntent.getService(this, 1, stopActionIntent, PendingIntent.FLAG_IMMUTABLE);

timerNotificationBuilder.addAction(R.drawable.stop, "Stop", stopActionPendingIntent);

正如我所说,按钮已经对用户点击它做出反应,所以这不是问题所在。

您可以尝试在 BroadcastReceiver 中接收点击,然后从那里打开 activity。

  1. 试试这个在您的通知中添加操作按钮:
timerNotificationBuilder.addAction(createNotificationActionButton("STOP");

createNotificationActionButton方法是这样的:

public NotificationCompat.Action createNotificationActionButton(String text){
        Intent intent = new Intent(this, StopwatchNotificationActionReceiver.class);

        @SuppressLint("InlinedApi") PendingIntent pendingIntent = PendingIntent.getBroadcast(this, new Random().nextInt(100), intent, PendingIntent.FLAG_IMMUTABLE);

        return new NotificationCompat.Action(0, text, pendingIntent);
    }
  1. 创建一个名为 StopwatchNotificationActionReceiver 的 class 并使其扩展为 BroadcastReceiver`。这是 class:
  2. 的代码
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

public class StopwatchNotificationActionReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        PrefUtil.setIsRunningInBackground(context, false);
        PrefUtil.setTimerSecondsPassed(context, 0);
        PrefUtil.setWasTimerRunning(context, false);
        context.stopService(MainActivity.serviceIntent);
        Intent activityIntent = new Intent(context, MainActivity.class);
        activityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActvity(activityIntent);
    }
}

您还需要像这样在您的清单中注册该接收器:

<receiver android:name="StopwatchNotificationActionReceiver"/>
  1. 其中 MainActivity.serviceIntent 是一个 public 静态变量,如下所示:
public static Intent serviceIntent;

并且这个意图只用于像这样启动服务:

//In onCreate
serviceIntent = new Intent(this, TimerService.class);

//In onPause
PrefUtil.setTimerSecondsPassed(this,seconds);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                startForegroundService(serviceIntent);
            }




或者您可以尝试简单的方法:

if (action != null && action.equals(ACTION_STOP_SERVICE)) {
    Context context = this;
    Intent activityIntent = new Intent(context, MainActivity.class);
        activityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActvity(activityIntent);
    killService();
}

编辑


这里有另一个解决方案。再次。你需要参考我的repo as I have made changes to the files in order to complete your task. In the service class, refer to this method. There, I start the activity if the action is reset(r). Or else, it opens the broadcast receiver. Then, in the activity, I receive that extra in the onResume() method. If the reset button is not clicked, it opens the Receiver class.

和往常一样,您可以查看应用的结果 from here

我希望代码能完成你的工作。

我找到了!参见 this answer
这个答案建议启用 ScreeanOverlay 设置,因为从 Android 10 开始,您无法再通过调用我使用过的行从后台打开 activity。
要使其正常工作,您必须通过 Manifest.xml:

添加此权限
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

然后用户必须启用 Display over other apps 设置。
我搜索了一个让用户更容易使用此设置的选项,并找到了 this answer.
这个答案给出了一个代码,将用户重定向到 Display over other apps 设置

if (!Settings.canDrawOverlays(this)) {
    Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName()));
    startActivityForResult(intent, 0);
}

然后我通过通知的内容(文本)指导用户如何启用该设置。
启用设置后,我之前使用的行将起作用。\

所以,问题解决了吗?

未完全解决

上述整个配置都有效,但前提是应用未被终止。
如果应用程序被杀死,我尝试了上面列出的方法,应用程序加入了最近的应用程序列表,但不会打开和显示。
解决此问题的解决方案也将被接受为答案,而不是这个。