Java 服务启动时显示的Android通知在创建后立即取消

Java 服务启动时显示的Android通知在创建后立即取消,java,android,android-service,android-notifications,Java,Android,Android Service,Android Notifications,我正在测试一个基于 我有一个带有按钮的活动,用于启动/停止服务。 启动服务后,我绑定了服务和活动,如示例中所述,一切都按照预期工作。 该服务有一个通知,正如示例所示:该通知显示在信使服务.onCreate()中,并在信使服务.onDestroy()中取消 现在,我想在活动显示时自动启动服务。我的活动onStart()如下所示(我删除了错误检查代码以使代码更具可读性): 使用从示例中获取的doBingService(): void doBindService() { Log.d( TAG,

我正在测试一个基于

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

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

使用从示例中获取的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;
}
现在,当我从androidstudio启动应用程序进行测试时,活动显示出来,我可以短暂地看到通知,然后,通知在大约一秒钟后消失。 该服务仍处于活动状态,因为我可以发送消息以强制返回通知

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

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启动应用程序时,似乎发生了以下事情:

  • 包已更改
  • 活动开始(并显示)
  • 服务已启动
  • 通知是可见的
  • 系统接收已删除/已添加的包,并删除此包的所有通知
  • 通知被驳回
我的问题是:如何在不被系统取消的情况下保留通知

一些补充说明:

  • 有时(大约10%的情况下),通知不会被取消,一切正常。但大多数时候,这种行为是不正常的
  • 当我从安装后的启动器启动应用程序时,而不是从Android Studio启动应用程序时,一切都很好
  • 在这些日志中,服务在另一个进程中启动(清单中的android:process=“:notification”),但在同一进程中启动不会改变行为
  • 这些测试是在Galaxy Nexus设备上进行的,该设备采用Android 4.3
编辑:


在本例中,我了解到,在一个“真正”的应用程序中,用户可能不会在升级应用程序之后,在系统正确关闭前一个包之前打开活动。我将startService从活动中移出,放在一个
PACKAGE\u替换的
接收器中(并且只有在新版本之前运行时才处理启动服务的所有内容),但是这个
PACKAGE\u替换的
意图是在我的通知取消后大约20秒收到的。因此,我仍然有一些时间,我的服务正在做一些事情(例如播放音乐),并弹出适当的通知,20秒后。

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

尝试将您的Dobind服务替换为

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

或者,如果您只是在测试,就不用担心了。

通知是从服务的onCreate()方法开始的,而不是onBind()方法,因此我还将startService()放在您的run()中。虽然更好,但仍然存在一些问题,Android在活动启动后超过1秒就终止了我的通知。当然,我可以增加延迟,但这并不是一个“干净”的解决方案。我编辑了这个问题,试图解释为什么在这个例子中我可以接受它,但在一个“真实世界”的应用程序(例如音乐播放器)中,我对这种行为不满意。我想不出一种方法可以在我的服务中始终显示通知。为什么媒体播放器在创建活动时会立即显示通知?通常,如果用户正在查看你的应用程序,他们也不需要来自应用程序的通知。通知通常在应用程序处于后台时显示。经过大量测试后,我接受“只是不必担心”部分。在调试模式下,我只设置了3秒的延迟。在发布版本中,我使用包来重新启动服务。它只在升级后20-30秒发生,但对用户来说,它似乎不像在活动启动时重新启动服务那么“麻烦”,并且通知会被取消,因为升级后时间太短。仅供参考,当活动位于前台时,也会显示通知,如“持久信息通知”,与ok fair相同。我很惊讶,20-30秒似乎比我预期的要长得多
new Handler().postDelayed(new Runnable() {
    @Override
    public void run() {
        doBindService();
    }
}, 1000);