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

时间:2014-02-21 10:29:41

标签: java android android-service android-notifications

我正在测试根据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接收器(并且只有在新版本之前运行时才处理启动服务的所有内容),但是这个PACKAGE_REPLACED意图大约是20我的通知取消后几秒钟。所以我仍然有一段时间我的服务正在做某事(例如播放音乐),并在20秒后弹出合适的通知。

1 个答案:

答案 0 :(得分:0)

您发现竞争条件是您立即绑定服务并显示通知。这可能不会引起太多注意,因为通常应用程序不会立即在其主要活动的创建活动中显示通知。

尝试用

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

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