【问题标题】:Android notification displayed at service startup is canceled just after creation服务启动时显示的Android通知在创建后被取消
【发布时间】:2014-02-21 10:29:40
【问题描述】:

我正在测试制作一个基于Remote Messenger Service Sample的小型应用程序

我有一个带有按钮的活动来启动/停止服务。 启动服务后,我绑定了服务和活动,如示例中所述,一切都按预期工作。 该服务有一个通知,就像示例一样:通知在MessengerService.onCreate() 中显示并在MessengerService.onDestroy() 中取消。

现在,我想在活动出现时自动启动服务。我的活动onStart() 如下(我删除了错误检查代码以使代码更具可读性):

@Override
public void onStart()
{
    super.onStart();

    Log.d( TAG, "start service at activity startup" );

    // Start the service automatically
    Intent intent = new Intent(this, MessengerService.class);
    startService(intent);

    // Bind to the service
    doBindService();
}

使用示例中的 doBingService():

void doBindService()
{
    Log.d( TAG, "doBindService call" );

    // Establish a connection with the service.  We use an explicit
    // class name because there is no reason to be able to let other
    // applications replace our component.
    bindService(new Intent(this, MessengerService.class), mConnection, Context.BIND_AUTO_CREATE);
    mIsBound = true;
}

现在,当我从 Android Studio 启动应用程序进行测试时,活动显示,我可以短暂看到通知,然后通知在大约一秒钟后消失。 该服务仍然存在,因为我可以发送消息强制通知返回。

经过一番调查,我在事件日志中看到:

02-20 22:35:03.342   383   396 I notification_cancel_all: [com.example.messengerservice,-1,0,0]
02-20 22:35:03.545   383   396 I notification_cancel_all: [com.example.messengerservice,-1,0,0]

以及相应的系统日志:

02-20 22:35:01.154 22884 22884 D example.Activity: start service at activity startup
02-20 22:35:01.170 22884 22884 D example.Activity: doBindService call
02-20 22:35:01.170   383  3814 I ActivityManager: Start proc com.example.messengerservice:notification for service com.example.messengerservice/.MessengerService: pid=22938 uid=10105 gids={50105, 1028}
02-20 22:35:01.232 22938 22938 I example.MessengerService: Service created
02-20 22:35:01.232 22938 22938 D example.MessengerService: Service bound
02-20 22:35:01.232 22938 22938 D example.MessengerService: Service start command
02-20 22:35:01.240 22938 22938 V example.MessengerService: Show notification
[...]
02-20 22:35:03.232   383  3801 I ActivityManager: Start proc com.google.android.apps.plus for broadcast com.google.android.apps.plus/.service.PackagesMediaMonitor: pid=23005 uid=10044 gids={50044, 3003, 3002, 1015, 1006, 1028}
02-20 22:35:03.271 22955 22957 D dalvikvm: GC_CONCURRENT freed 438K, 5% free 9179K/9656K, paused 2ms+4ms, total 28ms
02-20 22:35:03.271 22955 22955 D dalvikvm: WAIT_FOR_CONCURRENT_GC blocked 21ms
02-20 22:35:03.357   383   396 D BackupManagerService: Received broadcast Intent { act=android.intent.action.PACKAGE_REMOVED dat=package:com.example.messengerservice flg=0x8000010 (has extras) }
02-20 22:35:03.537 22837 22859 W GAV2    : Thread[GAThread,5,main]: Service unavailable (code=1), will retry.
02-20 22:35:03.537   383   394 W ActivityManager: Unable to start service Intent { act=com.google.android.gms.analytics.service.START (has extras) } U=0: not found
02-20 22:35:03.545   383   396 D BackupManagerService: Received broadcast Intent { act=android.intent.action.PACKAGE_ADDED dat=package:com.example.messengerservice flg=0x8000010 (has extras) }
02-20 22:35:03.545   383   396 V BackupManagerService: removePackageParticipantsLocked: uid=10105 #1
02-20 22:35:03.545   383   396 V BackupManagerService: addPackageParticipantsLocked: #1

似乎从 Android Studio 启动应用程序时,我发生了以下事情:

  • 包已更改
  • 活动开始(并显示)
  • 服务已启动
  • 通知可见
  • 系统收到 PACKAGE_REMOVED/PACKAGE_ADDED 并删除此包的所有通知
  • 通知被驳回

我的问题:如何在不被系统取消的情况下保留通知?

一些补充说明:

  • 有时(大约 10% 的时间),通知不会被取消并且一切都按预期工作。但大多数时候,这种行为是不正常的。
  • 当我从安装后的启动器而不是从 Android Studio 启动应用程序时,一切都很好。
  • 在这些日志中,服务在另一个进程中启动(清单中的 android:process=":notification"),但在同一个进程中启动不会改变行为。
  • 这些测试是在装有 Android 4.3 的 Galaxy Nexus 设备上完成的

编辑:

在这个例子中,我知道在一个“真实”的应用程序中,用户可能不会在升级应用程序之后和系统正确关闭以前的包之前打开活动。我将 startService 移出活动,在 PACKAGE_REPLACED 接收器中(并且仅在新版本之前运行时才处理启动服务的所有内容),但是在我的通知后大约 20 秒收到此 PACKAGE_REPLACED 意图已被取消。所以我仍然有一段时间我的服务正在做某事(例如播放音乐),并在 20 秒后弹出合适的通知。

【问题讨论】:

    标签: java android android-service android-notifications


    【解决方案1】:

    您会看到一个竞争条件,即您立即绑定服务并显示来自它的通知。这可能不会引起太多注意,因为通常应用不会在其主要活动的 onCreate 活动中立即显示通知。

    尝试将您的 doBindService 替换为

    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            doBindService();
        }
    }, 1000);
    

    或者,如果您只是在测试,请不要担心。

    【讨论】:

    • 通知是从服务的onCreate()方法启动的,不是onBind()所以我也把startService()放到你的run()里面。更好,但仍然存在 Android 在活动启动后超过 1 秒终止我的通知的问题。当然我可以增加延迟,但它看起来并不是一个始终有效的“干净”解决方案。
    • 我编辑了这个问题,试图解释为什么在这个例子中我可以忍受它,但在“现实世界”应用程序(例如音乐播放器)中,我对这种行为不满意.我想不出一种方法可以让我的服务始终收到通知。
    • 为什么媒体播放器会在创建活动时立即显示通知?通常,如果用户正在查看您的应用程序,他们也不需要来自它的通知。通知通常会在您的应用处于后台时显示。
    • 经过大量测试,我接受了“别担心”部分。在调试模式下,我只设置了 3 秒的延迟。在发布版本中,我使用 PACKAGE_REPLACED 意图重新启动服务。它在升级后仅发生 20-30 秒,但对用户来说似乎比在活动启动时重新启动服务更“错误”,并且通知消失了,因为升级后太快了。仅供参考,当活动处于前台时也会显示通知,例如“持久信息通知”,与play.google.com/store/apps/details?id=zzs.notisysinfo 相同
    • 还不错。我很惊讶,20-30 秒似乎比我预期的要长得多
    猜你喜欢
    • 1970-01-01
    • 2020-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多