START_STICKY,前台Android服务消失,恕不另行通知

时间:2011-07-08 01:50:07

标签: android service foreground

我已在我的新应用程序中启动了一项服务。该服务是有前途的,带有通知。当在AVD 2.1 API Level 7中运行时,一切正常。但是当它在运行Gingerbread的三星Galaxy Tab上运行时,服务将启动(图标和应用程序名称显示在通知区域的顶部),但几秒钟后,服务就会消失。我可以看到的Log中的最后一个条目与我的App相关联,是我的Log.d(“Taglines”,“Return with with”+ START_STICKY)的结果,它紧接在“return START_STICKY”之前。在我的服务的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>

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

2 个答案:

答案 0 :(得分:11)

一些事情:

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

  2. 前景Service仍然可以被杀死,他们不太可能被杀死。

  3. 2.3中存在一个错误(不确定它是否已修复),当Service被杀死并重新启动时,其onStartCommand()将不再被调用。相反,您将不得不在onCreate()进行任何设置。

答案 1 :(得分:1)

这两个代码仅在手机内存不足时才会生效,并在执行完毕前杀死ServiceSTART_STICKY告诉操作系统在有足够内存后重新创建服务,并再次使用空意图调用onStartCommand()START_NOT_STICKY告诉操作系统不要再次重新创建服务。还有第三个代码START_REDELIVER_INTENT告诉操作系统重新创建Service并将同一意图重新传递给onStartCommand()

Dianne Hackborn的

This article解释了这个背景比官方文档好得多。

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

  

START_STICKY与之前的行为基本相同,其中   服务保持“启动”状态,稍后将由系统重新启动。   与以前版本的平台的唯一区别是它   如果由于其进程被终止而重新启动,onStartCommand()   将使用null Intent在服务的下一个实例上调用   而不是根本不被召唤。使用此模式的服务应该   总是检查这个案子并妥善处理。

     

START_NOT_STICKY说,从onStartCreated()返回之后,如果   该进程被杀死,没有剩余的启动命令要传递,   然后服务将停止而不是重新启动。这样做了   对于那些只打算运行的服务更有意义   执行发送给他们的命令。例如,可以启动服务   从警报每15分钟轮询一些网络状态。如果它得到   在做这项工作时被杀,最好是让它成为现实   下次报警发生时停止并开始运行。

     

START_REDELIVER_INTENT就像START_NOT_STICKY,除非是   服务的进程在调用给定的stopSelf()之前被终止   意图,该意图将在完成之前重新发送给它   (除非经过多次尝试后仍无法完成,否则   系统放弃了哪一点)。这对于那些服务很有用   接收要做的工作命令,并希望确保他们这样做   最终完成发送的每个命令的工作。