8

我已经在我的新应用程序中启动了一项服务。该服务是前台的,带有一个通知。当它在 AVD 2.1 API Level 7 中运行时,一切正常。但是当它在运行 Gingerbread 的三星 Galaxy Tab 上运行时,该服务将启动(图标和应用程序名称出现在通知区域的顶部),但几秒钟后,该服务消失了。我可以看到的日志中的最后一个条目与我的应用程序相关联,是我的 Log.d("Taglines","Returning with " + START_STICKY) 的结果,它紧接在 "return START_STICKY ;" 之前 在我的 Service 的 onStartCommand 覆盖中,如下:

@Override
public int onStartCommand(Intent intent, int flags, int startId) {

    int rc ;
    Log.d("Taglines","onStartCommand()");
    Toast.makeText(this, "Starting service TagsManager", Toast.LENGTH_SHORT).show();
    Log.d("Taglines","Calling super.onStartCommand()");
    rc = super.onStartCommand(intent,flags,startId);
    Log.d("Taglines","super.onStartCommand return code was " + rc);
    createNotification(INITIAL_NOTIFICATION_TEXT);
    Log.d("Taglines","Returning with " + START_STICKY);
    return START_STICKY ;
}

通知设置如下:

void createNotification(String text) {

    Log.d("Taglines","createNotification called");
    if (mNotificationManager == null) {
        // Get a reference to the Notification Manager
        String ns = Context.NOTIFICATION_SERVICE;
        mNotificationManager = (NotificationManager) getSystemService(ns);
        Log.d("Taglines","Obtained reference to Notification Manager");
    }

    // Instantiate the Notification
    int icon = R.drawable.ic_notification;
    CharSequence tickerText = "Taglines";
    long when = System.currentTimeMillis();

    notification = new Notification(icon, tickerText, when);

    // Define Notification's expanded message and intent
    Log.d("Taglines","createNotificacion() .. getApplicationContext");
    context = getApplicationContext();
    contentText = text;
    // notificationIntent = new Intent(this, TagsOverview.class);
    notificationIntent = new Intent(this, TagsServiceMenu.class);
    contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);

    notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);

    // Pass the Notification to the NotificationManager: 
    Log.d("Taglines","createNotificacion() ... passing notification");
    mNotificationManager.notify(NOTIFICATION_ID, notification);
    Log.d("Taglines","Starting foreground");
    startForeground(NOTIFICATION_ID, notification);
    Log.d("Taglines","Started");
}

这是服务启动时“adb logcat”的结果:

D/Taglines(21863): Starting service
D/Taglines(21863): TagsManager(nullary) completed
D/Taglines(21863): onStartCommand()
D/Taglines(21863): Calling super.onStartCommand()
D/Taglines(21863): super.onStartCommand eturn code was 2
D/Taglines(21863): createNotification called
D/Taglines(21863): Obtained reference to Notification Manager
D/Taglines(21863): createNotificacion() .. getApplicationContext
D/Taglines(21863): createNotificacion() ... passing notification
D/Taglines(21863): Starting foreground
D/Taglines(21863): Started
D/Taglines(21863): Returning with 1

在那之后,没有什么特别的(PID 21863 没有任何东西)。只是一堆:

D/KeyguardViewMediator(  302): setHidden false
D/KeyguardViewMediator(  302): setHidden false
D/KeyguardViewMediator(  302): setHidden false
D/KeyguardViewMediator(  302): setHidden false
D/KeyguardViewMediator(  302): setHidden false
W/InputManagerService(  302): Window already focused, ignoring focus gain of:         com.android.internal.view.IInputMethodClient$Stub$Proxy@40bc06e8
D/KeyguardViewMediator(  302): setHidden false
D/KeyguardViewMediator(  302): setHidden false
D/KeyguardViewMediator(  302): setHidden false
D/KeyguardViewMediator(  302): setHidden false
D/KeyguardViewMediator(  302): setHidden false
D/KeyguardViewMediator(  302): setHidden false
D/KeyguardViewMediator(  302): setHidden false
D/KeyguardViewMediator(  302): setHidden false
D/KeyguardViewMediator(  302): setHidden false

我认为在这种情况下不需要它,但这是 AndroidManifest.xml 的相关部分:

    <service android:name=".TagsManager"
             android:exported="false">
    </service>

我可能哪里出错了?我还能提供哪些其他信息?

4

2 回答 2

11

一些东西:

  1. 摆脱mNotificationManager.notify(NOTIFICATION_ID, notification);. startForeground()为您显示通知图标。

  2. ForegroundService仍然可以被杀死,只是不太可能被杀死。

  3. 2.3 中有一个错误(不确定是否已修复),当 aService被杀死并重新启动时,它onStartCommand()不会再次被调用。相反,您将不得不在onCreate().

于 2011-07-29T19:19:49.210 回答
1

Service仅当手机内存不足并在完成执行之前将其杀死时,这两个代码才有意义。START_STICKY告诉操作系统在它有足够的内存后重新创建服务并onStartCommand()以空意图再次调用。START_NOT_STICKY告诉操作系统不要再费心重新创建服务。还有第三个代码START_REDELIVER_INTENT告诉操作系统重新创建ServiceAND 重新传递相同的意图到onStartCommand().

Dianne Hackborn 的这篇文章比官方文档更好地解释了这个背景。

这里的关键部分是函数返回的新结果代码,告诉系统如果它的进程在运行时被杀死,它应该如何处理服务:

START_STICKY 与之前的行为基本相同,服务保持“启动”状态,稍后将由系统重新启动。与平台先前版本的唯一区别是,如果它因为进程被终止而重新启动,onStartCommand() 将在服务的下一个实例上以空 Intent 调用,而不是根本不调用。使用此模式的服务应始终检查此情况并适当处理。

START_NOT_STICKY 表示,在从 onStartCreated() 返回后,如果进程被杀死且没有剩余的启动命令可交付,则服务将停止而不是重新启动。这对于仅在执行发送给它们的命令时才运行的服务更有意义。例如,一项服务可能会从警报开始每 15 分钟启动一次,以轮询某些网络状态。如果它在做这项工作时被杀死,最好让它停止并在下次警报触发时启动。

START_REDELIVER_INTENT 类似于 START_NOT_STICKY,除非服务的进程在它为给定意图调用 stopSelf() 之前被终止,否则该意图将被重新传递给它,直到它完成(除非经过多次尝试它仍然无法完成,此时系统放弃)。这对于接收工作命令的服务很有用,并希望确保它们最终完成每个发送命令的工作。

于 2013-11-12T16:12:08.373 回答