【问题标题】:How can you detect if your activity is being onPaused because of a PendingIntent which you created?您如何检测您的活动是否因为您创建的 PendingIntent 而被暂停?
【发布时间】:2013-01-04 14:48:17
【问题描述】:

如果我有一个位于前台的 Activity,并且我导航到我的应用程序中的另一个 Activity,我可以通过在您开始传输时设置一个标志并在您传输到新 Activity 时擦除它来检测这一点。这使我能够区分由于内部(标志设置)或外部(未设置标志)事件而导致的活动 onPause。

但是,我无法为嵌入在通知中的 PendingIntents 执行此操作。是否可以检测到我的 Activity 正在暂停,因为他们选择了我在通知栏上创建的通知?是否可以使用某种通知侦听器来触发通知触发和执行挂起的 Intent 以使我的 Activity 暂停?

我明白这有点令人困惑,所以我制作了一个框架项目来演示这个问题:

package com.example.notificationtest;

import android.os.Bundle;
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.view.View;

public class MainActivity extends Activity {

private static final int INCOMING_NOTIFICATION_ID = 1;
private static final String TAG = "NotificationTest";

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
}

@Override
public void onPause() {
    super.onPause();
    Log.e(TAG,"onPause");
}

@Override
public void onResume() {
    super.onResume();
    Log.e(TAG,"onResume");
}

public void onTransitionButtonClick(View view) {
    Intent intent = new Intent(this, MainActivity.class);
    Log.e(TAG,"About to start activity: onPause will be invoked.");
    startActivity(intent);
}

public void onNotificationButtonClick(View view) {
    Intent intent = new Intent(this, MainActivity.class); 
    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
    Notification notification = new Notification(android.R.drawable.alert_dark_frame, "Alert!", System.currentTimeMillis());
    notification.defaults |= Notification.DEFAULT_SOUND;
    notification.defaults |= Notification.DEFAULT_VIBRATE;
    notification.defaults |= Notification.DEFAULT_LIGHTS;
    notification.flags |= Notification.FLAG_AUTO_CANCEL;
    notification.flags |= Notification.FLAG_INSISTENT;
    notification.setLatestEventInfo(this, "Click to open", "Click to open", pendingIntent);

    // Show the alert.
    final NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
    notificationManager.notify(INCOMING_NOTIFICATION_ID, notification);
}

}

使用activity_main.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<Button
    android:id="@+id/notify_button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:padding="@dimen/padding_medium"
    android:text="Make a notification"
    android:onClick="onNotificationButtonClick"
    tools:context=".MainActivity" />

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_toRightOf="@id/notify_button"
    android:padding="@dimen/padding_medium"
    android:text="Normal transition"
    android:onClick="onTransitionButtonClick"
    tools:context=".MainActivity" />

</RelativeLayout>

如果您选择“正常转换”按钮,日志会打印“即将开始活动:将调用 onPause”。在 onPause 之前。

如果您选择“制作通知”按钮,然后向下拖动通知栏并点击通知,我希望在 onPause 之前收到该点击通知,以便我可以插入同一行“关于开始活动: onPause 将被调用。”。我该怎么做?

【问题讨论】:

  • 唉,这个世界上没有正义。
  • Tal Kanel 的回答更彻底,包含代码 sn-ps。对不起:(
  • 是的,我知道,我为此花费了五倍的时间,激励您完善您的问题。 :) 当然,我应该想出一个更性感的更新。

标签: android android-pendingintent activity-lifecycle


【解决方案1】:

除了持有启动活动的意图外,PendingIntent 还可以持有“发射”广播的意图

您可以使用此类自定义广播作为通知的触发器,然后实现将注册到该广播的BroadcastReceiver,并显示您想要的任何内容,然后才会启动所需的活动。

Intent intent = new Intent("my.custom.broadcast.action");
pendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);

接收器将如下所示:

private BroadcastReceiver mReceiver = new BroadcastReceiver() {

    @Override
    public void onReceive(Context context, Intent intent) {
        //do whatever you want
        // if this code is being executed - it's a sign that the user clicked on the notification...

        Intent intent = new Intent(this, MainActivity.class);
        Log.e(TAG,"About to start activity: onPause will be invoked.");
        startActivity(intent);

    }
};

不要忘记在onCreate() 调用时注册mReceiver,并取消注册onDestroy()

registerReceiver(mReceiver , new IntentFilter("my.custom.broadcast.action"));
unregisterReceiver(mReceiver);

在这种方法中,您可以准确控制用户单击通知时会发生什么。如您所见 - 只有在单击通知时才能发送广播。没有人说你必须开始活动。..

【讨论】:

    【解决方案2】:

    让我首先尝试将您的问题翻译成另一个问题(只是为了清楚起见):我怎样才能让我的活动在暂停之前执行代码,因为与我的通知相关联的活动(我可以控制)正在执行要显示?

    前提是译文足够好,能达到回答的目的:

    您确定这种方法可以解决问题吗?因为在很多情况下,您的 Activity 会暂停,并且用户“几乎立即”显示您的 Notification 的 Activity,而中间仍然会有步骤(例如首先查看其他通知时)。我认为从技术上讲,这意味着您仍然必须在那里执行相同的代码,同时您不能有任何迹象表明您的通知将在“不久的将来”被查看。

    因此,对于一个合适的答案,我相信人们必须跳出框框思考一下,这取决于您打算执行的代码的性质和执行它的动机。

    因此,如果您在这方面更新您的问题并通知我,我会很高兴再看一看。

    问题更新后更新:

    您可以避免在用户按下通知时触发下一个 Activity,而只需触发一个事件。如果您的 Activity 以编程方式注册了 BroadcastReceiver,它应该能够接收到此事件,然后按照您的意愿更新自身并启动下一个 Activity。

    【讨论】:

      猜你喜欢
      • 2015-12-06
      • 2017-07-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多